aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhalcy <halcy@ARARAGI-KUN>2022-11-27 02:43:22 +0200
committerhalcy <halcy@ARARAGI-KUN>2022-11-27 02:43:22 +0200
commit5cf0fa27a95f8c56280ea429dd1d57529fc490ee (patch)
tree26e4485d4e69052bc53c151ba807b8260185a419 /mastodon
parent7331f7774ae10d927e086318338989de6bc37cad (diff)
downloadmastodon.py-5cf0fa27a95f8c56280ea429dd1d57529fc490ee.tar.gz
add admin stats APIs
Diffstat (limited to 'mastodon')
-rw-r--r--mastodon/Mastodon.py139
1 files changed, 135 insertions, 4 deletions
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py
index 82e058c..03aa413 100644
--- a/mastodon/Mastodon.py
+++ b/mastodon/Mastodon.py
@@ -108,7 +108,6 @@ def api_version(created_ver, last_changed_ver, return_value_ver):
108 raise MastodonVersionError( 108 raise MastodonVersionError(
109 "Version check failed (Need version " + version + ")") 109 "Version check failed (Need version " + version + ")")
110 elif major == self.mastodon_major and minor > self.mastodon_minor: 110 elif major == self.mastodon_major and minor > self.mastodon_minor:
111 print(self.mastodon_minor)
112 raise MastodonVersionError( 111 raise MastodonVersionError(
113 "Version check failed (Need version " + version + ")") 112 "Version check failed (Need version " + version + ")")
114 elif major == self.mastodon_major and minor == self.mastodon_minor and patch > self.mastodon_patch: 113 elif major == self.mastodon_major and minor == self.mastodon_minor and patch > self.mastodon_patch:
@@ -264,6 +263,9 @@ class Mastodon:
264 __DICT_VERSION_ANNOUNCEMENT = bigger_version("3.1.0", __DICT_VERSION_REACTION) 263 __DICT_VERSION_ANNOUNCEMENT = bigger_version("3.1.0", __DICT_VERSION_REACTION)
265 __DICT_VERSION_STATUS_EDIT = "3.5.0" 264 __DICT_VERSION_STATUS_EDIT = "3.5.0"
266 __DICT_VERSION_ADMIN_DOMAIN_BLOCK = "4.0.0" 265 __DICT_VERSION_ADMIN_DOMAIN_BLOCK = "4.0.0"
266 __DICT_VERSION_ADMIN_MEASURE = "3.5.0"
267 __DICT_VERSION_ADMIN_DIMENSION = "3.5.0"
268 __DICT_VERSION_ADMIN_RETENTION = "3.5.0"
267 269
268 ### 270 ###
269 # Registering apps 271 # Registering apps
@@ -432,7 +434,6 @@ class Mastodon:
432 try_base_url = secret_file.readline().rstrip() 434 try_base_url = secret_file.readline().rstrip()
433 if try_base_url is not None and len(try_base_url) != 0: 435 if try_base_url is not None and len(try_base_url) != 0:
434 try_base_url = Mastodon.__protocolize(try_base_url) 436 try_base_url = Mastodon.__protocolize(try_base_url)
435 print(self.api_base_url, try_base_url)
436 if not (self.api_base_url is None or try_base_url == self.api_base_url): 437 if not (self.api_base_url is None or try_base_url == self.api_base_url):
437 raise MastodonIllegalArgumentError('Mismatch in base URLs between files and/or specified') 438 raise MastodonIllegalArgumentError('Mismatch in base URLs between files and/or specified')
438 self.api_base_url = try_base_url 439 self.api_base_url = try_base_url
@@ -544,7 +545,6 @@ class Mastodon:
544 We parse this from the hopefully present "Date" header, but make no effort to compensate for latency. 545 We parse this from the hopefully present "Date" header, but make no effort to compensate for latency.
545 """ 546 """
546 response = self.__api_request("HEAD", "/", return_response_object=True) 547 response = self.__api_request("HEAD", "/", return_response_object=True)
547 print(response.headers)
548 if 'Date' in response.headers: 548 if 'Date' in response.headers:
549 server_time_datetime = dateutil.parser.parse(response.headers['Date']) 549 server_time_datetime = dateutil.parser.parse(response.headers['Date'])
550 550
@@ -3456,6 +3456,130 @@ class Mastodon:
3456 else: 3456 else:
3457 raise AttributeError("You must provide an id of an existing domain block to remove it.") 3457 raise AttributeError("You must provide an id of an existing domain block to remove it.")
3458 3458
3459 @api_version("3.5.0", "3.5.0", __DICT_VERSION_ADMIN_MEASURE)
3460 def admin_measures(self, start_at, end_at, active_users=False, new_users=False, interactions=False, opened_reports = False, resolved_reports=False,
3461 tag_accounts=None, tag_uses=None, tag_servers=None, instance_accounts=None, instance_media_attachments=None, instance_reports=None,
3462 instance_statuses=None, instance_follows=None, instance_followers=None):
3463 """
3464 Retrieves numerical instance information for the time period (at day granularity) between `start_at` and `end_at`.
3465
3466 * `active_users`: Pass true to retrieve the number of active users on your instance within the time period
3467 * `new_users`: Pass true to retrieve the number of users who joined your instance within the time period
3468 * `interactions`: Pass true to retrieve the number of interactions (favourites, boosts, replies) on local statuses within the time period
3469 * `opened_reports`: Pass true to retrieve the number of reports filed within the time period
3470 * `resolved_reports` = Pass true to retrieve the number of reports resolved within the time period
3471 * `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
3472 * `tag_uses`: Pass a tag ID to get the number of statuses which used that tag within the time period
3473 * `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
3474 * `instance_accounts`: Pass a domain to get the number of accounts originating from that remote domain within the time period
3475 * `instance_media_attachments`: Pass a domain to get the amount of space used by media attachments from that remote domain within the time period
3476 * `instance_reports`: Pass a domain to get the number of reports filed against accounts from that remote domain within the time period
3477 * `instance_statuses`: Pass a domain to get the number of statuses originating from that remote domain within the time period
3478 * `instance_follows`: Pass a domain to get the number of accounts from a remote domain followed by that local user within the time period
3479 * `instance_followers`: Pass a domain to get the number of local accounts followed by accounts from that remote domain within the time period
3480
3481 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
3482 might take a long time to compute and, in fact, time out.
3483
3484 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
3485 release.
3486
3487 Returns a list of `admin measure dicts`_.
3488 """
3489 params_init = locals()
3490 keys = []
3491 for key in ["active_users", "new_users", "interactions", "opened_reports", "resolved_reports"]:
3492 if params_init[key] == True:
3493 keys.append(key)
3494
3495 params = {}
3496 for key in ["tag_accounts", "tag_uses", "tag_servers"]:
3497 if params_init[key] is not None:
3498 keys.append(key)
3499 params[key] = {"id": self.__unpack_id(params_init[key])}
3500 for key in ["instance_accounts", "instance_media_attachments", "instance_reports", "instance_statuses", "instance_follows", "instance_followers"]:
3501 if params_init[key] is not None:
3502 keys.append(key)
3503 params[key] = {"domain": Mastodon.__deprotocolize(params_init[key]).split("/")[0]}
3504
3505 if len(keys) == 0:
3506 raise MastodonIllegalArgumentError("Must request at least one metric.")
3507
3508 params["keys"] = keys
3509 params["start_at"] = self.__consistent_isoformat_utc(start_at)
3510 params["end_at"] = self.__consistent_isoformat_utc(end_at)
3511
3512 return self.__api_request('POST', '/api/v1/admin/measures', params, use_json=True)
3513
3514 @api_version("3.5.0", "3.5.0", __DICT_VERSION_ADMIN_DIMENSION)
3515 def admin_dimensions(self, start_at, end_at, limit=None, languages=False, sources=False, servers=False, space_usage=False, software_versions=False,
3516 tag_servers=None, tag_languages=None, instance_accounts=None, instance_languages=None):
3517 """
3518 Retrieves primarily categorical instance information for the time period (at day granularity) between `start_at` and `end_at`.
3519
3520 * `languages`: Pass true to get the most-used languages on this server
3521 * `sources`: Pass true to get the most-used client apps on this server
3522 * `servers`: Pass true to get the remote servers with the most statuses
3523 * `space_usage`: Pass true to get the how much space is used by different components your software stack
3524 * `software_versions`: Pass true to get the version numbers for your software stack
3525 * `tag_servers`: Pass a tag ID to get the most-common servers for statuses including a trending tag
3526 * `tag_languages`: Pass a tag ID to get the most-used languages for statuses including a trending tag
3527 * `instance_accounts`: Pass a domain to get the most-followed accounts from a remote server
3528 * `instance_languages`: Pass a domain to get the most-used languages from a remote server
3529
3530 Pass `limit` to set how many results you want on queries where that makes sense.
3531
3532 This API call is relatively expensive - watch your servers load if you want to get a lot of statistical data.
3533
3534 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
3535 release.
3536
3537 Returns a list of `admin dimensions dicts`_.
3538 """
3539 params_init = locals()
3540 keys = []
3541 for key in ["languages", "sources", "servers", "space_usage", "software_versions"]:
3542 if params_init[key] == True:
3543 keys.append(key)
3544
3545 params = {}
3546 for key in ["tag_servers", "tag_languages"]:
3547 if params_init[key] is not None:
3548 keys.append(key)
3549 params[key] = {"id": self.__unpack_id(params_init[key])}
3550 for key in ["instance_accounts", "instance_languages"]:
3551 if params_init[key] is not None:
3552 keys.append(key)
3553 params[key] = {"domain": Mastodon.__deprotocolize(params_init[key]).split("/")[0]}
3554
3555 if len(keys) == 0:
3556 raise MastodonIllegalArgumentError("Must request at least one dimension.")
3557
3558 params["keys"] = keys
3559 if limit is not None:
3560 params["limit"] = limit
3561 params["start_at"] = self.__consistent_isoformat_utc(start_at)
3562 params["end_at"] = self.__consistent_isoformat_utc(end_at)
3563
3564 return self.__api_request('POST', '/api/v1/admin/dimensions', params, use_json=True)
3565
3566 @api_version("3.5.0", "3.5.0", __DICT_VERSION_ADMIN_RETENTION)
3567 def admin_retention(self, start_at, end_at, frequency="day"):
3568 """
3569 Gets user retention statistics (at `frequency` - "day" or "month" - granularity) between `start_at` and `end_at`.
3570
3571 Returns a list of `admin retention dicts`_
3572 """
3573 if not frequency in ["day", "month"]:
3574 raise MastodonIllegalArgumentError("Frequency must be day or month")
3575
3576 params = {
3577 "start_at": self.__consistent_isoformat_utc(start_at),
3578 "end_at": self.__consistent_isoformat_utc(end_at),
3579 "frequency": frequency
3580 }
3581 return self.__api_request('POST', '/api/v1/admin/retention', params)
3582
3459 ### 3583 ###
3460 # Push subscription crypto utilities 3584 # Push subscription crypto utilities
3461 ### 3585 ###
@@ -3942,7 +4066,6 @@ class Mastodon:
3942 if not response_object.ok: 4066 if not response_object.ok:
3943 try: 4067 try:
3944 response = response_object.json(object_hook=self.__json_hooks) 4068 response = response_object.json(object_hook=self.__json_hooks)
3945 print(response)
3946 if isinstance(response, dict) and 'error' in response: 4069 if isinstance(response, dict) and 'error' in response:
3947 error_msg = response['error'] 4070 error_msg = response['error']
3948 elif isinstance(response, str): 4071 elif isinstance(response, str):
@@ -4348,6 +4471,14 @@ class Mastodon:
4348 base_url = base_url.rstrip("/") 4471 base_url = base_url.rstrip("/")
4349 return base_url 4472 return base_url
4350 4473
4474 @staticmethod
4475 def __deprotocolize(base_url):
4476 """Internal helper to strip http and https from a URL"""
4477 if base_url.startswith("http://"):
4478 base_url = base_url[7:]
4479 elif base_url.startswith("https://") or base_url.startswith("onion://"):
4480 base_url = base_url[8:]
4481 return base_url
4351 4482
4352## 4483##
4353# Exceptions 4484# Exceptions
Powered by cgit v1.2.3 (git 2.41.0)