summaryrefslogtreecommitdiffstats
path: root/gallery_dl/extractor/bunkr.py
diff options
context:
space:
mode:
Diffstat (limited to 'gallery_dl/extractor/bunkr.py')
-rw-r--r--gallery_dl/extractor/bunkr.py89
1 files changed, 89 insertions, 0 deletions
diff --git a/gallery_dl/extractor/bunkr.py b/gallery_dl/extractor/bunkr.py
new file mode 100644
index 0000000..9904d0a
--- /dev/null
+++ b/gallery_dl/extractor/bunkr.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2022 Mike Fährmann
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+"""Extractors for https://bunkr.is/"""
+
+from .lolisafe import LolisafeAlbumExtractor
+from .. import text
+import json
+
+
+class BunkrAlbumExtractor(LolisafeAlbumExtractor):
+ """Extractor for bunkr.is albums"""
+ category = "bunkr"
+ root = "https://app.bunkr.is"
+ pattern = r"(?:https?://)?(?:app\.)?bunkr\.(?:is|to)/a/([^/?#]+)"
+ test = (
+ ("https://app.bunkr.is/a/Lktg9Keq", {
+ "pattern": r"https://cdn\.bunkr\.is/test-テスト-\"&>-QjgneIQv\.png",
+ "content": "0c8768055e4e20e7c7259608b67799171b691140",
+ "keyword": {
+ "album_id": "Lktg9Keq",
+ "album_name": 'test テスト "&>',
+ "count": 1,
+ "filename": 'test-テスト-"&>-QjgneIQv',
+ "id": "QjgneIQv",
+ "name": 'test-テスト-"&>',
+ "num": int,
+ },
+ }),
+ # mp4 (#2239)
+ ("https://bunkr.is/a/ptRHaCn2", {
+ "pattern": r"https://media-files\.bunkr\.is/_-RnHoW69L\.mp4",
+ "content": "80e61d1dbc5896ae7ef9a28734c747b28b320471",
+ }),
+ ("https://bunkr.to/a/Lktg9Keq"),
+ )
+
+ def fetch_album(self, album_id):
+ if "//app." in self.root:
+ return self._fetch_album_api(album_id)
+ else:
+ return self._fetch_album_site(album_id)
+
+ def _fetch_album_api(self, album_id):
+ files, data = LolisafeAlbumExtractor.fetch_album(self, album_id)
+
+ for file in files:
+ url = file["file"]
+ if url.endswith(".mp4"):
+ file["file"] = url.replace(
+ "//cdn.bunkr.is/", "//media-files.bunkr.is/", 1)
+ else:
+ file["_fallback"] = (url.replace("//cdn.", "//cdn3.", 1),)
+
+ return files, data
+
+ def _fetch_album_site(self, album_id):
+ url = self.root + "/a/" + self.album_id
+
+ try:
+ data = json.loads(text.extract(
+ self.request(url).text,
+ 'id="__NEXT_DATA__" type="application/json">', '<')[0])
+ props = data["props"]["pageProps"]
+ album = props["album"]
+ files = props["files"]
+ except Exception as exc:
+ self.log.debug(exc)
+ self.root = self.root.replace("bunkr", "app.bunkr", 1)
+ return self._fetch_album_api(album_id)
+
+ for file in files:
+ name = file["name"]
+ if name.endswith(".mp4"):
+ file["file"] = "https://media-files.bunkr.is/" + name
+ else:
+ file["file"] = file["cdn"] + "/" + name
+
+ return files, {
+ "album_id" : self.album_id,
+ "album_name" : text.unescape(album["name"]),
+ "description": text.unescape(album["description"]),
+ "count" : len(files),
+ }