from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Any import requests from cross.service import Service from util.util import normalize_service_url def validate_and_transform(data: dict[str, Any]): if "token" not in data or "instance" not in data: raise KeyError("Missing required values 'token' or 'instance'") data["instance"] = normalize_service_url(data["instance"]) @dataclass(kw_only=True) class InstanceInfo: max_characters: int = 500 max_media_attachments: int = 4 characters_reserved_per_url: int = 23 image_size_limit: int = 16777216 video_size_limit: int = 103809024 text_format: str = "text/plain" @classmethod def from_api(cls, data: dict[str, Any]) -> "InstanceInfo": config: dict[str, Any] = {} if "statuses" in data: statuses_config: dict[str, Any] = data.get("statuses", {}) if "max_characters" in statuses_config: config["max_characters"] = statuses_config["max_characters"] if "max_media_attachments" in statuses_config: config["max_media_attachments"] = statuses_config[ "max_media_attachments" ] if "characters_reserved_per_url" in statuses_config: config["characters_reserved_per_url"] = statuses_config[ "characters_reserved_per_url" ] # glitch content type if "supported_mime_types" in statuses_config: text_mimes: list[str] = statuses_config["supported_mime_types"] if "text/x.misskeymarkdown" in text_mimes: config["text_format"] = "text/x.misskeymarkdown" elif "text/markdown" in text_mimes: config["text_format"] = "text/markdown" if "media_attachments" in data: media_config: dict[str, Any] = data["media_attachments"] if "image_size_limit" in media_config: config["image_size_limit"] = media_config["image_size_limit"] if "video_size_limit" in media_config: config["video_size_limit"] = media_config["video_size_limit"] # *oma extensions if "max_toot_chars" in data: config["max_characters"] = data["max_toot_chars"] if "upload_limit" in data: config["image_size_limit"] = data["upload_limit"] config["video_size_limit"] = data["upload_limit"] if "pleroma" in data: pleroma: dict[str, Any] = data["pleroma"] if "metadata" in pleroma: metadata: dict[str, Any] = pleroma["metadata"] if "post_formats" in metadata: post_formats: list[str] = metadata["post_formats"] if "text/x.misskeymarkdown" in post_formats: config["text_format"] = "text/x.misskeymarkdown" elif "text/markdown" in post_formats: config["text_format"] = "text/markdown" return InstanceInfo(**config) class MastodonService(ABC, Service): def verify_credentials(self): token = self._get_token() response = requests.get( f"{self.url}/api/v1/accounts/verify_credentials", headers={"Authorization": f"Bearer {token}"}, ) if response.status_code != 200: self.log.error("Failed to validate user credentials!") response.raise_for_status() return dict(response.json()) def fetch_instance_info(self): token = self._get_token() responce = requests.get( f"{self.url}/api/v1/instance", headers={"Authorization": f"Bearer {token}"}, ) if responce.status_code != 200: self.log.error("Failed to get instance info!") responce.raise_for_status() return dict(responce.json()) @abstractmethod def _get_token(self) -> str: pass