Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to how Redgifs temp auth tokens are handled #940

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bdfr/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import click
import requests

from bdfr import __version__
from bdfr.__init__ import __version__
from bdfr.archiver import Archiver
from bdfr.cloner import RedditCloner
from bdfr.completion import Completion
Expand Down
18 changes: 17 additions & 1 deletion bdfr/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import prawcore

from bdfr import exceptions as errors
from bdfr.site_downloaders import redgifs
from bdfr.configuration import Configuration
from bdfr.connector import RedditConnector
from bdfr.site_downloaders.download_factory import DownloadFactory
Expand Down Expand Up @@ -107,7 +108,22 @@ def _download_submission(self, submission: praw.models.Submission):
content = downloader.find_resources(self.authenticator)
except errors.SiteDownloaderError as e:
logger.error(f"Site {downloader_class.__name__} failed to download submission {submission.id}: {e}")
return
# Redgifs 401 error / temporary auth token handler
if (downloader_class.__name__ == "Redgifs") and (str(e).startswith("Server responded with 401")):
print("\n-=-=-=-=-=-=-=-=-=-=-=-\nRedgifs temporary API token out of date")

# Extracting URL from the error message
url_start_index = str(e).rfind("https://")
redgifs_url = str(e)[url_start_index:]

# Getting new temp API token
redgifs.Redgifs._get_token(redgifs.Redgifs, redgifs_url)

# Attempted redownload of link that hit the 401 error. Don't think it works though.
redgifs.Redgifs._get_link(redgifs_url)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the line that attempts to re-run the download with the skipped link from the 401 error.

I'm guessing the chain resolves somewhere else and the link doesn't get passed correctly.
Might be worth moving the entire error checking code into redgifs.py and just handle it over there.
Would be easier to pass the url and re-run the download function.

return
else:
return
for destination, res in self.file_name_formatter.format_resource_paths(content, self.download_directory):
if destination.exists():
logger.debug(f"File {destination} from submission {submission.id} already exists, continuing")
Expand Down
2 changes: 2 additions & 0 deletions bdfr/site_downloaders/base_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def retrieve_url(url: str, cookies: dict = None, headers: dict = None) -> reques
except requests.exceptions.RequestException as e:
logger.exception(e)
raise SiteDownloaderError(f"Failed to get page {url}")
if res.status_code == 429:
raise ResourceNotFound("\n\nToo many requests\nTry again in a little while\n")
if res.status_code != 200:
raise ResourceNotFound(f"Server responded with {res.status_code} to {url}")
return res
40 changes: 37 additions & 3 deletions bdfr/site_downloaders/redgifs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import json
import re
import os
import tempfile
from typing import Optional

import requests
Expand All @@ -15,13 +17,46 @@


class Redgifs(BaseDownloader):
# Setting temp token path. Probably would be better somewhere else, but os temp works.
TOKEN_FILE_PATH = os.path.join(tempfile.gettempdir(), "redgifs_token.txt")

def __init__(self, post: Submission):
super().__init__(post)

def find_resources(self, authenticator: Optional[SiteAuthenticator] = None) -> list[Resource]:
media_urls = self._get_link(self.post.url)
return [Resource(self.post, m, Resource.retry_download(m), None) for m in media_urls]

### Temporary auth token handling ###
def _load_token(self, url) -> Optional[str]:
try:
with open(self.TOKEN_FILE_PATH, "r") as file:
return file.read().strip()
except FileNotFoundError:
print("\n-=-=-=-=-=-=-=-=-=-=-=-\nRedgifs API token file not found, retrieving new token")
self._get_token(self, url)
with open(self.TOKEN_FILE_PATH, "r") as file:
return file.read().strip()

def _save_token(self, token: str, url):
print(f"Writing Redgifs temporary API token to {self.TOKEN_FILE_PATH}")
with open(self.TOKEN_FILE_PATH, "w") as file:
file.write(token)
print(f"Success!\n\nNew temporary token is: {token}\n-=-=-=-=-=-=-=-=-=-=-=-\n")
return token

def _get_token(self, redgif_id, other=None) -> str:
try:
print("Attempting to retrieve new temporary Redgifs API token")
response = self.retrieve_url("https://api.redgifs.com/v2/auth/temporary")
auth_token = json.loads(response.text)["token"]

self._save_token(self, auth_token, redgif_id)
except Exception as e:
raise SiteDownloaderError(f"Failed to retrieve Redgifs API token: {e}")
return auth_token
### End temporary auth token handling ###

@staticmethod
def _get_id(url: str) -> str:
try:
Expand All @@ -38,9 +73,8 @@ def _get_id(url: str) -> str:
def _get_link(url: str) -> set[str]:
redgif_id = Redgifs._get_id(url)

auth_token = json.loads(Redgifs.retrieve_url("https://api.redgifs.com/v2/auth/temporary").text)["token"]
if not auth_token:
raise SiteDownloaderError("Unable to retrieve Redgifs API token")
# Passing url here. Probably don't need to.
auth_token = Redgifs._load_token(Redgifs, url)

headers = {
"referer": "https://www.redgifs.com/",
Expand Down
Loading