diff options
author | Lorenz Diener <[email protected]> | 2018-05-06 15:55:32 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2018-05-06 15:55:32 +0200 |
commit | ca0ea36c6edd58dc15e5fd7f31f24ba5097d6e8d (patch) | |
tree | 98328e8776447334b19592992016d9b7f16ae98b /mastodon | |
parent | 06e32c14bcb5a1ef1a5e618a1b413ea011416c9d (diff) | |
parent | fbd4122fec092bff6b1cc9f44dfeda6ee693c41b (diff) | |
download | mastodon.py-ca0ea36c6edd58dc15e5fd7f31f24ba5097d6e8d.tar.gz |
Merge branch 'master' into stream-timeout
Diffstat (limited to 'mastodon')
-rw-r--r-- | mastodon/Mastodon.py | 81 |
1 files changed, 62 insertions, 19 deletions
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 49597ca..2e620ba 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -91,7 +91,7 @@ class Mastodon: | |||
91 | __DEFAULT_TIMEOUT = 300 | 91 | __DEFAULT_TIMEOUT = 300 |
92 | __DEFAULT_STREAM_TIMEOUT = 300 | 92 | __DEFAULT_STREAM_TIMEOUT = 300 |
93 | __DEFAULT_STREAM_RECONNECT_WAIT_SEC = 5 | 93 | __DEFAULT_STREAM_RECONNECT_WAIT_SEC = 5 |
94 | __SUPPORTED_MASTODON_VERSION = "2.2.0" | 94 | __SUPPORTED_MASTODON_VERSION = "2.3.0" |
95 | 95 | ||
96 | ### | 96 | ### |
97 | # Registering apps | 97 | # Registering apps |
@@ -195,6 +195,8 @@ class Mastodon: | |||
195 | 195 | ||
196 | self.request_timeout = request_timeout | 196 | self.request_timeout = request_timeout |
197 | 197 | ||
198 | self.session = requests.Session() | ||
199 | |||
198 | # Versioning | 200 | # Versioning |
199 | if mastodon_version == None: | 201 | if mastodon_version == None: |
200 | self.retrieve_mastodon_version() | 202 | self.retrieve_mastodon_version() |
@@ -347,7 +349,7 @@ class Mastodon: | |||
347 | ### | 349 | ### |
348 | # Reading data: Instances | 350 | # Reading data: Instances |
349 | ### | 351 | ### |
350 | @api_version("1.1.0", "1.4.2") | 352 | @api_version("1.1.0", "2.3.0") |
351 | def instance(self): | 353 | def instance(self): |
352 | """ | 354 | """ |
353 | Retrieve basic information about the instance, including the URI and administrative contact email. | 355 | Retrieve basic information about the instance, including the URI and administrative contact email. |
@@ -688,10 +690,11 @@ class Mastodon: | |||
688 | params) | 690 | params) |
689 | 691 | ||
690 | @api_version("1.0.0", "2.1.0") | 692 | @api_version("1.0.0", "2.1.0") |
691 | def account_search(self, q, limit=None): | 693 | def account_search(self, q, limit=None, following=False): |
692 | """ | 694 | """ |
693 | Fetch matching accounts. Will lookup an account remotely if the search term is | 695 | Fetch matching accounts. Will lookup an account remotely if the search term is |
694 | in the username@domain format and not yet in the database. | 696 | in the username@domain format and not yet in the database. Set `following` to |
697 | True to limit the search to users the logged-in user follows. | ||
695 | 698 | ||
696 | Returns a list of `user dicts`_. | 699 | Returns a list of `user dicts`_. |
697 | """ | 700 | """ |
@@ -706,6 +709,7 @@ class Mastodon: | |||
706 | 709 | ||
707 | Returns a list of `list dicts`_. | 710 | Returns a list of `list dicts`_. |
708 | """ | 711 | """ |
712 | id = self.__unpack_id(id) | ||
709 | params = self.__generate_params(locals(), ['id']) | 713 | params = self.__generate_params(locals(), ['id']) |
710 | url = '/api/v1/accounts/{0}/lists'.format(str(id)) | 714 | url = '/api/v1/accounts/{0}/lists'.format(str(id)) |
711 | return self.__api_request('GET', url, params) | 715 | return self.__api_request('GET', url, params) |
@@ -892,7 +896,7 @@ class Mastodon: | |||
892 | ### | 896 | ### |
893 | @api_version("1.0.0", "2.0.0") | 897 | @api_version("1.0.0", "2.0.0") |
894 | def status_post(self, status, in_reply_to_id=None, media_ids=None, | 898 | def status_post(self, status, in_reply_to_id=None, media_ids=None, |
895 | sensitive=False, visibility='', spoiler_text=None): | 899 | sensitive=False, visibility=None, spoiler_text=None): |
896 | """ | 900 | """ |
897 | Post a status. Can optionally be in reply to another status and contain | 901 | Post a status. Can optionally be in reply to another status and contain |
898 | media. | 902 | media. |
@@ -930,11 +934,14 @@ class Mastodon: | |||
930 | params_initial = locals() | 934 | params_initial = locals() |
931 | 935 | ||
932 | # Validate visibility parameter | 936 | # Validate visibility parameter |
933 | valid_visibilities = ['private', 'public', 'unlisted', 'direct', ''] | 937 | valid_visibilities = ['private', 'public', 'unlisted', 'direct'] |
934 | params_initial['visibility'] = params_initial['visibility'].lower() | 938 | if params_initial['visibility'] == None: |
935 | if params_initial['visibility'] not in valid_visibilities: | 939 | del params_initial['visibility'] |
936 | raise ValueError('Invalid visibility value! Acceptable ' | 940 | else: |
937 | 'values are %s' % valid_visibilities) | 941 | params_initial['visibility'] = params_initial['visibility'].lower() |
942 | if params_initial['visibility'] not in valid_visibilities: | ||
943 | raise ValueError('Invalid visibility value! Acceptable ' | ||
944 | 'values are %s' % valid_visibilities) | ||
938 | 945 | ||
939 | if params_initial['sensitive'] is False: | 946 | if params_initial['sensitive'] is False: |
940 | del [params_initial['sensitive']] | 947 | del [params_initial['sensitive']] |
@@ -1143,21 +1150,56 @@ class Mastodon: | |||
1143 | url = '/api/v1/accounts/{0}/unmute'.format(str(id)) | 1150 | url = '/api/v1/accounts/{0}/unmute'.format(str(id)) |
1144 | return self.__api_request('POST', url) | 1151 | return self.__api_request('POST', url) |
1145 | 1152 | ||
1146 | @api_version("1.1.1", "2.1.0") | 1153 | @api_version("1.1.1", "2.3.0") |
1147 | def account_update_credentials(self, display_name=None, note=None, | 1154 | def account_update_credentials(self, display_name=None, note=None, |
1148 | avatar=None, header=None): | 1155 | avatar=None, avatar_mime_type=None, |
1156 | header=None, header_mime_type=None, locked=None): | ||
1149 | """ | 1157 | """ |
1150 | Update the profile for the currently logged-in user. | 1158 | Update the profile for the currently logged-in user. |
1151 | 1159 | ||
1152 | 'note' is the user's bio. | 1160 | 'note' is the user's bio. |
1153 | 1161 | ||
1154 | 'avatar' and 'header' are images encoded in base64, prepended by a content-type | 1162 | 'avatar' and 'header' are images. As with media uploads, it is possible to either |
1155 | (for example: 'data:image/png;base64,iVBORw0KGgoAAAA[...]') | 1163 | pass image data and a mime type, or a filename of an image file, for either. |
1164 | |||
1165 | 'locked' specifies whether the user needs to manually approve follow requests. | ||
1156 | 1166 | ||
1157 | Returns the updated `user dict` of the logged-in user. | 1167 | Returns the updated `user dict` of the logged-in user. |
1158 | """ | 1168 | """ |
1159 | params = self.__generate_params(locals()) | 1169 | params_initial = locals() |
1160 | return self.__api_request('PATCH', '/api/v1/accounts/update_credentials', params) | 1170 | |
1171 | # Load avatar, if specified | ||
1172 | if avatar_mime_type is None and os.path.isfile(avatar): | ||
1173 | avatar_mime_type = mimetypes.guess_type(avatar)[0] | ||
1174 | avatar = open(avatar, 'rb') | ||
1175 | |||
1176 | if (not avatar is None and avatar_mime_type is None): | ||
1177 | raise MastodonIllegalArgumentError('Could not determine mime type or data passed directly without mime type.') | ||
1178 | |||
1179 | # Load header, if specified | ||
1180 | if header_mime_type is None and os.path.isfile(header): | ||
1181 | header_mime_type = mimetypes.guess_type(header)[0] | ||
1182 | header = open(header, 'rb') | ||
1183 | |||
1184 | if (not header is None and header_mime_type is None): | ||
1185 | raise MastodonIllegalArgumentError('Could not determine mime type or data passed directly without mime type.') | ||
1186 | |||
1187 | # Clean up params | ||
1188 | for param in ["avatar", "avatar_mime_type", "header", "header_mime_type"]: | ||
1189 | if param in params_initial: | ||
1190 | del params_initial[param] | ||
1191 | |||
1192 | # Create file info | ||
1193 | files = {} | ||
1194 | if not avatar is None: | ||
1195 | avatar_file_name = "mastodonpyupload_" + mimetypes.guess_extension(avatar_mime_type) | ||
1196 | files["avatar"] = (avatar_file_name, avatar, avatar_mime_type) | ||
1197 | if not header is None: | ||
1198 | header_file_name = "mastodonpyupload_" + mimetypes.guess_extension(avatar_mime_type) | ||
1199 | files["header"] = (header_file_name, header, header_mime_type) | ||
1200 | |||
1201 | params = self.__generate_params(params_initial) | ||
1202 | return self.__api_request('PATCH', '/api/v1/accounts/update_credentials', params, files=files) | ||
1161 | 1203 | ||
1162 | ### | 1204 | ### |
1163 | # Writing data: Lists | 1205 | # Writing data: Lists |
@@ -1547,7 +1589,7 @@ class Mastodon: | |||
1547 | else: | 1589 | else: |
1548 | kwargs['data'] = params | 1590 | kwargs['data'] = params |
1549 | 1591 | ||
1550 | response_object = requests.request( | 1592 | response_object = self.session.request( |
1551 | method, self.api_base_url + endpoint, **kwargs) | 1593 | method, self.api_base_url + endpoint, **kwargs) |
1552 | except Exception as e: | 1594 | except Exception as e: |
1553 | raise MastodonNetworkError("Could not complete request: %s" % e) | 1595 | raise MastodonNetworkError("Could not complete request: %s" % e) |
@@ -1701,7 +1743,7 @@ class Mastodon: | |||
1701 | # Connect function (called and then potentially passed to async handler) | 1743 | # Connect function (called and then potentially passed to async handler) |
1702 | def connect_func(): | 1744 | def connect_func(): |
1703 | headers = {"Authorization": "Bearer " + self.access_token} | 1745 | headers = {"Authorization": "Bearer " + self.access_token} |
1704 | connection = requests.get(url + endpoint, headers = headers, data = params, stream = True, | 1746 | connection = self.session.get(url + endpoint, headers = headers, data = params, stream = True, |
1705 | timeout=(self.request_timeout, timeout)) | 1747 | timeout=(self.request_timeout, timeout)) |
1706 | 1748 | ||
1707 | if connection.status_code != 200: | 1749 | if connection.status_code != 200: |
@@ -1769,7 +1811,8 @@ class Mastodon: | |||
1769 | 1811 | ||
1770 | if run_async: | 1812 | if run_async: |
1771 | handle = __stream_handle(connection, connect_func, reconnect_async, reconnect_async_wait_sec) | 1813 | handle = __stream_handle(connection, connect_func, reconnect_async, reconnect_async_wait_sec) |
1772 | t = threading.Thread(args=(), daemon = True, target=handle._threadproc) | 1814 | t = threading.Thread(args=(), target=handle._threadproc) |
1815 | t.daemon = True | ||
1773 | t.start() | 1816 | t.start() |
1774 | return handle | 1817 | return handle |
1775 | else: | 1818 | else: |