diff --git a/config.ini b/config.ini index 279b0e4..f5c74a3 100644 --- a/config.ini +++ b/config.ini @@ -12,14 +12,11 @@ instance = mastodon.example.org # ${instance}/settings/applications token = blahblah -# Mastodon user ID. Used to filter out posts. Unfortunately, I can't find a way -# to get it using token itself. GARGROOOOOOON!!!!! -# Anyways, you could navigate to your profile ${instance}/@${username} and -# look for your profile picture link. For example, for me it's -# https://mastodon.astrr.ru/system/accounts/avatars/107/914/495/779/447/227/original/9651ac2f47cb2993.jpg -# that part between "avarars" and "original" is the user ID. Grab it, remove -# all of the slashes and you should be left with, for example, this: -user = 107914495779447227 +# Your user ID. +# Doesn't necessarily yours, it can be any user's ID, but that user should be +# on the list for crossposter to find it. +# Setting it to "auto" will just grab yours instead. Don't worry about it +user = auto # Mastodon user list ID. AGAIN, UNFORTUNATELY, there is no way to reliably use # streaming API to get all of your posts. Using home timeline is unreliable and diff --git a/mastoposter/__main__.py b/mastoposter/__main__.py index 15eb5cb..3ba7de0 100644 --- a/mastoposter/__main__.py +++ b/mastoposter/__main__.py @@ -5,7 +5,12 @@ from mastoposter import execute_integrations, load_integrations_from from mastoposter.integrations import FilteredIntegration from mastoposter.sources import websocket_source from typing import AsyncGenerator, Callable, List -from mastoposter.types import Status +from mastoposter.types import Account, Status +from httpx import Client + + +WSOCK_TEMPLATE = "wss://{instance}/api/v1/streaming" +VERIFY_CREDS_TEMPLATE = "https://{instance}/api/v1/account/verify_credentials" async def listen( @@ -50,12 +55,22 @@ def main(config_path: str): modules: List[FilteredIntegration] = load_integrations_from(conf) + user_id: str = conf["main"]["user"] + if user_id == "auto": + with Client() as c: + rq = c.get( + VERIFY_CREDS_TEMPLATE.format(**conf["main"]), + params={"access_token": conf["main"]["token"]}, + ) + account = Account.from_dict(rq.json()) + user_id = account.id + url = "wss://{}/api/v1/streaming".format(conf["main"]["instance"]) run( listen( websocket_source, modules, - conf["main"]["user"], + user_id, url=url, reconnect=conf["main"].getboolean("auto_reconnect", False), list=conf["main"]["list"], diff --git a/mastoposter/types.py b/mastoposter/types.py index ecffd2f..e209c1c 100644 --- a/mastoposter/types.py +++ b/mastoposter/types.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass, field +from dataclasses import dataclass, field, fields from datetime import datetime from typing import Any, Callable, Optional, List, Literal, TypeVar @@ -47,7 +47,7 @@ class Emoji: @classmethod def from_dict(cls, data: dict) -> "Emoji": - return cls(**data) + return cls(**{f.name: data[f.name] for f in fields(cls) if f in data}) @dataclass @@ -122,7 +122,7 @@ class AttachmentMetaImage: @classmethod def from_dict(cls, data: dict) -> "AttachmentMetaImage": return cls( - **data, + **{f.name: data[f.name] for f in fields(cls) if f in data}, original=cls.AttachmentMetaImageDimensions(**data["original"]), small=cls.AttachmentMetaImageDimensions(**data["small"]), focus=cls.Vec2F(**data["focus"]) @@ -183,7 +183,7 @@ class Attachment: @classmethod def from_dict(cls, data: dict) -> "Attachment": - return cls(**data) + return cls(**{f.name: data[f.name] for f in fields(cls) if f in data}) @dataclass @@ -194,7 +194,7 @@ class Application: @classmethod def from_dict(cls, data: dict) -> "Application": - return cls(**data) + return cls(**{f.name: data[f.name] for f in fields(cls) if f in data}) @dataclass @@ -206,7 +206,7 @@ class Mention: @classmethod def from_dict(cls, data: dict) -> "Mention": - return cls(**data) + return cls(**{f.name: data[f.name] for f in fields(cls) if f in data}) @dataclass @@ -216,7 +216,7 @@ class Tag: @classmethod def from_dict(cls, data: dict) -> "Tag": - return cls(**data) + return cls(**{f.name: data[f.name] for f in fields(cls) if f in data}) @dataclass