kopia lustrzana https://github.com/halcy/Mastodon.py
add admin stats APIs
rodzic
7331f7774a
commit
5cf0fa27a9
4
TODO.md
4
TODO.md
|
@ -44,7 +44,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m
|
|||
* [x] Add support for incoming edited posts
|
||||
* [x] Add notifications for posts deleted by moderators <- by email. not actually API relevant.
|
||||
* [x] Add explore page with trending posts and links
|
||||
* [ ] Add graphs and retention metrics to admin dashboard
|
||||
* [x] Add graphs and retention metrics to admin dashboard
|
||||
* [ ] Add GET /api/v1/accounts/familiar_followers to REST API
|
||||
* [ ] Add POST /api/v1/accounts/:id/remove_from_followers to REST API
|
||||
* [x] Add category and rule_ids params to POST /api/v1/reports IN REST API
|
||||
|
@ -55,7 +55,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m
|
|||
|
||||
3.5.3
|
||||
-----
|
||||
* [ ] Add limited attribute to accounts in REST API
|
||||
* [later with tool to update dicts] Add limited attribute to accounts in REST API
|
||||
|
||||
4.0.0 and beyond
|
||||
----------------
|
||||
|
|
|
@ -345,6 +345,18 @@ Toot dicts
|
|||
'poll': # A poll dict if a poll is attached to this status.
|
||||
}
|
||||
|
||||
Status edit dicts
|
||||
~~~~~~~~~~~~~~~~~
|
||||
.. _status edit dict:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
mastodonstatus_history(id)[0]
|
||||
# Returns the following dictionary
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
Mention dicts
|
||||
~~~~~~~~~~~~~
|
||||
.. _mention dict:
|
||||
|
@ -902,13 +914,37 @@ Admin domain block dicts
|
|||
'obfuscate': #Boolean. True if domain name is obfuscated when listing.
|
||||
}
|
||||
|
||||
Status edit dicts
|
||||
~~~~~~~~~~~~~~~~~
|
||||
.. _status edit dict:
|
||||
Admin measure dicts
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
.. _admin measure dict:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
mastodonstatus_history(id)[0]
|
||||
api.admin_measures(datetime.now() - timedelta(hours=24*5), datetime.now(), active_users=True)
|
||||
# Returns the following dictionary
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
Admin dimension dicts
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
.. _admin dimension dict:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
api.admin_dimensions(datetime.now() - timedelta(hours=24*5), datetime.now(), languages=True)
|
||||
# Returns the following dictionary
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
Admin retention dicts
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
.. _admin retention dict:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
api.admin_retention(datetime.now() - timedelta(hours=24*5), datetime.now())
|
||||
# Returns the following dictionary
|
||||
{
|
||||
TODO
|
||||
|
@ -1471,6 +1507,11 @@ have admin: scopes attached with a lot of care, but be extra careful with those
|
|||
.. automethod:: Mastodon.admin_update_domain_block
|
||||
.. automethod:: Mastodon.admin_delete_domain_block
|
||||
|
||||
.. automethod:: Mastodon.admin_measures
|
||||
.. automethod:: Mastodon.admin_dimensions
|
||||
.. automethod:: Mastodon.admin_retention
|
||||
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
Mastodon.py contains work by a large number of contributors, many of which have
|
||||
|
|
|
@ -108,7 +108,6 @@ def api_version(created_ver, last_changed_ver, return_value_ver):
|
|||
raise MastodonVersionError(
|
||||
"Version check failed (Need version " + version + ")")
|
||||
elif major == self.mastodon_major and minor > self.mastodon_minor:
|
||||
print(self.mastodon_minor)
|
||||
raise MastodonVersionError(
|
||||
"Version check failed (Need version " + version + ")")
|
||||
elif major == self.mastodon_major and minor == self.mastodon_minor and patch > self.mastodon_patch:
|
||||
|
@ -264,6 +263,9 @@ class Mastodon:
|
|||
__DICT_VERSION_ANNOUNCEMENT = bigger_version("3.1.0", __DICT_VERSION_REACTION)
|
||||
__DICT_VERSION_STATUS_EDIT = "3.5.0"
|
||||
__DICT_VERSION_ADMIN_DOMAIN_BLOCK = "4.0.0"
|
||||
__DICT_VERSION_ADMIN_MEASURE = "3.5.0"
|
||||
__DICT_VERSION_ADMIN_DIMENSION = "3.5.0"
|
||||
__DICT_VERSION_ADMIN_RETENTION = "3.5.0"
|
||||
|
||||
###
|
||||
# Registering apps
|
||||
|
@ -432,7 +434,6 @@ class Mastodon:
|
|||
try_base_url = secret_file.readline().rstrip()
|
||||
if try_base_url is not None and len(try_base_url) != 0:
|
||||
try_base_url = Mastodon.__protocolize(try_base_url)
|
||||
print(self.api_base_url, try_base_url)
|
||||
if not (self.api_base_url is None or try_base_url == self.api_base_url):
|
||||
raise MastodonIllegalArgumentError('Mismatch in base URLs between files and/or specified')
|
||||
self.api_base_url = try_base_url
|
||||
|
@ -544,7 +545,6 @@ class Mastodon:
|
|||
We parse this from the hopefully present "Date" header, but make no effort to compensate for latency.
|
||||
"""
|
||||
response = self.__api_request("HEAD", "/", return_response_object=True)
|
||||
print(response.headers)
|
||||
if 'Date' in response.headers:
|
||||
server_time_datetime = dateutil.parser.parse(response.headers['Date'])
|
||||
|
||||
|
@ -3456,6 +3456,130 @@ class Mastodon:
|
|||
else:
|
||||
raise AttributeError("You must provide an id of an existing domain block to remove it.")
|
||||
|
||||
@api_version("3.5.0", "3.5.0", __DICT_VERSION_ADMIN_MEASURE)
|
||||
def admin_measures(self, start_at, end_at, active_users=False, new_users=False, interactions=False, opened_reports = False, resolved_reports=False,
|
||||
tag_accounts=None, tag_uses=None, tag_servers=None, instance_accounts=None, instance_media_attachments=None, instance_reports=None,
|
||||
instance_statuses=None, instance_follows=None, instance_followers=None):
|
||||
"""
|
||||
Retrieves numerical instance information for the time period (at day granularity) between `start_at` and `end_at`.
|
||||
|
||||
* `active_users`: Pass true to retrieve the number of active users on your instance within the time period
|
||||
* `new_users`: Pass true to retrieve the number of users who joined your instance within the time period
|
||||
* `interactions`: Pass true to retrieve the number of interactions (favourites, boosts, replies) on local statuses within the time period
|
||||
* `opened_reports`: Pass true to retrieve the number of reports filed within the time period
|
||||
* `resolved_reports` = Pass true to retrieve the number of reports resolved within the time period
|
||||
* `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
|
||||
* `tag_uses`: Pass a tag ID to get the number of statuses which used that tag within the time period
|
||||
* `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
|
||||
* `instance_accounts`: Pass a domain to get the number of accounts originating from that remote domain within the time period
|
||||
* `instance_media_attachments`: Pass a domain to get the amount of space used by media attachments from that remote domain within the time period
|
||||
* `instance_reports`: Pass a domain to get the number of reports filed against accounts from that remote domain within the time period
|
||||
* `instance_statuses`: Pass a domain to get the number of statuses originating from that remote domain within the time period
|
||||
* `instance_follows`: Pass a domain to get the number of accounts from a remote domain followed by that local user within the time period
|
||||
* `instance_followers`: Pass a domain to get the number of local accounts followed by accounts from that remote domain within the time period
|
||||
|
||||
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
|
||||
might take a long time to compute and, in fact, time out.
|
||||
|
||||
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
|
||||
release.
|
||||
|
||||
Returns a list of `admin measure dicts`_.
|
||||
"""
|
||||
params_init = locals()
|
||||
keys = []
|
||||
for key in ["active_users", "new_users", "interactions", "opened_reports", "resolved_reports"]:
|
||||
if params_init[key] == True:
|
||||
keys.append(key)
|
||||
|
||||
params = {}
|
||||
for key in ["tag_accounts", "tag_uses", "tag_servers"]:
|
||||
if params_init[key] is not None:
|
||||
keys.append(key)
|
||||
params[key] = {"id": self.__unpack_id(params_init[key])}
|
||||
for key in ["instance_accounts", "instance_media_attachments", "instance_reports", "instance_statuses", "instance_follows", "instance_followers"]:
|
||||
if params_init[key] is not None:
|
||||
keys.append(key)
|
||||
params[key] = {"domain": Mastodon.__deprotocolize(params_init[key]).split("/")[0]}
|
||||
|
||||
if len(keys) == 0:
|
||||
raise MastodonIllegalArgumentError("Must request at least one metric.")
|
||||
|
||||
params["keys"] = keys
|
||||
params["start_at"] = self.__consistent_isoformat_utc(start_at)
|
||||
params["end_at"] = self.__consistent_isoformat_utc(end_at)
|
||||
|
||||
return self.__api_request('POST', '/api/v1/admin/measures', params, use_json=True)
|
||||
|
||||
@api_version("3.5.0", "3.5.0", __DICT_VERSION_ADMIN_DIMENSION)
|
||||
def admin_dimensions(self, start_at, end_at, limit=None, languages=False, sources=False, servers=False, space_usage=False, software_versions=False,
|
||||
tag_servers=None, tag_languages=None, instance_accounts=None, instance_languages=None):
|
||||
"""
|
||||
Retrieves primarily categorical instance information for the time period (at day granularity) between `start_at` and `end_at`.
|
||||
|
||||
* `languages`: Pass true to get the most-used languages on this server
|
||||
* `sources`: Pass true to get the most-used client apps on this server
|
||||
* `servers`: Pass true to get the remote servers with the most statuses
|
||||
* `space_usage`: Pass true to get the how much space is used by different components your software stack
|
||||
* `software_versions`: Pass true to get the version numbers for your software stack
|
||||
* `tag_servers`: Pass a tag ID to get the most-common servers for statuses including a trending tag
|
||||
* `tag_languages`: Pass a tag ID to get the most-used languages for statuses including a trending tag
|
||||
* `instance_accounts`: Pass a domain to get the most-followed accounts from a remote server
|
||||
* `instance_languages`: Pass a domain to get the most-used languages from a remote server
|
||||
|
||||
Pass `limit` to set how many results you want on queries where that makes sense.
|
||||
|
||||
This API call is relatively expensive - watch your servers load if you want to get a lot of statistical data.
|
||||
|
||||
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
|
||||
release.
|
||||
|
||||
Returns a list of `admin dimensions dicts`_.
|
||||
"""
|
||||
params_init = locals()
|
||||
keys = []
|
||||
for key in ["languages", "sources", "servers", "space_usage", "software_versions"]:
|
||||
if params_init[key] == True:
|
||||
keys.append(key)
|
||||
|
||||
params = {}
|
||||
for key in ["tag_servers", "tag_languages"]:
|
||||
if params_init[key] is not None:
|
||||
keys.append(key)
|
||||
params[key] = {"id": self.__unpack_id(params_init[key])}
|
||||
for key in ["instance_accounts", "instance_languages"]:
|
||||
if params_init[key] is not None:
|
||||
keys.append(key)
|
||||
params[key] = {"domain": Mastodon.__deprotocolize(params_init[key]).split("/")[0]}
|
||||
|
||||
if len(keys) == 0:
|
||||
raise MastodonIllegalArgumentError("Must request at least one dimension.")
|
||||
|
||||
params["keys"] = keys
|
||||
if limit is not None:
|
||||
params["limit"] = limit
|
||||
params["start_at"] = self.__consistent_isoformat_utc(start_at)
|
||||
params["end_at"] = self.__consistent_isoformat_utc(end_at)
|
||||
|
||||
return self.__api_request('POST', '/api/v1/admin/dimensions', params, use_json=True)
|
||||
|
||||
@api_version("3.5.0", "3.5.0", __DICT_VERSION_ADMIN_RETENTION)
|
||||
def admin_retention(self, start_at, end_at, frequency="day"):
|
||||
"""
|
||||
Gets user retention statistics (at `frequency` - "day" or "month" - granularity) between `start_at` and `end_at`.
|
||||
|
||||
Returns a list of `admin retention dicts`_
|
||||
"""
|
||||
if not frequency in ["day", "month"]:
|
||||
raise MastodonIllegalArgumentError("Frequency must be day or month")
|
||||
|
||||
params = {
|
||||
"start_at": self.__consistent_isoformat_utc(start_at),
|
||||
"end_at": self.__consistent_isoformat_utc(end_at),
|
||||
"frequency": frequency
|
||||
}
|
||||
return self.__api_request('POST', '/api/v1/admin/retention', params)
|
||||
|
||||
###
|
||||
# Push subscription crypto utilities
|
||||
###
|
||||
|
@ -3942,7 +4066,6 @@ class Mastodon:
|
|||
if not response_object.ok:
|
||||
try:
|
||||
response = response_object.json(object_hook=self.__json_hooks)
|
||||
print(response)
|
||||
if isinstance(response, dict) and 'error' in response:
|
||||
error_msg = response['error']
|
||||
elif isinstance(response, str):
|
||||
|
@ -4348,6 +4471,14 @@ class Mastodon:
|
|||
base_url = base_url.rstrip("/")
|
||||
return base_url
|
||||
|
||||
@staticmethod
|
||||
def __deprotocolize(base_url):
|
||||
"""Internal helper to strip http and https from a URL"""
|
||||
if base_url.startswith("http://"):
|
||||
base_url = base_url[7:]
|
||||
elif base_url.startswith("https://") or base_url.startswith("onion://"):
|
||||
base_url = base_url[8:]
|
||||
return base_url
|
||||
|
||||
##
|
||||
# Exceptions
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
interactions:
|
||||
- request:
|
||||
body: '{"instance_accounts": {"domain": "chitter.xyz"}, "instance_media_attachments":
|
||||
{"domain": "chitter.xyz"}, "instance_reports": {"domain": "chitter.xyz"}, "instance_statuses":
|
||||
{"domain": "chitter.xyz"}, "instance_follows": {"domain": "chitter.xyz"}, "instance_followers":
|
||||
{"domain": "chitter.xyz"}, "keys": ["active_users", "new_users", "opened_reports",
|
||||
"resolved_reports", "instance_accounts", "instance_media_attachments", "instance_reports",
|
||||
"instance_statuses", "instance_follows", "instance_followers"], "start_at":
|
||||
"2022-11-22T00:42:51+00:00", "end_at": "2022-11-27T00:42:51+00:00"}'
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '587'
|
||||
Content-Type:
|
||||
- application/json
|
||||
User-Agent:
|
||||
- tests/v311
|
||||
method: POST
|
||||
uri: http://localhost:3000/api/v1/admin/measures
|
||||
response:
|
||||
body:
|
||||
string: '[{"key":"active_users","unit":null,"total":"2","previous_total":"0","data":[{"date":"2022-11-22T00:00:00Z","value":"0"},{"date":"2022-11-23T00:00:00Z","value":"0"},{"date":"2022-11-24T00:00:00Z","value":"0"},{"date":"2022-11-25T00:00:00Z","value":"0"},{"date":"2022-11-26T00:00:00Z","value":"2"}]},{"key":"new_users","unit":null,"total":"4","previous_total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"4"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"opened_reports","unit":null,"total":"0","previous_total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"resolved_reports","unit":null,"total":"0","previous_total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"instance_accounts","unit":null,"total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"instance_media_attachments","unit":"bytes","total":"0","human_value":"0
|
||||
Bytes","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":""},{"date":"2022-11-23T00:00:00.000+00:00","value":""},{"date":"2022-11-24T00:00:00.000+00:00","value":""},{"date":"2022-11-25T00:00:00.000+00:00","value":""},{"date":"2022-11-26T00:00:00.000+00:00","value":""},{"date":"2022-11-27T00:00:00.000+00:00","value":""}]},{"key":"instance_reports","unit":null,"total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"instance_statuses","unit":null,"total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"instance_follows","unit":null,"total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]},{"key":"instance_followers","unit":null,"total":"0","data":[{"date":"2022-11-22T00:00:00.000+00:00","value":"0"},{"date":"2022-11-23T00:00:00.000+00:00","value":"0"},{"date":"2022-11-24T00:00:00.000+00:00","value":"0"},{"date":"2022-11-25T00:00:00.000+00:00","value":"0"},{"date":"2022-11-26T00:00:00.000+00:00","value":"0"},{"date":"2022-11-27T00:00:00.000+00:00","value":"0"}]}]'
|
||||
headers:
|
||||
Cache-Control:
|
||||
- no-store
|
||||
Content-Security-Policy:
|
||||
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
|
||||
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
|
||||
style-src ''self'' http://localhost:3000 ''nonce-drS6KPeE5pwtqRFGPVh3ww=='';
|
||||
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
|
||||
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
|
||||
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
|
||||
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
|
||||
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
|
||||
worker-src ''self'' blob: http://localhost:3000'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
ETag:
|
||||
- W/"bb40e02b66cfdf5be1ff5a980c8242af"
|
||||
Referrer-Policy:
|
||||
- strict-origin-when-cross-origin
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept, Origin
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Download-Options:
|
||||
- noopen
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Permitted-Cross-Domain-Policies:
|
||||
- none
|
||||
X-Request-Id:
|
||||
- 11b2cb9c-d3c4-41ba-802d-888e1ee62c9e
|
||||
X-Runtime:
|
||||
- '0.540102'
|
||||
X-XSS-Protection:
|
||||
- 1; mode=block
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"instance_accounts": {"domain": "chitter.xyz"}, "instance_languages":
|
||||
{"domain": "chitter.xyz"}, "keys": ["languages", "sources", "servers", "space_usage",
|
||||
"instance_accounts", "instance_languages"], "limit": 3, "start_at": "2022-11-22T00:42:52+00:00",
|
||||
"end_at": "2022-11-27T00:42:52+00:00"}'
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '292'
|
||||
Content-Type:
|
||||
- application/json
|
||||
User-Agent:
|
||||
- tests/v311
|
||||
method: POST
|
||||
uri: http://localhost:3000/api/v1/admin/dimensions
|
||||
response:
|
||||
body:
|
||||
string: '[{"key":"languages","data":[{"key":"de","human_key":"German","value":"1"}]},{"key":"sources","data":[{"key":"web","human_key":"Website","value":"4"}]},{"key":"servers","data":[]},{"key":"space_usage","data":[{"key":"postgresql","human_key":"PostgreSQL","value":"16610095","unit":"bytes","human_value":"15.8
|
||||
MB"},{"key":"redis","human_key":"Redis","value":"1560216","unit":"bytes","human_value":"1.49
|
||||
MB"},{"key":"media","human_key":"Media storage","value":"0","unit":"bytes","human_value":"0
|
||||
Bytes"}]},{"key":"instance_accounts","data":[]},{"key":"instance_languages","data":[]}]'
|
||||
headers:
|
||||
Cache-Control:
|
||||
- no-store
|
||||
Content-Security-Policy:
|
||||
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
|
||||
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
|
||||
style-src ''self'' http://localhost:3000 ''nonce-tTPpzIcGAZb7y2EXyfEsFg=='';
|
||||
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
|
||||
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
|
||||
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
|
||||
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
|
||||
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
|
||||
worker-src ''self'' blob: http://localhost:3000'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
ETag:
|
||||
- W/"b5c3e0d37fd2fdab9859f566f5b2fa2e"
|
||||
Referrer-Policy:
|
||||
- strict-origin-when-cross-origin
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept, Origin
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Download-Options:
|
||||
- noopen
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Permitted-Cross-Domain-Policies:
|
||||
- none
|
||||
X-Request-Id:
|
||||
- 7332d9ca-00cb-4eaf-9d95-ee3baf8414f9
|
||||
X-Runtime:
|
||||
- '0.066790'
|
||||
X-XSS-Protection:
|
||||
- 1; mode=block
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: start_at=2022-11-17T00%3A42%3A52%2B00%3A00&end_at=2022-11-27T00%3A42%3A52%2B00%3A00&frequency=day
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '97'
|
||||
Content-Type:
|
||||
- application/x-www-form-urlencoded
|
||||
User-Agent:
|
||||
- tests/v311
|
||||
method: POST
|
||||
uri: http://localhost:3000/api/v1/admin/retention
|
||||
response:
|
||||
body:
|
||||
string: '[{"period":"2022-11-17T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-17T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-18T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-19T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-20T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-21T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-22T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-18T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-18T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-19T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-20T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-21T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-22T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-19T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-19T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-20T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-21T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-22T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-20T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-20T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-21T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-22T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-21T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-21T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-22T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-22T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-22T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-23T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-23T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-24T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-24T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-25T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-25T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-26T00:00:00+00:00","rate":0.0,"value":"0"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-26T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-26T00:00:00+00:00","rate":0.5,"value":"2"},{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]},{"period":"2022-11-27T00:00:00+00:00","frequency":"day","data":[{"date":"2022-11-27T00:00:00+00:00","rate":0.0,"value":"0"}]}]'
|
||||
headers:
|
||||
Cache-Control:
|
||||
- no-store
|
||||
Content-Security-Policy:
|
||||
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
|
||||
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
|
||||
style-src ''self'' http://localhost:3000 ''nonce-AkyM5KkEra/OBSMZSu3SqQ=='';
|
||||
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
|
||||
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
|
||||
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
|
||||
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
|
||||
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
|
||||
worker-src ''self'' blob: http://localhost:3000'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
ETag:
|
||||
- W/"c607f49eb27c19d561dab0434594a06e"
|
||||
Referrer-Policy:
|
||||
- strict-origin-when-cross-origin
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept, Origin
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Download-Options:
|
||||
- noopen
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Permitted-Cross-Domain-Policies:
|
||||
- none
|
||||
X-Request-Id:
|
||||
- 67a94c6b-e1fe-4c60-90c5-478c98e3e0f7
|
||||
X-Runtime:
|
||||
- '0.435749'
|
||||
X-XSS-Protection:
|
||||
- 1; mode=block
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
|
@ -27,6 +27,11 @@ UPDATE users SET
|
|||
encrypted_password = '$2a$10$8eAdhF69RiZiV0puZ.8iOOgMqBACmwJu8Z9X4CiN91iwRXbeC2jvi'
|
||||
WHERE email = 'mastodonpy_test_2@localhost:3000';
|
||||
|
||||
UPDATE users SET
|
||||
locale = 'de',
|
||||
encrypted_password = '$2a$10$8eAdhF69RiZiV0puZ.8iOOgMqBACmwJu8Z9X4CiN91iwRXbeC2jvi'
|
||||
WHERE email = 'zerocool@example.com';
|
||||
|
||||
INSERT INTO oauth_applications (
|
||||
id,
|
||||
name,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import pytest
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from mastodon import MastodonIllegalArgumentError
|
||||
|
||||
@pytest.mark.vcr()
|
||||
def test_admin_accounts(api2):
|
||||
|
@ -134,3 +136,49 @@ def test_admin_domain_blocks(api2):
|
|||
assert block3.private_comment == "jk ilu <3"
|
||||
api2.admin_delete_domain_block(block2)
|
||||
assert not block3.id in map(lambda x: x.id, api2.admin_domain_blocks())
|
||||
|
||||
@pytest.mark.vcr()
|
||||
def test_admin_stats(api2):
|
||||
assert api2.admin_measures(
|
||||
datetime.now() - timedelta(hours=24*5),
|
||||
datetime.now(),
|
||||
active_users=True,
|
||||
new_users=True,
|
||||
opened_reports=True,
|
||||
resolved_reports=True,
|
||||
instance_accounts="chitter.xyz",
|
||||
instance_media_attachments="chitter.xyz",
|
||||
instance_reports="http://chitter.xyz/",
|
||||
instance_statuses="chitter.xyz",
|
||||
instance_follows="http://chitter.xyz",
|
||||
instance_followers="chitter.xyz",
|
||||
#tag_accounts=0,
|
||||
#tag_uses=0,
|
||||
#tag_servers=0,
|
||||
)
|
||||
|
||||
assert api2.admin_dimensions(
|
||||
datetime.now() - timedelta(hours=24*5),
|
||||
datetime.now(),
|
||||
limit=3,
|
||||
languages=True,
|
||||
sources=True,
|
||||
servers=True,
|
||||
space_usage=True,
|
||||
#tag_servers=0,
|
||||
#tag_languages=0,
|
||||
instance_accounts="chitter.xyz",
|
||||
instance_languages="https://chitter.xyz"
|
||||
)
|
||||
|
||||
api2.admin_retention(
|
||||
datetime.now() - timedelta(days=10),
|
||||
datetime.now()
|
||||
)
|
||||
|
||||
with pytest.raises(MastodonIllegalArgumentError):
|
||||
api2.admin_retention(
|
||||
datetime.now() - timedelta(days=10),
|
||||
datetime.now(),
|
||||
frequency="dayz"
|
||||
)
|
Ładowanie…
Reference in New Issue