diff options
Diffstat (limited to 'mastodon/admin.py')
-rw-r--r-- | mastodon/admin.py | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/mastodon/admin.py b/mastodon/admin.py new file mode 100644 index 0000000..e2f5f20 --- /dev/null +++ b/mastodon/admin.py | |||
@@ -0,0 +1,572 @@ | |||
1 | # admin.py - admin / moderation endpoints | ||
2 | |||
3 | from .versions import _DICT_VERSION_ADMIN_ACCOUNT, _DICT_VERSION_REPORT, _DICT_VERSION_HASHTAG, _DICT_VERSION_STATUS, _DICT_VERSION_CARD, \ | ||
4 | _DICT_VERSION_ADMIN_DOMAIN_BLOCK, _DICT_VERSION_ADMIN_MEASURE, _DICT_VERSION_ADMIN_DIMENSION, _DICT_VERSION_ADMIN_RETENTION | ||
5 | from .errors import MastodonIllegalArgumentError | ||
6 | from .utility import api_version | ||
7 | |||
8 | from .internals import Mastodon as Internals | ||
9 | |||
10 | class Mastodon(Internals): | ||
11 | ### | ||
12 | # Moderation API | ||
13 | ### | ||
14 | @api_version("2.9.1", "4.0.0", _DICT_VERSION_ADMIN_ACCOUNT) | ||
15 | def admin_accounts_v2(self, origin=None, by_domain=None, status=None, username=None, display_name=None, email=None, ip=None, | ||
16 | permissions=None, invited_by=None, role_ids=None, max_id=None, min_id=None, since_id=None, limit=None): | ||
17 | """ | ||
18 | Fetches a list of accounts that match given criteria. By default, local accounts are returned. | ||
19 | |||
20 | * Set `origin` to "local" or "remote" to get only local or remote accounts. | ||
21 | * Set `by_domain` to a domain to get only accounts from that domain. | ||
22 | * Set `status` to one of "active", "pending", "disabled", "silenced" or "suspended" to get only accounts with that moderation status (default: active) | ||
23 | * Set `username` to a string to get only accounts whose username contains this string. | ||
24 | * Set `display_name` to a string to get only accounts whose display name contains this string. | ||
25 | * Set `email` to an email to get only accounts with that email (this only works on local accounts). | ||
26 | * Set `ip` to an ip (as a string, standard v4/v6 notation) to get only accounts whose last active ip is that ip (this only works on local accounts). | ||
27 | * Set `permissions` to "staff" to only get accounts with staff permissions. | ||
28 | * Set `invited_by` to an account id to get only accounts invited by this user. | ||
29 | * Set `role_ids` to a list of role IDs to get only accounts with those roles. | ||
30 | |||
31 | Returns a list of :ref:`admin account dicts <admin account dicts>`. | ||
32 | """ | ||
33 | if max_id is not None: | ||
34 | max_id = self.__unpack_id(max_id, dateconv=True) | ||
35 | |||
36 | if min_id is not None: | ||
37 | min_id = self.__unpack_id(min_id, dateconv=True) | ||
38 | |||
39 | if since_id is not None: | ||
40 | since_id = self.__unpack_id(since_id, dateconv=True) | ||
41 | |||
42 | if role_ids is not None: | ||
43 | if not isinstance(role_ids, list): | ||
44 | role_ids = [role_ids] | ||
45 | role_ids = list(map(self.__unpack_id, role_ids)) | ||
46 | |||
47 | if invited_by is not None: | ||
48 | invited_by = self.__unpack_id(invited_by) | ||
49 | |||
50 | if permissions is not None and not permissions in ["staff"]: | ||
51 | raise MastodonIllegalArgumentError("Permissions must be staff if passed") | ||
52 | |||
53 | if origin is not None and not origin in ["local", "remote"]: | ||
54 | raise MastodonIllegalArgumentError("Origin must be local or remote") | ||
55 | |||
56 | if status is not None and not status in ["active", "pending", "disabled", "silenced", "suspended"]: | ||
57 | raise MastodonIllegalArgumentError("Status must be local or active, pending, disabled, silenced or suspended") | ||
58 | |||
59 | if not by_domain is None: | ||
60 | by_domain = self.__deprotocolize(by_domain) | ||
61 | |||
62 | params = self.__generate_params(locals()) | ||
63 | return self.__api_request('GET', '/api/v2/admin/accounts', params) | ||
64 | |||
65 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
66 | 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): | ||
67 | """ | ||
68 | 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. | ||
69 | |||
70 | !!!!! 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. !!!!! | ||
71 | """ | ||
72 | return self.admin_accounts_v1( | ||
73 | remote=remote, | ||
74 | by_domain=by_domain, | ||
75 | status=status, | ||
76 | username=username, | ||
77 | display_name=display_name, | ||
78 | email=email, | ||
79 | ip=ip, | ||
80 | staff_only=staff_only, | ||
81 | max_id=max_id, | ||
82 | min_id=min_id, | ||
83 | since_id=since_id | ||
84 | ) | ||
85 | |||
86 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
87 | def admin_accounts_v1(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): | ||
88 | """ | ||
89 | Fetches a list of accounts that match given criteria. By default, local accounts are returned. | ||
90 | |||
91 | * Set `remote` to True to get remote accounts, otherwise local accounts are returned (default: local accounts) | ||
92 | * Set `by_domain` to a domain to get only accounts from that domain. | ||
93 | * Set `status` to one of "active", "pending", "disabled", "silenced" or "suspended" to get only accounts with that moderation status (default: active) | ||
94 | * Set `username` to a string to get only accounts whose username contains this string. | ||
95 | * Set `display_name` to a string to get only accounts whose display name contains this string. | ||
96 | * Set `email` to an email to get only accounts with that email (this only works on local accounts). | ||
97 | * Set `ip` to an ip (as a string, standard v4/v6 notation) to get only accounts whose last active ip is that ip (this only works on local accounts). | ||
98 | * Set `staff_only` to True to only get staff accounts (this only works on local accounts). | ||
99 | |||
100 | Note that setting the boolean parameters to False does not mean "give me users to which this does not apply" but | ||
101 | instead means "I do not care if users have this attribute". | ||
102 | |||
103 | Deprecated in Mastodon version 3.5.0. | ||
104 | |||
105 | Returns a list of :ref:`admin account dicts <admin account dicts>`. | ||
106 | """ | ||
107 | if max_id is not None: | ||
108 | max_id = self.__unpack_id(max_id, dateconv=True) | ||
109 | |||
110 | if min_id is not None: | ||
111 | min_id = self.__unpack_id(min_id, dateconv=True) | ||
112 | |||
113 | if since_id is not None: | ||
114 | since_id = self.__unpack_id(since_id, dateconv=True) | ||
115 | |||
116 | params = self.__generate_params(locals(), ['remote', 'status', 'staff_only']) | ||
117 | |||
118 | if remote: | ||
119 | params["remote"] = True | ||
120 | |||
121 | mod_statuses = ["active", "pending", "disabled", "silenced", "suspended"] | ||
122 | if not status in mod_statuses: | ||
123 | raise ValueError("Invalid moderation status requested.") | ||
124 | |||
125 | if staff_only: | ||
126 | params["staff"] = True | ||
127 | |||
128 | for mod_status in mod_statuses: | ||
129 | if status == mod_status: | ||
130 | params[status] = True | ||
131 | |||
132 | if not by_domain is None: | ||
133 | by_domain = self.__deprotocolize(by_domain) | ||
134 | |||
135 | return self.__api_request('GET', '/api/v1/admin/accounts', params) | ||
136 | |||
137 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
138 | def admin_account(self, id): | ||
139 | """ | ||
140 | Fetches a single :ref:`admin account dict <admin account dict>` for the user with the given id. | ||
141 | |||
142 | Returns that dict. | ||
143 | """ | ||
144 | id = self.__unpack_id(id) | ||
145 | return self.__api_request('GET', '/api/v1/admin/accounts/{0}'.format(id)) | ||
146 | |||
147 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
148 | def admin_account_enable(self, id): | ||
149 | """ | ||
150 | Reenables login for a local account for which login has been disabled. | ||
151 | |||
152 | Returns the updated :ref:`admin account dict <admin account dict>`. | ||
153 | """ | ||
154 | id = self.__unpack_id(id) | ||
155 | return self.__api_request('POST', '/api/v1/admin/accounts/{0}/enable'.format(id)) | ||
156 | |||
157 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
158 | def admin_account_approve(self, id): | ||
159 | """ | ||
160 | Approves a pending account. | ||
161 | |||
162 | Returns the updated :ref:`admin account dict <admin account dict>`. | ||
163 | """ | ||
164 | id = self.__unpack_id(id) | ||
165 | return self.__api_request('POST', '/api/v1/admin/accounts/{0}/approve'.format(id)) | ||
166 | |||
167 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
168 | def admin_account_reject(self, id): | ||
169 | """ | ||
170 | Rejects and deletes a pending account. | ||
171 | |||
172 | Returns the updated :ref:`admin account dict <admin account dict>` for the account that is now gone. | ||
173 | """ | ||
174 | id = self.__unpack_id(id) | ||
175 | return self.__api_request('POST', '/api/v1/admin/accounts/{0}/reject'.format(id)) | ||
176 | |||
177 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
178 | def admin_account_unsilence(self, id): | ||
179 | """ | ||
180 | Unsilences an account. | ||
181 | |||
182 | Returns the updated :ref:`admin account dict <admin account dict>`. | ||
183 | """ | ||
184 | id = self.__unpack_id(id) | ||
185 | return self.__api_request('POST', '/api/v1/admin/accounts/{0}/unsilence'.format(id)) | ||
186 | |||
187 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_ADMIN_ACCOUNT) | ||
188 | def admin_account_unsuspend(self, id): | ||
189 | """ | ||
190 | Unsuspends an account. | ||
191 | |||
192 | Returns the updated :ref:`admin account dict <admin account dict>`. | ||
193 | """ | ||
194 | id = self.__unpack_id(id) | ||
195 | return self.__api_request('POST', '/api/v1/admin/accounts/{0}/unsuspend'.format(id)) | ||
196 | |||
197 | @api_version("3.3.0", "3.3.0", _DICT_VERSION_ADMIN_ACCOUNT) | ||
198 | def admin_account_delete(self, id): | ||
199 | """ | ||
200 | Delete a local user account. | ||
201 | |||
202 | The deleted accounts :ref:`admin account dict <admin account dict>`. | ||
203 | """ | ||
204 | id = self.__unpack_id(id) | ||
205 | return self.__api_request('DELETE', '/api/v1/admin/accounts/{0}'.format(id)) | ||
206 | |||
207 | @api_version("3.3.0", "3.3.0", _DICT_VERSION_ADMIN_ACCOUNT) | ||
208 | def admin_account_unsensitive(self, id): | ||
209 | """ | ||
210 | Unmark an account as force-sensitive. | ||
211 | |||
212 | Returns the updated :ref:`admin account dict <admin account dict>`. | ||
213 | """ | ||
214 | id = self.__unpack_id(id) | ||
215 | return self.__api_request('POST', '/api/v1/admin/accounts/{0}/unsensitive'.format(id)) | ||
216 | |||
217 | @api_version("2.9.1", "2.9.1", "2.9.1") | ||
218 | def admin_account_moderate(self, id, action=None, report_id=None, warning_preset_id=None, text=None, send_email_notification=True): | ||
219 | """ | ||
220 | Perform a moderation action on an account. | ||
221 | |||
222 | Valid actions are: | ||
223 | * "disable" - for a local user, disable login. | ||
224 | * "silence" - hide the users posts from all public timelines. | ||
225 | * "suspend" - irreversibly delete all the user's posts, past and future. | ||
226 | * "sensitive" - forcce an accounts media visibility to always be sensitive. | ||
227 | |||
228 | If no action is specified, the user is only issued a warning. | ||
229 | |||
230 | Specify the id of a report as `report_id` to close the report with this moderation action as the resolution. | ||
231 | Specify `warning_preset_id` to use a warning preset as the notification text to the user, or `text` to specify text directly. | ||
232 | If both are specified, they are concatenated (preset first). Note that there is currently no API to retrieve or create | ||
233 | warning presets. | ||
234 | |||
235 | Set `send_email_notification` to False to not send the user an email notification informing them of the moderation action. | ||
236 | """ | ||
237 | if action is None: | ||
238 | action = "none" | ||
239 | |||
240 | if not send_email_notification: | ||
241 | send_email_notification = None | ||
242 | |||
243 | id = self.__unpack_id(id) | ||
244 | if report_id is not None: | ||
245 | report_id = self.__unpack_id(report_id) | ||
246 | |||
247 | params = self.__generate_params(locals(), ['id', 'action']) | ||
248 | |||
249 | params["type"] = action | ||
250 | |||
251 | self.__api_request( | ||
252 | 'POST', '/api/v1/admin/accounts/{0}/action'.format(id), params) | ||
253 | |||
254 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_REPORT) | ||
255 | def admin_reports(self, resolved=False, account_id=None, target_account_id=None, max_id=None, min_id=None, since_id=None, limit=None): | ||
256 | """ | ||
257 | Fetches the list of reports. | ||
258 | |||
259 | Set `resolved` to True to search for resolved reports. `account_id` and `target_account_id` | ||
260 | can be used to get reports filed by or about a specific user. | ||
261 | |||
262 | Returns a list of :ref:`report dicts <report dicts>`. | ||
263 | """ | ||
264 | if max_id is not None: | ||
265 | max_id = self.__unpack_id(max_id, dateconv=True) | ||
266 | |||
267 | if min_id is not None: | ||
268 | min_id = self.__unpack_id(min_id, dateconv=True) | ||
269 | |||
270 | if since_id is not None: | ||
271 | since_id = self.__unpack_id(since_id, dateconv=True) | ||
272 | |||
273 | if account_id is not None: | ||
274 | account_id = self.__unpack_id(account_id) | ||
275 | |||
276 | if target_account_id is not None: | ||
277 | target_account_id = self.__unpack_id(target_account_id) | ||
278 | |||
279 | if not resolved: | ||
280 | resolved = None | ||
281 | |||
282 | params = self.__generate_params(locals()) | ||
283 | return self.__api_request('GET', '/api/v1/admin/reports', params) | ||
284 | |||
285 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_REPORT) | ||
286 | def admin_report(self, id): | ||
287 | """ | ||
288 | Fetches the report with the given id. | ||
289 | |||
290 | Returns a :ref:`report dict <report dict>`. | ||
291 | """ | ||
292 | id = self.__unpack_id(id) | ||
293 | return self.__api_request('GET', '/api/v1/admin/reports/{0}'.format(id)) | ||
294 | |||
295 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_REPORT) | ||
296 | def admin_report_assign(self, id): | ||
297 | """ | ||
298 | Assigns the given report to the logged-in user. | ||
299 | |||
300 | Returns the updated :ref:`report dict <report dict>`. | ||
301 | """ | ||
302 | id = self.__unpack_id(id) | ||
303 | return self.__api_request('POST', '/api/v1/admin/reports/{0}/assign_to_self'.format(id)) | ||
304 | |||
305 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_REPORT) | ||
306 | def admin_report_unassign(self, id): | ||
307 | """ | ||
308 | Unassigns the given report from the logged-in user. | ||
309 | |||
310 | Returns the updated :ref:`report dict <report dict>`. | ||
311 | """ | ||
312 | id = self.__unpack_id(id) | ||
313 | return self.__api_request('POST', '/api/v1/admin/reports/{0}/unassign'.format(id)) | ||
314 | |||
315 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_REPORT) | ||
316 | def admin_report_reopen(self, id): | ||
317 | """ | ||
318 | Reopens a closed report. | ||
319 | |||
320 | Returns the updated :ref:`report dict <report dict>`. | ||
321 | """ | ||
322 | id = self.__unpack_id(id) | ||
323 | return self.__api_request('POST', '/api/v1/admin/reports/{0}/reopen'.format(id)) | ||
324 | |||
325 | @api_version("2.9.1", "2.9.1", _DICT_VERSION_REPORT) | ||
326 | def admin_report_resolve(self, id): | ||
327 | """ | ||
328 | Marks a report as resolved (without taking any action). | ||
329 | |||
330 | Returns the updated :ref:`report dict <report dict>`. | ||
331 | """ | ||
332 | id = self.__unpack_id(id) | ||
333 | return self.__api_request('POST', '/api/v1/admin/reports/{0}/resolve'.format(id)) | ||
334 | |||
335 | @api_version("3.5.0", "3.5.0", _DICT_VERSION_HASHTAG) | ||
336 | def admin_trending_tags(self, limit=None): | ||
337 | """ | ||
338 | Admin version of :ref:`trending_tags() <trending_tags()>`. Includes unapproved tags. | ||
339 | |||
340 | Returns a list of :ref:`hashtag dicts <hashtag dicts>`, sorted by the instance's trending algorithm, | ||
341 | descending. | ||
342 | """ | ||
343 | params = self.__generate_params(locals()) | ||
344 | return self.__api_request('GET', '/api/v1/admin/trends/tags', params) | ||
345 | |||
346 | @api_version("3.5.0", "3.5.0", _DICT_VERSION_STATUS) | ||
347 | def admin_trending_statuses(self): | ||
348 | """ | ||
349 | Admin version of :ref:`trending_statuses() <trending_statuses()>`. Includes unapproved tags. | ||
350 | |||
351 | Returns a list of :ref:`status dicts <status dicts>`, sorted by the instance's trending algorithm, | ||
352 | descending. | ||
353 | """ | ||
354 | params = self.__generate_params(locals()) | ||
355 | return self.__api_request('GET', '/api/v1/admin/trends/statuses', params) | ||
356 | |||
357 | @api_version("3.5.0", "3.5.0", _DICT_VERSION_CARD) | ||
358 | def admin_trending_links(self): | ||
359 | """ | ||
360 | Admin version of :ref:`trending_links() <trending_links()>`. Includes unapproved tags. | ||
361 | |||
362 | Returns a list of :ref:`card dicts <card dicts>`, sorted by the instance's trending algorithm, | ||
363 | descending. | ||
364 | """ | ||
365 | params = self.__generate_params(locals()) | ||
366 | return self.__api_request('GET', '/api/v1/admin/trends/links', params) | ||
367 | |||
368 | @api_version("4.0.0", "4.0.0", _DICT_VERSION_ADMIN_DOMAIN_BLOCK) | ||
369 | def admin_domain_blocks(self, id=None, limit:int=None): | ||
370 | """ | ||
371 | Fetches a list of blocked domains. Requires scope `admin:read:domain_blocks`. | ||
372 | |||
373 | Provide an `id` to fetch a specific domain block based on its database id. | ||
374 | |||
375 | Returns a list of :ref:`admin domain block dicts <admin domain block dicts>`, raises a `MastodonAPIError` if the specified block does not exist. | ||
376 | """ | ||
377 | if id is not None: | ||
378 | id = self.__unpack_id(id) | ||
379 | return self.__api_request('GET', '/api/v1/admin/domain_blocks/{0}'.format(id)) | ||
380 | else: | ||
381 | params = self.__generate_params(locals(),['limit']) | ||
382 | return self.__api_request('GET', '/api/v1/admin/domain_blocks/', params) | ||
383 | |||
384 | @api_version("4.0.0", "4.0.0", _DICT_VERSION_ADMIN_DOMAIN_BLOCK) | ||
385 | 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): | ||
386 | """ | ||
387 | Perform a moderation action on a domain. Requires scope `admin:write:domain_blocks`. | ||
388 | |||
389 | Valid severities are: | ||
390 | * "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. | ||
391 | * "suspend" - deny interactions with this instance going forward. This action is reversible. | ||
392 | * "limit" - generally used with reject_media=true to force reject media from an instance without silencing or suspending.. | ||
393 | |||
394 | If no action is specified, the domain is only silenced. | ||
395 | `domain` is the domain to block. Note that using the top level domain will also imapct all subdomains. ie, example.com will also impact subdomain.example.com. | ||
396 | `reject_media` will not download remote media on to your local instance media storage. | ||
397 | `reject_reports` ignores all reports from the remote instance. | ||
398 | `private_comment` sets a private admin comment for the domain. | ||
399 | `public_comment` sets a publicly available comment for this domain, which will be available to local users and may be available to everyone depending on your settings. | ||
400 | `obfuscate` censors some part of the domain name. Useful if the domain name contains unwanted words like slurs. | ||
401 | |||
402 | Returns the new domain block as an :ref:`admin domain block dict <admin domain block dict>`. | ||
403 | """ | ||
404 | if domain is None: | ||
405 | raise AttributeError("Must provide a domain to block a domain") | ||
406 | params = self.__generate_params(locals()) | ||
407 | return self.__api_request('POST', '/api/v1/admin/domain_blocks/', params) | ||
408 | |||
409 | @api_version("4.0.0", "4.0.0", _DICT_VERSION_ADMIN_DOMAIN_BLOCK) | ||
410 | def admin_update_domain_block(self, id, severity:str=None, reject_media:bool=None, reject_reports:bool=None, private_comment:str=None, public_comment:str=None, obfuscate:bool=None): | ||
411 | """ | ||
412 | Modify existing moderation action on a domain. Requires scope `admin:write:domain_blocks`. | ||
413 | |||
414 | Valid severities are: | ||
415 | * "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. | ||
416 | * "suspend" - deny interactions with this instance going forward. This action is reversible. | ||
417 | * "limit" - generally used with reject_media=true to force reject media from an instance without silencing or suspending. | ||
418 | |||
419 | If no action is specified, the domain is only silenced. | ||
420 | `domain` is the domain to block. Note that using the top level domain will also imapct all subdomains. ie, example.com will also impact subdomain.example.com. | ||
421 | `reject_media` will not download remote media on to your local instance media storage. | ||
422 | `reject_reports` ignores all reports from the remote instance. | ||
423 | `private_comment` sets a private admin comment for the domain. | ||
424 | `public_comment` sets a publicly available comment for this domain, which will be available to local users and may be available to everyone depending on your settings. | ||
425 | `obfuscate` censors some part of the domain name. Useful if the domain name contains unwanted words like slurs. | ||
426 | |||
427 | Returns the modified domain block as an :ref:`admin domain block dict <admin domain block dict>`, raises a `MastodonAPIError` if the specified block does not exist. | ||
428 | """ | ||
429 | if id is None: | ||
430 | raise AttributeError("Must provide an id to modify the existing moderation actions on a given domain.") | ||
431 | id = self.__unpack_id(id) | ||
432 | params = self.__generate_params(locals(), ["id"]) | ||
433 | return self.__api_request('PUT', '/api/v1/admin/domain_blocks/{0}'.format(id), params) | ||
434 | |||
435 | @api_version("4.0.0", "4.0.0", _DICT_VERSION_ADMIN_DOMAIN_BLOCK) | ||
436 | def admin_delete_domain_block(self, id=None): | ||
437 | """ | ||
438 | Removes moderation action against a given domain. Requires scope `admin:write:domain_blocks`. | ||
439 | |||
440 | Provide an `id` to remove a specific domain block based on its database id. | ||
441 | |||
442 | Raises a `MastodonAPIError` if the specified block does not exist. | ||
443 | """ | ||
444 | if id is not None: | ||
445 | id = self.__unpack_id(id) | ||
446 | self.__api_request('DELETE', '/api/v1/admin/domain_blocks/{0}'.format(id)) | ||
447 | else: | ||
448 | raise AttributeError("You must provide an id of an existing domain block to remove it.") | ||
449 | |||
450 | @api_version("3.5.0", "3.5.0", _DICT_VERSION_ADMIN_MEASURE) | ||
451 | def admin_measures(self, start_at, end_at, active_users=False, new_users=False, interactions=False, opened_reports = False, resolved_reports=False, | ||
452 | tag_accounts=None, tag_uses=None, tag_servers=None, instance_accounts=None, instance_media_attachments=None, instance_reports=None, | ||
453 | instance_statuses=None, instance_follows=None, instance_followers=None): | ||
454 | """ | ||
455 | Retrieves numerical instance information for the time period (at day granularity) between `start_at` and `end_at`. | ||
456 | |||
457 | * `active_users`: Pass true to retrieve the number of active users on your instance within the time period | ||
458 | * `new_users`: Pass true to retrieve the number of users who joined your instance within the time period | ||
459 | * `interactions`: Pass true to retrieve the number of interactions (favourites, boosts, replies) on local statuses within the time period | ||
460 | * `opened_reports`: Pass true to retrieve the number of reports filed within the time period | ||
461 | * `resolved_reports` = Pass true to retrieve the number of reports resolved within the time period | ||
462 | * `tag_accounts`: Pass a tag ID to get the number of accounts which used that tag in at least one status within the time period | ||
463 | * `tag_uses`: Pass a tag ID to get the number of statuses which used that tag within the time period | ||
464 | * `tag_servers`: Pass a tag ID to to get the number of remote origin servers for statuses which used that tag within the time period | ||
465 | * `instance_accounts`: Pass a domain to get the number of accounts originating from that remote domain within the time period | ||
466 | * `instance_media_attachments`: Pass a domain to get the amount of space used by media attachments from that remote domain within the time period | ||
467 | * `instance_reports`: Pass a domain to get the number of reports filed against accounts from that remote domain within the time period | ||
468 | * `instance_statuses`: Pass a domain to get the number of statuses originating from that remote domain within the time period | ||
469 | * `instance_follows`: Pass a domain to get the number of accounts from a remote domain followed by that local user within the time period | ||
470 | * `instance_followers`: Pass a domain to get the number of local accounts followed by accounts from that remote domain within the time period | ||
471 | |||
472 | This API call is relatively expensive - watch your servers load if you want to get a lot of statistical data. Especially the instance_statuses stats | ||
473 | might take a long time to compute and, in fact, time out. | ||
474 | |||
475 | There is currently no way to get tag IDs implemented in Mastodon.py, because the Mastodon public API does not implement one. This will be fixed in a future | ||
476 | release. | ||
477 | |||
478 | Returns a list of :ref:`admin measure dicts <admin measure dicts>`. | ||
479 | """ | ||
480 | params_init = locals() | ||
481 | keys = [] | ||
482 | for key in ["active_users", "new_users", "interactions", "opened_reports", "resolved_reports"]: | ||
483 | if params_init[key] == True: | ||
484 | keys.append(key) | ||
485 | |||
486 | params = {} | ||
487 | for key in ["tag_accounts", "tag_uses", "tag_servers"]: | ||
488 | if params_init[key] is not None: | ||
489 | keys.append(key) | ||
490 | params[key] = {"id": self.__unpack_id(params_init[key])} | ||
491 | for key in ["instance_accounts", "instance_media_attachments", "instance_reports", "instance_statuses", "instance_follows", "instance_followers"]: | ||
492 | if params_init[key] is not None: | ||
493 | keys.append(key) | ||
494 | params[key] = {"domain": Mastodon.__deprotocolize(params_init[key]).split("/")[0]} | ||
495 | |||
496 | if len(keys) == 0: | ||
497 | raise MastodonIllegalArgumentError("Must request at least one metric.") | ||
498 | |||
499 | params["keys"] = keys | ||
500 | params["start_at"] = self.__consistent_isoformat_utc(start_at) | ||
501 | params["end_at"] = self.__consistent_isoformat_utc(end_at) | ||
502 | |||
503 | return self.__api_request('POST', '/api/v1/admin/measures', params, use_json=True) | ||
504 | |||
505 | @api_version("3.5.0", "3.5.0", _DICT_VERSION_ADMIN_DIMENSION) | ||
506 | def admin_dimensions(self, start_at, end_at, limit=None, languages=False, sources=False, servers=False, space_usage=False, software_versions=False, | ||
507 | tag_servers=None, tag_languages=None, instance_accounts=None, instance_languages=None): | ||
508 | """ | ||
509 | Retrieves primarily categorical instance information for the time period (at day granularity) between `start_at` and `end_at`. | ||
510 | |||
511 | * `languages`: Pass true to get the most-used languages on this server | ||
512 | * `sources`: Pass true to get the most-used client apps on this server | ||
513 | * `servers`: Pass true to get the remote servers with the most statuses | ||
514 | * `space_usage`: Pass true to get the how much space is used by different components your software stack | ||
515 | * `software_versions`: Pass true to get the version numbers for your software stack | ||
516 | * `tag_servers`: Pass a tag ID to get the most-common servers for statuses including a trending tag | ||
517 | * `tag_languages`: Pass a tag ID to get the most-used languages for statuses including a trending tag | ||
518 | * `instance_accounts`: Pass a domain to get the most-followed accounts from a remote server | ||
519 | * `instance_languages`: Pass a domain to get the most-used languages from a remote server | ||
520 | |||
521 | Pass `limit` to set how many results you want on queries where that makes sense. | ||
522 | |||
523 | This API call is relatively expensive - watch your servers load if you want to get a lot of statistical data. | ||
524 | |||
525 | There is currently no way to get tag IDs implemented in Mastodon.py, because the Mastodon public API does not implement one. This will be fixed in a future | ||
526 | release. | ||
527 | |||
528 | Returns a list of :ref:`admin dimension dicts <admin dimension dicts>`. | ||
529 | """ | ||
530 | params_init = locals() | ||
531 | keys = [] | ||
532 | for key in ["languages", "sources", "servers", "space_usage", "software_versions"]: | ||
533 | if params_init[key] == True: | ||
534 | keys.append(key) | ||
535 | |||
536 | params = {} | ||
537 | for key in ["tag_servers", "tag_languages"]: | ||
538 | if params_init[key] is not None: | ||
539 | keys.append(key) | ||
540 | params[key] = {"id": self.__unpack_id(params_init[key])} | ||
541 | for key in ["instance_accounts", "instance_languages"]: | ||
542 | if params_init[key] is not None: | ||
543 | keys.append(key) | ||
544 | params[key] = {"domain": Mastodon.__deprotocolize(params_init[key]).split("/")[0]} | ||
545 | |||
546 | if len(keys) == 0: | ||
547 | raise MastodonIllegalArgumentError("Must request at least one dimension.") | ||
548 | |||
549 | params["keys"] = keys | ||
550 | if limit is not None: | ||
551 | params["limit"] = limit | ||
552 | params["start_at"] = self.__consistent_isoformat_utc(start_at) | ||
553 | params["end_at"] = self.__consistent_isoformat_utc(end_at) | ||
554 | |||
555 | return self.__api_request('POST', '/api/v1/admin/dimensions', params, use_json=True) | ||
556 | |||
557 | @api_version("3.5.0", "3.5.0", _DICT_VERSION_ADMIN_RETENTION) | ||
558 | def admin_retention(self, start_at, end_at, frequency="day"): | ||
559 | """ | ||
560 | Gets user retention statistics (at `frequency` - "day" or "month" - granularity) between `start_at` and `end_at`. | ||
561 | |||
562 | Returns a list of :ref:`admin retention dicts <admin retention dicts>` | ||
563 | """ | ||
564 | if not frequency in ["day", "month"]: | ||
565 | raise MastodonIllegalArgumentError("Frequency must be day or month") | ||
566 | |||
567 | params = { | ||
568 | "start_at": self.__consistent_isoformat_utc(start_at), | ||
569 | "end_at": self.__consistent_isoformat_utc(end_at), | ||
570 | "frequency": frequency | ||
571 | } | ||
572 | return self.__api_request('POST', '/api/v1/admin/retention', params) \ No newline at end of file | ||