Merge remote-tracking branch 'origin/master' into catgoat/domain_blocks

pull/281/head
micah 2022-11-25 21:45:52 +00:00
commit dd23f8b7c5
16 zmienionych plików z 889 dodań i 113 usunięć

Wyświetl plik

@ -2,6 +2,15 @@ A note on versioning: This librarys major version will grow with the APIs
version number. Breaking changes will be indicated by a change in the minor
(or major) version number, and will generally be avoided.
v1.8.0 (in progress)
--------------------
* BREAKING CHANGE: Switch the base URL to None, throw an error when no base url is passed. Having mastosoc as default was sensible when there were only three mastodon servers. It is not sensible now and trips people up constantly.
* Fix an issue with the fix for the Pleroma date bug (thanks adbenitez)
* Add trending APIs (`trending_tags`, `trending_statuses`, `trending_links`, `admin_trending_tags`, `admin_trending_statuses`, `admin_trending_links`)
* Add `lang` parameter and document what it does properly.
* Add `category` and `rule_ids` to `reports`
* This too isn't really a changelog entry but in the same vein as the last post, thank you Claire and Gargron for clarifying many things about the API when asked.
v1.7.0
------
* Cleaned code up a bit (thanks eumiro)

Wyświetl plik

@ -43,12 +43,12 @@ 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.
* [ ] Add explore page with trending posts and links
* [x] Add explore page with trending posts and links
* [ ] 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
* [ ] Add category and rule_ids params to POST /api/v1/reports IN REST API
* [ ] Add global lang param to REST API
* [x] Add category and rule_ids params to POST /api/v1/reports IN REST API
* [x] Add global lang param to REST API
* [x] Add types param to GET /api/v1/notifications in REST API
* [x] Add notifications for moderators about new sign-ups
* [ ] v2 admin account api
@ -66,4 +66,4 @@ General improvements that would be good to do before doing another release:
* [x] Fix the CI
* [ ] Get test coverage like, real high
* [x] Add all those streaming events??
* [ ] Document return values
* [ ] Document return values (skipping this for a bit to then do it at the end with tooling)

Wyświetl plik

@ -1089,6 +1089,9 @@ Reading data: Searching
Reading data: Trends
--------------------
.. automethod:: Mastodon.trending_tags
.. automethod:: Mastodon.trending_statuses
.. automethod:: Mastodon.trending_links
.. automethod:: Mastodon.trends
Reading data: Mutes and blocks
@ -1440,6 +1443,10 @@ have admin: scopes attached with a lot of care, but be extra careful with those
.. automethod:: Mastodon.admin_report_reopen
.. automethod:: Mastodon.admin_report_resolve
.. automethod:: Mastodon.admin_trending_tags
.. automethod:: Mastodon.admin_trending_statuses
.. automethod:: Mastodon.admin_trending_links
Acknowledgements
----------------
Mastodon.py contains work by a large number of contributors, many of which have

Wyświetl plik

@ -167,7 +167,6 @@ class Mastodon:
If anything is unclear, check the official API docs at
https://github.com/mastodon/documentation/blob/master/content/en/client/intro.md
"""
__DEFAULT_BASE_URL = 'https://mastodon.social'
__DEFAULT_TIMEOUT = 300
__DEFAULT_STREAM_TIMEOUT = 300
__DEFAULT_STREAM_RECONNECT_WAIT_SEC = 5
@ -260,17 +259,17 @@ class Mastodon:
###
@staticmethod
def create_app(client_name, scopes=__DEFAULT_SCOPES, redirect_uris=None, website=None, to_file=None,
api_base_url=__DEFAULT_BASE_URL, request_timeout=__DEFAULT_TIMEOUT, session=None):
api_base_url=None, request_timeout=__DEFAULT_TIMEOUT, session=None):
"""
Create a new app with given `client_name` and `scopes` (The basic scopes are "read", "write", "follow" and "push"
- more granular scopes are available, please refer to Mastodon documentation for which).
- more granular scopes are available, please refer to Mastodon documentation for which) on the instance given
by `api_base_url`.
Specify `redirect_uris` if you want users to be redirected to a certain page after authenticating in an OAuth flow.
You can specify multiple URLs by passing a list. Note that if you wish to use OAuth authentication with redirects,
the redirect URI must be one of the URLs specified here.
Specify `to_file` to persist your app's info to a file so you can use it in the constructor.
Specify `api_base_url` if you want to register an app on an instance different from the flagship one.
Specify `website` to give a website for your app.
Specify `session` with a requests.Session for it to be used instead of the default. This can be
@ -282,6 +281,8 @@ class Mastodon:
Returns `client_id` and `client_secret`, both as strings.
"""
if api_base_url is None:
raise MastodonIllegalArgumentError("API base URL is required.")
api_base_url = Mastodon.__protocolize(api_base_url)
request_data = {
@ -299,12 +300,10 @@ class Mastodon:
if website is not None:
request_data['website'] = website
if session:
ret = session.post(api_base_url + '/api/v1/apps',
data=request_data, timeout=request_timeout)
ret = session.post(api_base_url + '/api/v1/apps', data=request_data, timeout=request_timeout)
response = ret.json()
else:
response = requests.post(
api_base_url + '/api/v1/apps', data=request_data, timeout=request_timeout)
response = requests.post(api_base_url + '/api/v1/apps', data=request_data, timeout=request_timeout)
response = response.json()
except Exception as e:
raise MastodonNetworkError("Could not complete request: %s" % e)
@ -321,17 +320,15 @@ class Mastodon:
###
# Authentication, including constructor
###
def __init__(self, client_id=None, client_secret=None, access_token=None,
api_base_url=None, debug_requests=False,
ratelimit_method="wait", ratelimit_pacefactor=1.1,
request_timeout=__DEFAULT_TIMEOUT, mastodon_version=None,
version_check_mode="created", session=None, feature_set="mainline", user_agent="mastodonpy"):
def __init__(self, client_id=None, client_secret=None, access_token=None, api_base_url=None, debug_requests=False,
ratelimit_method="wait", ratelimit_pacefactor=1.1, request_timeout=__DEFAULT_TIMEOUT, mastodon_version=None,
version_check_mode="created", session=None, feature_set="mainline", user_agent="mastodonpy", lang=None):
"""
Create a new API wrapper instance based on the given `client_secret` and `client_id`. If you
give a `client_id` and it is not a file, you must also give a secret. If you specify an
`access_token` then you don't need to specify a `client_id`. It is allowed to specify
neither - in this case, you will be restricted to only using endpoints that do not
require authentication. If a file is given as `client_id`, client ID, secret and
Create a new API wrapper instance based on the given `client_secret` and `client_id` on the
instance given by `api_base_url`. If you give a `client_id` and it is not a file, you must
also give a secret. If you specify an `access_token` then you don't need to specify a `client_id`.
It is allowed to specify neither - in this case, you will be restricted to only using endpoints
that do not require authentication. If a file is given as `client_id`, client ID, secret and
base url are read from that file.
You can also specify an `access_token`, directly or as a file (as written by `log_in()`_). If
@ -347,10 +344,6 @@ class Mastodon:
even in "wait" and "pace" mode, requests can still fail due to network or other problems! Also
note that "pace" and "wait" are NOT thread safe.
Specify `api_base_url` if you wish to talk to an instance other than the flagship one. When
reading from client id or access token files as written by Mastodon.py 1.5.0 or larger,
this can be omitted.
By default, a timeout of 300 seconds is used for all requests. If you wish to change this,
pass the desired timeout (in seconds) as `request_timeout`.
@ -376,12 +369,15 @@ class Mastodon:
the app name will be used as `User-Agent` header as default. It is possible to modify old secret files and append
a client app name to use it as a `User-Agent` name.
`lang` can be used to change the locale Mastodon will use to generate responses. Valid parameters are all ISO 639-1 (two letter)
or for a language that has none, 639-3 (three letter) language codes. This affects some error messages (those related to validation) and
trends. You can change the language using `set_language()`_.
If no other `User-Agent` is specified, "mastodonpy" will be used.
"""
self.api_base_url = None
if api_base_url is not None:
self.api_base_url = Mastodon.__protocolize(api_base_url)
self.api_base_url = api_base_url
if self.api_base_url is not None:
self.api_base_url = self.__protocolize(self.api_base_url)
self.client_id = client_id
self.client_secret = client_secret
self.access_token = access_token
@ -389,7 +385,7 @@ class Mastodon:
self.ratelimit_method = ratelimit_method
self._token_expired = datetime.datetime.now()
self._refresh_token = None
self.__logged_in_id = None
self.ratelimit_limit = 300
@ -412,6 +408,9 @@ class Mastodon:
# General defined user-agent
self.user_agent = user_agent
# Save language
self.lang = lang
# Token loading
if self.client_id is not None:
if os.path.isfile(self.client_id):
@ -422,9 +421,9 @@ 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')
raise MastodonIllegalArgumentError('Mismatch in base URLs between files and/or specified')
self.api_base_url = try_base_url
# With new registrations we support the 4th line to store a client_name and use it as user-agent
@ -433,8 +432,7 @@ class Mastodon:
self.user_agent = client_name.rstrip()
else:
if self.client_secret is None:
raise MastodonIllegalArgumentError(
'Specified client id directly, but did not supply secret')
raise MastodonIllegalArgumentError('Specified client id directly, but did not supply secret')
if self.access_token is not None and os.path.isfile(self.access_token):
with open(self.access_token, 'r') as token_file:
@ -444,10 +442,14 @@ class Mastodon:
if try_base_url is not None and len(try_base_url) != 0:
try_base_url = Mastodon.__protocolize(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')
raise MastodonIllegalArgumentError('Mismatch in base URLs between files and/or specified')
self.api_base_url = try_base_url
# Verify we have a base URL, protocolize
if self.api_base_url is None:
raise MastodonIllegalArgumentError("API base URL is required.")
self.api_base_url = Mastodon.__protocolize(self.api_base_url)
if not version_check_mode in ["created", "changed", "none"]:
raise MastodonIllegalArgumentError("Invalid version check method.")
self.version_check_mode = version_check_mode
@ -470,6 +472,13 @@ class Mastodon:
if ratelimit_method not in ["throw", "wait", "pace"]:
raise MastodonIllegalArgumentError("Invalid ratelimit method.")
def set_language(self, lang):
"""
Set the locale Mastodon will use to generate responses. Valid parameters are all ISO 639-1 (two letter) or, for languages that do
not have one, 639-3 (three letter) language codes. This affects some error messages (those related to validation) and trends.
"""
self.lang = lang
def __normalize_version_string(self, version_string):
# Split off everything after the first space, to take care of Pleromalikes so that the parser doesn't get confused in case those have a + somewhere in their version
version_string = version_string.split(" ")[0]
@ -541,24 +550,27 @@ class Mastodon:
"""
return Mastodon.__SUPPORTED_MASTODON_VERSION
def auth_request_url(self, client_id=None, redirect_uris="urn:ietf:wg:oauth:2.0:oob", scopes=__DEFAULT_SCOPES, force_login=False, state=None):
def auth_request_url(self, client_id=None, redirect_uris="urn:ietf:wg:oauth:2.0:oob", scopes=__DEFAULT_SCOPES, force_login=False, state=None, lang=None):
"""
Returns the URL that a client needs to request an OAuth grant from the server.
To log in with OAuth, send your user to this URL. The user will then log in and
get a code which you can pass to log_in.
get a code which you can pass to `log_in()`_.
scopes are as in `log_in()`_, redirect_uris is where the user should be redirected to
after authentication. Note that redirect_uris must be one of the URLs given during
`scopes` are as in `log_in()`_, redirect_uris is where the user should be redirected to
after authentication. Note that `redirect_uris` must be one of the URLs given during
app registration. When using urn:ietf:wg:oauth:2.0:oob, the code is simply displayed,
otherwise it is added to the given URL as the "code" request parameter.
Pass force_login if you want the user to always log in even when already logged
into web Mastodon (i.e. when registering multiple different accounts in an app).
State is the oauth `state`parameter to pass to the server. It is strongly suggested
`state` is the oauth `state` parameter to pass to the server. It is strongly suggested
to use a random, nonguessable value (i.e. nothing meaningful and no incrementing ID)
to preserve security guarantees. It can be left out for non-web login flows.
Pass an ISO 639-1 (two letter) or, for languages that do not have one, 639-3 (three letter)
language code as `lang` to control the display language for the oauth form.
"""
if client_id is None:
client_id = self.client_id
@ -574,6 +586,7 @@ class Mastodon:
params['scope'] = " ".join(scopes)
params['force_login'] = force_login
params['state'] = state
params['lang'] = lang
formatted_params = urlencode(params)
return "".join([self.api_base_url, "/oauth/authorize?", formatted_params])
@ -675,8 +688,9 @@ class Mastodon:
Creates a new user account with the given username, password and email. "agreement"
must be set to true (after showing the user the instance's user agreement and having
them agree to it), "locale" specifies the language for the confirmation email as an
ISO 639-1 (two-letter) language code. `reason` can be used to specify why a user
would like to join if approved-registrations mode is on.
ISO 639-1 (two letter) or, if a language does not have one, 639-3 (three letter) language
code. `reason` can be used to specify why a user would like to join if approved-registrations
mode is on.
Does not require an access token, but does require a client grant.
@ -999,7 +1013,7 @@ class Mastodon:
Does not require authentication for publicly visible statuses.
This function is deprecated as of 3.0.0 and the endpoint does not
exist anymore - you should just use the "card" field of the status dicts
exist anymore - you should just use the "card" field of the toot dicts
instead. Mastodon.py will try to mimic the old behaviour, but this
is somewhat inefficient and not guaranteed to be the case forever.
@ -1540,8 +1554,15 @@ class Mastodon:
###
# Reading data: Trends
###
@api_version("2.4.3", "3.0.0", __DICT_VERSION_HASHTAG)
@api_version("2.4.3", "3.5.0", __DICT_VERSION_HASHTAG)
def trends(self, limit=None):
"""
Alias for `trending_tags()`_
"""
return self.trending_tags(limit=limit)
@api_version("3.5.0", "3.5.0", __DICT_VERSION_HASHTAG)
def trending_tags(self, limit=None, lang=None):
"""
Fetch trending-hashtag information, if the instance provides such information.
@ -1551,13 +1572,49 @@ class Mastodon:
Does not require authentication unless locked down by the administrator.
Important versioning note: This endpoint does not exist for Mastodon versions
between 2.8.0 (inclusive) and 3.0.0 (exclusive).
between 2.8.0 (inclusive) and 3.0.0 (exclusive).
Pass `lang` to override the global locale parameter, which may affect trend ordering.
Returns a list of `hashtag dicts`_, sorted by the instance's trending algorithm,
descending.
"""
params = self.__generate_params(locals())
return self.__api_request('GET', '/api/v1/trends', params)
if self.verify_minimum_version("3.5.0", cached=True):
# Starting 3.5.0, old version is deprecated
return self.__api_request('GET', '/api/v1/trends/tags', params)
else:
return self.__api_request('GET', '/api/v1/trends', params)
@api_version("3.5.0", "3.5.0", __DICT_VERSION_STATUS)
def trending_statuses(self):
"""
Fetch trending-status information, if the instance provides such information.
Specify `limit` to limit how many results are returned (the maximum number
of results is 10, the endpoint is not paginated).
Pass `lang` to override the global locale parameter, which may affect trend ordering.
Returns a list of `toot dicts`_, sorted by the instances's trending algorithm,
descending.
"""
params = self.__generate_params(locals())
return self.__api_request('GET', '/api/v1/trends/statuses', params)
@api_version("3.5.0", "3.5.0", __DICT_VERSION_CARD)
def trending_links(self):
"""
Fetch trending-link information, if the instance provides such information.
Specify `limit` to limit how many results are returned (the maximum number
of results is 10, the endpoint is not paginated).
Returns a list of `card dicts`_, sorted by the instances's trending algorithm,
descending.
"""
params = self.__generate_params(locals())
return self.__api_request('GET', '/api/v1/trends/links', params)
###
# Reading data: Lists
@ -1656,6 +1713,8 @@ class Mastodon:
Warning: This method has now finally been removed, and will not
work on Mastodon versions 2.5.0 and above.
"""
if self.verify_minimum_version("2.5.0", cached=True):
raise MastodonVersionError("API removed in Mastodon 2.5.0")
return self.__api_request('GET', '/api/v1/reports')
###
@ -1943,7 +2002,8 @@ class Mastodon:
displayed.
Specify `language` to override automatic language detection. The parameter
accepts all valid ISO 639-2 language codes.
accepts all valid ISO 639-1 (2-letter) or for languages where that do not
have one, 639-3 (three letter) language codes.
You can set `idempotency_key` to a value to uniquely identify an attempt
at posting a status. Even if you call this function more than once,
@ -2496,7 +2556,7 @@ class Mastodon:
"""
Set a note (visible to the logged in user only) for the given account.
Returns a `status dict`_ with the `note` updated.
Returns a `toot dict`_ with the `note` updated.
"""
id = self.__unpack_id(id)
params = self.__generate_params(locals(), ["id"])
@ -2662,18 +2722,25 @@ class Mastodon:
###
# Writing data: Reports
###
@api_version("1.1.0", "2.5.0", __DICT_VERSION_REPORT)
def report(self, account_id, status_ids=None, comment=None, forward=False):
@api_version("1.1.0", "3.5.0", __DICT_VERSION_REPORT)
def report(self, account_id, status_ids=None, comment=None, forward=False, category=None, rule_ids=None):
"""
Report statuses to the instances administrators.
Accepts a list of toot IDs associated with the report, and a comment.
Set forward to True to forward a report of a remote user to that users
Starting with Mastodon 3.5.0, you can also pass a `category` (one out of
"spam", "violation" or "other") and `rule_ids` (a list of rule IDs corresponding
to the rules returned by the `instance()`_ API).
Set `forward` to True to forward a report of a remote user to that users
instance as well as sending it to the instance local administrators.
Returns a `report dict`_.
"""
if category is not None and not category in ["spam", "violation", "other"]:
raise MastodonIllegalArgumentError("Invalid report category (must be spam, violation or other)")
account_id = self.__unpack_id(account_id)
if status_ids is not None:
@ -3263,6 +3330,39 @@ class Mastodon:
id = self.__unpack_id(id)
return self.__api_request('POST', '/api/v1/admin/reports/{0}/resolve'.format(id))
@api_version("3.5.0", "3.5.0", __DICT_VERSION_HASHTAG)
def admin_trending_tags(self, limit=None):
"""
Admin version of `trending_tags()`_. Includes unapproved tags.
Returns a list of `hashtag dicts`_, sorted by the instance's trending algorithm,
descending.
"""
params = self.__generate_params(locals())
return self.__api_request('GET', '/api/v1/admin/trends/tags', params)
@api_version("3.5.0", "3.5.0", __DICT_VERSION_STATUS)
def admin_trending_statuses(self):
"""
Admin version of `trending_statuses()`_. Includes unapproved tags.
Returns a list of `toot dicts`_, sorted by the instance's trending algorithm,
descending.
"""
params = self.__generate_params(locals())
return self.__api_request('GET', '/api/v1/admin/trends/statuses', params)
@api_version("3.5.0", "3.5.0", __DICT_VERSION_CARD)
def admin_trending_links(self):
"""
Admin version of `trending_links()`_. Includes unapproved tags.
Returns a list of `card dicts`_, sorted by the instance's trending algorithm,
descending.
"""
params = self.__generate_params(locals())
return self.__api_request('GET', '/api/v1/admin/trends/links', params)
@api_version("4.0.0","4.0.0","4.0.0")
def admin_domain_blocks(self, id:str=None, limit:int=None):
"""
@ -3275,7 +3375,7 @@ class Mastodon:
id = self.__unpack_id(id)
if id is not None:
return self.__api_request('GET', '/api/v1/admin/domain_blocks/{0}'.format(id))
else
else:
params = params = self.__generate_params(locals(),['limit'])
return self.__api_request('GET', '/api/v1/admin/domain_blocks/')
@ -3303,8 +3403,7 @@ class Mastodon:
params = self.__generate_params(locals())
self.__api_request(
'POST', '/api/v1/admin/domain_blocks/, params)
self.__api_request('POST', '/api/v1/admin/domain_blocks/', params)
@api_version("4.0.0","4.0.0","4.0.0")
def admin_update_domain_block(self, id:str, severity:str=None, reject_media:bool=None, reject_reports:bool=None, private_comment:str=None, public_comment:str=None, obfuscate:bool=None):
@ -3329,8 +3428,7 @@ class Mastodon:
params = self.__generate_params(locals())
self.__api_request(
'PUT', '/api/v1/admin/domain_blocks/, params)
self.__api_request('PUT', '/api/v1/admin/domain_blocks/', params)
@api_version("4.0.0","4.0.0","4.0.0")
def admin_delete_domain_blocks(self, id:str=None):
@ -3344,7 +3442,7 @@ class Mastodon:
id = self.__unpack_id(id)
if id is not None:
return self.__api_request('DELETE', '/api/v1/admin/domain_blocks/{0}'.format(id))
else
else:
raise AttributeError("You must provide an id of an existing domain block to remove it.")
###
@ -3644,6 +3742,7 @@ class Mastodon:
"""
known_date_fields = ["created_at", "week", "day", "expires_at", "scheduled_at",
"updated_at", "last_status_at", "starts_at", "ends_at", "published_at", "edited_at"]
mark_delete = []
for k, v in json_object.items():
if k in known_date_fields:
if v is not None:
@ -3653,11 +3752,11 @@ class Mastodon:
else:
json_object[k] = dateutil.parser.parse(v)
except:
if isinstance(v, str) and len(x.strip()) == 0:
# Pleroma bug workaround: Empty string becomes start of epoch
json_object[k] = datetime.datetime.fromtimestamp(0)
else:
raise MastodonAPIError('Encountered invalid date.')
# When we can't parse a date, we just leave the field out
mark_delete.append(k)
# Two step process because otherwise python gets very upset
for k in mark_delete:
del json_object[k]
return json_object
@staticmethod
@ -3710,12 +3809,20 @@ class Mastodon:
isotime = isotime[:-2] + ":" + isotime[-2:]
return isotime
def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True, return_response_object=False, skip_error_check=False):
def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None,
do_ratelimiting=True, use_json=False, parse=True, return_response_object=False, skip_error_check=False, lang_override=None):
"""
Internal API request helper.
"""
response = None
remaining_wait = 0
# Add language to params if not None
lang = self.lang
if lang_override is not None:
lang = lang_override
if lang is not None:
params["lang"] = lang
# "pace" mode ratelimiting: Assume constant rate of requests, sleep a little less long than it
# would take to not hit the rate limit at that request rate.
@ -3774,8 +3881,7 @@ class Mastodon:
else:
kwargs['data'] = params
response_object = self.session.request(
method, base_url + endpoint, **kwargs)
response_object = self.session.request(method, base_url + endpoint, **kwargs)
except Exception as e:
raise MastodonNetworkError(
"Could not complete request: %s" % e)
@ -3818,15 +3924,14 @@ class Mastodon:
# Handle response
if self.debug_requests:
print('Mastodon: Response received with code ' +
str(response_object.status_code) + '.')
print('Mastodon: Response received with code ' + str(response_object.status_code) + '.')
print('response headers: ' + str(response_object.headers))
print('Response text content: ' + str(response_object.text))
if not response_object.ok:
try:
response = response_object.json(
object_hook=self.__json_hooks)
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):
@ -3880,8 +3985,7 @@ class Mastodon:
if parse:
try:
response = response_object.json(
object_hook=self.__json_hooks)
response = response_object.json(object_hook=self.__json_hooks)
except:
raise MastodonAPIError(
"Could not parse response as JSON, response code was %s, "

Wyświetl plik

@ -0,0 +1,234 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/admin/trends/tags
response:
body:
string: '[]'
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-riTO9qzezJtfpKUBo5FfRw=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- 7f790ab8-9fba-4fd4-b1d1-32f98f057ced
X-Runtime:
- '0.019713'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/admin/trends/statuses
response:
body:
string: '[]'
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-LJrdU51JLzwv175738dEzQ=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- 247300e7-df10-49fa-81b7-5ee6fd5d82a4
X-Runtime:
- '0.027509'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/admin/trends/links
response:
body:
string: '[]'
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-UsGPkqqgkgw3xXRrC/rS6Q=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- f9838813-fc1a-455b-8ee4-6c4e38f62be0
X-Runtime:
- '0.018125'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/admin/trends/tags?limit=5
response:
body:
string: '[]'
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-yIFkCE0nhCUfZnXpKkcTiQ=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- 51da904e-4de6-49d8-8680-b02a8dce3feb
X-Runtime:
- '0.008825'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
version: 1

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -19,14 +19,14 @@ interactions:
response:
body:
string: '{"access_token":"__MASTODON_PY_TEST_ACCESS_TOKEN_3","token_type":"Bearer","scope":"read
write follow push","created_at":1669069472}'
write follow push","created_at":1669078552}'
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-2hAAmzxVIF2o8Dybbe/Nlw=='';
style-src ''self'' http://localhost:3000 ''nonce-qgSt4nG9WHHoLhv8/BTiNA=='';
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
@ -36,7 +36,7 @@ interactions:
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"2f20b949ed12ddfc15861ec448b5551f"
- W/"64a8679bd2f3d37be418066de7284ddd"
Pragma:
- no-cache
Referrer-Policy:
@ -54,9 +54,9 @@ interactions:
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 8e26834c-db67-484e-bf41-80e3a1e48c83
- f7be8646-6edb-4018-89b2-525917883907
X-Runtime:
- '0.056343'
- '0.072228'
X-XSS-Protection:
- 1; mode=block
status:
@ -79,14 +79,14 @@ interactions:
uri: http://localhost:3000/api/v1/instance/
response:
body:
string: '{"uri":"localhost:3000","title":"Mastodon","short_description":"","description":"","email":"","version":"4.0.0rc2","urls":{"streaming_api":"ws://localhost:4000"},"stats":{"user_count":4,"status_count":1,"domain_count":0},"thumbnail":"http://localhost:3000/packs/media/images/preview-6399aebd96ccf025654e2977454f168f.png","languages":["en"],"registrations":true,"approval_required":false,"invites_enabled":true,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":null,"rules":[]}'
string: '{"uri":"localhost:3000","title":"Mastodon","short_description":"","description":"","email":"","version":"4.0.0rc2","urls":{"streaming_api":"ws://localhost:4000"},"stats":{"user_count":4,"status_count":8,"domain_count":0},"thumbnail":"http://localhost:3000/packs/media/images/preview-6399aebd96ccf025654e2977454f168f.png","languages":["en"],"registrations":true,"approval_required":false,"invites_enabled":true,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":null,"rules":[]}'
headers:
Cache-Control:
- max-age=180, public
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-p/U3iDcksaJMkQ5IvZDsGQ=='';
style-src ''self'' http://localhost:3000 ''nonce-Xujah3tRsHYiM+FbWsiFuA=='';
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
@ -96,9 +96,9 @@ interactions:
Content-Type:
- application/json; charset=utf-8
Date:
- Mon, 21 Nov 2022 20:24:59 GMT
- Thu, 24 Nov 2022 21:56:42 GMT
ETag:
- W/"bf317ffab393d8d1da7195269f28968a"
- W/"b3134b9b6dd4c58f0150831d75c86c06"
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
@ -114,9 +114,9 @@ interactions:
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 1d68749b-1782-4ee2-b0b4-f3b08b1253eb
- 902f84f2-1256-449b-8c98-e593b8b72998
X-Runtime:
- '0.029627'
- '0.042336'
X-XSS-Protection:
- 1; mode=block
status:
@ -150,7 +150,7 @@ interactions:
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-DWtDMY1MqGERclXgCGbr0Q=='';
style-src ''self'' http://localhost:3000 ''nonce-WT+/lb3ulLnfgMU4/kyt6A=='';
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
@ -176,9 +176,9 @@ interactions:
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- a63c3472-347e-48f5-8a11-4e5b6ebf4836
- 8c35a1e3-0ad8-4035-bb05-0795e74bace4
X-Runtime:
- '0.025417'
- '0.015637'
X-XSS-Protection:
- 1; mode=block
status:
@ -210,7 +210,7 @@ interactions:
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-8Wq3rXCQa6b3gM8cbtEXVQ=='';
style-src ''self'' http://localhost:3000 ''nonce-YJJZ0jnA7xjMKXR0QxnZpg=='';
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
@ -239,14 +239,74 @@ interactions:
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 220822bd-2303-424b-96d7-babf8edfc5b9
- 0a52d3a9-ad38-4fe9-8fd4-91e90d3180c5
X-Runtime:
- '0.543121'
- '0.648647'
X-XSS-Protection:
- 1; mode=block
status:
code: 401
message: Unauthorized
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_3
Connection:
- keep-alive
User-Agent:
- mastodonpy
method: GET
uri: http://localhost:3000/api/v1/instance/
response:
body:
string: '{"uri":"localhost:3000","title":"Mastodon","short_description":"","description":"","email":"","version":"4.0.0rc2","urls":{"streaming_api":"ws://localhost:4000"},"stats":{"user_count":4,"status_count":8,"domain_count":0},"thumbnail":"http://localhost:3000/packs/media/images/preview-6399aebd96ccf025654e2977454f168f.png","languages":["en"],"registrations":true,"approval_required":false,"invites_enabled":true,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":null,"rules":[]}'
headers:
Cache-Control:
- max-age=180, public
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-F1GvF0zbODWtYZVC3JI4wA=='';
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
Date:
- Thu, 24 Nov 2022 21:56:43 GMT
ETag:
- W/"b3134b9b6dd4c58f0150831d75c86c06"
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:
- 2bf6c22d-2f68-45a4-bd92-389a130454b4
X-Runtime:
- '0.015512'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: status=illegal+access+detected
headers:
@ -254,6 +314,8 @@ interactions:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_3
Connection:
- keep-alive
Content-Length:
@ -261,19 +323,19 @@ interactions:
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
- mastodonpy
method: POST
uri: http://localhost:3000/api/v1/statuses
response:
body:
string: '{"error":"The access token is invalid"}'
string: "{\"error\":\"\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u53D6\u308A\u6D88\u3055\u308C\u3066\u3044\u307E\u3059\"}"
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-fMWth9zD7qWcG79MyycwRQ=='';
style-src ''self'' http://localhost:3000 ''nonce-VHNNI4iV+hIATnI9wOKj0w=='';
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
@ -291,8 +353,7 @@ interactions:
Vary:
- Accept, Origin
WWW-Authenticate:
- Bearer realm="Doorkeeper", error="invalid_token", error_description="The access
token is invalid"
- "Bearer realm=\"Doorkeeper\", error=\"invalid_token\", error_description=\"\xE3\x82\xA2\xE3\x82\xAF\xE3\x82\xBB\xE3\x82\xB9\xE3\x83\x88\xE3\x83\xBC\xE3\x82\xAF\xE3\x83\xB3\xE3\x81\xAF\xE5\x8F\x96\xE3\x82\x8A\xE6\xB6\x88\xE3\x81\x95\xE3\x82\x8C\xE3\x81\xA6\xE3\x81\x84\xE3\x81\xBE\xE3\x81\x99\""
X-Content-Type-Options:
- nosniff
X-Download-Options:
@ -302,9 +363,9 @@ interactions:
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 17a0fa0b-62a6-44ef-90a4-91a90dcd68c8
- ddb03e7b-25bf-4711-93a4-74e63bf8dbc5
X-Runtime:
- '0.005676'
- '0.008214'
X-XSS-Protection:
- 1; mode=block
status:

Wyświetl plik

@ -13,7 +13,7 @@ interactions:
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/trends
uri: http://localhost:3000/api/v1/trends/links
response:
body:
string: '[]'
@ -23,7 +23,7 @@ interactions:
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-wweJU6CNiZOq8p6GOgvKMg=='';
style-src ''self'' http://localhost:3000 ''nonce-7UiLUEyJEVY9JgarYKBdCg=='';
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
@ -49,9 +49,9 @@ interactions:
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 04d49bc9-1ad7-48de-a189-e93e527942e0
- 623f9c94-2540-4c4f-b0ae-1c3db0b9ca35
X-Runtime:
- '0.010606'
- '0.016081'
X-XSS-Protection:
- 1; mode=block
status:

Wyświetl plik

@ -0,0 +1,60 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/trends/statuses
response:
body:
string: '[]'
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-Qp9U6bbMsEloa3BOJP+ApA=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- 9b65a082-dbab-436e-9544-9d3ceae169b0
X-Runtime:
- '0.022649'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
version: 1

Wyświetl plik

@ -0,0 +1,118 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/trends/tags
response:
body:
string: '[]'
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-x84HIusoB0oMG/yq6Q4NDg=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- e26034bb-bfdb-4f3a-bbef-9d2e51f88c14
X-Runtime:
- '0.029510'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/trends/tags
response:
body:
string: '[]'
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-mRWh2zKUzi/z+WYqVSZD1g=='';
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/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
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:
- c1cc20bc-a0b0-4ffa-bd72-686a094e1da0
X-Runtime:
- '0.015007'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
version: 1

Wyświetl plik

@ -108,7 +108,14 @@ def test_admin_reports(api, api2, status):
report2 = api2.admin_report(report)
assert(report2)
assert(report2.id == report.id)
@pytest.mark.vcr()
def test_admin_trends(api2):
assert isinstance(api2.admin_trending_tags(), list)
assert isinstance(api2.admin_trending_statuses(), list)
assert isinstance(api2.admin_trending_links(), list)
assert isinstance(api2.admin_trending_tags(limit=5), list)
@pytest.mark.skip(reason="reject / accept of account requests isn't really testable without modifying instance settings. anyone want to fumble those into the DB setup and write this test, please do.")
def test_admin_accountrequests(api2):
pass

Wyświetl plik

@ -34,7 +34,7 @@ def test_log_in_password(api_anonymous):
def test_revoke(api_anonymous):
token = api_anonymous.log_in(
username='mastodonpy_test_2@localhost:3000',
password='5fc638e0e53eafd9c4145b6bb852667d'
password='5fc638e0e53eafd9c4145b6bb852667d',
)
api_anonymous.revoke_access_token()
@ -45,9 +45,9 @@ def test_revoke(api_anonymous):
print(e)
pass
api_revoked_token = Mastodon(access_token = token)
api_revoked_token = Mastodon(access_token = token, api_base_url='http://localhost:3000')
try:
api_anonymous.toot("illegal access detected")
api_revoked_token.toot("illegal access detected")
assert False
except Exception as e:
print(e)

Wyświetl plik

@ -8,8 +8,10 @@ def test_constructor_from_filenames(tmpdir):
access = tmpdir.join('access')
access.write_text(u'baz\n', 'UTF-8')
api = Mastodon(
str(client),
access_token=str(access))
str(client),
access_token=str(access),
api_base_url="mastodon.social"
)
assert api.client_id == 'foo'
assert api.client_secret == 'bar'
assert api.access_token == 'baz'

Wyświetl plik

@ -1,5 +1,7 @@
import pytest
import vcr
from mastodon.Mastodon import MastodonAPIError
import json
try:
from mock import MagicMock
@ -8,8 +10,7 @@ except ImportError:
def test_nonstandard_errors(api):
response = MagicMock()
response.json = MagicMock(return_value=
"I am a non-standard instance and this error is a plain string.")
response.json = MagicMock(return_value="I am a non-standard instance and this error is a plain string.")
response.ok = False
response.status_code = 501
session = MagicMock()
@ -19,3 +20,23 @@ def test_nonstandard_errors(api):
with pytest.raises(MastodonAPIError):
api.instance()
@pytest.mark.vcr()
def test_lang_for_errors(api):
try:
api.status_post("look at me i am funny shark gawr gura: " + "a" * 50000)
except Exception as e:
e1 = str(e)
api.set_language("de")
try:
api.status_post("look at me i am funny shark gawr gura: " + "a" * 50000)
except Exception as e:
e2 = str(e)
assert e1 != e2
def test_broken_date(api):
dict1 = json.loads('{"uri":"icosahedron.website", "created_at": "", "edited_at": "2012-09-27"}', object_hook=api._Mastodon__json_hooks)
dict2 = json.loads('{"uri":"icosahedron.website", "created_at": "2012-09-27", "subfield": {"edited_at": "null"}}', object_hook=api._Mastodon__json_hooks)
assert "edited_at" in dict1
assert not "created_at" in dict1
assert "created_at" in dict2
assert not "edited_at" in dict2.subfield

Wyświetl plik

@ -62,10 +62,6 @@ def test_nodeinfo(api):
assert nodeinfo
assert nodeinfo.version == '2.0'
@pytest.mark.vcr()
def test_trends(api):
assert isinstance(api.trends(), list)
@pytest.mark.vcr()
def test_directory(api):
directory = api.directory()

Wyświetl plik

@ -0,0 +1,21 @@
import pytest
import time
import vcr
@pytest.mark.vcr()
def test_trending_tags(api):
tags = api.trending_tags()
assert isinstance(tags, list)
tags = api.trends()
assert isinstance(tags, list)
@pytest.mark.vcr()
def test_trending_statuses(api):
statuses = api.trending_statuses()
assert isinstance(statuses, list)
@pytest.mark.vcr()
def test_trending_links(api):
links = api.trending_links()
assert isinstance(links, list)