diff options
Diffstat (limited to 'mastodon')
-rw-r--r-- | mastodon/Mastodon.py | 134 |
1 files changed, 83 insertions, 51 deletions
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 7bd6473..36f20d2 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -27,7 +27,7 @@ class Mastodon: | |||
27 | @staticmethod | 27 | @staticmethod |
28 | def create_app(client_name, scopes = ['read', 'write', 'follow'], redirect_uris = None, to_file = None, api_base_url = __DEFAULT_BASE_URL): | 28 | def create_app(client_name, scopes = ['read', 'write', 'follow'], redirect_uris = None, to_file = None, api_base_url = __DEFAULT_BASE_URL): |
29 | """ | 29 | """ |
30 | Creates a new app with given client_name and scopes (read, write, follow) | 30 | Create a new app with given client_name and scopes (read, write, follow) |
31 | 31 | ||
32 | Specify redirect_uris if you want users to be redirected to a certain page after authenticating. | 32 | Specify redirect_uris if you want users to be redirected to a certain page after authenticating. |
33 | Specify to_file to persist your apps info to a file so you can use them in the constructor. | 33 | Specify to_file to persist your apps info to a file so you can use them in the constructor. |
@@ -59,7 +59,7 @@ class Mastodon: | |||
59 | ### | 59 | ### |
60 | def __init__(self, client_id, client_secret = None, access_token = None, api_base_url = __DEFAULT_BASE_URL, debug_requests = False): | 60 | def __init__(self, client_id, client_secret = None, access_token = None, api_base_url = __DEFAULT_BASE_URL, debug_requests = False): |
61 | """ | 61 | """ |
62 | Creates a new API wrapper instance based on the given client_secret and client_id. If you | 62 | Create a new API wrapper instance based on the given client_secret and client_id. If you |
63 | give a client_id and it is not a file, you must also give a secret. | 63 | give a client_id and it is not a file, you must also give a secret. |
64 | 64 | ||
65 | You can also directly specify an access_token, directly or as a file. | 65 | You can also directly specify an access_token, directly or as a file. |
@@ -87,7 +87,7 @@ class Mastodon: | |||
87 | 87 | ||
88 | def log_in(self, username, password, scopes = ['read', 'write', 'follow'], to_file = None): | 88 | def log_in(self, username, password, scopes = ['read', 'write', 'follow'], to_file = None): |
89 | """ | 89 | """ |
90 | Logs in and sets access_token to what was returned. | 90 | Log in and set access_token to what was returned. |
91 | Can persist access token to file. | 91 | Can persist access token to file. |
92 | 92 | ||
93 | Will throw an exception if username / password are wrong, scopes are not | 93 | Will throw an exception if username / password are wrong, scopes are not |
@@ -124,35 +124,45 @@ class Mastodon: | |||
124 | ## | 124 | ## |
125 | def timeline(self, timeline = "home", max_id = None, since_id = None, limit = None): | 125 | def timeline(self, timeline = "home", max_id = None, since_id = None, limit = None): |
126 | """ | 126 | """ |
127 | Returns statuses, most recent ones first. Timeline can be home, mentions, public | 127 | Fetch statuses, most recent ones first. Timeline can be home, mentions, public |
128 | or tag/hashtag. See the following functions documentation for what those do. | 128 | or tag/hashtag. See the following functions documentation for what those do. |
129 | 129 | ||
130 | The default timeline is the "home" timeline. | 130 | The default timeline is the "home" timeline. |
131 | |||
132 | Returns a list of toot dicts. | ||
131 | """ | 133 | """ |
132 | params = self.__generate_params(locals(), ['timeline']) | 134 | params = self.__generate_params(locals(), ['timeline']) |
133 | return self.__api_request('GET', '/api/v1/timelines/' + timeline, params) | 135 | return self.__api_request('GET', '/api/v1/timelines/' + timeline, params) |
134 | 136 | ||
135 | def timeline_home(self, max_id = None, since_id = None, limit = None): | 137 | def timeline_home(self, max_id = None, since_id = None, limit = None): |
136 | """ | 138 | """ |
137 | Returns the authenticated users home timeline (i.e. followed users and self). | 139 | Fetch the authenticated users home timeline (i.e. followed users and self). |
140 | |||
141 | Returns a list of toot dicts. | ||
138 | """ | 142 | """ |
139 | return self.timeline('home', max_id = max_id, since_id = since_id, limit = limit) | 143 | return self.timeline('home', max_id = max_id, since_id = since_id, limit = limit) |
140 | 144 | ||
141 | def timeline_mentions(self, max_id = None, since_id = None, limit = None): | 145 | def timeline_mentions(self, max_id = None, since_id = None, limit = None): |
142 | """ | 146 | """ |
143 | Returns the authenticated users mentions. | 147 | Fetches the authenticated users mentions. |
148 | |||
149 | Returns a list of toot dicts. | ||
144 | """ | 150 | """ |
145 | return self.timeline('mentions', max_id = max_id, since_id = since_id, limit = limit) | 151 | return self.timeline('mentions', max_id = max_id, since_id = since_id, limit = limit) |
146 | 152 | ||
147 | def timeline_public(self, max_id = None, since_id = None, limit = None): | 153 | def timeline_public(self, max_id = None, since_id = None, limit = None): |
148 | """ | 154 | """ |
149 | Returns the public / visible-network timeline. | 155 | Fetches the public / visible-network timeline. |
156 | |||
157 | Returns a list of toot dicts. | ||
150 | """ | 158 | """ |
151 | return self.timeline('public', max_id = max_id, since_id = since_id, limit = limit) | 159 | return self.timeline('public', max_id = max_id, since_id = since_id, limit = limit) |
152 | 160 | ||
153 | def timeline_hashtag(self, hashtag, max_id = None, since_id = None, limit = None): | 161 | def timeline_hashtag(self, hashtag, max_id = None, since_id = None, limit = None): |
154 | """ | 162 | """ |
155 | Returns all toots with a given hashtag. | 163 | Fetch a timeline of toots with a given hashtag. |
164 | |||
165 | Returns a list of toot dicts. | ||
156 | """ | 166 | """ |
157 | return self.timeline('tag/' + str(hashtag), max_id = max_id, since_id = since_id, limit = limit) | 167 | return self.timeline('tag/' + str(hashtag), max_id = max_id, since_id = since_id, limit = limit) |
158 | 168 | ||
@@ -161,25 +171,33 @@ class Mastodon: | |||
161 | ### | 171 | ### |
162 | def status(self, id): | 172 | def status(self, id): |
163 | """ | 173 | """ |
164 | Returns a status. | 174 | Fetch information about a single toot. |
175 | |||
176 | Returns a toot dict. | ||
165 | """ | 177 | """ |
166 | return self.__api_request('GET', '/api/v1/statuses/' + str(id)) | 178 | return self.__api_request('GET', '/api/v1/statuses/' + str(id)) |
167 | 179 | ||
168 | def status_context(self, id): | 180 | def status_context(self, id): |
169 | """ | 181 | """ |
170 | Returns ancestors and descendants of the status. | 182 | Fetch information about ancestors and descendants of a toot. |
183 | |||
184 | Returns a context dict. | ||
171 | """ | 185 | """ |
172 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/context') | 186 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/context') |
173 | 187 | ||
174 | def status_reblogged_by(self, id): | 188 | def status_reblogged_by(self, id): |
175 | """ | 189 | """ |
176 | Returns a list of users that have reblogged a status. | 190 | Fetch a list of users that have reblogged a status. |
191 | |||
192 | Returns a list of user dicts. | ||
177 | """ | 193 | """ |
178 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/reblogged_by') | 194 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/reblogged_by') |
179 | 195 | ||
180 | def status_favourited_by(self, id): | 196 | def status_favourited_by(self, id): |
181 | """ | 197 | """ |
182 | Returns a list of users that have favourited a status. | 198 | Fetch a list of users that have favourited a status. |
199 | |||
200 | Returns a list of user dicts. | ||
183 | """ | 201 | """ |
184 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/favourited_by') | 202 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/favourited_by') |
185 | 203 | ||
@@ -188,8 +206,10 @@ class Mastodon: | |||
188 | ### | 206 | ### |
189 | def notifications(self): | 207 | def notifications(self): |
190 | """ | 208 | """ |
191 | Returns notifications (mentions, favourites, reblogs, follows) for the authenticated | 209 | Fetch notifications (mentions, favourites, reblogs, follows) for the authenticated |
192 | user. | 210 | user. |
211 | |||
212 | Returns: TODO | ||
193 | """ | 213 | """ |
194 | return self.__api_request('GET', '/api/v1/notifications') | 214 | return self.__api_request('GET', '/api/v1/notifications') |
195 | 215 | ||
@@ -198,53 +218,61 @@ class Mastodon: | |||
198 | ### | 218 | ### |
199 | def account(self, id): | 219 | def account(self, id): |
200 | """ | 220 | """ |
201 | Returns account. | 221 | Fetch account information by user id. |
222 | |||
223 | Returns a user dict. | ||
202 | """ | 224 | """ |
203 | return self.__api_request('GET', '/api/v1/accounts/' + str(id)) | 225 | return self.__api_request('GET', '/api/v1/accounts/' + str(id)) |
204 | 226 | ||
205 | def account_verify_credentials(self): | 227 | def account_verify_credentials(self): |
206 | """ | 228 | """ |
207 | Returns authenticated user's account. | 229 | Fetch authenticated user's account information. |
230 | |||
231 | Returns a user dict. | ||
208 | """ | 232 | """ |
209 | return self.__api_request('GET', '/api/v1/accounts/verify_credentials') | 233 | return self.__api_request('GET', '/api/v1/accounts/verify_credentials') |
210 | 234 | ||
211 | def account_statuses(self, id, max_id = None, since_id = None, limit = None): | 235 | def account_statuses(self, id, max_id = None, since_id = None, limit = None): |
212 | """ | 236 | """ |
213 | Returns statuses by user. Same options as timeline are permitted. | 237 | Fetch statuses by user id. Same options as timeline are permitted. |
238 | |||
239 | Returns a list of toot dicts. | ||
214 | """ | 240 | """ |
215 | params = self.__generate_params(locals(), ['id']) | 241 | params = self.__generate_params(locals(), ['id']) |
216 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/statuses', params) | 242 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/statuses', params) |
217 | 243 | ||
218 | def account_following(self, id): | 244 | def account_following(self, id): |
219 | """ | 245 | """ |
220 | Returns users the given user is following. | 246 | Fetch users the given user is following. |
247 | |||
248 | Returns a list of user dicts. | ||
221 | """ | 249 | """ |
222 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/following') | 250 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/following') |
223 | 251 | ||
224 | def account_followers(self, id): | 252 | def account_followers(self, id): |
225 | """ | 253 | """ |
226 | Returns users the given user is followed by. | 254 | Fetch users the given user is followed by. |
255 | |||
256 | Returns a list of user dicts. | ||
227 | """ | 257 | """ |
228 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/followers') | 258 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/followers') |
229 | 259 | ||
230 | def account_relationships(self, id): | 260 | def account_relationships(self, id): |
231 | """ | 261 | """ |
232 | Returns relationships (following, followed_by, blocking) of the logged in user to | 262 | Fetch relationships (following, followed_by, blocking) of the logged in user to |
233 | a given account. id can be a list. | 263 | a given account. id can be a list. |
264 | |||
265 | Returns a list of relationship dicts. | ||
234 | """ | 266 | """ |
235 | params = self.__generate_params(locals()) | 267 | params = self.__generate_params(locals()) |
236 | return self.__api_request('GET', '/api/v1/accounts/relationships', params) | 268 | return self.__api_request('GET', '/api/v1/accounts/relationships', params) |
237 | |||
238 | def account_suggestions(self): | ||
239 | """ | ||
240 | Returns accounts that the system suggests the authenticated user to follow. | ||
241 | """ | ||
242 | return self.__api_request('GET', '/api/v1/accounts/suggestions') | ||
243 | 269 | ||
244 | def account_search(self, q, limit = None): | 270 | def account_search(self, q, limit = None): |
245 | """ | 271 | """ |
246 | Returns matching accounts. Will lookup an account remotely if the search term is | 272 | Fetch matching accounts. Will lookup an account remotely if the search term is |
247 | in the username@domain format and not yet in the database. | 273 | in the username@domain format and not yet in the database. |
274 | |||
275 | Returns a list of user dicts. | ||
248 | """ | 276 | """ |
249 | params = self.__generate_params(locals()) | 277 | params = self.__generate_params(locals()) |
250 | return self.__api_request('GET', '/api/v1/accounts/search', params) | 278 | return self.__api_request('GET', '/api/v1/accounts/search', params) |
@@ -254,10 +282,10 @@ class Mastodon: | |||
254 | ### | 282 | ### |
255 | def status_post(self, status, in_reply_to_id = None, media_ids = None): | 283 | def status_post(self, status, in_reply_to_id = None, media_ids = None): |
256 | """ | 284 | """ |
257 | Posts a status. Can optionally be in reply to another status and contain | 285 | Post a status. Can optionally be in reply to another status and contain |
258 | up to four pieces of media (Uploaded via media_post()). | 286 | up to four pieces of media (Uploaded via media_post()). |
259 | 287 | ||
260 | Returns the new status. | 288 | Returns a toot dict with the new status. |
261 | """ | 289 | """ |
262 | params = self.__generate_params(locals()) | 290 | params = self.__generate_params(locals()) |
263 | return self.__api_request('POST', '/api/v1/statuses', params) | 291 | return self.__api_request('POST', '/api/v1/statuses', params) |
@@ -265,41 +293,46 @@ class Mastodon: | |||
265 | def toot(self, status): | 293 | def toot(self, status): |
266 | """ | 294 | """ |
267 | Synonym for status_post that only takes the status text as input. | 295 | Synonym for status_post that only takes the status text as input. |
296 | |||
297 | Returns a toot dict with the new status. | ||
268 | """ | 298 | """ |
269 | return self.status_post(status) | 299 | return self.status_post(status) |
270 | 300 | ||
271 | def status_delete(self, id): | 301 | def status_delete(self, id): |
272 | """ | 302 | """ |
273 | Deletes a status | 303 | Delete a status |
304 | |||
305 | Returns an empty dict for good measure. | ||
274 | """ | 306 | """ |
275 | return self.__api_request('DELETE', '/api/v1/statuses/' + str(id)) | 307 | return self.__api_request('DELETE', '/api/v1/statuses/' + str(id)) |
276 | 308 | ||
277 | def status_reblog(self, id): | 309 | def status_reblog(self, id): |
278 | """Reblogs a status. | 310 | """Reblog a status. |
279 | 311 | ||
280 | Returns a new status that wraps around the reblogged one.""" | 312 | Returns a toot with with a new status that wraps around the reblogged one. |
313 | """ | ||
281 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/reblog") | 314 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/reblog") |
282 | 315 | ||
283 | def status_unreblog(self, id): | 316 | def status_unreblog(self, id): |
284 | """ | 317 | """ |
285 | Un-reblogs a status. | 318 | Un-reblog a status. |
286 | 319 | ||
287 | Returns the status that used to be reblogged. | 320 | Returns a toot dict with the status that used to be reblogged. |
288 | """ | 321 | """ |
289 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unreblog") | 322 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unreblog") |
290 | 323 | ||
291 | def status_favourite(self, id): | 324 | def status_favourite(self, id): |
292 | """ | 325 | """ |
293 | Favourites a status. | 326 | Favourite a status. |
294 | 327 | ||
295 | Returns the favourited status. | 328 | Returns a toot dict with the favourited status. |
296 | """ | 329 | """ |
297 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/favourite") | 330 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/favourite") |
298 | 331 | ||
299 | def status_unfavourite(self, id): | 332 | def status_unfavourite(self, id): |
300 | """Favourites a status. | 333 | """Favourite a status. |
301 | 334 | ||
302 | Returns the un-favourited status. | 335 | Returns a toot dict with the un-favourited status. |
303 | """ | 336 | """ |
304 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unfavourite") | 337 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unfavourite") |
305 | 338 | ||
@@ -308,33 +341,33 @@ class Mastodon: | |||
308 | ### | 341 | ### |
309 | def account_follow(self, id): | 342 | def account_follow(self, id): |
310 | """ | 343 | """ |
311 | Follows a user. | 344 | Follow a user. |
312 | 345 | ||
313 | Returns the updated relationship to the user. | 346 | Returns a relationship dict containing the updated relationship to the user. |
314 | """ | 347 | """ |
315 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/follow") | 348 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/follow") |
316 | 349 | ||
317 | def account_unfollow(self, id): | 350 | def account_unfollow(self, id): |
318 | """ | 351 | """ |
319 | Unfollows a user. | 352 | Unfollow a user. |
320 | 353 | ||
321 | Returns the updated relationship to the user. | 354 | Returns a relationship dict containing the updated relationship to the user. |
322 | """ | 355 | """ |
323 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unfollow") | 356 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unfollow") |
324 | 357 | ||
325 | def account_block(self, id): | 358 | def account_block(self, id): |
326 | """ | 359 | """ |
327 | Blocks a user. | 360 | Block a user. |
328 | 361 | ||
329 | Returns the updated relationship to the user. | 362 | Returns a relationship dict containing the updated relationship to the user. |
330 | """ | 363 | """ |
331 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/block") | 364 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/block") |
332 | 365 | ||
333 | def account_unblock(self, id): | 366 | def account_unblock(self, id): |
334 | """ | 367 | """ |
335 | Unblocks a user. | 368 | Unblock a user. |
336 | 369 | ||
337 | Returns the updated relationship to the user. | 370 | Returns a relationship dict containing the updated relationship to the user. |
338 | """ | 371 | """ |
339 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unblock") | 372 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unblock") |
340 | 373 | ||
@@ -343,20 +376,19 @@ class Mastodon: | |||
343 | ### | 376 | ### |
344 | def media_post(self, media_file, mime_type = None): | 377 | def media_post(self, media_file, mime_type = None): |
345 | """ | 378 | """ |
346 | Posts an image. media_file can either be image data or | 379 | Post an image. media_file can either be image data or |
347 | a file name. If image data is passed directly, the mime | 380 | a file name. If image data is passed directly, the mime |
348 | type has to be specified manually, otherwise, it is | 381 | type has to be specified manually, otherwise, it is |
349 | determined from the file name. | 382 | determined from the file name. |
350 | 383 | ||
351 | Returns the uploaded media metadata object. Importantly, this contains | ||
352 | the ID that can then be used in status_post() to attach the media to | ||
353 | a toot. | ||
354 | |||
355 | Throws a ValueError if the mime type of the passed data or file can | 384 | Throws a ValueError if the mime type of the passed data or file can |
356 | not be determined properly. | 385 | not be determined properly. |
386 | |||
387 | Returns a media dict. This contains the id that can be used in | ||
388 | status_post to attach the media file to a toot. | ||
357 | """ | 389 | """ |
358 | 390 | ||
359 | if os.path.isfile(media_file): | 391 | if os.path.isfile(media_file) and mime_type == None: |
360 | mime_type = mimetypes.guess_type(media_file)[0] | 392 | mime_type = mimetypes.guess_type(media_file)[0] |
361 | media_file = open(media_file, 'rb') | 393 | media_file = open(media_file, 'rb') |
362 | 394 | ||