From 1e4293ae3e32481d5d9e536eb2bb89f3c930ee2f Mon Sep 17 00:00:00 2001 From: halcy Date: Sun, 17 Aug 2025 23:07:09 +0300 Subject: [PATCH] add new featured tags endpoints --- CHANGELOG.rst | 1 + TODO.md | 2 +- docs/06_accounts.rst | 7 +- mastodon/hashtags.py | 28 ++ tests/cassettes/test_featured_tags_2.yaml | 368 ++++++++++++++++++++++ tests/test_account.py | 32 ++ tests/test_admin_trends.yaml | 238 -------------- 7 files changed, 435 insertions(+), 241 deletions(-) create mode 100644 tests/cassettes/test_featured_tags_2.yaml delete mode 100644 tests/test_admin_trends.yaml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d57e79b..a33be98 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -26,6 +26,7 @@ v2.1.0 (IN PROGRESS) * Added `attribution_domains` parameter to `account_update_credentials`. * Added `date_of_birth` parameter to `create_account`. * Added `account_endorse` and `account_unendorse` methods (replacing "pin" methods) +* Added `tag_feature` and `tag_unfeature` methods (replacing previous featured tag api) v2.0.1 ------ diff --git a/TODO.md b/TODO.md index c9416b0..5762c78 100644 --- a/TODO.md +++ b/TODO.md @@ -6,7 +6,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m ----------- * [x] Fix all the issues * [x] New endpoints for endorsements, replacing "pin" api, which is now deprecated: accounts_endorsements(id), account_endorse(id), account_unendorse(id) -* [ ] New endpoints for featured tags: tag_feature(name), tag_unfeature(name) +* [x] New endpoints for featured tags: tag_feature(name), tag_unfeature(name) * [ ] New endpoint: instance_terms, with or without date (format?) * [x] Some oauth stuff (userinfo? capability discovery? see issue for that) * [x] status_delete now has a media delete param diff --git a/docs/06_accounts.rst b/docs/06_accounts.rst index c9cb4a0..660ba82 100644 --- a/docs/06_accounts.rst +++ b/docs/06_accounts.rst @@ -38,8 +38,8 @@ Writing .. automethod:: Mastodon.account_note_set -.. automethod:: Mastodon.featured_tag_create -.. automethod:: Mastodon.featured_tag_delete +.. automethod:: Mastodon.tag_feature +.. automethod:: Mastodon.tag_unfeature .. _status_pin(): .. automethod:: Mastodon.status_pin @@ -54,6 +54,9 @@ Deprecated .. automethod:: Mastodon.account_pin .. automethod:: Mastodon.account_unpin +.. automethod:: Mastodon.featured_tag_create +.. automethod:: Mastodon.featured_tag_delete + Following and followers ----------------------- These functions allow you to get information about the logged in users followers and users that the logged in users follows as well as follow requests and follow suggestions, and to diff --git a/mastodon/hashtags.py b/mastodon/hashtags.py index 0ddc57e..b93ea73 100644 --- a/mastodon/hashtags.py +++ b/mastodon/hashtags.py @@ -36,6 +36,8 @@ class Mastodon(Internals): Creates a new featured hashtag displayed on the logged-in user's profile. The returned object is the newly featured tag. + + Obsoleted by `tag_feature` / `tag_unfeature`. """ params = self.__generate_params(locals()) return self.__api_request('POST', '/api/v1/featured_tags', params) @@ -44,10 +46,36 @@ class Mastodon(Internals): def featured_tag_delete(self, id: Union[FeaturedTag, IdType]): """ Deletes one of the logged-in user's featured hashtags. + + Obsoleted by `tag_feature` / `tag_unfeature`. """ id = self.__unpack_id(id) self.__api_request('DELETE', f'/api/v1/featured_tags/{id}') + @api_version("4.4.0", "4.4.0") + def tag_feature(self, name: str) -> Tag: + """ + Creates a new featured hashtag displayed on the logged-in user's profile. + + Same effect as above, but newer. Likely obsoletes `featured_tag_create`. + """ + name = self.__unpack_id(name, field="name") + if name.startswith("#"): + raise MastodonIllegalArgumentError("Hashtag parameter should omit leading #") + return self.__api_request('POST', f'/api/v1/tags/{name}/feature') + + @api_version("4.4.0", "4.4.0") + def tag_unfeature(self, name: str) -> Tag: + """ + Deletes one of the logged-in user's featured hashtags. + + Same effect as above, but newer. Likely obsoletes `featured_tag_delete`. + """ + name = self.__unpack_id(name, field="name") + if name.startswith("#"): + raise MastodonIllegalArgumentError("Hashtag parameter should omit leading #") + return self.__api_request('POST', f'/api/v1/tags/{name}/unfeature') + ### # Reading data: Followed tags ### diff --git a/tests/cassettes/test_featured_tags_2.yaml b/tests/cassettes/test_featured_tags_2.yaml new file mode 100644 index 0000000..52a884c --- /dev/null +++ b/tests/cassettes/test_featured_tags_2.yaml @@ -0,0 +1,368 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - tests/v311 + method: POST + uri: http://localhost:3000/api/v1/tags/ringtones/feature + response: + body: + string: '{"id":"1","name":"ringtones","url":"http://localhost:3000/tags/ringtones","history":[{"day":"1755388800","accounts":"1","uses":"1"},{"day":"1755302400","accounts":"0","uses":"0"},{"day":"1755216000","accounts":"0","uses":"0"},{"day":"1755129600","accounts":"0","uses":"0"},{"day":"1755043200","accounts":"0","uses":"0"},{"day":"1754956800","accounts":"0","uses":"0"},{"day":"1754870400","accounts":"0","uses":"0"}],"following":false,"featuring":true}' + headers: + Content-Length: + - '450' + cache-control: + - private, no-store + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + content-type: + - application/json; charset=utf-8 + etag: + - W/"cfddeb6f9af49b97def2c924319257ef" + referrer-policy: + - strict-origin-when-cross-origin + server-timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=7.01, cache_generate.active_support;dur=2.23, + cache_write.active_support;dur=0.09, instantiation.active_record;dur=0.25, + start_processing.action_controller;dur=0.00, start_transaction.active_record;dur=0.00, + transaction.active_record;dur=7.88, render.active_model_serializers;dur=3.01, + process_action.action_controller;dur=47.66 + vary: + - Authorization, Origin + 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-08-17T20:10:00.947997Z' + x-request-id: + - 0c0ae4c9-46f9-46bc-8f61-734005c4e02e + x-runtime: + - '0.076207' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - tests/v311 + method: POST + uri: http://localhost:3000/api/v1/tags/coolfree/feature + response: + body: + string: '{"id":"2","name":"coolfree","url":"http://localhost:3000/tags/coolfree","history":[{"day":"1755388800","accounts":"0","uses":"0"},{"day":"1755302400","accounts":"0","uses":"0"},{"day":"1755216000","accounts":"0","uses":"0"},{"day":"1755129600","accounts":"0","uses":"0"},{"day":"1755043200","accounts":"0","uses":"0"},{"day":"1754956800","accounts":"0","uses":"0"},{"day":"1754870400","accounts":"0","uses":"0"}],"following":false,"featuring":true}' + headers: + Content-Length: + - '448' + cache-control: + - private, no-store + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + content-type: + - application/json; charset=utf-8 + etag: + - W/"369c2c496de2cba8c54e640098740f5c" + referrer-policy: + - strict-origin-when-cross-origin + server-timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=8.15, cache_generate.active_support;dur=1.33, + cache_write.active_support;dur=0.09, instantiation.active_record;dur=0.20, + start_processing.action_controller;dur=0.00, start_transaction.active_record;dur=0.00, + transaction.active_record;dur=9.10, render.active_model_serializers;dur=3.20, + process_action.action_controller;dur=46.14 + vary: + - Authorization, Origin + 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-08-17T20:10:00.018667Z' + x-request-id: + - 2ab0c9d7-f7e5-421a-98a7-545c414a1ccb + x-runtime: + - '0.062602' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - tests/v311 + method: POST + uri: http://localhost:3000/api/v1/tags/ringtones/unfeature + response: + body: + string: '{"id":"1","name":"ringtones","url":"http://localhost:3000/tags/ringtones","history":[{"day":"1755388800","accounts":"1","uses":"1"},{"day":"1755302400","accounts":"0","uses":"0"},{"day":"1755216000","accounts":"0","uses":"0"},{"day":"1755129600","accounts":"0","uses":"0"},{"day":"1755043200","accounts":"0","uses":"0"},{"day":"1754956800","accounts":"0","uses":"0"},{"day":"1754870400","accounts":"0","uses":"0"}],"following":false,"featuring":false}' + headers: + Content-Length: + - '451' + cache-control: + - private, no-store + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + content-type: + - application/json; charset=utf-8 + etag: + - W/"dfe77db42bbfd5d597c16c0dfe2945c7" + referrer-policy: + - strict-origin-when-cross-origin + server-timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=6.55, cache_generate.active_support;dur=1.33, + cache_write.active_support;dur=0.38, instantiation.active_record;dur=0.32, + start_processing.action_controller;dur=0.00, start_transaction.active_record;dur=0.00, + transaction.active_record;dur=4.94, render.active_model_serializers;dur=4.91, + process_action.action_controller;dur=44.17 + vary: + - Authorization, Origin + 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-08-17T20:10:00.093785Z' + x-request-id: + - f3bf5ab0-9600-4239-9455-1e09fbb0a3bf + x-runtime: + - '0.060955' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/accounts/verify_credentials + response: + body: + string: '{"id":"115045656361106495","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"indexable":false,"group":false,"created_at":"2025-08-17T00: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":5,"last_status_at":"2025-08-17","hide_collections":null,"noindex":false,"source":{"privacy":"public","sensitive":false,"language":null,"note":"","fields":[],"follow_requests_count":0,"hide_collections":null,"discoverable":null,"indexable":false,"attribution_domains":[]},"emojis":[],"roles":[],"fields":[],"role":{"id":"-99","name":"","permissions":"65536","color":"","highlighted":false}}' + headers: + Content-Length: + - '1034' + cache-control: + - private, no-store + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + content-type: + - application/json; charset=utf-8 + etag: + - W/"d34f4c1f6ca67de3682d7588c4d94032" + referrer-policy: + - strict-origin-when-cross-origin + server-timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=1.19, cache_generate.active_support;dur=1.30, + cache_write.active_support;dur=0.10, instantiation.active_record;dur=0.24, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=4.02, + process_action.action_controller;dur=29.46 + vary: + - Authorization, Origin + 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-08-17T20:10:00.166936Z' + x-request-id: + - 392b3749-2703-4e24-ac9e-c95846e3b452 + x-runtime: + - '0.045363' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/accounts/115045656361106495/featured_tags + response: + body: + string: '[{"id":"7","name":"coolfree","url":"http://localhost:3000/@mastodonpy_test/tagged/coolfree","statuses_count":"0","last_status_at":null}]' + headers: + Content-Length: + - '136' + cache-control: + - private, no-store + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + content-type: + - application/json; charset=utf-8 + etag: + - W/"02b32cb3c6a3d9e7ec4e781b5519f559" + referrer-policy: + - strict-origin-when-cross-origin + server-timing: + - cache_read.active_support;dur=0.03, sql.active_record;dur=1.27, cache_generate.active_support;dur=1.00, + cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.29, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.35, + process_action.action_controller;dur=28.51 + vary: + - Authorization, Origin + 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-08-17T20:10:00.236386Z' + x-request-id: + - 5e499fab-6790-4057-a807-0b0218c97849 + x-runtime: + - '0.046001' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - tests/v311 + method: POST + uri: http://localhost:3000/api/v1/tags/coolfree/unfeature + response: + body: + string: '{"id":"2","name":"coolfree","url":"http://localhost:3000/tags/coolfree","history":[{"day":"1755388800","accounts":"0","uses":"0"},{"day":"1755302400","accounts":"0","uses":"0"},{"day":"1755216000","accounts":"0","uses":"0"},{"day":"1755129600","accounts":"0","uses":"0"},{"day":"1755043200","accounts":"0","uses":"0"},{"day":"1754956800","accounts":"0","uses":"0"},{"day":"1754870400","accounts":"0","uses":"0"}],"following":false,"featuring":false}' + headers: + Content-Length: + - '449' + cache-control: + - private, no-store + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + content-type: + - application/json; charset=utf-8 + etag: + - W/"4711c271647bd109398a6a11173507e7" + referrer-policy: + - strict-origin-when-cross-origin + server-timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=6.10, cache_generate.active_support;dur=1.37, + cache_write.active_support;dur=0.10, instantiation.active_record;dur=0.33, + start_processing.action_controller;dur=0.00, start_transaction.active_record;dur=0.00, + transaction.active_record;dur=4.66, render.active_model_serializers;dur=4.13, + process_action.action_controller;dur=41.84 + vary: + - Authorization, Origin + 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-08-17T20:10:00.292085Z' + x-request-id: + - 6b33ec4d-f656-4322-9167-1c585ae2ebdc + x-runtime: + - '0.058299' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_account.py b/tests/test_account.py index 7bd1ac9..7cf8f7f 100644 --- a/tests/test_account.py +++ b/tests/test_account.py @@ -338,6 +338,38 @@ def test_featured_tags(api): if featured_tag_2 is not None: api.featured_tag_delete(featured_tag_2) +@pytest.mark.vcr() +def test_featured_tags_2(api): + featured_tag = None + featured_tag_2 = None + try: + featured_tag = api.tag_feature("ringtones") + assert featured_tag + assert featured_tag.name == "ringtones" + assert featured_tag.featuring == True + + with pytest.raises(MastodonIllegalArgumentError): + api.tag_feature("#daddycool") + + featured_tag_2 = api.tag_feature("coolfree") + assert featured_tag_2 + assert featured_tag_2.name == "coolfree" + assert featured_tag_2.featuring == True + + unfeatured_tag = api.tag_unfeature(featured_tag) + assert unfeatured_tag.featuring == False + featured_tag = None + + featured_tag_list = api.account_featured_tags(api.account_verify_credentials()) + assert len(featured_tag_list) == 1 + assert featured_tag_list[0].name == "coolfree" + assert "url" in featured_tag_list[0] + finally: + if featured_tag is not None: + api.tag_unfeature(featured_tag) + if featured_tag_2 is not None: + api.tag_unfeature(featured_tag_2) + @pytest.mark.vcr() def test_followed_hashtags(api): api.tag_unfollow("heeho") diff --git a/tests/test_admin_trends.yaml b/tests/test_admin_trends.yaml deleted file mode 100644 index cb00c0c..0000000 --- a/tests/test_admin_trends.yaml +++ /dev/null @@ -1,238 +0,0 @@ -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: - - 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/"4f53cda18c2baa0c0354bb5f9a3ecbe5" - Referrer-Policy: - - strict-origin-when-cross-origin - Server-Timing: - - cache_read.active_support;dur=0.04, sql.active_record;dur=0.86, cache_generate.active_support;dur=1.59, - cache_write.active_support;dur=0.11, instantiation.active_record;dur=0.29, - start_processing.action_controller;dur=0.01, render.active_model_serializers;dur=0.04, - process_action.action_controller;dur=22.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-13T22:00:00.999188Z' - X-Request-Id: - - ead883ad-0f5c-4e20-8434-3a4a6d90037e - X-Runtime: - - '0.041461' - 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/v1/admin/trends/statuses - 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/"4f53cda18c2baa0c0354bb5f9a3ecbe5" - Referrer-Policy: - - strict-origin-when-cross-origin - Server-Timing: - - cache_read.active_support;dur=0.04, sql.active_record;dur=2.29, cache_generate.active_support;dur=1.54, - cache_write.active_support;dur=0.10, instantiation.active_record;dur=0.28, - start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.04, - process_action.action_controller;dur=27.11 - 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-13T22:00:00.042879Z' - X-Request-Id: - - 4c60559f-e07e-4261-9268-fd3802d67a1c - X-Runtime: - - '0.045720' - X-XSS-Protection: - - '0' - vary: - - Authorization, Accept-Language, 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/v1/admin/trends/links - 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/"4f53cda18c2baa0c0354bb5f9a3ecbe5" - Referrer-Policy: - - strict-origin-when-cross-origin - Server-Timing: - - cache_read.active_support;dur=0.04, sql.active_record;dur=4.14, cache_generate.active_support;dur=1.57, - cache_write.active_support;dur=0.11, instantiation.active_record;dur=0.26, - start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.04, - process_action.action_controller;dur=30.35 - 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-13T22:00:00.096615Z' - X-Request-Id: - - 542d5e6d-46c2-411f-845a-14cbc4b00560 - X-Runtime: - - '0.053313' - X-XSS-Protection: - - '0' - vary: - - Authorization, Accept-Language, 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/v1/admin/trends/tags?limit=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/"4f53cda18c2baa0c0354bb5f9a3ecbe5" - Referrer-Policy: - - strict-origin-when-cross-origin - Server-Timing: - - cache_read.active_support;dur=0.05, sql.active_record;dur=8.99, cache_generate.active_support;dur=4.99, - cache_write.active_support;dur=0.12, instantiation.active_record;dur=0.42, - start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.05, - process_action.action_controller;dur=37.07 - 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-13T22:00:00.148901Z' - X-Request-Id: - - d71eb8d1-ffd9-492e-be08-4448ffb7c9ff - X-Runtime: - - '0.052562' - X-XSS-Protection: - - '0' - vary: - - Authorization, Origin - status: - code: 200 - message: OK -version: 1