pull/397/head
halcy 2025-02-15 21:54:08 +02:00
rodzic 2fde93fd3c
commit 108ae64f9e
9 zmienionych plików z 1399 dodań i 38 usunięć

Wyświetl plik

@ -44,7 +44,7 @@ v2.0.0 (IN PROGRESS)
* Add notification policy and requests (`notifications_policy`, `update_notifications_policy`, `notifications_requests`, `notification_request`, `accept_notification_request`, `reject_notification_request`, `notifications_merged`, `accept_multiple_notification_requests`, `dismiss_multiple_notification_requests`)
* Add `instance_languages`
* Add notification grouping (`grouped_notifications`, `grouped_notification`, `dismiss_grouped_notification`, `grouped_notification_accounts`, `unread_grouped_notifications_count`)
* Add v2 filer API (`filters_v2`, `filter_v2`, `create_filter_v2`, `update_filter_v2`, `delete_filter_v2`, `filter_keywords_v2`, `add_filter_keyword_v2`, `delete_filter_keyword_v2`, `filter_statuses_v2`, `add_filter_status_v2`, `filter_status_v2`, `delete_filter_status_v2`)
v1.8.1
------

Wyświetl plik

@ -6,10 +6,6 @@ Refer to mastodon changelog and API docs for details when implementing, add or m
-----------
* [ ] to be collected here
4.3.0 TODOs
-----------
* ?????
General improvements that would be good to do before doing another release
--------------------------------------------------------------------------
* [ ] Get test coverage like, real high

Wyświetl plik

@ -45,26 +45,26 @@ to accept or reject notification requests for filtered notifications.
.. automethod:: Mastodon.notifications_merged
Keyword filters
---------------
Keyword Filters (v2)
--------------------
These functions allow you to get information about keyword filters as well as to create and update filters.
**Very Important Note: The filtering system was revised in 4.0.0. This means that these functions will now not work anymore if an instance is on Mastodon 4.0.0 or above.
When updating Mastodon.py for 4.0.0, we'll make an effort to emulate old behaviour, but this will not always be possible. Consider these methods deprecated, for now.**
NB: The filters are checked server side, but the server still returns all statuses to the client, just with
a `filtered` attribute. Filtered notifications most likely end up as notification requests, but I have not
validated this.
The filters are applied to everything - notifications, timeline, ....
Reading
~~~~~~~
.. automethod:: Mastodon.filters
.. automethod:: Mastodon.filter
.. automethod:: Mastodon.filters_apply
Writing
~~~~~~~
.. automethod:: Mastodon.filter_create
.. automethod:: Mastodon.filter_update
.. automethod:: Mastodon.filter_delete
.. automethod:: Mastodon.filters_v2
.. automethod:: Mastodon.filter_v2
.. automethod:: Mastodon.create_filter_v2
.. automethod:: Mastodon.update_filter_v2
.. automethod:: Mastodon.delete_filter_v2
.. automethod:: Mastodon.filter_keywords_v2
.. automethod:: Mastodon.add_filter_keyword_v2
.. automethod:: Mastodon.delete_filter_keyword_v2
.. automethod:: Mastodon.filter_statuses_v2
.. automethod:: Mastodon.add_filter_status_v2
.. automethod:: Mastodon.filter_status_v2
.. automethod:: Mastodon.delete_filter_status_v2
Push notifications
@ -119,4 +119,22 @@ This is a minimal usage example for the push API, including a small http server
pass
finally:
httpd.server_close()
api.push_subscription_delete()
api.push_subscription_delete()
Keyword filters (v1, deprecated)
--------------------------------
These functions allow you to get information about keyword filters as well as to create and update filters.
These APIs are deprecated in favor of the v2 APIs - I would recommend using those instead.
Reading
~~~~~~~
.. automethod:: Mastodon.filters
.. automethod:: Mastodon.filter
.. automethod:: Mastodon.filters_apply
Writing
~~~~~~~
.. automethod:: Mastodon.filter_create
.. automethod:: Mastodon.filter_update
.. automethod:: Mastodon.filter_delete

Wyświetl plik

@ -6,10 +6,10 @@ from mastodon.errors import MastodonIllegalArgumentError
from mastodon.utility import api_version
from mastodon.internals import Mastodon as Internals
from mastodon.return_types import Filter, FilterV2, Status, Notification
from mastodon.return_types import Filter, FilterV2, Status, Notification, FilterKeyword, FilterStatus
from mastodon.types_base import PaginatableList, NonPaginatableList, IdType
from typing import Union, Optional
from typing import Union, Optional, List, Dict
class Mastodon(Internals):
@ -17,22 +17,20 @@ class Mastodon(Internals):
# Reading data: Keyword filters
###
@api_version("2.4.3", "2.4.3")
def filters(self) -> Union[NonPaginatableList[Filter], NonPaginatableList[FilterV2]]:
def filters(self) -> NonPaginatableList[Filter]:
"""
Fetch all of the logged-in user's filters.
"""
return self.__api_request('GET', '/api/v1/filters')
@api_version("2.4.3", "2.4.3")
def filter(self, id: Union[Filter, FilterV2, IdType]) -> Union[Filter, FilterV2]:
def filter(self, id: Union[Filter, IdType]) -> Filter:
"""
Fetches information about the filter with the specified `id`.
"""
id = self.__unpack_id(id)
return self.__api_request('GET', f'/api/v1/filters/{id}')
# TODO: Add v2 filter support
# TODO: test this properly
@api_version("2.4.3", "2.4.3")
def filters_apply(self, objects: Union[PaginatableList[Status], PaginatableList[Notification]], filters: Union[NonPaginatableList[Filter], NonPaginatableList[FilterV2]], context: str) -> Union[PaginatableList[Status], PaginatableList[Notification]]:
"""
@ -41,6 +39,9 @@ class Mastodon(Internals):
apply all filters that match the context provided in `context`, i.e.
if you want to apply only notification-relevant filters, specify
'notifications'. Valid contexts are 'home', 'notifications', 'public' and 'thread'.
NB: This is for v1 filters. v2 filters are applied by the server, which adds the "filtered"
attribute to filtered statuses.
"""
# Build filter regex
filter_strings = []
@ -71,7 +72,7 @@ class Mastodon(Internals):
# Writing data: Keyword filters
###
@api_version("2.4.3", "2.4.3")
def filter_create(self, phrase: str, context: str, irreversible: bool = False, whole_word: bool = True, expires_in: Optional[int] = None) -> Union[Filter, FilterV2]:
def filter_create(self, phrase: str, context: str, irreversible: bool = False, whole_word: bool = True, expires_in: Optional[int] = None) -> Filter:
"""
Creates a new keyword filter. `phrase` is the phrase that should be
filtered out, `context` specifies from where to filter the keywords.
@ -97,7 +98,7 @@ class Mastodon(Internals):
return self.__api_request('POST', '/api/v1/filters', params)
@api_version("2.4.3", "2.4.3")
def filter_update(self, id: Union[Filter, FilterV2, IdType], phrase: Optional[str] = None, context: Optional[str] = None, irreversible: Optional[bool] = None, whole_word: Optional[bool] = None, expires_in: Optional[int] = None) -> Union[Filter, FilterV2]:
def filter_update(self, id: Union[Filter, IdType], phrase: Optional[str] = None, context: Optional[str] = None, irreversible: Optional[bool] = None, whole_word: Optional[bool] = None, expires_in: Optional[int] = None) -> Filter:
"""
Updates the filter with the given `id`. Parameters are the same
as in `filter_create()`.
@ -115,3 +116,150 @@ class Mastodon(Internals):
"""
id = self.__unpack_id(id)
self.__api_request('DELETE', f'/api/v1/filters/{id}')
###
# Filters v2 api
###
@api_version("4.0.0", "4.0.0")
def filters_v2(self) -> NonPaginatableList[FilterV2]:
"""
Fetch all filters for the authenticated user.
"""
return self.__api_request('GET', '/api/v2/filters')
@api_version("4.0.0", "4.0.0")
def filter_v2(self, filter_id: Union[Filter, IdType]) -> Filter:
"""
Fetch a specific filter by its ID.
"""
filter_id = self.__unpack_id(filter_id)
return self.__api_request('GET', f'/api/v2/filters/{filter_id}')
@api_version("4.0.0", "4.0.0")
def create_filter_v2(
self,
title: str,
context: List[str],
filter_action: str,
expires_in: Optional[int] = None,
keywords_attributes: Optional[List[Dict[str, Union[str, bool]]]] = None
) -> FilterV2:
"""
Create a new filter with the given parameters.
`title` is a human readable name for the filter.
`context` is list of contexts where the filter should apply. Valid values are:
- "home": Filter applies to the home timeline.
- "notifications": Filter applies to notifications. Filtered notifications land in notification requests.
- "public": Filter applies to the public timelines.
- "thread": Filter applies to conversations.
- "account": Filter applies to account timelines.
`filter_action` gives the policy to be applied when the filter is matched. Valid values are:
- "warn": The user is warned if the content matches the filter.
- "hide": The content is completely hidden if it matches the filter.
NB: Even if you specify "hide", the status will still be returned - it will just have the "filtered" attribute set.
pass a number of seconds as `expires_in` to make the filter expire in that many seconds. Use None for no expiration.
pass a list of keyword dicts to initially as `keywords_attributes`, each with the following values:
- "keyword": The term to filter on.
- "whole_word": Whether word boundaries should be considered.
"""
params = self.__generate_params(locals(), for_json=True)
return self.__api_request('POST', '/api/v2/filters', params, use_json=True)
@api_version("4.0.0", "4.0.0")
def update_filter_v2(
self,
filter_id: Union[FilterV2, IdType],
title: Optional[str] = None,
context: Optional[List[str]] = None,
filter_action: Optional[str] = None,
expires_in: Optional[int] = None,
keywords_attributes: Optional[List[Dict[str, Union[str, bool, int]]]] = None
) -> FilterV2:
"""
Update an existing filter with the given parameters.
Parameters are as in `create_filter_v2()`. Only the parameters you want to update need to be provided.
"""
filter_id = self.__unpack_id(filter_id)
params = self.__generate_params(locals(), for_json=True)
return self.__api_request('PUT', f'/api/v2/filters/{filter_id}', params, use_json=True)
@api_version("4.0.0", "4.0.0")
def delete_filter_v2(self, filter_id: Union[FilterV2, IdType]) -> None:
"""
Delete an existing filter.
"""
filter_id = self.__unpack_id(filter_id)
self.__api_request('DELETE', f'/api/v2/filters/{filter_id}')
@api_version("4.0.0", "4.0.0")
def filter_keywords_v2(self, filter_id: Union[FilterV2, IdType]) -> NonPaginatableList[FilterKeyword]:
"""
Fetch all keywords associated with a given filter.
"""
filter_id = self.__unpack_id(filter_id)
return self.__api_request('GET', f'/api/v2/filters/{filter_id}/keywords')
@api_version("4.0.0", "4.0.0")
def add_filter_keyword_v2(
self,
filter_id: Union[FilterV2, IdType],
keyword: str,
whole_word: bool = False
) -> FilterKeyword:
"""
Add a single keyword to an existing filter.
Parameters are as in `create_filter_v2()` `keywords_attributes`.
"""
filter_id = self.__unpack_id(filter_id)
params = self.__generate_params(locals())
return self.__api_request('POST', f'/api/v2/filters/{filter_id}/keywords', params)
@api_version("4.0.0", "4.0.0")
def delete_filter_keyword_v2(self, keyword_id: Union[FilterKeyword, IdType]) -> None:
"""
Delete a single keyword from any filter.
"""
keyword_id = self.__unpack_id(keyword_id)
self.__api_request('DELETE', f'/api/v2/filters/keywords/{keyword_id}')
@api_version("4.0.0", "4.0.0")
def filter_statuses_v2(self, filter_id: Union[FilterV2, IdType]) -> List[FilterStatus]:
"""
Retrieve all status-based filters for a FilterV2.
"""
filter_id = self.__unpack_id(filter_id)
return self.__api_request('GET', f'/api/v2/filters/{filter_id}/statuses')
@api_version("4.0.0", "4.0.0")
def add_filter_status_v2(self, filter_id: Union[FilterV2, IdType], status_id: Union[Status, IdType]) -> FilterStatus:
"""
Add a status to a filter, which will then match on that status in addition to any keywords.
Includes reblogs, does not include replies.
"""
filter_id = self.__unpack_id(filter_id)
status_id = self.__unpack_id(status_id)
params = self.__generate_params({"status_id": status_id})
return self.__api_request('POST', f'/api/v2/filters/{filter_id}/statuses', params)
@api_version("4.0.0", "4.0.0")
def filter_status_v2(self, filter_status_id: Union[FilterStatus, IdType]) -> FilterStatus:
"""
Fetch a single status-based filter by its ID.
"""
filter_status_id = self.__unpack_id(filter_status_id)
return self.__api_request('GET', f'/api/v2/filters/statuses/{filter_status_id}')
@api_version("4.0.0", "4.0.0")
def delete_filter_status_v2(self, filter_status_id: Union[FilterStatus, IdType]) -> None:
"""
Remove a status filter from a FilterV2.
"""
filter_status_id = self.__unpack_id(filter_status_id)
self.__api_request('DELETE', f'/api/v2/filters/statuses/{filter_status_id}')

Wyświetl plik

@ -275,7 +275,7 @@ class Mastodon():
response = response_object.content
# Parse link headers
if isinstance(response, list) or force_pagination and 'Link' in response_object.headers and response_object.headers['Link'] != "":
if (isinstance(response, list) or force_pagination) and 'Link' in response_object.headers and response_object.headers['Link'] != "":
if not isinstance(response, PaginatableList) and not force_pagination:
response = PaginatableList(response)
tmp_urls = requests.utils.parse_header_links(response_object.headers['Link'].rstrip('>').replace('>,<', ',<'))

Wyświetl plik

@ -2712,7 +2712,7 @@
{
"name": "Filter (v2)",
"python_name": "FilterV2",
"func_call": "mastodon.filters()[0]",
"func_call": "mastodon.filters_v2()[0]",
"masto_doc_link": "https://docs.joinmastodon.org/entities/Filter/",
"func_call_real": null,
"func_call_additional": null,
@ -8638,7 +8638,7 @@
{
"name": "Filter keyword",
"python_name": "FilterKeyword",
"func_call": "TODO_TO_BE_IMPLEMENTED",
"func_call": "mastodon.filters_v2()[0].keywords[0]",
"func_call_real": null,
"func_call_additional": null,
"func_alternate_acc": null,
@ -8696,7 +8696,7 @@
{
"name": "Filter status",
"python_name": "FilterStatus",
"func_call": "TODO_TO_BE_IMPLEMENTED",
"func_call": "mastodon.filter_statuses_v2(mastodon.filters_v2()[0])[0]",
"func_call_real": null,
"func_call_additional": null,
"func_alternate_acc": null,
@ -9423,7 +9423,7 @@
{
"name": "Grouped Notifications Results",
"python_name": "GroupedNotificationsResults",
"func_call": "TODO_TO_BE_IMPLEMENTED",
"func_call": "mastodon.grouped_notifications()",
"func_call_real": null,
"func_call_additional": null,
"func_alternate_acc": null,
@ -9496,7 +9496,7 @@
{
"name": "Partial Account With Avatar",
"python_name": "PartialAccountWithAvatar",
"func_call": "TODO_TO_BE_IMPLEMENTED",
"func_call": "mastodon.grouped_notifications().partial_accounts[0]",
"func_call_real": null,
"func_call_additional": null,
"func_alternate_acc": null,
@ -9579,7 +9579,7 @@
{
"name": "Notification Group",
"python_name": "NotificationGroup",
"func_call": "TODO_TO_BE_IMPLEMENTED",
"func_call": "mastodon.grouped_notifications().notification_groups[0]",
"func_call_real": null,
"func_call_additional": null,
"func_alternate_acc": null,

Wyświetl plik

@ -0,0 +1,556 @@
interactions:
- request:
body: '{"title": "Test Filter", "context": ["home", "public"], "filter_action":
"warn", "keywords_attributes": [{"keyword": "spam", "whole_word": true}, {"keyword":
"eggs", "whole_word": false}]}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
Content-Length:
- '188'
Content-Type:
- application/json
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v2/filters
response:
body:
string: '{"id":"3","title":"Test Filter","context":["home","public"],"expires_at":null,"filter_action":"warn","keywords":[{"id":"3","keyword":"spam","whole_word":true},{"id":"4","keyword":"eggs","whole_word":false}],"statuses":[]}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '221'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"ef312da2a51d3dd730869912d62e8291"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.05, sql.active_record;dur=8.10, cache_generate.active_support;dur=1.75,
cache_write.active_support;dur=0.13, instantiation.active_record;dur=0.71,
start_processing.action_controller;dur=0.00, unpermitted_parameters.action_controller;dur=0.00,
transaction.active_record;dur=6.02, cache_delete.active_support;dur=0.02,
render.active_model_serializers;dur=2.59, process_action.action_controller;dur=31.66
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.740703Z'
X-Request-Id:
- 310e16c6-d402-405c-b0d2-a9d1237f59a6
X-Runtime:
- '0.056475'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/3
response:
body:
string: '{"id":"3","title":"Test Filter","context":["home","public"],"expires_at":null,"filter_action":"warn","keywords":[{"id":"3","keyword":"spam","whole_word":true},{"id":"4","keyword":"eggs","whole_word":false}],"statuses":[]}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '221'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"ef312da2a51d3dd730869912d62e8291"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.78, cache_generate.active_support;dur=0.86,
cache_write.active_support;dur=0.08, instantiation.active_record;dur=0.34,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=2.11,
process_action.action_controller;dur=34.30
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.791946Z'
X-Request-Id:
- 51c60902-1535-42da-a13e-171a92121aa5
X-Runtime:
- '0.048975'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
- request:
body: '{"filter_id": "3", "title": "Updated Title", "filter_action": "hide"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
Content-Length:
- '69'
Content-Type:
- application/json
User-Agent:
- tests/v311
method: PUT
uri: http://localhost:3000/api/v2/filters/3
response:
body:
string: '{"id":"3","title":"Updated Title","context":["home","public"],"expires_at":null,"filter_action":"hide","keywords":[{"id":"3","keyword":"spam","whole_word":true},{"id":"4","keyword":"eggs","whole_word":false}],"statuses":[]}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '223'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"ef90ce7160a9385a7e513d9523756dd2"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=4.16, cache_generate.active_support;dur=0.79,
cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.38,
start_processing.action_controller;dur=0.00, unpermitted_parameters.action_controller;dur=0.00,
transaction.active_record;dur=3.96, cache_delete.active_support;dur=0.02,
render.active_model_serializers;dur=2.02, process_action.action_controller;dur=37.48
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.856526Z'
X-Request-Id:
- 923a6488-e0da-442e-a610-d1ad4e20248a
X-Runtime:
- '0.052710'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/3/keywords
response:
body:
string: '[{"id":"3","keyword":"spam","whole_word":true},{"id":"4","keyword":"eggs","whole_word":false}]'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '94'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"fd65742072146847502a0a2c6a04f472"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.64, cache_generate.active_support;dur=0.68,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.31,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.21,
process_action.action_controller;dur=19.97
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.902788Z'
X-Request-Id:
- 0feb5320-7184-4733-a299-751865258133
X-Runtime:
- '0.034602'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
- request:
body: filter_id=3&keyword=foo&whole_word=1
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
Content-Length:
- '36'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v2/filters/3/keywords
response:
body:
string: '{"id":"5","keyword":"foo","whole_word":true}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '44'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"1b64a2f9390c9282d3922ce7fa6a55a4"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=3.38, cache_generate.active_support;dur=0.67,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.29,
start_processing.action_controller;dur=0.00, unpermitted_parameters.action_controller;dur=0.00,
transaction.active_record;dur=2.88, cache_delete.active_support;dur=0.01,
render.active_model_serializers;dur=0.14, process_action.action_controller;dur=24.91
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.942786Z'
X-Request-Id:
- ab80df2e-e971-4de5-80e3-a8de25d2563a
X-Runtime:
- '0.039518'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/3/keywords
response:
body:
string: '[{"id":"3","keyword":"spam","whole_word":true},{"id":"4","keyword":"eggs","whole_word":false},{"id":"5","keyword":"foo","whole_word":true}]'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '139'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"a3c7206fea8e0a68cdbb63e7454aadd2"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.57, cache_generate.active_support;dur=0.67,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.27,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.24,
process_action.action_controller;dur=18.91
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.983496Z'
X-Request-Id:
- 9c69600a-f430-4d93-afdb-c541f94bc4af
X-Runtime:
- '0.032516'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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
Content-Length:
- '0'
User-Agent:
- tests/v311
method: DELETE
uri: http://localhost:3000/api/v2/filters/keywords/3
response:
body:
string: '{}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '2'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"44136fa355b3678a1146ad16f7e8649e"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.01, sql.active_record;dur=3.93, cache_generate.active_support;dur=0.54,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.62,
start_processing.action_controller;dur=0.00, transaction.active_record;dur=3.35,
cache_delete.active_support;dur=0.02, render.active_model_serializers;dur=0.03,
process_action.action_controller;dur=28.96
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.019360Z'
X-Request-Id:
- deefa0be-2b24-4fd6-93dc-4e2f43b3bd5c
X-Runtime:
- '0.042246'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/3/keywords
response:
body:
string: '[{"id":"4","keyword":"eggs","whole_word":false},{"id":"5","keyword":"foo","whole_word":true}]'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '93'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"ae9198d796f6174ca3033d3f89b908cc"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.59, cache_generate.active_support;dur=0.90,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.28,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.20,
process_action.action_controller;dur=30.29
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.076833Z'
X-Request-Id:
- 34eb8d75-a112-421a-80af-8dc34c2a9197
X-Runtime:
- '0.044549'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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
Content-Length:
- '0'
User-Agent:
- tests/v311
method: DELETE
uri: http://localhost:3000/api/v2/filters/3
response:
body:
string: '{}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '2'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"44136fa355b3678a1146ad16f7e8649e"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=3.85, cache_generate.active_support;dur=0.59,
cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.36,
start_processing.action_controller;dur=0.00, transaction.active_record;dur=5.77,
cache_delete.active_support;dur=0.02, render.active_model_serializers;dur=0.03,
process_action.action_controller;dur=25.98
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:45:00.114148Z'
X-Request-Id:
- b71d21d2-2e27-478c-8b5f-eb053ddac138
X-Runtime:
- '0.039812'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
version: 1

Wyświetl plik

@ -0,0 +1,559 @@
interactions:
- request:
body: '{"title": "Status Filter Test", "context": ["home"], "filter_action": "warn"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
Content-Length:
- '77'
Content-Type:
- application/json
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v2/filters
response:
body:
string: '{"id":"5","title":"Status Filter Test","context":["home"],"expires_at":null,"filter_action":"warn","keywords":[],"statuses":[]}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '127'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"bafc2639f8776dc7b204e418be951a08"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.03, sql.active_record;dur=4.61, cache_generate.active_support;dur=1.26,
cache_write.active_support;dur=0.12, instantiation.active_record;dur=0.46,
start_processing.action_controller;dur=0.00, unpermitted_parameters.action_controller;dur=0.00,
transaction.active_record;dur=4.12, cache_delete.active_support;dur=0.02,
render.active_model_serializers;dur=7.12, process_action.action_controller;dur=32.97
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.442802Z'
X-Request-Id:
- df6666ea-6834-41d8-b40c-950e2fe46f32
X-Runtime:
- '0.050382'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
- request:
body: status=This+is+a+test+status+for+filter%21&visibility=public
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
Content-Length:
- '60'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v1/statuses
response:
body:
string: '{"id":"114009620185192115","created_at":"2025-02-15T19:45:45.502Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"public","language":"ja","uri":"http://localhost:3000/users/mastodonpy_test/statuses/114009620185192115","url":"http://localhost:3000/@mastodonpy_test/114009620185192115","replies_count":0,"reblogs_count":0,"favourites_count":0,"edited_at":null,"favourited":false,"reblogged":false,"muted":false,"bookmarked":false,"pinned":false,"content":"\u003cp\u003eThis
is a test status for filter!\u003c/p\u003e","filtered":[],"reblog":null,"application":{"name":"Mastodon.py
test suite","website":null},"account":{"id":"114009019326978043","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"indexable":false,"group":false,"created_at":"2025-02-15T00:00:00.000Z","note":"","url":"http://localhost:3000/@mastodonpy_test","uri":"http://localhost:3000/users/mastodonpy_test","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":2,"last_status_at":"2025-02-15","hide_collections":null,"noindex":false,"emojis":[],"roles":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '1508'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"a87810105cba0ef1ee5b9b4df19ed227"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.07, sql.active_record;dur=12.11, cache_generate.active_support;dur=3.18,
cache_write.active_support;dur=0.24, instantiation.active_record;dur=0.50,
start_processing.action_controller;dur=0.00, transaction.active_record;dur=12.75,
render.active_model_serializers;dur=12.94, process_action.action_controller;dur=57.88
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '295'
X-RateLimit-Reset:
- '2025-02-15T21:00:00.537289Z'
X-Request-Id:
- bfa31377-96dd-4adf-9d22-d848247ea7cb
X-Runtime:
- '0.072455'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
- request:
body: status_id=114009620185192115
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
Connection:
- keep-alive
Content-Length:
- '28'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v2/filters/5/statuses
response:
body:
string: '{"id":"1","status_id":"114009620185192115"}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '43'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"6f22aff59bd092b2dbe5960b33c5417a"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=5.94, cache_generate.active_support;dur=0.96,
cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.59,
start_processing.action_controller;dur=0.00, unpermitted_parameters.action_controller;dur=0.00,
transaction.active_record;dur=10.71, cache_delete.active_support;dur=0.02,
render.active_model_serializers;dur=0.20, process_action.action_controller;dur=39.17
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.599982Z'
X-Request-Id:
- b25c0312-bd58-4e65-87cb-1de757937b8d
X-Runtime:
- '0.055019'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/5/statuses
response:
body:
string: '[{"id":"1","status_id":"114009620185192115"}]'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '45'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"8eab4711dd0ffd6329a3d42c15ef7ec5"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.74, cache_generate.active_support;dur=4.99,
cache_write.active_support;dur=0.08, instantiation.active_record;dur=0.34,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.17,
process_action.action_controller;dur=20.18
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.661225Z'
X-Request-Id:
- c90842b6-03c7-4745-94b5-4e4c12f47bf1
X-Runtime:
- '0.039457'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/statuses/1
response:
body:
string: '{"id":"1","status_id":"114009620185192115"}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '43'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"6f22aff59bd092b2dbe5960b33c5417a"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.90, cache_generate.active_support;dur=0.65,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.65,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.20,
process_action.action_controller;dur=20.98
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.699471Z'
X-Request-Id:
- f3e2f718-f74c-4170-9c6c-914276108d3b
X-Runtime:
- '0.035255'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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/v2/filters/5/statuses
response:
body:
string: '[{"id":"1","status_id":"114009620185192115"}]'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '45'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"8eab4711dd0ffd6329a3d42c15ef7ec5"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=0.78, cache_generate.active_support;dur=0.77,
cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.30,
start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.16,
process_action.action_controller;dur=20.17
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.738456Z'
X-Request-Id:
- f1d09889-4335-420b-b6f0-1fe860272fcd
X-Runtime:
- '0.034827'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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
Content-Length:
- '0'
User-Agent:
- tests/v311
method: DELETE
uri: http://localhost:3000/api/v2/filters/statuses/1
response:
body:
string: '{}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '2'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"44136fa355b3678a1146ad16f7e8649e"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=3.93, cache_generate.active_support;dur=0.74,
cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.37,
start_processing.action_controller;dur=0.00, transaction.active_record;dur=3.25,
cache_delete.active_support;dur=0.02, render.active_model_serializers;dur=0.04,
process_action.action_controller;dur=24.55
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.776839Z'
X-Request-Id:
- f53a1489-e5c4-4124-b45a-4c5b07407ae1
X-Runtime:
- '0.038984'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
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
Content-Length:
- '0'
User-Agent:
- tests/v311
method: DELETE
uri: http://localhost:3000/api/v2/filters/5
response:
body:
string: '{}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '2'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"44136fa355b3678a1146ad16f7e8649e"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.02, sql.active_record;dur=3.21, cache_generate.active_support;dur=0.70,
cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.35,
start_processing.action_controller;dur=0.00, transaction.active_record;dur=3.93,
cache_delete.active_support;dur=0.02, render.active_model_serializers;dur=0.02,
process_action.action_controller;dur=30.31
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '300'
X-RateLimit-Remaining:
- '299'
X-RateLimit-Reset:
- '2025-02-15T19:50:00.818776Z'
X-Request-Id:
- a9e30741-58ea-4e6b-bbad-8813bced2035
X-Runtime:
- '0.044376'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
Content-Length:
- '0'
User-Agent:
- tests/v311
method: DELETE
uri: http://localhost:3000/api/v1/statuses/114009620185192115
response:
body:
string: '{"id":"114009620185192115","created_at":"2025-02-15T19:45:45.502Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"public","language":"ja","uri":"http://localhost:3000/users/mastodonpy_test/statuses/114009620185192115","url":"http://localhost:3000/@mastodonpy_test/114009620185192115","replies_count":0,"reblogs_count":0,"favourites_count":0,"edited_at":null,"favourited":false,"reblogged":false,"muted":false,"bookmarked":false,"pinned":false,"text":"This
is a test status for filter!","filtered":[],"reblog":null,"application":{"name":"Mastodon.py
test suite","website":null},"account":{"id":"114009019326978043","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"indexable":false,"group":false,"created_at":"2025-02-15T00:00:00.000Z","note":"","url":"http://localhost:3000/@mastodonpy_test","uri":"http://localhost:3000/users/mastodonpy_test","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":1,"last_status_at":"2025-02-15","hide_collections":null,"noindex":false,"emojis":[],"roles":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null}'
headers:
Cache-Control:
- private, no-store
Content-Length:
- '1478'
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'; form-action 'none'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"23a5447cefb48522ba69e630745b64ee"
Referrer-Policy:
- strict-origin-when-cross-origin
Server-Timing:
- cache_read.active_support;dur=0.05, sql.active_record;dur=6.79, cache_generate.active_support;dur=2.78,
cache_write.active_support;dur=0.13, instantiation.active_record;dur=0.65,
start_processing.action_controller;dur=0.00, transaction.active_record;dur=3.95,
render.active_model_serializers;dur=16.41, process_action.action_controller;dur=43.33
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-RateLimit-Limit:
- '30'
X-RateLimit-Remaining:
- '29'
X-RateLimit-Reset:
- '2025-02-15T20:00:00.867159Z'
X-Request-Id:
- 238dbde5-f195-469e-871f-69bb758f2ddc
X-Runtime:
- '0.057672'
X-XSS-Protection:
- '0'
vary:
- Authorization, Origin
status:
code: 200
message: OK
version: 1

Wyświetl plik

@ -115,3 +115,87 @@ def test_filter_clientside(api, api2):
api2.status_delete(status_2)
api2.status_delete(status_3)
api2.status_delete(status_4)
@pytest.mark.vcr()
def test_v2_filters_keywords(api2):
new_filter = api2.create_filter_v2(
title="Test Filter",
context=["home", "public"],
filter_action="warn",
keywords_attributes=[
{"keyword": "spam", "whole_word": True},
{"keyword": "eggs", "whole_word": False}
]
)
assert new_filter is not None
assert new_filter["title"] == "Test Filter"
assert len(new_filter["keywords"]) == 2
filter_id = new_filter["id"]
try:
fetched_filter = api2.filter_v2(filter_id)
assert fetched_filter["title"] == "Test Filter"
updated_filter = api2.update_filter_v2(
filter_id,
title="Updated Title",
filter_action="hide"
)
assert updated_filter["title"] == "Updated Title"
assert updated_filter["filter_action"] == "hide"
filter_keywords = api2.filter_keywords_v2(filter_id)
assert len(filter_keywords) == 2
keyword_ids = [kw["id"] for kw in filter_keywords]
new_kw = api2.add_filter_keyword_v2(filter_id, keyword="foo", whole_word=True)
assert new_kw["keyword"] == "foo"
updated_keywords = api2.filter_keywords_v2(filter_id)
assert len(updated_keywords) == 3
api2.delete_filter_keyword_v2(keyword_ids[0])
after_delete_keywords = api2.filter_keywords_v2(filter_id)
assert len(after_delete_keywords) == 2
finally:
api2.delete_filter_v2(filter_id)
@pytest.mark.vcr()
def test_v2_filters_statuses(api2, api):
new_filter = api2.create_filter_v2(
title="Status Filter Test",
context=["home"],
filter_action="warn",
)
assert new_filter is not None
filter_id = new_filter["id"]
status = api.status_post("This is a test status for filter!", visibility="public")
status_id = status["id"]
try:
filter_status = api2.add_filter_status_v2(filter_id, status_id)
assert filter_status is not None
assert filter_status["status_id"] == status_id
statuses_list = api2.filter_statuses_v2(filter_id)
assert len(statuses_list) == 1
assert statuses_list[0]["status_id"] == status_id
filter_status_id = statuses_list[0]["id"]
single_status = api2.filter_status_v2(filter_status_id)
assert single_status["id"] == filter_status_id
assert single_status["status_id"] == status_id
finally:
statuses_list = api2.filter_statuses_v2(filter_id)
for st in statuses_list:
api2.delete_filter_status_v2(st["id"])
api2.delete_filter_v2(filter_id)
# Clean up the status
if status_id:
api.status_delete(status_id)