social media crossposting tool. 3rd time's the charm
mastodon misskey crossposting bluesky
1from dataclasses import dataclass 2from pathlib import Path 3from typing import Any, override 4 5from cross.service import OutputService 6from mastodon.info import InstanceInfo, MastodonService 7from util.util import LOGGER 8 9ALLOWED_POSTING_VISIBILITY: list[str] = ["public", "unlisted", "private"] 10 11 12@dataclass(kw_only=True) 13class MastodonOutputOptions: 14 token: str 15 instance: str 16 visibility: str = "public" 17 18 @classmethod 19 def from_dict(cls, data: dict[str, Any]) -> "MastodonOutputOptions": 20 data["instance"] = ( 21 data["instance"][:-1] 22 if data["instance"].endswith("/") 23 else data["instance"] 24 ) 25 26 if "visibility" in data: 27 if data["visibility"] not in ALLOWED_POSTING_VISIBILITY: 28 raise ValueError(f"Invalid visibility option {data['visibility']}!") 29 30 return MastodonOutputOptions(**data) 31 32 33# TODO 34class MastodonOutputService(MastodonService, OutputService): 35 def __init__(self, db: Path, options: MastodonOutputOptions) -> None: 36 super().__init__(options.instance, db) 37 self.options: MastodonOutputOptions = options 38 39 LOGGER.info("Verifying %s credentails...", self.url) 40 responce = self.verify_credentials() 41 self.user_id: str = responce["id"] 42 43 LOGGER.info("Getting %s configuration...", self.url) 44 responce = self.fetch_instance_info() 45 self.instance_info = InstanceInfo.from_api(responce) 46 47 @override 48 def _get_token(self) -> str: 49 return self.options.token