redgifs.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #!/usr/bin/env python3
  2. import json
  3. import re
  4. import urllib.parse
  5. from typing import Optional
  6. from praw.models import Submission
  7. from bdfr.exceptions import SiteDownloaderError
  8. from bdfr.resource import Resource
  9. from bdfr.site_authenticator import SiteAuthenticator
  10. from bdfr.site_downloaders.base_downloader import BaseDownloader
  11. class Redgifs(BaseDownloader):
  12. def __init__(self, post: Submission):
  13. super().__init__(post)
  14. def find_resources(self, authenticator: Optional[SiteAuthenticator] = None) -> list[Resource]:
  15. media_urls = self._get_link(self.post.url)
  16. return [Resource(self.post, m, Resource.retry_download(m), None) for m in media_urls]
  17. @staticmethod
  18. def _get_link(url: str) -> set[str]:
  19. try:
  20. redgif_id = re.match(r'.*/(.*?)(\..{0,})?$', url).group(1)
  21. except AttributeError:
  22. raise SiteDownloaderError(f'Could not extract Redgifs ID from {url}')
  23. content = Redgifs.retrieve_url(f'https://api.redgifs.com/v1/gifs/{redgif_id}')
  24. if content is None:
  25. raise SiteDownloaderError('Could not read the page source')
  26. try:
  27. response_json = json.loads(content.text)
  28. except json.JSONDecodeError as e:
  29. raise SiteDownloaderError(f'Received data was not valid JSON: {e}')
  30. out = set()
  31. try:
  32. if response_json['gfyItem']['type'] == 1: # type 1 is a video
  33. out.add(response_json['gfyItem']['mp4Url'])
  34. elif response_json['gfyItem']['type'] == 2: # type 2 is an image
  35. if 'gallery' in response_json['gfyItem']:
  36. content = Redgifs.retrieve_url(
  37. f'https://api.redgifs.com/v2/gallery/{response_json["gfyItem"]["gallery"]}')
  38. response_json = json.loads(content.text)
  39. out = {p['urls']['hd'] for p in response_json['gifs']}
  40. else:
  41. out.add(response_json['gfyItem']['content_urls']['large']['url'])
  42. else:
  43. raise KeyError
  44. except (KeyError, AttributeError):
  45. raise SiteDownloaderError('Failed to find JSON data in page')
  46. # Update subdomain if old one is returned
  47. out = {re.sub('thumbs2', 'thumbs3', link) for link in out}
  48. out = {re.sub('thumbs3', 'thumbs4', link) for link in out}
  49. return out