diff options
author | Lorenz Diener <[email protected]> | 2016-11-24 00:36:00 +0100 |
---|---|---|
committer | Lorenz Diener <[email protected]> | 2016-11-24 00:36:00 +0100 |
commit | 98e1bf7f40929de6268f51bc2e1616f5cfb9974c (patch) | |
tree | cf02957a25d07aaf2d9e02032d81d0db5b4d8258 | |
parent | e89c7bda86f132c8ee9d48a0584d32b95bf80d9b (diff) | |
download | mastodon.py-98e1bf7f40929de6268f51bc2e1616f5cfb9974c.tar.gz |
Docstring cleanup
-rw-r--r-- | Mastodon.py | 173 |
1 files changed, 114 insertions, 59 deletions
diff --git a/Mastodon.py b/Mastodon.py index 5119688..2519bc8 100644 --- a/Mastodon.py +++ b/Mastodon.py | |||
@@ -5,16 +5,17 @@ import os | |||
5 | import os.path | 5 | import os.path |
6 | 6 | ||
7 | class Mastodon: | 7 | class Mastodon: |
8 | """ Super basic but thorough and easy to use mastodon.social | 8 | """ |
9 | api wrapper in python. | 9 | Super basic but thorough and easy to use mastodon.social |
10 | api wrapper in python. | ||
10 | 11 | ||
11 | If anything is unclear, check the official API docs at | 12 | If anything is unclear, check the official API docs at |
12 | https://github.com/Gargron/mastodon/wiki/API | 13 | https://github.com/Gargron/mastodon/wiki/API |
13 | 14 | ||
14 | Presently, only username-password login is supported, somebody please | 15 | Presently, only username-password login is supported, somebody please |
15 | patch in Real Proper OAuth if desired. | 16 | patch in Real Proper OAuth if desired. |
16 | 17 | ||
17 | KNOWN BUGS: Media api does not work, reason unclear. | 18 | KNOWN BUGS: Media api does not work, reason unclear. |
18 | """ | 19 | """ |
19 | __DEFAULT_BASE_URL = 'https://mastodon.social' | 20 | __DEFAULT_BASE_URL = 'https://mastodon.social' |
20 | 21 | ||
@@ -23,13 +24,14 @@ class Mastodon: | |||
23 | ### | 24 | ### |
24 | @staticmethod | 25 | @staticmethod |
25 | def create_app(client_name, scopes = ['read', 'write', 'follow'], redirect_uris = None, to_file = None, api_base_url = __DEFAULT_BASE_URL): | 26 | def create_app(client_name, scopes = ['read', 'write', 'follow'], redirect_uris = None, to_file = None, api_base_url = __DEFAULT_BASE_URL): |
26 | """Creates a new app with given client_name and scopes (read, write, follow) | 27 | """ |
28 | Creates a new app with given client_name and scopes (read, write, follow) | ||
27 | 29 | ||
28 | Specify redirect_uris if you want users to be redirected to a certain page after authenticating. | 30 | Specify redirect_uris if you want users to be redirected to a certain page after authenticating. |
29 | Specify to_file to persist your apps info to a file so you can use them in the constructor. | 31 | Specify to_file to persist your apps info to a file so you can use them in the constructor. |
30 | Specify api_base_url if you want to register an app on an instance different from the flagship one. | 32 | Specify api_base_url if you want to register an app on an instance different from the flagship one. |
31 | 33 | ||
32 | returns client_id and client_secret | 34 | Returns client_id and client_secret. |
33 | """ | 35 | """ |
34 | request_data = { | 36 | request_data = { |
35 | 'client_name': client_name, | 37 | 'client_name': client_name, |
@@ -54,13 +56,14 @@ class Mastodon: | |||
54 | # Authentication, including constructor | 56 | # Authentication, including constructor |
55 | ### | 57 | ### |
56 | def __init__(self, client_id, client_secret = None, access_token = None, api_base_url = __DEFAULT_BASE_URL): | 58 | def __init__(self, client_id, client_secret = None, access_token = None, api_base_url = __DEFAULT_BASE_URL): |
57 | """Create a new API wrapper instance based on the given client_secret and client_id. If you | 59 | """ |
58 | give a client_id and it is not a file, you must also give a secret. | 60 | Creates a new API wrapper instance based on the given client_secret and client_id. If you |
61 | give a client_id and it is not a file, you must also give a secret. | ||
59 | 62 | ||
60 | You can also directly specify an access_token, directly or as a file. | 63 | You can also directly specify an access_token, directly or as a file. |
61 | 64 | ||
62 | Specify api_base_url if you wish to talk to an instance other than the flagship one. | 65 | Specify api_base_url if you wish to talk to an instance other than the flagship one. |
63 | If a file is given as client_id, read client ID and secret from that file | 66 | If a file is given as client_id, read client ID and secret from that file |
64 | """ | 67 | """ |
65 | self.api_base_url = api_base_url | 68 | self.api_base_url = api_base_url |
66 | self.client_id = client_id | 69 | self.client_id = client_id |
@@ -80,10 +83,11 @@ class Mastodon: | |||
80 | self.access_token = token_file.readline().rstrip() | 83 | self.access_token = token_file.readline().rstrip() |
81 | 84 | ||
82 | def log_in(self, username, password, scopes = ['read', 'write', 'follow'], to_file = None): | 85 | def log_in(self, username, password, scopes = ['read', 'write', 'follow'], to_file = None): |
83 | """Logs in and sets access_token to what was returned. | 86 | """ |
84 | Can persist access token to file. | 87 | Logs in and sets access_token to what was returned. |
88 | Can persist access token to file. | ||
85 | 89 | ||
86 | Returns the access_token, as well. | 90 | Returns the access_token, as well. |
87 | """ | 91 | """ |
88 | params = self.__generate_params(locals()) | 92 | params = self.__generate_params(locals()) |
89 | params['client_id'] = self.client_id | 93 | params['client_id'] = self.client_id |
@@ -104,8 +108,10 @@ class Mastodon: | |||
104 | # Reading data: Timelines | 108 | # Reading data: Timelines |
105 | ## | 109 | ## |
106 | def timeline(self, timeline = 'home', max_id = None, since_id = None, limit = None): | 110 | def timeline(self, timeline = 'home', max_id = None, since_id = None, limit = None): |
107 | """Returns statuses, most recent ones first. Timeline can be home, mentions, public | 111 | """ |
108 | or tag/:hashtag""" | 112 | Returns statuses, most recent ones first. Timeline can be home, mentions, public |
113 | or tag/:hashtag | ||
114 | """ | ||
109 | params = self.__generate_params(locals(), ['timeline']) | 115 | params = self.__generate_params(locals(), ['timeline']) |
110 | return self.__api_request('GET', '/api/v1/timelines/' + timeline, params) | 116 | return self.__api_request('GET', '/api/v1/timelines/' + timeline, params) |
111 | 117 | ||
@@ -113,58 +119,82 @@ class Mastodon: | |||
113 | # Reading data: Statuses | 119 | # Reading data: Statuses |
114 | ### | 120 | ### |
115 | def status(self, id): | 121 | def status(self, id): |
116 | """Returns status.""" | 122 | """ |
123 | Returns a status. | ||
124 | """ | ||
117 | return self.__api_request('GET', '/api/v1/statuses/' + str(id)) | 125 | return self.__api_request('GET', '/api/v1/statuses/' + str(id)) |
118 | 126 | ||
119 | def status_context(self, id): | 127 | def status_context(self, id): |
120 | """Returns ancestors and descendants of the status.""" | 128 | """ |
129 | Returns ancestors and descendants of the status. | ||
130 | """ | ||
121 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/context') | 131 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/context') |
122 | 132 | ||
123 | def status_reblogged_by(self, id): | 133 | def status_reblogged_by(self, id): |
124 | """Returns a list of users that have reblogged a status.""" | 134 | """ |
135 | Returns a list of users that have reblogged a status. | ||
136 | """ | ||
125 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/reblogged_by') | 137 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/reblogged_by') |
126 | 138 | ||
127 | def status_favourited_by(self, id): | 139 | def status_favourited_by(self, id): |
128 | """Returns a list of users that have favourited a status.""" | 140 | """ |
141 | Returns a list of users that have favourited a status. | ||
142 | """ | ||
129 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/favourited_by') | 143 | return self.__api_request('GET', '/api/v1/statuses/' + str(id) + '/favourited_by') |
130 | 144 | ||
131 | ### | 145 | ### |
132 | # Reading data: Accounts | 146 | # Reading data: Accounts |
133 | ### | 147 | ### |
134 | def account(self, id): | 148 | def account(self, id): |
135 | """Returns account.""" | 149 | """ |
150 | Returns account. | ||
151 | """ | ||
136 | return self.__api_request('GET', '/api/v1/accounts/' + str(id)) | 152 | return self.__api_request('GET', '/api/v1/accounts/' + str(id)) |
137 | 153 | ||
138 | def account_verify_credentials(self): | 154 | def account_verify_credentials(self): |
139 | """Returns authenticated user's account.""" | 155 | """ |
156 | Returns authenticated user's account. | ||
157 | """ | ||
140 | return self.__api_request('GET', '/api/v1/accounts/verify_credentials') | 158 | return self.__api_request('GET', '/api/v1/accounts/verify_credentials') |
141 | 159 | ||
142 | def account_statuses(self, id, max_id = None, since_id = None, limit = None): | 160 | def account_statuses(self, id, max_id = None, since_id = None, limit = None): |
143 | """Returns statuses by user. Same options as timeline are permitted.""" | 161 | """ |
162 | Returns statuses by user. Same options as timeline are permitted. | ||
163 | """ | ||
144 | params = self.__generate_params(locals(), ['id']) | 164 | params = self.__generate_params(locals(), ['id']) |
145 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/statuses') | 165 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/statuses') |
146 | 166 | ||
147 | def account_following(self, id): | 167 | def account_following(self, id): |
148 | """Returns users the given user is following.""" | 168 | """ |
169 | Returns users the given user is following. | ||
170 | """ | ||
149 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/following') | 171 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/following') |
150 | 172 | ||
151 | def account_followers(self, id): | 173 | def account_followers(self, id): |
152 | """Returns users the given user is followed by.""" | 174 | """ |
175 | Returns users the given user is followed by. | ||
176 | """ | ||
153 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/followers') | 177 | return self.__api_request('GET', '/api/v1/accounts/' + str(id) + '/followers') |
154 | 178 | ||
155 | def account_relationships(self, id): | 179 | def account_relationships(self, id): |
156 | """Returns relationships (following, followed_by, blocking) of the logged in user to | 180 | """ |
157 | a given account. id can be a list.""" | 181 | Returns relationships (following, followed_by, blocking) of the logged in user to |
182 | a given account. id can be a list. | ||
183 | """ | ||
158 | params = self.__generate_params(locals()) | 184 | params = self.__generate_params(locals()) |
159 | return self.__api_request('GET', '/api/v1/accounts/relationships', params) | 185 | return self.__api_request('GET', '/api/v1/accounts/relationships', params) |
160 | 186 | ||
161 | def account_suggestions(self): | 187 | def account_suggestions(self): |
162 | """Returns accounts that the system suggests the authenticated user to follow.""" | 188 | """ |
189 | Returns accounts that the system suggests the authenticated user to follow. | ||
190 | """ | ||
163 | return self.__api_request('GET', '/api/v1/accounts/suggestions') | 191 | return self.__api_request('GET', '/api/v1/accounts/suggestions') |
164 | 192 | ||
165 | def account_search(self, q, limit = None): | 193 | def account_search(self, q, limit = None): |
166 | """Returns matching accounts. Will lookup an account remotely if the search term is | 194 | """ |
167 | in the username@domain format and not yet in the database.""" | 195 | Returns matching accounts. Will lookup an account remotely if the search term is |
196 | in the username@domain format and not yet in the database. | ||
197 | """ | ||
168 | params = self.__generate_params(locals()) | 198 | params = self.__generate_params(locals()) |
169 | return self.__api_request('GET', '/api/v1/accounts/search', params) | 199 | return self.__api_request('GET', '/api/v1/accounts/search', params) |
170 | 200 | ||
@@ -172,19 +202,25 @@ class Mastodon: | |||
172 | # Writing data: Statuses | 202 | # Writing data: Statuses |
173 | ### | 203 | ### |
174 | def status_post(self, status, in_reply_to_id = None, media_ids = None): | 204 | def status_post(self, status, in_reply_to_id = None, media_ids = None): |
175 | """Posts a status. Can optionally be in reply to another status and contain | 205 | """ |
176 | up to four pieces of media (Uploaded via media_post()). | 206 | Posts a status. Can optionally be in reply to another status and contain |
207 | up to four pieces of media (Uploaded via media_post()). | ||
177 | 208 | ||
178 | Returns the new status.""" | 209 | Returns the new status. |
210 | """ | ||
179 | params = self.__generate_params(locals()) | 211 | params = self.__generate_params(locals()) |
180 | return self.__api_request('POST', '/api/v1/statuses', params) | 212 | return self.__api_request('POST', '/api/v1/statuses', params) |
181 | 213 | ||
182 | def toot(self, status): | 214 | def toot(self, status): |
183 | """Synonym for status_post that only takes the status text as input.""" | 215 | """ |
216 | Synonym for status_post that only takes the status text as input. | ||
217 | """ | ||
184 | return self.status_post(status) | 218 | return self.status_post(status) |
185 | 219 | ||
186 | def status_delete(self, id): | 220 | def status_delete(self, id): |
187 | """Deletes a status""" | 221 | """ |
222 | Deletes a status | ||
223 | """ | ||
188 | return self.__api_request('DELETE', '/api/v1/statuses/' + str(id)) | 224 | return self.__api_request('DELETE', '/api/v1/statuses/' + str(id)) |
189 | 225 | ||
190 | def status_reblog(self, id): | 226 | def status_reblog(self, id): |
@@ -194,58 +230,73 @@ class Mastodon: | |||
194 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/reblog") | 230 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/reblog") |
195 | 231 | ||
196 | def status_unreblog(self, id): | 232 | def status_unreblog(self, id): |
197 | """Un-reblogs a status. | 233 | """ |
234 | Un-reblogs a status. | ||
198 | 235 | ||
199 | Returns the status that used to be reblogged.""" | 236 | Returns the status that used to be reblogged. |
237 | """ | ||
200 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unreblog") | 238 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unreblog") |
201 | 239 | ||
202 | def status_favourite(self, id): | 240 | def status_favourite(self, id): |
203 | """Favourites a status. | 241 | """ |
242 | Favourites a status. | ||
204 | 243 | ||
205 | Returns the favourited status.""" | 244 | Returns the favourited status. |
245 | """ | ||
206 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/favourite") | 246 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/favourite") |
207 | 247 | ||
208 | def status_unfavourite(self, id): | 248 | def status_unfavourite(self, id): |
209 | """Favourites a status. | 249 | """Favourites a status. |
210 | 250 | ||
211 | Returns the un-favourited status.""" | 251 | Returns the un-favourited status. |
252 | """ | ||
212 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unfavourite") | 253 | return self.__api_request('POST', '/api/v1/statuses/' + str(id) + "/unfavourite") |
213 | 254 | ||
214 | ### | 255 | ### |
215 | # Writing data: Statuses | 256 | # Writing data: Statuses |
216 | ### | 257 | ### |
217 | def account_follow(self, id): | 258 | def account_follow(self, id): |
218 | """Follows a user. | 259 | """ |
260 | Follows a user. | ||
219 | 261 | ||
220 | Returns the updated relationship to the user.""" | 262 | Returns the updated relationship to the user. |
263 | """ | ||
221 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/follow") | 264 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/follow") |
222 | 265 | ||
223 | def account_unfollow(self, id): | 266 | def account_unfollow(self, id): |
224 | """Unfollows a user. | 267 | """ |
268 | Unfollows a user. | ||
225 | 269 | ||
226 | Returns the updated relationship to the user.""" | 270 | Returns the updated relationship to the user. |
271 | """ | ||
227 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unfollow") | 272 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unfollow") |
228 | 273 | ||
229 | def account_block(self, id): | 274 | def account_block(self, id): |
230 | """Blocks a user. | 275 | """ |
276 | Blocks a user. | ||
231 | 277 | ||
232 | Returns the updated relationship to the user.""" | 278 | Returns the updated relationship to the user. |
279 | """ | ||
233 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/block") | 280 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/block") |
234 | 281 | ||
235 | def account_unblock(self, id): | 282 | def account_unblock(self, id): |
236 | """Unblocks a user. | 283 | """ |
284 | Unblocks a user. | ||
237 | 285 | ||
238 | Returns the updated relationship to the user.""" | 286 | Returns the updated relationship to the user. |
287 | """ | ||
239 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unblock") | 288 | return self.__api_request('POST', '/api/v1/accounts/' + str(id) + "/unblock") |
240 | 289 | ||
241 | ### | 290 | ### |
242 | # Writing data: Media | 291 | # Writing data: Media |
243 | ### | 292 | ### |
244 | def media_post(self, media_file): | 293 | def media_post(self, media_file): |
245 | """Posts an image. media_file can either be image data or | 294 | """ |
246 | a file name. | 295 | Posts an image. media_file can either be image data or |
296 | a file name. | ||
247 | 297 | ||
248 | Returns the ID of the media that can then be used in status_post().""" | 298 | Returns the ID of the media that can then be used in status_post(). |
299 | """ | ||
249 | if os.path.isfile(media_file): | 300 | if os.path.isfile(media_file): |
250 | media_file = open(media_file, 'rb') | 301 | media_file = open(media_file, 'rb') |
251 | 302 | ||
@@ -255,7 +306,9 @@ class Mastodon: | |||
255 | # Internal helpers, dragons probably | 306 | # Internal helpers, dragons probably |
256 | ### | 307 | ### |
257 | def __api_request(self, method, endpoint, params = {}, files = {}): | 308 | def __api_request(self, method, endpoint, params = {}, files = {}): |
258 | """ Internal API request helper.""" | 309 | """ |
310 | Internal API request helper. | ||
311 | """ | ||
259 | response = None | 312 | response = None |
260 | headers = None | 313 | headers = None |
261 | 314 | ||
@@ -280,7 +333,9 @@ class Mastodon: | |||
280 | return response.json() | 333 | return response.json() |
281 | 334 | ||
282 | def __generate_params(self, params, exclude = []): | 335 | def __generate_params(self, params, exclude = []): |
283 | """Internal named-parameters-to-dict helper""" | 336 | """ |
337 | Internal named-parameters-to-dict helper. | ||
338 | """ | ||
284 | params = dict(params) | 339 | params = dict(params) |
285 | 340 | ||
286 | del params['self'] | 341 | del params['self'] |