aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md4
-rw-r--r--docs/index.rst12
-rw-r--r--mastodon/Mastodon.py12
-rw-r--r--tests/cassettes/test_featured_tags.yaml308
-rw-r--r--tests/conftest.py2
-rw-r--r--tests/test_account.py21
6 files changed, 344 insertions, 15 deletions
diff --git a/TODO.md b/TODO.md
index 99e9644..292968e 100644
--- a/TODO.md
+++ b/TODO.md
@@ -24,8 +24,8 @@ Refer to mastodon changelog and API docs for details when implementing, add or m
24* [ ] Add duration option to the mute function 24* [ ] Add duration option to the mute function
25* [ ] Add ability to block access or limit sign-ups from chosen IPs 25* [ ] Add ability to block access or limit sign-ups from chosen IPs
26* [ ] Add support for managing multiple stream subscriptions in a single connection 26* [ ] Add support for managing multiple stream subscriptions in a single connection
27* [ ] Add support for limiting results by both min_id and max_id at the same time in REST API 27* [x] Add support for limiting results by both min_id and max_id at the same time in REST API
28* [ ] Add GET /api/v1/accounts/:id/featured_tags to REST API 28* [x] Add GET /api/v1/accounts/:id/featured_tags to REST API
29 29
303.4.0 303.4.0
31----- 31-----
diff --git a/docs/index.rst b/docs/index.rst
index dad7669..c2caf3a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -130,11 +130,12 @@ allows you to specify the largest id you want. By specifying either min_id or `m
130(generally, only one, not both, though specifying both is supported starting with Mastodon 130(generally, only one, not both, though specifying both is supported starting with Mastodon
131version 3.3.0) of them you can go through pages forwards and backwards. 131version 3.3.0) of them you can go through pages forwards and backwards.
132 132
133On Mastodon mainline, you can, pass datetime objects as IDs, since the IDs used are 133On Mastodon mainline, you can, pass datetime objects as IDs when fetching posts,
134Snowflake IDs and dates can be approximately converted to those. This is guaranteed 134since the IDs used are Snowflake IDs and dates can be approximately converted to those.
135to work on mainline Mastodon servers and very likely to work on all forks, but will 135This is guaranteed to work on mainline Mastodon servers and very likely to work on all
136**not** work on other servers implementing the API, like Pleroma, Misskey or Gotosocial. 136forks, but will **not** work on other servers implementing the API, like Pleroma, Misskey
137You should not use this if you want your application to be universally compatible. 137or Gotosocial. You should not use this if you want your application to be universally
138compatible.
138 139
139`limit` allows you to specify how many results you would like returned. Note that an 140`limit` allows you to specify how many results you would like returned. Note that an
140instance may choose to return less results than you requested - by default, Mastodon 141instance may choose to return less results than you requested - by default, Mastodon
@@ -1178,6 +1179,7 @@ These functions allow you to interact with other accounts: To (un)follow and
1178.. automethod:: Mastodon.account_unpin 1179.. automethod:: Mastodon.account_unpin
1179.. automethod:: Mastodon.account_update_credentials 1180.. automethod:: Mastodon.account_update_credentials
1180.. automethod:: Mastodon.account_note_set 1181.. automethod:: Mastodon.account_note_set
1182.. automethod:: Mastodon.account_featured_tags
1181 1183
1182Writing data: Featured tags 1184Writing data: Featured tags
1183~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1185~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py
index c3e3122..c55e006 100644
--- a/mastodon/Mastodon.py
+++ b/mastodon/Mastodon.py
@@ -2265,12 +2265,22 @@ class Mastodon:
2265 """ 2265 """
2266 Set a note (visible to the logged in user only) for the given account. 2266 Set a note (visible to the logged in user only) for the given account.
2267 2267
2268 returns a `status dict`_ with the `note` updated. 2268 Returns a `status dict`_ with the `note` updated.
2269 """ 2269 """
2270 id = self.__unpack_id(id) 2270 id = self.__unpack_id(id)
2271 params = self.__generate_params(locals(), ["id"]) 2271 params = self.__generate_params(locals(), ["id"])
2272 return self.__api_request('POST', '/api/v1/accounts/{0}/note'.format(str(id)), params) 2272 return self.__api_request('POST', '/api/v1/accounts/{0}/note'.format(str(id)), params)
2273 2273
2274 @api_version("3.3.0", "3.3.0", __DICT_VERSION_HASHTAG)
2275 def account_featured_tags(self, id):
2276 """
2277 Get an accounts featured hashtags.
2278
2279 Returns a list of `hashtag dicts`_ (NOT `featured tag dicts`_).
2280 """
2281 id = self.__unpack_id(id)
2282 return self.__api_request('GET', '/api/v1/accounts/{0}/featured_tags'.format(str(id)))
2283
2274 ### 2284 ###
2275 # Writing data: Featured hashtags 2285 # Writing data: Featured hashtags
2276 ### 2286 ###
diff --git a/tests/cassettes/test_featured_tags.yaml b/tests/cassettes/test_featured_tags.yaml
index f4ea314..955b9d0 100644
--- a/tests/cassettes/test_featured_tags.yaml
+++ b/tests/cassettes/test_featured_tags.yaml
@@ -20,14 +20,14 @@ interactions:
20 uri: http://localhost:3000/api/v1/featured_tags 20 uri: http://localhost:3000/api/v1/featured_tags
21 response: 21 response:
22 body: 22 body:
23 string: '{"id":"1","name":"ringtones","url":"http://localhost:3000/@mastodonpy_test/tagged/ringtones","statuses_count":"0","last_status_at":null}' 23 string: '{"id":"9","name":"ringtones","url":"http://localhost:3000/@mastodonpy_test/tagged/ringtones","statuses_count":"0","last_status_at":null}'
24 headers: 24 headers:
25 Cache-Control: 25 Cache-Control:
26 - no-store 26 - no-store
27 Content-Security-Policy: 27 Content-Security-Policy:
28 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src 28 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
29 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000; 29 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
30 style-src ''self'' http://localhost:3000 ''nonce-GjXyZZckExmvwzB75bXrRw==''; 30 style-src ''self'' http://localhost:3000 ''nonce-Ev7aLLklDn9ahF6Z9ITjPw=='';
31 media-src ''self'' https: data: http://localhost:3000; frame-src ''self'' 31 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
32 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self'' 32 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
33 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000 33 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
@@ -37,7 +37,7 @@ interactions:
37 Content-Type: 37 Content-Type:
38 - application/json; charset=utf-8 38 - application/json; charset=utf-8
39 ETag: 39 ETag:
40 - W/"aa2380f6b72962d051f0cd1ca31074a1" 40 - W/"41bf7bfddac6e1ad15287c517fb9e4ef"
41 Referrer-Policy: 41 Referrer-Policy:
42 - strict-origin-when-cross-origin 42 - strict-origin-when-cross-origin
43 Transfer-Encoding: 43 Transfer-Encoding:
@@ -53,9 +53,307 @@ interactions:
53 X-Permitted-Cross-Domain-Policies: 53 X-Permitted-Cross-Domain-Policies:
54 - none 54 - none
55 X-Request-Id: 55 X-Request-Id:
56 - 40a41ecb-53f4-4d6a-816b-ea0bdec7283c 56 - 45375d50-283d-420d-bca7-02f5d80c48e1
57 X-Runtime: 57 X-Runtime:
58 - '0.262286' 58 - '0.019871'
59 X-XSS-Protection:
60 - 1; mode=block
61 status:
62 code: 200
63 message: OK
64- request:
65 body: name=%23coolfree
66 headers:
67 Accept:
68 - '*/*'
69 Accept-Encoding:
70 - gzip, deflate
71 Authorization:
72 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
73 Connection:
74 - keep-alive
75 Content-Length:
76 - '16'
77 Content-Type:
78 - application/x-www-form-urlencoded
79 User-Agent:
80 - tests/v311
81 method: POST
82 uri: http://localhost:3000/api/v1/featured_tags
83 response:
84 body:
85 string: '{"id":"10","name":"coolfree","url":"http://localhost:3000/@mastodonpy_test/tagged/coolfree","statuses_count":"0","last_status_at":null}'
86 headers:
87 Cache-Control:
88 - no-store
89 Content-Security-Policy:
90 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
91 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
92 style-src ''self'' http://localhost:3000 ''nonce-3E1/Qr00Zf5SwlBjP0neqw=='';
93 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
94 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
95 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
96 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
97 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
98 worker-src ''self'' blob: http://localhost:3000'
99 Content-Type:
100 - application/json; charset=utf-8
101 ETag:
102 - W/"65ef3503d8d2223dcf8599eff3bfba43"
103 Referrer-Policy:
104 - strict-origin-when-cross-origin
105 Transfer-Encoding:
106 - chunked
107 Vary:
108 - Accept, Origin
109 X-Content-Type-Options:
110 - nosniff
111 X-Download-Options:
112 - noopen
113 X-Frame-Options:
114 - SAMEORIGIN
115 X-Permitted-Cross-Domain-Policies:
116 - none
117 X-Request-Id:
118 - 21ca1fdf-4f9e-43b9-9df8-58f11f9689cc
119 X-Runtime:
120 - '0.018429'
121 X-XSS-Protection:
122 - 1; mode=block
123 status:
124 code: 200
125 message: OK
126- request:
127 body: null
128 headers:
129 Accept:
130 - '*/*'
131 Accept-Encoding:
132 - gzip, deflate
133 Authorization:
134 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
135 Connection:
136 - keep-alive
137 Content-Length:
138 - '0'
139 User-Agent:
140 - tests/v311
141 method: DELETE
142 uri: http://localhost:3000/api/v1/featured_tags/9
143 response:
144 body:
145 string: '{}'
146 headers:
147 Cache-Control:
148 - no-store
149 Content-Security-Policy:
150 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
151 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
152 style-src ''self'' http://localhost:3000 ''nonce-hyd1sSf9Too/TRXACKsomg=='';
153 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
154 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
155 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
156 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
157 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
158 worker-src ''self'' blob: http://localhost:3000'
159 Content-Type:
160 - application/json; charset=utf-8
161 ETag:
162 - W/"44136fa355b3678a1146ad16f7e8649e"
163 Referrer-Policy:
164 - strict-origin-when-cross-origin
165 Transfer-Encoding:
166 - chunked
167 Vary:
168 - Accept, Origin
169 X-Content-Type-Options:
170 - nosniff
171 X-Download-Options:
172 - noopen
173 X-Frame-Options:
174 - SAMEORIGIN
175 X-Permitted-Cross-Domain-Policies:
176 - none
177 X-Request-Id:
178 - 278e1df2-92cc-4580-a15e-1596b5ba1c74
179 X-Runtime:
180 - '0.008709'
181 X-XSS-Protection:
182 - 1; mode=block
183 status:
184 code: 200
185 message: OK
186- request:
187 body: null
188 headers:
189 Accept:
190 - '*/*'
191 Accept-Encoding:
192 - gzip, deflate
193 Authorization:
194 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
195 Connection:
196 - keep-alive
197 User-Agent:
198 - tests/v311
199 method: GET
200 uri: http://localhost:3000/api/v1/accounts/verify_credentials
201 response:
202 body:
203 string: '{"id":"109336567574114486","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-13T00:00:00.000Z","note":"","url":"http://localhost:3000/@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":0,"last_status_at":null,"noindex":false,"source":{"privacy":"public","sensitive":false,"language":null,"note":"","fields":[],"follow_requests_count":0},"emojis":[],"fields":[],"role":{"id":"-99","name":"","permissions":"65536","color":"","highlighted":false}}'
204 headers:
205 Cache-Control:
206 - no-store
207 Content-Security-Policy:
208 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
209 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
210 style-src ''self'' http://localhost:3000 ''nonce-0+vVDdfw4sA92jsxcIsAaA=='';
211 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
212 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
213 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
214 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
215 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
216 worker-src ''self'' blob: http://localhost:3000'
217 Content-Type:
218 - application/json; charset=utf-8
219 ETag:
220 - W/"9656ddb7266788f144a437312303d9f2"
221 Referrer-Policy:
222 - strict-origin-when-cross-origin
223 Transfer-Encoding:
224 - chunked
225 Vary:
226 - Accept, Origin
227 X-Content-Type-Options:
228 - nosniff
229 X-Download-Options:
230 - noopen
231 X-Frame-Options:
232 - SAMEORIGIN
233 X-Permitted-Cross-Domain-Policies:
234 - none
235 X-Request-Id:
236 - 62c7f6f3-89aa-4424-acf3-029447793322
237 X-Runtime:
238 - '0.010940'
239 X-XSS-Protection:
240 - 1; mode=block
241 status:
242 code: 200
243 message: OK
244- request:
245 body: null
246 headers:
247 Accept:
248 - '*/*'
249 Accept-Encoding:
250 - gzip, deflate
251 Authorization:
252 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
253 Connection:
254 - keep-alive
255 User-Agent:
256 - tests/v311
257 method: GET
258 uri: http://localhost:3000/api/v1/accounts/109336567574114486/featured_tags
259 response:
260 body:
261 string: '[{"id":"10","name":"coolfree","url":"http://localhost:3000/@mastodonpy_test/tagged/coolfree","statuses_count":"0","last_status_at":null}]'
262 headers:
263 Cache-Control:
264 - no-store
265 Content-Security-Policy:
266 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
267 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
268 style-src ''self'' http://localhost:3000 ''nonce-eCUaxB/0/Z9vIZ+ICDuW9A=='';
269 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
270 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
271 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
272 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
273 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
274 worker-src ''self'' blob: http://localhost:3000'
275 Content-Type:
276 - application/json; charset=utf-8
277 ETag:
278 - W/"48bb4e5567243bbb4d2d33f21aed2597"
279 Referrer-Policy:
280 - strict-origin-when-cross-origin
281 Transfer-Encoding:
282 - chunked
283 Vary:
284 - Accept, Origin
285 X-Content-Type-Options:
286 - nosniff
287 X-Download-Options:
288 - noopen
289 X-Frame-Options:
290 - SAMEORIGIN
291 X-Permitted-Cross-Domain-Policies:
292 - none
293 X-Request-Id:
294 - e4471af9-a407-4a37-b03a-7f9b3086b163
295 X-Runtime:
296 - '0.007852'
297 X-XSS-Protection:
298 - 1; mode=block
299 status:
300 code: 200
301 message: OK
302- request:
303 body: null
304 headers:
305 Accept:
306 - '*/*'
307 Accept-Encoding:
308 - gzip, deflate
309 Authorization:
310 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
311 Connection:
312 - keep-alive
313 Content-Length:
314 - '0'
315 User-Agent:
316 - tests/v311
317 method: DELETE
318 uri: http://localhost:3000/api/v1/featured_tags/10
319 response:
320 body:
321 string: '{}'
322 headers:
323 Cache-Control:
324 - no-store
325 Content-Security-Policy:
326 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
327 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
328 style-src ''self'' http://localhost:3000 ''nonce-Yp9i56vd+caB7l7es3mkNw=='';
329 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
330 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
331 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
332 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
333 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
334 worker-src ''self'' blob: http://localhost:3000'
335 Content-Type:
336 - application/json; charset=utf-8
337 ETag:
338 - W/"44136fa355b3678a1146ad16f7e8649e"
339 Referrer-Policy:
340 - strict-origin-when-cross-origin
341 Transfer-Encoding:
342 - chunked
343 Vary:
344 - Accept, Origin
345 X-Content-Type-Options:
346 - nosniff
347 X-Download-Options:
348 - noopen
349 X-Frame-Options:
350 - SAMEORIGIN
351 X-Permitted-Cross-Domain-Policies:
352 - none
353 X-Request-Id:
354 - 6e5dac5e-e1f8-4e09-ae2f-1f4234840d32
355 X-Runtime:
356 - '0.007759'
59 X-XSS-Protection: 357 X-XSS-Protection:
60 - 1; mode=block 358 - 1; mode=block
61 status: 359 status:
diff --git a/tests/conftest.py b/tests/conftest.py
index 0d2634c..5978547 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -3,7 +3,7 @@ import pytest
3# Set this to True to debug issues with tests 3# Set this to True to debug issues with tests
4DEBUG_REQUESTS = True 4DEBUG_REQUESTS = True
5 5
6def _api(access_token='__MASTODON_PY_TEST_ACCESS_TOKEN', version="3.1.1", version_check_mode="created"): 6def _api(access_token='__MASTODON_PY_TEST_ACCESS_TOKEN', version="4.0.0", version_check_mode="created"):
7 import mastodon 7 import mastodon
8 return mastodon.Mastodon( 8 return mastodon.Mastodon(
9 api_base_url='http://localhost:3000', 9 api_base_url='http://localhost:3000',
diff --git a/tests/test_account.py b/tests/test_account.py
index ef48d4e..231f85c 100644
--- a/tests/test_account.py
+++ b/tests/test_account.py
@@ -232,7 +232,26 @@ def test_suggested_tags(api):
232 232
233@pytest.mark.vcr() 233@pytest.mark.vcr()
234def test_featured_tags(api): 234def test_featured_tags(api):
235 featured_tag = api.featured_tag_create("ringtones") 235 try:
236 featured_tag = api.featured_tag_create("ringtones")
237 assert featured_tag
238 assert featured_tag.name == "ringtones"
239
240 featured_tag_2 = api.featured_tag_create("#coolfree")
241 assert featured_tag_2
242 assert featured_tag_2.name == "coolfree"
243
244 api.featured_tag_delete(featured_tag)
245 featured_tag = None
246
247 featured_tag_list = api.account_featured_tags(api.account_verify_credentials())
248 assert len(featured_tag_list) == 1
249 assert featured_tag_list[0].name == "coolfree"
250 assert "url" in featured_tag_list[0]
251 finally:
252 if not featured_tag is None:
253 api.featured_tag_delete(featured_tag)
254 api.featured_tag_delete(featured_tag_2)
236 255
237@pytest.mark.vcr() 256@pytest.mark.vcr()
238def test_account_notes(api, api2): 257def test_account_notes(api, api2):
Powered by cgit v1.2.3 (git 2.41.0)