Add endorsements (with docs and tests)

This commit is contained in:
Lorenz Diener 2019-04-27 22:13:27 +02:00
parent 4deeb7875b
commit 72e3290d8c
6 changed files with 314 additions and 5 deletions

View file

@ -800,6 +800,12 @@ Reading data: Emoji
.. automethod:: Mastodon.custom_emojis
Reading data: Endorsements
--------------------------
.. automethod:: Mastodon.endorsements
Writing data: Statuses
----------------------
These functions allow you to post statuses to Mastodon and to
@ -838,6 +844,8 @@ These functions allow you to interact with other accounts: To (un)follow and
.. automethod:: Mastodon.account_unblock
.. automethod:: Mastodon.account_mute
.. automethod:: Mastodon.account_unmute
.. automethod:: Mastodon.account_pin
.. automethod:: Mastodon.account_unpin
.. automethod:: Mastodon.account_update_credentials
Writing data: Keyword filters

View file

@ -923,6 +923,20 @@ class Mastodon:
"""
return self.__api_request('GET', '/api/v1/suggestions')
###
# Reading data: Endorsements
###
@api_version("2.5.0", "2.5.0", __DICT_VERSION_ACCOUNT)
def endorsements(self):
"""
Fetch list of users endorsemed by the logged-in user.
Returns a list of `user dicts`_.
"""
return self.__api_request('GET', '/api/v1/endorsements')
###
# Reading data: Searching
###
@ -1463,8 +1477,9 @@ class Mastodon:
Returns a `relationship dict`_ containing the updated relationship to the user.
"""
id = self.__unpack_id(id)
params = self.__generate_params(locals(), ['id'])
url = '/api/v1/accounts/{0}/mute'.format(str(id))
return self.__api_request('POST', url)
return self.__api_request('POST', url, params)
@api_version("1.1.0", "1.4.0", __DICT_VERSION_RELATIONSHIP)
def account_unmute(self, id):
@ -1545,6 +1560,28 @@ class Mastodon:
return self.__api_request('PATCH', '/api/v1/accounts/update_credentials', params, files=files)
@api_version("2.5.0", "2.5.0", __DICT_VERSION_RELATIONSHIP)
def account_pin(self, id):
"""
Pin / endorse a user.
Returns a `relationship dict`_ containing the updated relationship to the user.
"""
id = self.__unpack_id(id)
url = '/api/v1/accounts/{0}/pin'.format(str(id))
return self.__api_request('POST', url)
@api_version("2.5.0", "2.5.0", __DICT_VERSION_RELATIONSHIP)
def account_unpin(self, id):
"""
Unpin / un-endorse a user.
Returns a `relationship dict`_ containing the updated relationship to the user.
"""
id = self.__unpack_id(id)
url = '/api/v1/accounts/{0}/unpin'.format(str(id))
return self.__api_request('POST', url)
###
# Writing data: Keyword filters
###

View file

@ -0,0 +1,233 @@
interactions:
- request:
body: null
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2]
Connection: [keep-alive]
User-Agent: [python-requests/2.18.4]
method: GET
uri: http://localhost:3000/api/v1/accounts/verify_credentials
response:
body: {string: '{"id":"1","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2019-04-27T18:52:42.626Z","note":"\u003cp\u003e\u003c/p\u003e","url":"http://localhost/@admin","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":0,"statuses_count":0,"source":{"privacy":"public","sensitive":false,"language":null,"note":"","fields":[]},"emojis":[],"fields":[]}'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"0f8b38bbae62fe172a62496fe49e206e"]
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: [692fe5c4-e557-4dd5-99f0-44b812f2e9f3]
X-Runtime: ['0.019931']
X-XSS-Protection: [1; mode=block]
content-length: ['609']
status: {code: 200, message: OK}
- request:
body: reblogs=1&id=1
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Authorization: [Bearer __MASTODON_PY_TEST_ACCESS_TOKEN]
Connection: [keep-alive]
Content-Length: ['14']
Content-Type: [application/x-www-form-urlencoded]
User-Agent: [python-requests/2.18.4]
method: POST
uri: http://localhost:3000/api/v1/accounts/1/follow
response:
body: {string: '{"id":"1","following":true,"showing_reblogs":true,"followed_by":false,"blocking":false,"blocked_by":false,"muting":false,"muting_notifications":false,"requested":false,"domain_blocking":false,"endorsed":false}'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"1e1fa14c270ff6960152323eda93cc79"]
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: [ad3bfb7e-d816-4b51-8c90-e431d2330775]
X-Runtime: ['0.062775']
X-XSS-Protection: [1; mode=block]
content-length: ['209']
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: POST
uri: http://localhost:3000/api/v1/accounts/1/unpin
response:
body: {string: '{"id":"1","following":true,"showing_reblogs":true,"followed_by":false,"blocking":false,"blocked_by":false,"muting":false,"muting_notifications":false,"requested":false,"domain_blocking":false,"endorsed":false}'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"1e1fa14c270ff6960152323eda93cc79"]
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: [312e2867-4349-4145-8bb0-231e59e3d02c]
X-Runtime: ['0.065496']
X-XSS-Protection: [1; mode=block]
content-length: ['209']
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: POST
uri: http://localhost:3000/api/v1/accounts/1/pin
response:
body: {string: '{"id":"1","following":true,"showing_reblogs":true,"followed_by":false,"blocking":false,"blocked_by":false,"muting":false,"muting_notifications":false,"requested":false,"domain_blocking":false,"endorsed":true}'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"c6dfb53299bc83b46a9edb08d3930925"]
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: [c9dae17d-d180-447b-bb49-4f6d4ce07f40]
X-Runtime: ['0.050245']
X-XSS-Protection: [1; mode=block]
content-length: ['208']
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/endorsements
response:
body: {string: '[{"id":"1","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2019-04-27T18:52:42.626Z","note":"\u003cp\u003e\u003c/p\u003e","url":"http://localhost/@admin","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":1,"following_count":0,"statuses_count":0,"emojis":[],"fields":[]}]'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"ae491d6254719d99832526fc14bfb68b"]
Link: ['<http://localhost:3000/api/v1/endorsements?since_id=1>; rel="prev"']
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: [855af719-1d1a-4fe0-93e7-b2ff9293a363]
X-Runtime: ['0.018452']
X-XSS-Protection: [1; mode=block]
content-length: ['525']
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: POST
uri: http://localhost:3000/api/v1/accounts/1/unpin
response:
body: {string: '{"id":"1","following":true,"showing_reblogs":true,"followed_by":false,"blocking":false,"blocked_by":false,"muting":false,"muting_notifications":false,"requested":false,"domain_blocking":false,"endorsed":false}'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"1e1fa14c270ff6960152323eda93cc79"]
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: [e750e8c4-eae0-4ed6-9563-00ac35d85daa]
X-Runtime: ['0.025393']
X-XSS-Protection: [1; mode=block]
content-length: ['209']
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/endorsements
response:
body: {string: '[]'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"e2dc74be154e07a1d543fffa1604d2ab"]
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: [15996817-bf63-4f5e-a34d-c6cf7702822c]
X-Runtime: ['0.019443']
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]
Content-Length: ['0']
User-Agent: [python-requests/2.18.4]
method: POST
uri: http://localhost:3000/api/v1/accounts/1/unfollow
response:
body: {string: '{"id":"1","following":false,"showing_reblogs":false,"followed_by":false,"blocking":false,"blocked_by":false,"muting":false,"muting_notifications":false,"requested":false,"domain_blocking":false,"endorsed":false}'}
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"714cd19713205feb75ce771b61d4564b"]
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: [7710c7c9-40d9-4cd9-b483-2863d00916ff]
X-Runtime: ['0.041778']
X-XSS-Protection: [1; mode=block]
content-length: ['211']
status: {code: 200, message: OK}
version: 1

View file

@ -14,7 +14,7 @@ interactions:
headers:
Cache-Control: ['max-age=0, private, must-revalidate']
Content-Type: [application/json; charset=utf-8]
ETag: [W/"90b6becb2b7152e68f928ca54703d5b5"]
ETag: [W/"0c6c8cc3cb75164dfb4ec124c252008f"]
Referrer-Policy: [strict-origin-when-cross-origin]
Transfer-Encoding: [chunked]
Vary: ['Accept-Encoding, Origin']
@ -22,8 +22,8 @@ interactions:
X-Download-Options: [noopen]
X-Frame-Options: [SAMEORIGIN]
X-Permitted-Cross-Domain-Policies: [none]
X-Request-Id: [1ecc4a5b-3fa6-4aab-9f51-62a63df2668c]
X-Runtime: ['0.021739']
X-Request-Id: [1bef2ecf-ea12-422d-802a-456ab7096e0b]
X-Runtime: ['0.060542']
X-XSS-Protection: [1; mode=block]
content-length: ['2']
status: {code: 200, message: OK}

View file

@ -1,6 +1,6 @@
import pytest
def _api(access_token='__MASTODON_PY_TEST_ACCESS_TOKEN', version="2.4.3", version_check_mode="created"):
def _api(access_token='__MASTODON_PY_TEST_ACCESS_TOKEN', version="2.8.0", version_check_mode="created"):
import mastodon
return mastodon.Mastodon(
api_base_url='http://localhost:3000',

View file

@ -175,3 +175,34 @@ def test_follow_suggestions(api2, status):
suggestions2 = api2.suggestions()
assert(len(suggestions2) < len(suggestions))
@pytest.mark.vcr()
def test_account_pin_unpin(api, api2):
user = api2.account_verify_credentials()
# Make sure we are in the correct state
try:
api.account_follow(user)
except:
pass
try:
api.account_unpin(user)
except:
pass
relationship = api.account_pin(user)
endorsed = api.endorsements()
try:
assert relationship
assert relationship['endorsed']
assert user["id"] in map(lambda x: x["id"], endorsed)
finally:
relationship = api.account_unpin(user)
endorsed2 = api.endorsements()
api.account_unfollow(user)
assert relationship
assert not relationship['endorsed']
assert not user["id"] in map(lambda x: x["id"], endorsed2)