Implement, test and document featured and suggested tags APIs (fixes #191)
This commit is contained in:
pare
3194b1295e
commit
63bf5afc61
S'han modificat 5 arxius amb 312 adicions i 1 eliminacions
|
@ -756,6 +756,21 @@ Preference dicts
|
|||
# content warnings by default
|
||||
}
|
||||
|
||||
Featured tag dicts
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
.. _featured tag dict:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
mastodon.featured_tags()[0]
|
||||
# Returns the following dictionary:
|
||||
{
|
||||
'id': # The featured tags id
|
||||
'name': # The featured tags name (without leading #)
|
||||
'statuses_count': # Number of publicly visible statuses posted with this hashtag that this instance knows about
|
||||
'last_status_at': # The last time a public status containing this hashtag was added to this instances database
|
||||
# (can be None if there are none)
|
||||
}
|
||||
|
||||
Admin account dicts
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -907,6 +922,13 @@ their relationships.
|
|||
.. automethod:: Mastodon.account_relationships
|
||||
.. automethod:: Mastodon.account_search
|
||||
|
||||
Reading data: Featured tags
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
These functions allow retrieving info about a users featured and suggested tags.
|
||||
|
||||
.. automethod:: Mastodon.featured_tags
|
||||
.. automethod:: Mastodon.featured_tag_suggestions
|
||||
|
||||
Reading data: Keyword filters
|
||||
-----------------------------
|
||||
These functions allow you to get information about keyword filters.
|
||||
|
@ -1058,6 +1080,13 @@ These functions allow you to interact with other accounts: To (un)follow and
|
|||
.. automethod:: Mastodon.account_unpin
|
||||
.. automethod:: Mastodon.account_update_credentials
|
||||
|
||||
Writing data: Featured tags
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
These functions allow setting which tags are featured on a users profile.
|
||||
|
||||
.. automethod:: Mastodon.featured_tag_create
|
||||
.. automethod:: Mastodon.featured_tag_delete
|
||||
|
||||
Writing data: Keyword filters
|
||||
-----------------------------
|
||||
These functions allow you to manipulate keyword filters.
|
||||
|
|
|
@ -212,6 +212,7 @@ class Mastodon:
|
|||
__DICT_VERSION_SCHEDULED_STATUS = bigger_version("2.7.0", __DICT_VERSION_STATUS)
|
||||
__DICT_VERSION_PREFERENCES = "2.8.0"
|
||||
__DICT_VERSION_ADMIN_ACCOUNT = "2.9.1"
|
||||
__DICT_VERSION_FEATURED_TAG = "3.0.0"
|
||||
|
||||
###
|
||||
# Registering apps
|
||||
|
@ -1144,6 +1145,28 @@ class Mastodon:
|
|||
url = '/api/v1/accounts/{0}/lists'.format(str(id))
|
||||
return self.__api_request('GET', url, params)
|
||||
|
||||
###
|
||||
# Reading data: Featured hashtags
|
||||
###
|
||||
@api_version("3.0.0", "3.0.0", __DICT_VERSION_FEATURED_TAG)
|
||||
def featured_tags(self):
|
||||
"""
|
||||
Return the hashtags the logged-in user has set to be featured on
|
||||
their profile as a list of `featured tag dicts`_.
|
||||
|
||||
Returns a list of `featured tag dicts`_.
|
||||
"""
|
||||
return self.__api_request('GET', '/api/v1/featured_tags')
|
||||
|
||||
@api_version("3.0.0", "3.0.0", __DICT_VERSION_HASHTAG)
|
||||
def featured_tag_suggestions(self):
|
||||
"""
|
||||
Returns the logged-in users 10 most commonly hashtags.
|
||||
|
||||
Returns a list of `hashtag dicts`_.
|
||||
"""
|
||||
return self.__api_request('GET', '/api/v1/featured_tags/suggestions')
|
||||
|
||||
###
|
||||
# Reading data: Keyword filters
|
||||
###
|
||||
|
@ -2137,6 +2160,28 @@ class Mastodon:
|
|||
url = '/api/v1/accounts/{0}/unpin'.format(str(id))
|
||||
return self.__api_request('POST', url)
|
||||
|
||||
###
|
||||
# Writing data: Featured hashtags
|
||||
###
|
||||
@api_version("3.0.0", "3.0.0", __DICT_VERSION_FEATURED_TAG)
|
||||
def featured_tag_create(self, name):
|
||||
"""
|
||||
Creates a new featured hashtag displayed on the logged-in users profile.
|
||||
|
||||
Returns a `featured tag dict`_ with the newly featured tag.
|
||||
"""
|
||||
params = self.__generate_params(locals())
|
||||
return self.__api_request('POST', '/api/v1/featured_tags', params)
|
||||
|
||||
@api_version("3.0.0", "3.0.0", __DICT_VERSION_FEATURED_TAG)
|
||||
def featured_tag_delete(self, id):
|
||||
"""
|
||||
Deletes one of the logged-in users featured hashtags.
|
||||
"""
|
||||
id = self.__unpack_id(id)
|
||||
url = '/api/v1/featured_tags/{0}'.format(str(id))
|
||||
self.__api_request('DELETE', url)
|
||||
|
||||
###
|
||||
# Writing data: Keyword filters
|
||||
###
|
||||
|
@ -2982,7 +3027,7 @@ class Mastodon:
|
|||
"""
|
||||
Parse dates in certain known json fields, if possible.
|
||||
"""
|
||||
known_date_fields = ["created_at", "week", "day", "expires_at", "scheduled_at", "updated_at"]
|
||||
known_date_fields = ["created_at", "week", "day", "expires_at", "scheduled_at", "updated_at", "last_status_at"]
|
||||
for k, v in json_object.items():
|
||||
if k in known_date_fields:
|
||||
if v != None:
|
||||
|
|
113
tests/cassettes/test_featured_tags.yaml
Normal file
113
tests/cassettes/test_featured_tags.yaml
Normal file
|
@ -0,0 +1,113 @@
|
|||
interactions:
|
||||
- request:
|
||||
body: name=mastopytesttag
|
||||
headers:
|
||||
Accept: ['*/*']
|
||||
Accept-Encoding: ['gzip, deflate']
|
||||
Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN]
|
||||
Connection: [keep-alive]
|
||||
Content-Length: ['19']
|
||||
Content-Type: [application/x-www-form-urlencoded]
|
||||
User-Agent: [python-requests/2.18.4]
|
||||
method: POST
|
||||
uri: http://localhost:3000/api/v1/featured_tags
|
||||
response:
|
||||
body: {string: '{"id":"1","name":"mastopytesttag","statuses_count":0,"last_status_at":null}'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [319b60a5-1408-4515-9b41-91a9eb90b81c]
|
||||
X-Runtime: ['0.122775']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['75']
|
||||
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: [python-requests/2.18.4]
|
||||
method: GET
|
||||
uri: http://localhost:3000/api/v1/featured_tags
|
||||
response:
|
||||
body: {string: '[{"id":"1","name":"mastopytesttag","statuses_count":0,"last_status_at":null}]'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [6c35b860-5264-46a1-9219-388f2d65f038]
|
||||
X-Runtime: ['0.030432']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['77']
|
||||
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: [python-requests/2.18.4]
|
||||
method: DELETE
|
||||
uri: http://localhost:3000/api/v1/featured_tags/1
|
||||
response:
|
||||
body: {string: '{}'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [7c062d77-90bd-4400-9476-42495d98d77b]
|
||||
X-Runtime: ['0.031225']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['2']
|
||||
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: [python-requests/2.18.4]
|
||||
method: GET
|
||||
uri: http://localhost:3000/api/v1/featured_tags
|
||||
response:
|
||||
body: {string: '[]'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [8e5eaf25-5e6a-4998-bb44-188b123b726c]
|
||||
X-Runtime: ['0.020343']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['2']
|
||||
status: {code: 200, message: OK}
|
||||
version: 1
|
90
tests/cassettes/test_suggested_tags.yaml
Normal file
90
tests/cassettes/test_suggested_tags.yaml
Normal file
|
@ -0,0 +1,90 @@
|
|||
interactions:
|
||||
- request:
|
||||
body: status=cool+free+%23ringtones
|
||||
headers:
|
||||
Accept: ['*/*']
|
||||
Accept-Encoding: ['gzip, deflate']
|
||||
Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN]
|
||||
Connection: [keep-alive]
|
||||
Content-Length: ['29']
|
||||
Content-Type: [application/x-www-form-urlencoded]
|
||||
User-Agent: [python-requests/2.18.4]
|
||||
method: POST
|
||||
uri: http://localhost:3000/api/v1/statuses
|
||||
response:
|
||||
body: {string: '{"id":"102951123020457171","created_at":"2019-10-12T19:44:29.956Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"public","language":"ja","uri":"http://localhost/users/mastodonpy_test/statuses/102951123020457171","url":"http://localhost/@mastodonpy_test/102951123020457171","replies_count":0,"reblogs_count":0,"favourites_count":0,"favourited":false,"reblogged":false,"muted":false,"pinned":false,"content":"\u003cp\u003ecool
|
||||
free \u003ca href=\"http://localhost/tags/ringtones\" class=\"mention hashtag\"
|
||||
rel=\"tag\"\u003e#\u003cspan\u003eringtones\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e","reblog":null,"application":{"name":"Mastodon.py
|
||||
test suite","website":null},"account":{"id":"1234567890123456","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":false,"bot":false,"created_at":"2019-06-22T23:11:52.441Z","note":"\u003cp\u003e\u003c/p\u003e","url":"http://localhost/@mastodonpy_test","avatar":"http://localhost/avatars/original/missing.png","avatar_static":"http://localhost/avatars/original/missing.png","header":"http://localhost/headers/original/missing.png","header_static":"http://localhost/headers/original/missing.png","followers_count":0,"following_count":1,"statuses_count":3,"last_status_at":"2019-10-12T19:44:29.976Z","emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[{"name":"ringtones","url":"http://localhost/tags/ringtones"}],"emojis":[],"card":null,"poll":null}'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [7c348bde-1d33-451a-8ae0-87cb09d8a1a2]
|
||||
X-Runtime: ['0.222922']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['1494']
|
||||
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: [python-requests/2.18.4]
|
||||
method: GET
|
||||
uri: http://localhost:3000/api/v1/featured_tags/suggestions
|
||||
response:
|
||||
body: {string: '[{"name":"ringtones","url":"http://localhost/tags/ringtones","history":[{"day":"1570838400","uses":"1","accounts":"1"},{"day":"1570752000","uses":"0","accounts":"0"},{"day":"1570665600","uses":"0","accounts":"0"},{"day":"1570579200","uses":"0","accounts":"0"},{"day":"1570492800","uses":"0","accounts":"0"},{"day":"1570406400","uses":"0","accounts":"0"},{"day":"1570320000","uses":"0","accounts":"0"}]}]'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [fc6ec1a8-9c2e-4c08-925d-f80522d5bf65]
|
||||
X-Runtime: ['0.061457']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['403']
|
||||
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: [python-requests/2.18.4]
|
||||
method: DELETE
|
||||
uri: http://localhost:3000/api/v1/statuses/102951123020457171
|
||||
response:
|
||||
body: {string: '{"id":"102951123020457171","created_at":"2019-10-12T19:44:29.956Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"public","language":"ja","uri":"http://localhost/users/mastodonpy_test/statuses/102951123020457171","url":"http://localhost/@mastodonpy_test/102951123020457171","replies_count":0,"reblogs_count":0,"favourites_count":0,"favourited":false,"reblogged":false,"muted":false,"pinned":false,"text":"cool
|
||||
free #ringtones","reblog":null,"application":{"name":"Mastodon.py test suite","website":null},"account":{"id":"1234567890123456","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":false,"bot":false,"created_at":"2019-06-22T23:11:52.441Z","note":"\u003cp\u003e\u003c/p\u003e","url":"http://localhost/@mastodonpy_test","avatar":"http://localhost/avatars/original/missing.png","avatar_static":"http://localhost/avatars/original/missing.png","header":"http://localhost/headers/original/missing.png","header_static":"http://localhost/headers/original/missing.png","followers_count":0,"following_count":1,"statuses_count":3,"last_status_at":"2019-10-12T19:44:29.976Z","emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[{"name":"ringtones","url":"http://localhost/tags/ringtones"}],"emojis":[],"card":null,"poll":null}'}
|
||||
headers:
|
||||
Cache-Control: ['no-cache, no-store']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Referrer-Policy: [strict-origin-when-cross-origin]
|
||||
Transfer-Encoding: [chunked]
|
||||
Vary: ['Accept-Encoding, Origin']
|
||||
X-Content-Type-Options: [nosniff]
|
||||
X-Download-Options: [noopen]
|
||||
X-Frame-Options: [SAMEORIGIN]
|
||||
X-Permitted-Cross-Domain-Policies: [none]
|
||||
X-Request-Id: [68301b80-982f-4397-8c6b-d9e7d8cd308b]
|
||||
X-Runtime: ['0.118422']
|
||||
X-XSS-Protection: [1; mode=block]
|
||||
content-length: ['1325']
|
||||
status: {code: 200, message: OK}
|
||||
version: 1
|
|
@ -1,6 +1,7 @@
|
|||
import pytest
|
||||
from mastodon.Mastodon import MastodonAPIError, MastodonIllegalArgumentError
|
||||
import re
|
||||
import time
|
||||
|
||||
@pytest.mark.vcr()
|
||||
def test_account(api):
|
||||
|
@ -215,3 +216,36 @@ def test_account_pin_unpin(api, api2):
|
|||
def test_preferences(api):
|
||||
prefs = api.preferences()
|
||||
assert prefs
|
||||
|
||||
@pytest.mark.vcr()
|
||||
def test_suggested_tags(api):
|
||||
try:
|
||||
status = api.status_post("cool free #ringtones")
|
||||
time.sleep(2)
|
||||
|
||||
suggests = api.featured_tag_suggestions()
|
||||
assert suggests
|
||||
assert len(suggests) > 0
|
||||
finally:
|
||||
api.status_delete(status)
|
||||
|
||||
@pytest.mark.vcr()
|
||||
def test_featured_tags(api):
|
||||
featured_tag = api.featured_tag_create("mastopytesttag")
|
||||
assert featured_tag
|
||||
|
||||
tag_list = api.featured_tags()
|
||||
assert featured_tag.name in list(map(lambda x: x.name, tag_list))
|
||||
|
||||
api.featured_tag_delete(featured_tag)
|
||||
tag_list = api.featured_tags()
|
||||
assert not featured_tag.name in list(map(lambda x: x.name, tag_list))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Referencia en una nova incidència