2022-06-15 22:51:40 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2023-09-11 16:30:55 +02:00
|
|
|
# Copyright 2022-2023 Mike Fährmann
|
2022-06-15 22:51:40 +02:00
|
|
|
#
|
|
|
|
# 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://itaku.ee/"""
|
|
|
|
|
|
|
|
from .common import Extractor, Message
|
|
|
|
from ..cache import memcache
|
|
|
|
from .. import text
|
|
|
|
|
|
|
|
BASE_PATTERN = r"(?:https?://)?itaku\.ee"
|
|
|
|
|
|
|
|
|
|
|
|
class ItakuExtractor(Extractor):
|
|
|
|
"""Base class for itaku extractors"""
|
|
|
|
category = "itaku"
|
|
|
|
root = "https://itaku.ee"
|
|
|
|
directory_fmt = ("{category}", "{owner_username}")
|
2022-06-20 19:35:46 +02:00
|
|
|
filename_fmt = ("{id}{title:? //}.{extension}")
|
2022-06-15 22:51:40 +02:00
|
|
|
archive_fmt = "{id}"
|
|
|
|
request_interval = (0.5, 1.5)
|
|
|
|
|
|
|
|
def __init__(self, match):
|
|
|
|
Extractor.__init__(self, match)
|
|
|
|
self.item = match.group(1)
|
2023-07-25 20:09:44 +02:00
|
|
|
|
|
|
|
def _init(self):
|
|
|
|
self.api = ItakuAPI(self)
|
2022-06-20 19:47:53 +02:00
|
|
|
self.videos = self.config("videos", True)
|
2022-06-15 22:51:40 +02:00
|
|
|
|
|
|
|
def items(self):
|
|
|
|
for post in self.posts():
|
2022-06-20 19:28:15 +02:00
|
|
|
|
|
|
|
post["date"] = text.parse_datetime(
|
2022-07-10 20:45:51 +02:00
|
|
|
post["date_added"], "%Y-%m-%dT%H:%M:%S.%fZ")
|
2022-06-20 19:28:15 +02:00
|
|
|
for category, tags in post.pop("categorized_tags").items():
|
|
|
|
post["tags_" + category.lower()] = [t["name"] for t in tags]
|
|
|
|
post["tags"] = [t["name"] for t in post["tags"]]
|
2022-06-29 22:34:07 +02:00
|
|
|
|
|
|
|
sections = []
|
|
|
|
for s in post["sections"]:
|
|
|
|
group = s["group"]
|
|
|
|
if group:
|
|
|
|
sections.append(group["title"] + "/" + s["title"])
|
|
|
|
else:
|
|
|
|
sections.append(s["title"])
|
|
|
|
post["sections"] = sections
|
2022-06-20 19:28:15 +02:00
|
|
|
|
2022-06-20 19:47:53 +02:00
|
|
|
if post["video"] and self.videos:
|
|
|
|
url = post["video"]["video"]
|
|
|
|
else:
|
|
|
|
url = post["image"]
|
|
|
|
|
2022-06-15 22:51:40 +02:00
|
|
|
yield Message.Directory, post
|
|
|
|
yield Message.Url, url, text.nameext_from_url(url, post)
|
|
|
|
|
|
|
|
|
|
|
|
class ItakuGalleryExtractor(ItakuExtractor):
|
|
|
|
"""Extractor for posts from an itaku user gallery"""
|
|
|
|
subcategory = "gallery"
|
|
|
|
pattern = BASE_PATTERN + r"/profile/([^/?#]+)/gallery"
|
2023-09-11 16:30:55 +02:00
|
|
|
example = "https://itaku.ee/profile/USER/gallery"
|
2022-06-15 22:51:40 +02:00
|
|
|
|
|
|
|
def posts(self):
|
|
|
|
return self.api.galleries_images(self.item)
|
|
|
|
|
|
|
|
|
|
|
|
class ItakuImageExtractor(ItakuExtractor):
|
|
|
|
subcategory = "image"
|
|
|
|
pattern = BASE_PATTERN + r"/images/(\d+)"
|
2023-09-11 16:30:55 +02:00
|
|
|
example = "https://itaku.ee/images/12345"
|
2022-06-15 22:51:40 +02:00
|
|
|
|
|
|
|
def posts(self):
|
|
|
|
return (self.api.image(self.item),)
|
|
|
|
|
|
|
|
|
|
|
|
class ItakuAPI():
|
|
|
|
|
|
|
|
def __init__(self, extractor):
|
|
|
|
self.extractor = extractor
|
|
|
|
self.root = extractor.root + "/api"
|
|
|
|
self.headers = {
|
|
|
|
"Accept": "application/json, text/plain, */*",
|
|
|
|
}
|
|
|
|
|
|
|
|
def galleries_images(self, username, section=None):
|
|
|
|
endpoint = "/galleries/images/"
|
|
|
|
params = {
|
|
|
|
"cursor" : None,
|
|
|
|
"owner" : self.user(username)["owner"],
|
|
|
|
"section" : section,
|
|
|
|
"date_range": "",
|
2022-11-24 11:09:00 +01:00
|
|
|
"maturity_rating": ("SFW", "Questionable", "NSFW"),
|
2022-06-15 22:51:40 +02:00
|
|
|
"ordering" : "-date_added",
|
|
|
|
"page" : "1",
|
|
|
|
"page_size" : "30",
|
|
|
|
"visibility": ("PUBLIC", "PROFILE_ONLY"),
|
|
|
|
}
|
|
|
|
return self._pagination(endpoint, params, self.image)
|
|
|
|
|
|
|
|
def image(self, image_id):
|
2022-06-29 22:34:07 +02:00
|
|
|
endpoint = "/galleries/images/{}/".format(image_id)
|
2022-06-15 22:51:40 +02:00
|
|
|
return self._call(endpoint)
|
|
|
|
|
2022-07-01 20:50:38 +02:00
|
|
|
@memcache(keyarg=1)
|
2022-06-15 22:51:40 +02:00
|
|
|
def user(self, username):
|
|
|
|
return self._call("/user_profiles/{}/".format(username))
|
|
|
|
|
|
|
|
def _call(self, endpoint, params=None):
|
|
|
|
if not endpoint.startswith("http"):
|
|
|
|
endpoint = self.root + endpoint
|
|
|
|
response = self.extractor.request(
|
|
|
|
endpoint, params=params, headers=self.headers)
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
def _pagination(self, endpoint, params, extend):
|
|
|
|
data = self._call(endpoint, params)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
if extend:
|
|
|
|
for result in data["results"]:
|
|
|
|
yield extend(result["id"])
|
|
|
|
else:
|
|
|
|
yield from data["results"]
|
|
|
|
|
|
|
|
url_next = data["links"].get("next")
|
|
|
|
if not url_next:
|
|
|
|
return
|
|
|
|
|
|
|
|
data = self._call(url_next)
|