summaryrefslogtreecommitdiffstats
path: root/gallery_dl/extractor/redgifs.py
diff options
context:
space:
mode:
Diffstat (limited to 'gallery_dl/extractor/redgifs.py')
-rw-r--r--gallery_dl/extractor/redgifs.py123
1 files changed, 104 insertions, 19 deletions
diff --git a/gallery_dl/extractor/redgifs.py b/gallery_dl/extractor/redgifs.py
index e078bef..df50f70 100644
--- a/gallery_dl/extractor/redgifs.py
+++ b/gallery_dl/extractor/redgifs.py
@@ -8,15 +8,60 @@
"""Extractors for https://redgifs.com/"""
-from .gfycat import GfycatExtractor, GfycatAPI
+from .common import Extractor, Message
from .. import text
-class RedgifsExtractor(GfycatExtractor):
+class RedgifsExtractor(Extractor):
"""Base class for redgifs extractors"""
category = "redgifs"
+ filename_fmt = "{category}_{id}.{extension}"
+ archive_fmt = "{id}"
root = "https://www.redgifs.com"
+ def __init__(self, match):
+ Extractor.__init__(self, match)
+ self.key = match.group(1)
+
+ formats = self.config("format")
+ if formats is None:
+ formats = ("hd", "sd", "gif")
+ elif isinstance(formats, str):
+ formats = (formats, "hd", "sd", "gif")
+ self.formats = formats
+
+ def items(self):
+ metadata = self.metadata()
+ for gif in self.gifs():
+ url = self._process(gif)
+ if not url:
+ self.log.warning("Skipping '%s' (format not available)",
+ gif["id"])
+ continue
+
+ gif.update(metadata)
+ yield Message.Directory, gif
+ yield Message.Url, url, gif
+
+ def _process(self, gif):
+ gif["_fallback"] = formats = self._formats(gif)
+ gif["date"] = text.parse_timestamp(gif.get("createDate"))
+ return next(formats, None)
+
+ def _formats(self, gif):
+ urls = gif["urls"]
+ for fmt in self.formats:
+ url = urls.get(fmt)
+ if url:
+ text.nameext_from_url(url, gif)
+ yield url
+
+ def metadata(self):
+ return {}
+
+ def gifs(self):
+ return ()
+
class RedgifsUserExtractor(RedgifsExtractor):
"""Extractor for redgifs user profiles"""
@@ -24,11 +69,14 @@ class RedgifsUserExtractor(RedgifsExtractor):
directory_fmt = ("{category}", "{userName}")
pattern = r"(?:https?://)?(?:www\.)?redgifs\.com/users/([^/?#]+)"
test = ("https://www.redgifs.com/users/Natalifiction", {
- "pattern": r"https://\w+\.(redgifs|gfycat)\.com/[A-Za-z]+\.mp4",
- "count": ">= 100",
+ "pattern": r"https://\w+\.redgifs\.com/[A-Za-z]+\.mp4",
+ "count": ">= 120",
})
- def gfycats(self):
+ def metadata(self):
+ return {"userName": self.key}
+
+ def gifs(self):
return RedgifsAPI(self).user(self.key)
@@ -36,19 +84,23 @@ class RedgifsSearchExtractor(RedgifsExtractor):
"""Extractor for redgifs search results"""
subcategory = "search"
directory_fmt = ("{category}", "Search", "{search}")
- pattern = r"(?:https?://)?(?:www\.)?redgifs\.com/gifs/browse/([^/?#]+)"
- test = ("https://www.redgifs.com/gifs/browse/jav", {
- "pattern": r"https://\w+\.(redgifs|gfycat)\.com/[A-Za-z]+\.mp4",
- "range": "1-10",
- "count": 10,
- })
+ pattern = r"(?:https?://)?(?:www\.)?redgifs\.com/browse/?\?([^#]+)"
+ test = (
+ ("https://www.redgifs.com/browse?tags=JAV", {
+ "pattern": r"https://\w+\.redgifs\.com/[A-Za-z]+\.mp4",
+ "range": "1-10",
+ "count": 10,
+ }),
+ ("https://www.redgifs.com/browse?type=i&verified=y&order=top7"),
+ )
def metadata(self):
- self.key = text.unquote(self.key).replace("-", " ")
- return {"search": self.key}
+ self.params = params = text.parse_query(self.key)
+ search = params.get("tags") or params.get("order") or "trending"
+ return {"search": search}
- def gfycats(self):
- return RedgifsAPI(self).search(self.key)
+ def gifs(self):
+ return RedgifsAPI(self).search(self.params)
class RedgifsImageExtractor(RedgifsExtractor):
@@ -58,7 +110,7 @@ class RedgifsImageExtractor(RedgifsExtractor):
r"|gifdeliverynetwork.com)/([A-Za-z]+)")
test = (
("https://redgifs.com/watch/foolishforkedabyssiniancat", {
- "pattern": r"https://\w+\.(redgifs|gfycat)\.com"
+ "pattern": r"https://\w+\.redgifs\.com"
r"/FoolishForkedAbyssiniancat\.mp4",
"content": "f6e03f1df9a2ff2a74092f53ee7580d2fb943533",
}),
@@ -66,9 +118,42 @@ class RedgifsImageExtractor(RedgifsExtractor):
("https://www.gifdeliverynetwork.com/foolishforkedabyssiniancat"),
)
- def gfycats(self):
- return (RedgifsAPI(self).gfycat(self.key),)
+ def gifs(self):
+ return (RedgifsAPI(self).gif(self.key),)
-class RedgifsAPI(GfycatAPI):
+class RedgifsAPI():
API_ROOT = "https://api.redgifs.com"
+
+ def __init__(self, extractor):
+ self.extractor = extractor
+
+ def gif(self, gif_id):
+ endpoint = "/v2/gifs/" + gif_id.lower()
+ return self._call(endpoint)["gif"]
+
+ def user(self, user, order="best"):
+ endpoint = "/v2/users/{}/search".format(user.lower())
+ params = {"order": order}
+ return self._pagination(endpoint, params)
+
+ def search(self, params):
+ endpoint = "/v2/gifs/search"
+ params["search_text"] = params.pop("tags", None)
+ params.pop("needSendGtm", None)
+ return self._pagination(endpoint, params)
+
+ def _call(self, endpoint, params=None):
+ url = self.API_ROOT + endpoint
+ return self.extractor.request(url, params=params).json()
+
+ def _pagination(self, endpoint, params):
+ params["page"] = 1
+
+ while True:
+ data = self._call(endpoint, params)
+ yield from data["gifs"]
+
+ if params["page"] >= data["pages"]:
+ return
+ params["page"] += 1