2021-02-07 17:46:20 +13:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2020-06-04 03:10:25 +12:00
|
|
|
import json
|
2021-02-07 17:46:20 +13:00
|
|
|
import logging
|
2021-02-25 23:40:08 +13:00
|
|
|
from typing import Optional
|
2021-02-07 01:29:13 +13:00
|
|
|
|
2020-06-04 03:10:25 +12:00
|
|
|
import requests
|
2021-02-11 12:10:40 +13:00
|
|
|
from praw.models import Submission
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2021-02-26 21:57:05 +13:00
|
|
|
from bulkredditdownloader.site_authenticator import SiteAuthenticator
|
2021-03-05 16:32:24 +13:00
|
|
|
from bulkredditdownloader.exceptions import NotADownloadableLinkError, ResourceNotFound, SiteDownloaderError
|
2021-02-25 23:40:08 +13:00
|
|
|
from bulkredditdownloader.resource import Resource
|
2021-02-07 20:08:24 +13:00
|
|
|
from bulkredditdownloader.site_downloaders.base_downloader import BaseDownloader
|
|
|
|
from bulkredditdownloader.site_downloaders.direct import Direct
|
2021-02-07 17:46:20 +13:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2021-02-25 22:32:06 +13:00
|
|
|
|
2021-02-07 14:33:19 +13:00
|
|
|
class Imgur(BaseDownloader):
|
2021-02-06 21:35:50 +13:00
|
|
|
imgur_image_domain = "https://i.imgur.com/"
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2021-02-15 18:12:27 +13:00
|
|
|
def __init__(self, post: Submission):
|
|
|
|
super().__init__(post)
|
2021-02-07 17:46:20 +13:00
|
|
|
self.raw_data = {}
|
|
|
|
|
2021-02-26 21:57:05 +13:00
|
|
|
def find_resources(self, authenticator: Optional[SiteAuthenticator] = None) -> list[Resource]:
|
2021-02-11 12:10:40 +13:00
|
|
|
link = self.post.url
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2020-06-04 03:10:25 +12:00
|
|
|
if link.endswith(".gifv"):
|
2021-02-15 18:12:27 +13:00
|
|
|
direct_thing = Direct(self.post)
|
2021-02-25 23:40:08 +13:00
|
|
|
return direct_thing.find_resources(authenticator)
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2021-02-07 17:46:20 +13:00
|
|
|
self.raw_data = self._get_data(link)
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2021-02-27 19:22:42 +13:00
|
|
|
if self._is_album():
|
2021-02-06 21:35:50 +13:00
|
|
|
if self.raw_data["album_images"]["count"] != 1:
|
2021-02-11 12:10:40 +13:00
|
|
|
out = self._download_album(self.raw_data["album_images"])
|
2020-06-04 03:10:25 +12:00
|
|
|
else:
|
2021-02-11 12:10:40 +13:00
|
|
|
out = self._download_image(self.raw_data["album_images"]["images"][0])
|
2020-06-04 03:10:25 +12:00
|
|
|
else:
|
2021-02-11 12:10:40 +13:00
|
|
|
out = self._download_image(self.raw_data)
|
|
|
|
return out
|
2020-06-02 00:05:02 +12:00
|
|
|
|
2021-02-07 17:46:20 +13:00
|
|
|
def _download_album(self, images: dict):
|
2021-02-06 21:35:50 +13:00
|
|
|
images_length = images["count"]
|
2020-05-29 06:42:11 +12:00
|
|
|
|
2021-02-11 12:10:40 +13:00
|
|
|
out = []
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-06 21:35:50 +13:00
|
|
|
for i in range(images_length):
|
2021-02-07 17:46:20 +13:00
|
|
|
extension = self._validate_extension(images["images"][i]["ext"])
|
2021-02-06 21:35:50 +13:00
|
|
|
image_url = self.imgur_image_domain + images["images"][i]["hash"] + extension
|
2021-02-25 23:40:08 +13:00
|
|
|
out.append(Resource(self.post, image_url))
|
2021-02-11 12:10:40 +13:00
|
|
|
return out
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-07 17:46:20 +13:00
|
|
|
def _download_image(self, image: dict):
|
|
|
|
extension = self._validate_extension(image["ext"])
|
2021-02-06 21:35:50 +13:00
|
|
|
image_url = self.imgur_image_domain + image["hash"] + extension
|
2021-02-25 23:40:08 +13:00
|
|
|
return [Resource(self.post, image_url)]
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-07 17:46:20 +13:00
|
|
|
def _is_album(self) -> bool:
|
2021-02-06 21:35:50 +13:00
|
|
|
return "album_images" in self.raw_data
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-25 22:32:06 +13:00
|
|
|
@staticmethod
|
2021-02-07 17:46:20 +13:00
|
|
|
def _get_data(link: str) -> dict:
|
2021-01-07 22:45:16 +13:00
|
|
|
cookies = {"over18": "1", "postpagebeta": "0"}
|
2020-06-04 03:10:25 +12:00
|
|
|
res = requests.get(link, cookies=cookies)
|
2021-02-25 22:32:06 +13:00
|
|
|
if res.status_code != 200:
|
2021-02-15 19:30:39 +13:00
|
|
|
raise ResourceNotFound(f"Server responded with {res.status_code} to {link}")
|
2021-02-06 21:35:50 +13:00
|
|
|
page_source = requests.get(link, cookies=cookies).text
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-06 21:35:50 +13:00
|
|
|
starting_string = "image : "
|
|
|
|
ending_string = "group :"
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-06 21:35:50 +13:00
|
|
|
starting_string_lenght = len(starting_string)
|
2020-06-04 03:10:25 +12:00
|
|
|
try:
|
2021-02-06 21:35:50 +13:00
|
|
|
start_index = page_source.index(starting_string) + starting_string_lenght
|
|
|
|
end_index = page_source.index(ending_string, start_index)
|
2020-06-04 03:10:25 +12:00
|
|
|
except ValueError:
|
2021-02-25 22:32:06 +13:00
|
|
|
raise NotADownloadableLinkError(
|
|
|
|
f"Could not read the page source on {link}")
|
2020-06-04 03:10:25 +12:00
|
|
|
|
2021-02-06 21:35:50 +13:00
|
|
|
while page_source[end_index] != "}":
|
|
|
|
end_index -= 1
|
2021-01-07 22:45:16 +13:00
|
|
|
try:
|
2021-02-06 21:35:50 +13:00
|
|
|
data = page_source[start_index:end_index + 2].strip()[:-1]
|
2021-02-07 17:46:20 +13:00
|
|
|
except IndexError:
|
2021-02-06 21:35:50 +13:00
|
|
|
page_source[end_index + 1] = '}'
|
|
|
|
data = page_source[start_index:end_index + 3].strip()[:-1]
|
2020-06-04 03:10:25 +12:00
|
|
|
|
|
|
|
return json.loads(data)
|
2020-05-29 06:42:11 +12:00
|
|
|
|
|
|
|
@staticmethod
|
2021-02-07 17:46:20 +13:00
|
|
|
def _validate_extension(extension_suffix: str) -> str:
|
2021-02-06 21:35:50 +13:00
|
|
|
possible_extensions = [".jpg", ".png", ".mp4", ".gif"]
|
|
|
|
for extension in possible_extensions:
|
2021-02-07 17:46:20 +13:00
|
|
|
if extension in extension_suffix:
|
2021-02-25 22:32:06 +13:00
|
|
|
return extension
|
2021-02-06 21:35:50 +13:00
|
|
|
else:
|
2021-02-15 19:30:39 +13:00
|
|
|
raise SiteDownloaderError(f'"{extension_suffix}" is not recognized as a valid extension for Imgur')
|