From 76930ad44c3fde46bed4b7be30f508446a632059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Sat, 10 Jan 2026 17:37:33 +0100 Subject: [PATCH] [saint] support 'turbovid.cr' URLs (#8851) --- docs/supportedsites.md | 6 +++++ gallery_dl/extractor/lolisafe.py | 5 ++-- gallery_dl/extractor/saint.py | 37 +++++++++++++++++++------- scripts/supportedsites.py | 6 +++++ test/results/saint.py | 45 ++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 12 deletions(-) diff --git a/docs/supportedsites.md b/docs/supportedsites.md index d8b8eab4..fc2d8e05 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -1129,6 +1129,12 @@ Consider all listed sites to potentially be NSFW. Models, Posts, User Profiles + + turbovid.cr + https://turbovid.cr/ + Albums, Media Files + + Twibooru https://twibooru.org/ diff --git a/gallery_dl/extractor/lolisafe.py b/gallery_dl/extractor/lolisafe.py index 1ddce55b..cb9f489a 100644 --- a/gallery_dl/extractor/lolisafe.py +++ b/gallery_dl/extractor/lolisafe.py @@ -60,10 +60,11 @@ class LolisafeAlbumExtractor(LolisafeExtractor): file["filename"] = file["name"] else: file["id"] = fid - file["filename"] = file["name"] + "-" + fid + file["filename"] = f"{file['name']}-{fid}" elif "id" in file: file["name"] = file["filename"] - file["filename"] = f"{file['name']}-{file['id']}" + if file["filename"] != file["id"]: + file["filename"] = f"{file['name']}-{file['id']}" else: file["name"], sep, file["id"] = \ file["filename"].rpartition("-") diff --git a/gallery_dl/extractor/saint.py b/gallery_dl/extractor/saint.py index 9618b7d2..da66b3af 100644 --- a/gallery_dl/extractor/saint.py +++ b/gallery_dl/extractor/saint.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- -# Copyright 2024-2025 Mike Fährmann +# Copyright 2024-2026 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://saint2.su/""" +"""Extractors for https://saint2.su/ and https://turbovid.cr/""" from .lolisafe import LolisafeAlbumExtractor from .. import text -BASE_PATTERN = r"(?:https?://)?saint\d*\.(?:su|pk|cr|to)" +BASE_PATTERN = r"(?:https?://)?(?:turbovid\.cr|saint\d*\.(?:su|pk|cr|to))" class SaintAlbumExtractor(LolisafeAlbumExtractor): @@ -26,18 +26,27 @@ class SaintAlbumExtractor(LolisafeAlbumExtractor): response = self.request(self.root + "/a/" + album_id) extr = text.extract_from(response.text) - title = extr("", "<") - descr = extr('name="description" content="', '"') + title = extr("<title>", "</title") + descr = extr('name="description" content="', '"/>') files = [] while True: - id2 = extr("/thumbs/", "-") + id2 = extr("/thumbs/", '"') if not id2: break + + id2, sep, ts = id2.rpartition(".")[0].rpartition("-") + if sep: + date = self.parse_timestamp(ts) + else: + date = None + id2 = ts + files.append({ - "id2" : id2, - "date" : self.parse_timestamp(extr("", ".")), "id" : extr("/embed/", '"'), + "id2" : id2, + "date" : date, + # "extension": extr("<td>", "</"), "size" : text.parse_int(extr('data="', '"')), "file" : text.unescape(extr( "onclick=\"play(", ")").strip("\"'")), @@ -70,10 +79,18 @@ class SaintMediaExtractor(SaintAlbumExtractor): extr = text.extract_from(response.text) if embed: + id2, sep, ts = extr( + "/thumbs/", '"').rpartition(".")[0].rpartition("-") + if sep: + date = self.parse_timestamp(ts) + else: + date = None + id2 = ts + file = { "id" : album_id, - "id2" : extr("/thumbs/", "-"), - "date" : self.parse_timestamp(extr("", ".")), + "id2" : id2, + "date" : date, "file" : text.unescape(extr('<source src="', '"')), "id_dl": extr("/d/", "'"), } diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py index 495e385f..1f1f8ab5 100755 --- a/scripts/supportedsites.py +++ b/scripts/supportedsites.py @@ -198,6 +198,7 @@ CATEGORY_MAP = { "tmohentai" : "TMOHentai", "tumblrgallery" : "TumblrGallery", "turboimagehost" : "TurboImageHost.com", + "turbovid" : "turbovid.cr", "vanillarock" : "もえぴりあ", "vidyart2" : "/v/idyart2", "vidyapics" : "Vidya Booru", @@ -703,6 +704,11 @@ def build_extractor_list(): default["wikifeetx"] = default["wikifeet"] domains["wikifeetx"] = "https://www.wikifeetx.com/" + # turbovid + default["turbovid"] = default["saint"] + domains["turbovid"] = "https://turbovid.cr/" + domains["saint"] = "https://saint2.su/" + # imgdrive / imgtaxi / imgwallet base = categories["imagehost"] base["imgtaxi"] = base["imgdrive"] diff --git a/test/results/saint.py b/test/results/saint.py index 97a09225..1ded68b6 100644 --- a/test/results/saint.py +++ b/test/results/saint.py @@ -37,6 +37,34 @@ __tests__ = ( "num" : {1, 2}, }, +{ + "#url" : "https://turbovid.cr/a/FiphGijfJoR", + "#comment" : "'turbovid' album (#8851)", + "#category": ("lolisafe", "saint", "album"), + "#class" : saint.SaintAlbumExtractor, + "#results" : ( + "https://data.saint2.cr/data/jZqe1xxqw9bX7.mp4", + "https://data.saint2.cr/data/eJ9fLurGdaHqS.mp4", + "https://data.saint2.cr/data/WkD7hRaHdBpBI.mp4", + ), + + "album_id" : "FiphGijfJoR", + "album_name" : """test-???-"&> album""", + "album_size" : 37165256, + "count" : 3, + "num" : range(1, 3), + "date" : None, + "description": """test-???-"&> description""", + "extension" : "mp4", + "file" : r"re:https://data.saint2.cr/data/\w+.mp4", + "filename" : str, + "id" : str, + "id2" : str, + "id_dl" : str, + "name" : str, + "size" : int, +}, + { "#url" : "https://saint2.su/embed/6lC7mKrJst8", "#class": saint.SaintMediaExtractor, @@ -85,4 +113,21 @@ __tests__ = ( "#class": saint.SaintMediaExtractor, }, +{ + "#url" : "https://turbovid.cr/embed/WkD7hRaHdBpBI", + "#comment" : "'turbovid' URL/video", + "#category": ("lolisafe", "saint", "media"), + "#class" : saint.SaintMediaExtractor, + "#results" : "https://data.saint2.cr/data/WkD7hRaHdBpBI.mp4", + + "date" : None, + "extension" : "mp4", + "file" : "https://data.saint2.cr/data/WkD7hRaHdBpBI.mp4", + "filename" : "WkD7hRaHdBpBI", + "id" : "WkD7hRaHdBpBI", + "id2" : "WkD7hRaHdBpBI", + "id_dl" : "V2tEN2hSYUhkQnBCSS5tcDQ=", + "name" : "WkD7hRaHdBpBI", +}, + )