diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 23e4d9e..e4ec656 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py @@ -64,13 +64,14 @@ from .push import Mastodon as Push from .admin import Mastodon as Admin from .streaming_endpoints import Mastodon as Streaming + ### # The actual Mastodon class # # Almost all code is now imported from smaller files to make editing a bit more pleasant ### -class Mastodon(Utility, Authentication, Accounts, Instance, Timeline, Statuses, Polls, Notifications, Hashtags, - Filters, Suggestions, Endorsements, Relationships, Lists, Trends, Search, Favourites, Reports, +class Mastodon(Utility, Authentication, Accounts, Instance, Timeline, Statuses, Polls, Notifications, Hashtags, + Filters, Suggestions, Endorsements, Relationships, Lists, Trends, Search, Favourites, Reports, Preferences, Push, Admin, Conversations, Media, Streaming): """ Thorough and easy to use Mastodon diff --git a/mastodon/accounts.py b/mastodon/accounts.py index cd43c57..ce6dd71 100644 --- a/mastodon/accounts.py +++ b/mastodon/accounts.py @@ -9,6 +9,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): @api_version("2.7.0", "2.7.0", "3.4.0") def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=_DEFAULT_SCOPES, to_file=None, return_detailed_error=False): @@ -16,8 +17,8 @@ class Mastodon(Internals): Creates a new user account with the given username, password and email. "agreement" must be set to true (after showing the user the instance's user agreement and having them agree to it), "locale" specifies the language for the confirmation email as an - ISO 639-1 (two letter) or, if a language does not have one, 639-3 (three letter) language - code. `reason` can be used to specify why a user would like to join if approved-registrations + ISO 639-1 (two letter) or, if a language does not have one, 639-3 (three letter) language + code. `reason` can be used to specify why a user would like to join if approved-registrations mode is on. Does not require an access token, but does require a client grant. @@ -30,11 +31,11 @@ class Mastodon(Internals): By default, the function will throw if the account could not be created. Alternately, when `return_detailed_error` is passed, Mastodon.py will return the detailed error - response that the API provides (Starting from version 3.4.0 - not checked here) as an dict with - error details as the second return value and the token returned as `None` in case of error. - The dict will contain a text `error` values as well as a `details` value which is a dict with - one optional key for each potential field (`username`, `password`, `email` and `agreement`), - each if present containing a dict with an `error` category and free text `description`. + response that the API provides (Starting from version 3.4.0 - not checked here) as an dict with + error details as the second return value and the token returned as `None` in case of error. + The dict will contain a text `error` values as well as a `details` value which is a dict with + one optional key for each potential field (`username`, `password`, `email` and `agreement`), + each if present containing a dict with an `error` category and free text `description`. Valid error categories are: * ERR_BLOCKED - When e-mail provider is not allowed @@ -77,7 +78,7 @@ class Mastodon(Internals): raise MastodonIllegalArgumentError(f'Invalid request: {e}') self.access_token = response['access_token'] self.__set_refresh_token(response.get('refresh_token')) - self.__set_token_expired(int(response.get('expires_in', 0))) + self.__set_token_expired(int(response.get('expires_in', 0))) except Exception as e: raise MastodonIllegalArgumentError('Invalid request') @@ -274,14 +275,14 @@ class Mastodon(Internals): def account_lookup(self, acct): """ Look up an account from user@instance form (@instance allowed but not required for - local accounts). Will only return accounts that the instance already knows about, - and not do any webfinger requests. Use `account_search` if you need to resolve users + local accounts). Will only return accounts that the instance already knows about, + and not do any webfinger requests. Use `account_search` if you need to resolve users through webfinger from remote. Returns an :ref:`account dict `. """ return self.__api_request('GET', '/api/v1/accounts/lookup', self.__generate_params(locals())) - + @api_version("3.5.0", "3.5.0", _DICT_VERSION_FAMILIAR_FOLLOWERS) def account_familiar_followers(self, id): """ @@ -347,7 +348,6 @@ class Mastodon(Internals): """ id = self.__unpack_id(id) return self.__api_request('POST', f'/api/v1/accounts/{id}/remove_from_followers') - @api_version("1.0.0", "1.4.0", _DICT_VERSION_RELATIONSHIP) def account_block(self, id): diff --git a/mastodon/admin.py b/mastodon/admin.py index 405b30b..b9d72ed 100644 --- a/mastodon/admin.py +++ b/mastodon/admin.py @@ -7,12 +7,13 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Moderation API ### @api_version("2.9.1", "4.0.0", _DICT_VERSION_ADMIN_ACCOUNT) - def admin_accounts_v2(self, origin=None, by_domain=None, status=None, username=None, display_name=None, email=None, ip=None, + def admin_accounts_v2(self, origin=None, by_domain=None, status=None, username=None, display_name=None, email=None, ip=None, permissions=None, invited_by=None, role_ids=None, max_id=None, min_id=None, since_id=None, limit=None): """ Fetches a list of accounts that match given criteria. By default, local accounts are returned. @@ -65,8 +66,8 @@ class Mastodon(Internals): @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) def admin_accounts(self, remote=False, by_domain=None, status='active', username=None, display_name=None, email=None, ip=None, staff_only=False, max_id=None, min_id=None, since_id=None, limit=None): """ - Currently a synonym for admin_accounts_v1, now deprecated. You are strongly encouraged to use admin_accounts_v2 instead, since this one is kind of bad. - + Currently a synonym for admin_accounts_v1, now deprecated. You are strongly encouraged to use admin_accounts_v2 instead, since this one is kind of bad. + !!!!! This function may be switched to calling the v2 API in the future. This is your warning. If you want to keep using v1, use it explicitly. !!!!! """ return self.admin_accounts_v1( @@ -377,16 +378,16 @@ class Mastodon(Internals): id = self.__unpack_id(id) return self.__api_request('GET', f'/api/v1/admin/domain_blocks/{id}') else: - params = self.__generate_params(locals(),['limit']) + params = self.__generate_params(locals(), ['limit']) return self.__api_request('GET', '/api/v1/admin/domain_blocks/', params) - + @api_version("4.0.0", "4.0.0", _DICT_VERSION_ADMIN_DOMAIN_BLOCK) def admin_create_domain_block(self, domain:str, severity:str=None, reject_media:bool=None, reject_reports:bool=None, private_comment:str=None, public_comment:str=None, obfuscate:bool=None): """ Perform a moderation action on a domain. Requires scope `admin:write:domain_blocks`. Valid severities are: - * "silence" - hide all posts from federated timelines and do not show notifications to local users from the remote instance's users unless they are following the remote user. + * "silence" - hide all posts from federated timelines and do not show notifications to local users from the remote instance's users unless they are following the remote user. * "suspend" - deny interactions with this instance going forward. This action is reversible. * "limit" - generally used with reject_media=true to force reject media from an instance without silencing or suspending.. @@ -411,7 +412,7 @@ class Mastodon(Internals): Modify existing moderation action on a domain. Requires scope `admin:write:domain_blocks`. Valid severities are: - * "silence" - hide all posts from federated timelines and do not show notifications to local users from the remote instance's users unless they are following the remote user. + * "silence" - hide all posts from federated timelines and do not show notifications to local users from the remote instance's users unless they are following the remote user. * "suspend" - deny interactions with this instance going forward. This action is reversible. * "limit" - generally used with reject_media=true to force reject media from an instance without silencing or suspending. @@ -481,7 +482,7 @@ class Mastodon(Internals): for key in ["active_users", "new_users", "interactions", "opened_reports", "resolved_reports"]: if params_init[key] == True: keys.append(key) - + params = {} for key in ["tag_accounts", "tag_uses", "tag_servers"]: if params_init[key] is not None: @@ -498,7 +499,7 @@ class Mastodon(Internals): params["keys"] = keys params["start_at"] = self.__consistent_isoformat_utc(start_at) params["end_at"] = self.__consistent_isoformat_utc(end_at) - + return self.__api_request('POST', '/api/v1/admin/measures', params, use_json=True) @api_version("3.5.0", "3.5.0", _DICT_VERSION_ADMIN_DIMENSION) @@ -531,7 +532,7 @@ class Mastodon(Internals): for key in ["languages", "sources", "servers", "space_usage", "software_versions"]: if params_init[key] == True: keys.append(key) - + params = {} for key in ["tag_servers", "tag_languages"]: if params_init[key] is not None: @@ -550,7 +551,7 @@ class Mastodon(Internals): params["limit"] = limit params["start_at"] = self.__consistent_isoformat_utc(start_at) params["end_at"] = self.__consistent_isoformat_utc(end_at) - + return self.__api_request('POST', '/api/v1/admin/dimensions', params, use_json=True) @api_version("3.5.0", "3.5.0", _DICT_VERSION_ADMIN_RETENTION) @@ -568,4 +569,4 @@ class Mastodon(Internals): "end_at": self.__consistent_isoformat_utc(end_at), "frequency": frequency } - return self.__api_request('POST', '/api/v1/admin/retention', params) \ No newline at end of file + return self.__api_request('POST', '/api/v1/admin/retention', params) diff --git a/mastodon/authentication.py b/mastodon/authentication.py index 9f42587..9835f11 100644 --- a/mastodon/authentication.py +++ b/mastodon/authentication.py @@ -14,6 +14,7 @@ from .utility import parse_version_string, api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Registering apps @@ -43,7 +44,7 @@ class Mastodon(Internals): Returns `client_id` and `client_secret`, both as strings. """ if api_base_url is None: - raise MastodonIllegalArgumentError("API base URL is required.") + raise MastodonIllegalArgumentError("API base URL is required.") api_base_url = Mastodon.__protocolize(api_base_url) request_data = { @@ -86,9 +87,9 @@ class Mastodon(Internals): version_check_mode="created", session=None, feature_set="mainline", user_agent="mastodonpy", lang=None): """ Create a new API wrapper instance based on the given `client_secret` and `client_id` on the - instance given by `api_base_url`. If you give a `client_id` and it is not a file, you must + instance given by `api_base_url`. If you give a `client_id` and it is not a file, you must also give a secret. If you specify an `access_token` then you don't need to specify a `client_id`. - It is allowed to specify neither - in this case, you will be restricted to only using endpoints + It is allowed to specify neither - in this case, you will be restricted to only using endpoints that do not require authentication. If a file is given as `client_id`, client ID, secret and base url are read from that file. @@ -216,7 +217,7 @@ class Mastodon(Internals): # Verify we have a base URL, protocolize if self.api_base_url is None: - raise MastodonIllegalArgumentError("API base URL is required.") + raise MastodonIllegalArgumentError("API base URL is required.") self.api_base_url = Mastodon.__protocolize(self.api_base_url) if not version_check_mode in ["created", "changed", "none"]: diff --git a/mastodon/conversations.py b/mastodon/conversations.py index 5482fb7..302acad 100644 --- a/mastodon/conversations.py +++ b/mastodon/conversations.py @@ -5,7 +5,8 @@ from .utility import api_version from .internals import Mastodon as Internals -class Mastodon(Internals): + +class Mastodon(Internals): ### # Reading data: Conversations ### diff --git a/mastodon/defaults.py b/mastodon/defaults.py index 950ffa2..cac8fa7 100644 --- a/mastodon/defaults.py +++ b/mastodon/defaults.py @@ -61,4 +61,4 @@ _SCOPE_SETS = { } _VALID_SCOPES = ['read', 'write', 'follow', 'push', 'admin:read', 'admin:write'] + \ _SCOPE_SETS['read'] + _SCOPE_SETS['write'] + \ - _SCOPE_SETS['admin:read'] + _SCOPE_SETS['admin:write'] \ No newline at end of file + _SCOPE_SETS['admin:read'] + _SCOPE_SETS['admin:write'] diff --git a/mastodon/endorsements.py b/mastodon/endorsements.py index b6c27a0..ed1569a 100644 --- a/mastodon/endorsements.py +++ b/mastodon/endorsements.py @@ -5,7 +5,8 @@ from .utility import api_version from .internals import Mastodon as Internals -class Mastodon(Internals): + +class Mastodon(Internals): ### # Reading data: Endorsements ### diff --git a/mastodon/favourites.py b/mastodon/favourites.py index 9d86424..2f8df49 100644 --- a/mastodon/favourites.py +++ b/mastodon/favourites.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Favourites @@ -49,4 +50,3 @@ class Mastodon(Internals): params = self.__generate_params(locals()) return self.__api_request('GET', '/api/v1/bookmarks', params) - \ No newline at end of file diff --git a/mastodon/filters.py b/mastodon/filters.py index 8841ba8..72c3991 100644 --- a/mastodon/filters.py +++ b/mastodon/filters.py @@ -8,6 +8,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Keyword filters diff --git a/mastodon/hashtags.py b/mastodon/hashtags.py index f894c11..f550c7b 100644 --- a/mastodon/hashtags.py +++ b/mastodon/hashtags.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Featured hashtags diff --git a/mastodon/instance.py b/mastodon/instance.py index 1217596..f8f170a 100644 --- a/mastodon/instance.py +++ b/mastodon/instance.py @@ -7,6 +7,7 @@ from .compat import urlparse from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Instances diff --git a/mastodon/internals.py b/mastodon/internals.py index d94a116..32541fd 100644 --- a/mastodon/internals.py +++ b/mastodon/internals.py @@ -22,10 +22,11 @@ from .errors import MastodonNetworkError, MastodonIllegalArgumentError, Mastodon from .compat import urlparse, magic, PurePath from .defaults import _DEFAULT_STREAM_TIMEOUT, _DEFAULT_STREAM_RECONNECT_WAIT_SEC + ### # Internal helpers, dragons probably ### -class Mastodon(): +class Mastodon(): def __datetime_to_epoch(self, date_time): """ Converts a python datetime to unix epoch, accounting for @@ -37,7 +38,6 @@ class Mastodon(): date_time = date_time.replace(tzinfo=datetime.timezone.utc) return date_time.timestamp() - def __get_logged_in_id(self): """ Fetch the logged in user's ID, with caching. ID is reset on calls to log_in. @@ -77,7 +77,7 @@ class Mastodon(): mark_delete.append(k) # Two step process because otherwise python gets very upset for k in mark_delete: - del json_object[k] + del json_object[k] return json_object @staticmethod @@ -98,7 +98,7 @@ class Mastodon(): """ Converts json string numerals to native python bignums. """ - for key in ('id', 'week', 'in_reply_to_id', 'in_reply_to_account_id', 'logins', 'registrations', 'statuses', + for key in ('id', 'week', 'in_reply_to_id', 'in_reply_to_account_id', 'logins', 'registrations', 'statuses', 'day', 'last_read_id', 'value', 'frequency', 'rate', 'invited_by_account_id', 'count'): if (key in json_object and isinstance(json_object[key], six.text_type)): try: @@ -131,14 +131,14 @@ class Mastodon(): isotime = isotime[:-2] + ":" + isotime[-2:] return isotime - def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, + def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True, return_response_object=False, skip_error_check=False, lang_override=None): """ Internal API request helper. """ response = None remaining_wait = 0 - + # Add language to params if not None lang = self.lang if lang_override is not None: @@ -270,7 +270,7 @@ class Mastodon(): time.sleep(to_next) request_complete = False continue - + if not skip_error_check: if response_object.status_code == 404: ex_type = MastodonNotFoundError @@ -665,4 +665,4 @@ class Mastodon(): return version_string.split("+")[1] except: # If this fails, assume that if there is a +, what is before that is the masto version (or that there is no +) - return version_string.split("+")[0] \ No newline at end of file + return version_string.split("+")[0] diff --git a/mastodon/lists.py b/mastodon/lists.py index 57ced46..aa92283 100644 --- a/mastodon/lists.py +++ b/mastodon/lists.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Lists @@ -107,4 +108,4 @@ class Mastodon(Internals): account_ids = list(map(lambda x: self.__unpack_id(x), account_ids)) params = self.__generate_params(locals(), ['id']) - self.__api_request('DELETE', f'/api/v1/lists/{id}/accounts', params) \ No newline at end of file + self.__api_request('DELETE', f'/api/v1/lists/{id}/accounts', params) diff --git a/mastodon/media.py b/mastodon/media.py index 41843a6..6d8674a 100644 --- a/mastodon/media.py +++ b/mastodon/media.py @@ -8,6 +8,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Media diff --git a/mastodon/notifications.py b/mastodon/notifications.py index 6d2d1f7..e2c6a17 100644 --- a/mastodon/notifications.py +++ b/mastodon/notifications.py @@ -6,6 +6,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Notifications @@ -16,7 +17,7 @@ class Mastodon(Internals): Fetch notifications (mentions, favourites, reblogs, follows) for the logged-in user. Pass `account_id` to get only notifications originating from the given account. - There are different types of notifications: + There are different types of notifications: * `follow` - A user followed the logged in user * `follow_request` - A user has requested to follow the logged in user (for locked accounts) * `favourite` - A user favourited a post by the logged in user @@ -29,7 +30,7 @@ class Mastodon(Internals): * `admin.report` - For accounts with appropriate permissions (TODO: document which those are when adding the permission API): A new report has been received Parameters `exclude_types` and `types` are array of these types, specifying them will in- or exclude the types of notifications given. It is legal to give both parameters at the same tine, the result will then - be the intersection of the results of both filters. Specifying `mentions_only` is a deprecated way to set + be the intersection of the results of both filters. Specifying `mentions_only` is a deprecated way to set `exclude_types` to all but mentions. Can be passed an `id` to fetch a single notification. diff --git a/mastodon/polls.py b/mastodon/polls.py index 2722ba8..d13cfe4 100644 --- a/mastodon/polls.py +++ b/mastodon/polls.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Polls @@ -56,4 +57,4 @@ class Mastodon(Internals): """ poll_params = locals() del poll_params["self"] - return poll_params \ No newline at end of file + return poll_params diff --git a/mastodon/preferences.py b/mastodon/preferences.py index 5e7435f..0011eb1 100644 --- a/mastodon/preferences.py +++ b/mastodon/preferences.py @@ -8,6 +8,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Preferences @@ -68,4 +69,3 @@ class Mastodon(Internals): params[timeline]["last_read_id"] = self.__unpack_id(last_read_id) return self.__api_request('POST', '/api/v1/markers', params, use_json=True) - \ No newline at end of file diff --git a/mastodon/push.py b/mastodon/push.py index def348a..8d63349 100644 --- a/mastodon/push.py +++ b/mastodon/push.py @@ -12,6 +12,7 @@ from .compat import IMPL_HAS_ECE, http_ece from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Webpush subscriptions @@ -148,14 +149,14 @@ class Mastodon(Internals): push_key_pair = ec.generate_private_key(ec.SECP256R1(), default_backend()) push_key_priv = push_key_pair.private_numbers().private_value - try: + try: push_key_pub = push_key_pair.public_key().public_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint, ) except: push_key_pub = push_key_pair.public_key().public_numbers().encode_point() - + push_shared_secret = os.urandom(16) priv_dict = { diff --git a/mastodon/relationships.py b/mastodon/relationships.py index 043174c..a33ee2d 100644 --- a/mastodon/relationships.py +++ b/mastodon/relationships.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Mutes and Blocks @@ -131,4 +132,4 @@ class Mastodon(Internals): Remove a domain block for the logged-in user. """ params = self.__generate_params(locals()) - self.__api_request('DELETE', '/api/v1/domain_blocks', params) \ No newline at end of file + self.__api_request('DELETE', '/api/v1/domain_blocks', params) diff --git a/mastodon/reports.py b/mastodon/reports.py index 3d6380e..78ce1d3 100644 --- a/mastodon/reports.py +++ b/mastodon/reports.py @@ -7,6 +7,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Reports @@ -59,4 +60,4 @@ class Mastodon(Internals): del params_initial['forward'] params = self.__generate_params(params_initial) - return self.__api_request('POST', '/api/v1/reports/', params) \ No newline at end of file + return self.__api_request('POST', '/api/v1/reports/', params) diff --git a/mastodon/search.py b/mastodon/search.py index b77002f..37bd920 100644 --- a/mastodon/search.py +++ b/mastodon/search.py @@ -6,6 +6,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Searching diff --git a/mastodon/statuses.py b/mastodon/statuses.py index eb372d8..f10ff98 100644 --- a/mastodon/statuses.py +++ b/mastodon/statuses.py @@ -9,7 +9,8 @@ from .utility import api_version from .internals import Mastodon as Internals -class Mastodon(Internals): + +class Mastodon(Internals): ### # Reading data: Statuses ### @@ -244,19 +245,19 @@ class Mastodon(Internals): Returns a :ref:`status dict ` with the new status. """ - return self.__status_internal( - status, - in_reply_to_id, - media_ids, - sensitive, - visibility, - spoiler_text, - language, - idempotency_key, - content_type, - scheduled_at, - poll, - quote_id, + return self.__status_internal( + status, + in_reply_to_id, + media_ids, + sensitive, + visibility, + spoiler_text, + language, + idempotency_key, + content_type, + scheduled_at, + poll, + quote_id, edit=None ) @@ -272,7 +273,7 @@ class Mastodon(Internals): return self.status_post(status) @api_version("3.5.0", "3.5.0", _DICT_VERSION_STATUS) - def status_update(self, id, status = None, spoiler_text = None, sensitive = None, media_ids = None, poll = None): + def status_update(self, id, status=None, spoiler_text=None, sensitive=None, media_ids=None, poll=None): """ Edit a status. The meanings of the fields are largely the same as in :ref:`status_post() `, though not every field can be edited. @@ -280,13 +281,13 @@ class Mastodon(Internals): Note that editing a poll will reset the votes. """ return self.__status_internal( - status = status, - media_ids = media_ids, - sensitive = sensitive, - spoiler_text = spoiler_text, - poll = poll, - edit = id - ) + status=status, + media_ids=media_ids, + sensitive=sensitive, + spoiler_text=spoiler_text, + poll=poll, + edit=id + ) @api_version("3.5.0", "3.5.0", _DICT_VERSION_STATUS_EDIT) def status_history(self, id): @@ -317,7 +318,7 @@ class Mastodon(Internals): scheduled_at=None, poll=None, untag=False): """ Helper function - acts like status_post, but prepends the name of all - the users that are being replied to to the status text and retains + the users that are being replied to the status text and retains CW and visibility if not explicitly overridden. Set `untag` to True if you want the reply to only go to the user you diff --git a/mastodon/streaming.py b/mastodon/streaming.py index ed09705..05b23c2 100644 --- a/mastodon/streaming.py +++ b/mastodon/streaming.py @@ -84,7 +84,7 @@ class StreamListener(object): contains the content of the unknown event. """ pass - + def handle_heartbeat(self): """The server has sent us a keep-alive message. This callback may be useful to carry out periodic housekeeping tasks, or just to confirm @@ -217,6 +217,7 @@ class StreamListener(object): else: handler(name, payload) + class CallbackStreamListener(StreamListener): """ Simple callback stream handler class. @@ -226,21 +227,20 @@ class CallbackStreamListener(StreamListener): for diagnostics. """ - def __init__(self, - update_handler=None, - local_update_handler=None, - delete_handler=None, - notification_handler=None, - conversation_handler=None, - unknown_event_handler=None, - status_update_handler=None, - filters_changed_handler=None, - announcement_handler=None, - announcement_reaction_handler=None, - announcement_delete_handler=None, - encryted_message_handler=None - - ): + def __init__(self, + update_handler=None, + local_update_handler=None, + delete_handler=None, + notification_handler=None, + conversation_handler=None, + unknown_event_handler=None, + status_update_handler=None, + filters_changed_handler=None, + announcement_handler=None, + announcement_reaction_handler=None, + announcement_delete_handler=None, + encryted_message_handler=None + ): super(CallbackStreamListener, self).__init__() self.update_handler = update_handler self.local_update_handler = local_update_handler @@ -306,4 +306,4 @@ class CallbackStreamListener(StreamListener): def on_unknown_event(self, name, unknown_event=None): if self.unknown_event_handler is not None: - self.unknown_event_handler(name, unknown_event) \ No newline at end of file + self.unknown_event_handler(name, unknown_event) diff --git a/mastodon/streaming_endpoints.py b/mastodon/streaming_endpoints.py index fc705e6..e319cca 100644 --- a/mastodon/streaming_endpoints.py +++ b/mastodon/streaming_endpoints.py @@ -7,6 +7,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Streaming diff --git a/mastodon/suggestions.py b/mastodon/suggestions.py index a94204b..fff1fe2 100644 --- a/mastodon/suggestions.py +++ b/mastodon/suggestions.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Follow suggestions diff --git a/mastodon/timeline.py b/mastodon/timeline.py index 37790c8..9bde25c 100644 --- a/mastodon/timeline.py +++ b/mastodon/timeline.py @@ -6,6 +6,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Timelines @@ -101,4 +102,3 @@ class Mastodon(Internals): """ id = self.__unpack_id(id) return self.timeline(f'list/{id}', max_id=max_id, min_id=min_id, since_id=since_id, limit=limit, only_media=only_media, local=local, remote=remote) - diff --git a/mastodon/trends.py b/mastodon/trends.py index 09a0ae5..03d3ea0 100644 --- a/mastodon/trends.py +++ b/mastodon/trends.py @@ -5,6 +5,7 @@ from .utility import api_version from .internals import Mastodon as Internals + class Mastodon(Internals): ### # Reading data: Trends @@ -14,7 +15,7 @@ class Mastodon(Internals): """ Alias for :ref:`trending_tags() ` """ - return self.trending_tags(limit=limit) + return self.trending_tags(limit=limit) @api_version("3.5.0", "3.5.0", _DICT_VERSION_HASHTAG) def trending_tags(self, limit=None, lang=None): @@ -27,7 +28,7 @@ class Mastodon(Internals): Does not require authentication unless locked down by the administrator. Important versioning note: This endpoint does not exist for Mastodon versions - between 2.8.0 (inclusive) and 3.0.0 (exclusive). + between 2.8.0 (inclusive) and 3.0.0 (exclusive). Pass `lang` to override the global locale parameter, which may affect trend ordering. diff --git a/mastodon/utility.py b/mastodon/utility.py index 200f5c1..815d9d5 100644 --- a/mastodon/utility.py +++ b/mastodon/utility.py @@ -24,10 +24,12 @@ def parse_version_string(version_string): ) return version_parts + def max_version(*version_strings): """Returns the maximum version of all provided version strings.""" return max(version_strings, key=parse_version_string) + def api_version(created_ver, last_changed_ver, return_value_ver): """Version check decorator. Currently only checks Bigger Than.""" def api_min_version_decorator(function): @@ -49,6 +51,7 @@ def api_version(created_ver, last_changed_ver, return_value_ver): return decorate(function, wrapper) return api_min_version_decorator + ### # Dict helper class. # Defined at top level so it can be pickled. @@ -91,7 +94,7 @@ class Mastodon(): not have one, 639-3 (three letter) language codes. This affects some error messages (those related to validation) and trends. """ self.lang = lang - + def retrieve_mastodon_version(self): """ Determine installed Mastodon version and set major, minor and patch (not including RC info) accordingly. @@ -127,7 +130,7 @@ class Mastodon(): elif major == self.mastodon_major and minor == self.mastodon_minor and patch > self.mastodon_patch: return False return True - + def get_approx_server_time(self): """ Retrieve the approximate server time diff --git a/mastodon/versions.py b/mastodon/versions.py index bf439b4..1c333e3 100644 --- a/mastodon/versions.py +++ b/mastodon/versions.py @@ -37,4 +37,4 @@ _DICT_VERSION_FAMILIAR_FOLLOWERS = max_version("3.5.0", _DICT_VERSION_ACCOUNT) _DICT_VERSION_ADMIN_DOMAIN_BLOCK = "4.0.0" _DICT_VERSION_ADMIN_MEASURE = "3.5.0" _DICT_VERSION_ADMIN_DIMENSION = "3.5.0" -_DICT_VERSION_ADMIN_RETENTION = "3.5.0" \ No newline at end of file +_DICT_VERSION_ADMIN_RETENTION = "3.5.0"