aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhalcy <halcy@ARARAGI-KUN>2022-11-22 00:10:02 +0200
committerhalcy <halcy@ARARAGI-KUN>2022-11-22 00:10:02 +0200
commitf3d25fa19deb2caf0793d685a542509f94c2c8a9 (patch)
tree92e45bf340668cffe014d8d7df66dff2d594064a
parent6abaff55e7e78b83bd03af9f370a1256e7271b4a (diff)
downloadmastodon.py-f3d25fa19deb2caf0793d685a542509f94c2c8a9.tar.gz
add status editing
-rw-r--r--TODO.md2
-rw-r--r--docs/index.rst17
-rw-r--r--mastodon/Mastodon.py218
-rw-r--r--tests/cassettes/test_status_edit.yaml379
-rw-r--r--tests/test_status.py16
5 files changed, 549 insertions, 83 deletions
diff --git a/TODO.md b/TODO.md
index cf845fc..d1b1e7a 100644
--- a/TODO.md
+++ b/TODO.md
@@ -65,5 +65,5 @@ General improvements that would be good to do before doing another release:
65* [ ] Split mastodon.py into parts in some way that makes sense, it's getting very unwieldy 65* [ ] Split mastodon.py into parts in some way that makes sense, it's getting very unwieldy
66* [x] Fix the CI 66* [x] Fix the CI
67* [ ] Get test coverage like, real high 67* [ ] Get test coverage like, real high
68* [ ] Add all those streaming events?? 68* [x] Add all those streaming events??
69* [ ] Document return values 69* [ ] Document return values
diff --git a/docs/index.rst b/docs/index.rst
index 450300e..3d52b08 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -876,6 +876,19 @@ Admin account dicts
876 'account': # The user's account, as a standard user dict 876 'account': # The user's account, as a standard user dict
877 } 877 }
878 878
879Status edit dicts
880~~~~~~~~~~~~~~~~~
881.. _status edit dict:
882
883.. code-block:: python
884
885 mastodonstatus_history(id)[0]
886 # Returns the following dictionary
887 {
888 TODO
889 }
890
891
879App registration and user authentication 892App registration and user authentication
880---------------------------------------- 893----------------------------------------
881Before you can use the Mastodon API, you have to register your 894Before you can use the Mastodon API, you have to register your
@@ -967,6 +980,8 @@ These functions allow you to get information about single statuses.
967.. automethod:: Mastodon.status_reblogged_by 980.. automethod:: Mastodon.status_reblogged_by
968.. automethod:: Mastodon.status_favourited_by 981.. automethod:: Mastodon.status_favourited_by
969.. automethod:: Mastodon.status_card 982.. automethod:: Mastodon.status_card
983.. automethod:: Mastodon.status_history
984.. automethod:: Mastodon.status_source
970 985
971Reading data: Scheduled statuses 986Reading data: Scheduled statuses
972~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 987~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1142,6 +1157,8 @@ interact with already posted statuses.
1142.. automethod:: Mastodon.status_bookmark 1157.. automethod:: Mastodon.status_bookmark
1143.. automethod:: Mastodon.status_unbookmark 1158.. automethod:: Mastodon.status_unbookmark
1144.. automethod:: Mastodon.status_delete 1159.. automethod:: Mastodon.status_delete
1160.. automethod:: Mastodon.status_update
1161
1145 1162
1146Writing data: Scheduled statuses 1163Writing data: Scheduled statuses
1147~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1164~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py
index 2a70ce7..48b1307 100644
--- a/mastodon/Mastodon.py
+++ b/mastodon/Mastodon.py
@@ -229,30 +229,25 @@ class Mastodon:
229 __DICT_VERSION_HASHTAG = "2.3.4" 229 __DICT_VERSION_HASHTAG = "2.3.4"
230 __DICT_VERSION_EMOJI = "3.0.0" 230 __DICT_VERSION_EMOJI = "3.0.0"
231 __DICT_VERSION_RELATIONSHIP = "3.3.0" 231 __DICT_VERSION_RELATIONSHIP = "3.3.0"
232 __DICT_VERSION_NOTIFICATION = bigger_version(bigger_version( 232 __DICT_VERSION_NOTIFICATION = bigger_version(bigger_version("1.0.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS)
233 "1.0.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS)
234 __DICT_VERSION_CONTEXT = bigger_version("1.0.0", __DICT_VERSION_STATUS) 233 __DICT_VERSION_CONTEXT = bigger_version("1.0.0", __DICT_VERSION_STATUS)
235 __DICT_VERSION_LIST = "2.1.0" 234 __DICT_VERSION_LIST = "2.1.0"
236 __DICT_VERSION_CARD = "3.2.0" 235 __DICT_VERSION_CARD = "3.2.0"
237 __DICT_VERSION_SEARCHRESULT = bigger_version(bigger_version(bigger_version( 236 __DICT_VERSION_SEARCHRESULT = bigger_version(bigger_version(bigger_version("1.0.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS), __DICT_VERSION_HASHTAG)
238 "1.0.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS), __DICT_VERSION_HASHTAG)
239 __DICT_VERSION_ACTIVITY = "2.1.2" 237 __DICT_VERSION_ACTIVITY = "2.1.2"
240 __DICT_VERSION_REPORT = "2.9.1" 238 __DICT_VERSION_REPORT = "2.9.1"
241 __DICT_VERSION_PUSH = "2.4.0" 239 __DICT_VERSION_PUSH = "2.4.0"
242 __DICT_VERSION_PUSH_NOTIF = "2.4.0" 240 __DICT_VERSION_PUSH_NOTIF = "2.4.0"
243 __DICT_VERSION_FILTER = "2.4.3" 241 __DICT_VERSION_FILTER = "2.4.3"
244 __DICT_VERSION_CONVERSATION = bigger_version(bigger_version( 242 __DICT_VERSION_CONVERSATION = bigger_version(bigger_version("2.6.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS)
245 "2.6.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS) 243 __DICT_VERSION_SCHEDULED_STATUS = bigger_version("2.7.0", __DICT_VERSION_STATUS)
246 __DICT_VERSION_SCHEDULED_STATUS = bigger_version(
247 "2.7.0", __DICT_VERSION_STATUS)
248 __DICT_VERSION_PREFERENCES = "2.8.0" 244 __DICT_VERSION_PREFERENCES = "2.8.0"
249 __DICT_VERSION_ADMIN_ACCOUNT = bigger_version( 245 __DICT_VERSION_ADMIN_ACCOUNT = bigger_version("2.9.1", __DICT_VERSION_ACCOUNT)
250 "2.9.1", __DICT_VERSION_ACCOUNT)
251 __DICT_VERSION_FEATURED_TAG = "3.0.0" 246 __DICT_VERSION_FEATURED_TAG = "3.0.0"
252 __DICT_VERSION_MARKER = "3.0.0" 247 __DICT_VERSION_MARKER = "3.0.0"
253 __DICT_VERSION_REACTION = "3.1.0" 248 __DICT_VERSION_REACTION = "3.1.0"
254 __DICT_VERSION_ANNOUNCEMENT = bigger_version( 249 __DICT_VERSION_ANNOUNCEMENT = bigger_version("3.1.0", __DICT_VERSION_REACTION)
255 "3.1.0", __DICT_VERSION_REACTION) 250 __DICT_VERSION_STATUS_EDIT = "3.5.0"
256 251
257 ### 252 ###
258 # Registering apps 253 # Registering apps
@@ -1797,80 +1792,21 @@ class Mastodon:
1797 ### 1792 ###
1798 # Writing data: Statuses 1793 # Writing data: Statuses
1799 ### 1794 ###
1800 @api_version("1.0.0", "2.8.0", __DICT_VERSION_STATUS) 1795 def __status_internal(self, status, in_reply_to_id=None, media_ids=None,
1801 def status_post(self, status, in_reply_to_id=None, media_ids=None,
1802 sensitive=False, visibility=None, spoiler_text=None, 1796 sensitive=False, visibility=None, spoiler_text=None,
1803 language=None, idempotency_key=None, content_type=None, 1797 language=None, idempotency_key=None, content_type=None,
1804 scheduled_at=None, poll=None, quote_id=None): 1798 scheduled_at=None, poll=None, quote_id=None, edit=False):
1805 """
1806 Post a status. Can optionally be in reply to another status and contain
1807 media.
1808
1809 `media_ids` should be a list. (If it's not, the function will turn it
1810 into one.) It can contain up to four pieces of media (uploaded via
1811 `media_post()`_). `media_ids` can also be the `media dicts`_ returned
1812 by `media_post()`_ - they are unpacked automatically.
1813
1814 The `sensitive` boolean decides whether or not media attached to the post
1815 should be marked as sensitive, which hides it by default on the Mastodon
1816 web front-end.
1817
1818 The visibility parameter is a string value and accepts any of:
1819 'direct' - post will be visible only to mentioned users
1820 'private' - post will be visible only to followers
1821 'unlisted' - post will be public but not appear on the public timeline
1822 'public' - post will be public
1823
1824 If not passed in, visibility defaults to match the current account's
1825 default-privacy setting (starting with Mastodon version 1.6) or its
1826 locked setting - private if the account is locked, public otherwise
1827 (for Mastodon versions lower than 1.6).
1828
1829 The `spoiler_text` parameter is a string to be shown as a warning before
1830 the text of the status. If no text is passed in, no warning will be
1831 displayed.
1832
1833 Specify `language` to override automatic language detection. The parameter
1834 accepts all valid ISO 639-2 language codes.
1835
1836 You can set `idempotency_key` to a value to uniquely identify an attempt
1837 at posting a status. Even if you call this function more than once,
1838 if you call it with the same `idempotency_key`, only one status will
1839 be created.
1840
1841 Pass a datetime as `scheduled_at` to schedule the toot for a specific time
1842 (the time must be at least 5 minutes into the future). If this is passed,
1843 status_post returns a `scheduled toot dict`_ instead.
1844
1845 Pass `poll` to attach a poll to the status. An appropriate object can be
1846 constructed using `make_poll()`_ . Note that as of Mastodon version
1847 2.8.2, you can only have either media or a poll attached, not both at
1848 the same time.
1849
1850 **Specific to "pleroma" feature set:**: Specify `content_type` to set
1851 the content type of your post on Pleroma. It accepts 'text/plain' (default),
1852 'text/markdown', 'text/html' and 'text/bbcode'. This parameter is not
1853 supported on Mastodon servers, but will be safely ignored if set.
1854
1855 **Specific to "fedibird" feature set:**: The `quote_id` parameter is
1856 a non-standard extension that specifies the id of a quoted status.
1857
1858 Returns a `toot dict`_ with the new status.
1859 """
1860 if quote_id is not None: 1799 if quote_id is not None:
1861 if self.feature_set != "fedibird": 1800 if self.feature_set != "fedibird":
1862 raise MastodonIllegalArgumentError( 1801 raise MastodonIllegalArgumentError('quote_id is only available with feature set fedibird')
1863 'quote_id is only available with feature set fedibird')
1864 quote_id = self.__unpack_id(quote_id) 1802 quote_id = self.__unpack_id(quote_id)
1865 1803
1866 if content_type is not None: 1804 if content_type is not None:
1867 if self.feature_set != "pleroma": 1805 if self.feature_set != "pleroma":
1868 raise MastodonIllegalArgumentError( 1806 raise MastodonIllegalArgumentError('content_type is only available with feature set pleroma')
1869 'content_type is only available with feature set pleroma')
1870 # It would be better to read this from nodeinfo and cache, but this is easier 1807 # It would be better to read this from nodeinfo and cache, but this is easier
1871 if not content_type in ["text/plain", "text/html", "text/markdown", "text/bbcode"]: 1808 if not content_type in ["text/plain", "text/html", "text/markdown", "text/bbcode"]:
1872 raise MastodonIllegalArgumentError( 1809 raise MastodonIllegalArgumentError('Invalid content type specified')
1873 'Invalid content type specified')
1874 1810
1875 if in_reply_to_id is not None: 1811 if in_reply_to_id is not None:
1876 in_reply_to_id = self.__unpack_id(in_reply_to_id) 1812 in_reply_to_id = self.__unpack_id(in_reply_to_id)
@@ -1893,8 +1829,7 @@ class Mastodon:
1893 else: 1829 else:
1894 params_initial['visibility'] = params_initial['visibility'].lower() 1830 params_initial['visibility'] = params_initial['visibility'].lower()
1895 if params_initial['visibility'] not in valid_visibilities: 1831 if params_initial['visibility'] not in valid_visibilities:
1896 raise ValueError('Invalid visibility value! Acceptable ' 1832 raise ValueError('Invalid visibility value! Acceptable values are %s' % valid_visibilities)
1897 'values are %s' % valid_visibilities)
1898 1833
1899 if params_initial['language'] is None: 1834 if params_initial['language'] is None:
1900 del params_initial['language'] 1835 del params_initial['language']
@@ -1914,8 +1849,7 @@ class Mastodon:
1914 for media_id in media_ids: 1849 for media_id in media_ids:
1915 media_ids_proper.append(self.__unpack_id(media_id)) 1850 media_ids_proper.append(self.__unpack_id(media_id))
1916 except Exception as e: 1851 except Exception as e:
1917 raise MastodonIllegalArgumentError("Invalid media " 1852 raise MastodonIllegalArgumentError("Invalid media dict: %s" % e)
1918 "dict: %s" % e)
1919 1853
1920 params_initial["media_ids"] = media_ids_proper 1854 params_initial["media_ids"] = media_ids_proper
1921 1855
@@ -1926,8 +1860,89 @@ class Mastodon:
1926 if poll is not None: 1860 if poll is not None:
1927 use_json = True 1861 use_json = True
1928 1862
1929 params = self.__generate_params(params_initial, ['idempotency_key']) 1863 params = self.__generate_params(params_initial, ['idempotency_key', 'edit'])
1930 return self.__api_request('POST', '/api/v1/statuses', params, headers=headers, use_json=use_json) 1864 if edit is None:
1865 # Post
1866 return self.__api_request('POST', '/api/v1/statuses', params, headers=headers, use_json=use_json)
1867 else:
1868 # Edit
1869 return self.__api_request('PUT', '/api/v1/statuses/{0}'.format(str(self.__unpack_id(edit))), params, headers=headers, use_json=use_json)
1870
1871 @api_version("1.0.0", "2.8.0", __DICT_VERSION_STATUS)
1872 def status_post(self, status, in_reply_to_id=None, media_ids=None,
1873 sensitive=False, visibility=None, spoiler_text=None,
1874 language=None, idempotency_key=None, content_type=None,
1875 scheduled_at=None, poll=None, quote_id=None):
1876 """
1877 Post a status. Can optionally be in reply to another status and contain
1878 media.
1879
1880 `media_ids` should be a list. (If it's not, the function will turn it
1881 into one.) It can contain up to four pieces of media (uploaded via
1882 `media_post()`_). `media_ids` can also be the `media dicts`_ returned
1883 by `media_post()`_ - they are unpacked automatically.
1884
1885 The `sensitive` boolean decides whether or not media attached to the post
1886 should be marked as sensitive, which hides it by default on the Mastodon
1887 web front-end.
1888
1889 The visibility parameter is a string value and accepts any of:
1890 'direct' - post will be visible only to mentioned users
1891 'private' - post will be visible only to followers
1892 'unlisted' - post will be public but not appear on the public timeline
1893 'public' - post will be public
1894
1895 If not passed in, visibility defaults to match the current account's
1896 default-privacy setting (starting with Mastodon version 1.6) or its
1897 locked setting - private if the account is locked, public otherwise
1898 (for Mastodon versions lower than 1.6).
1899
1900 The `spoiler_text` parameter is a string to be shown as a warning before
1901 the text of the status. If no text is passed in, no warning will be
1902 displayed.
1903
1904 Specify `language` to override automatic language detection. The parameter
1905 accepts all valid ISO 639-2 language codes.
1906
1907 You can set `idempotency_key` to a value to uniquely identify an attempt
1908 at posting a status. Even if you call this function more than once,
1909 if you call it with the same `idempotency_key`, only one status will
1910 be created.
1911
1912 Pass a datetime as `scheduled_at` to schedule the toot for a specific time
1913 (the time must be at least 5 minutes into the future). If this is passed,
1914 status_post returns a `scheduled toot dict`_ instead.
1915
1916 Pass `poll` to attach a poll to the status. An appropriate object can be
1917 constructed using `make_poll()`_ . Note that as of Mastodon version
1918 2.8.2, you can only have either media or a poll attached, not both at
1919 the same time.
1920
1921 **Specific to "pleroma" feature set:**: Specify `content_type` to set
1922 the content type of your post on Pleroma. It accepts 'text/plain' (default),
1923 'text/markdown', 'text/html' and 'text/bbcode'. This parameter is not
1924 supported on Mastodon servers, but will be safely ignored if set.
1925
1926 **Specific to "fedibird" feature set:**: The `quote_id` parameter is
1927 a non-standard extension that specifies the id of a quoted status.
1928
1929 Returns a `toot dict`_ with the new status.
1930 """
1931 return self.__status_internal(
1932 status,
1933 in_reply_to_id,
1934 media_ids,
1935 sensitive,
1936 visibility,
1937 spoiler_text,
1938 language,
1939 idempotency_key,
1940 content_type,
1941 scheduled_at,
1942 poll,
1943 quote_id,
1944 edit=None
1945 )
1931 1946
1932 @api_version("1.0.0", "2.8.0", __DICT_VERSION_STATUS) 1947 @api_version("1.0.0", "2.8.0", __DICT_VERSION_STATUS)
1933 def toot(self, status): 1948 def toot(self, status):
@@ -1940,6 +1955,45 @@ class Mastodon:
1940 """ 1955 """
1941 return self.status_post(status) 1956 return self.status_post(status)
1942 1957
1958 @api_version("3.5.0", "3.5.0", __DICT_VERSION_STATUS)
1959 def status_update(self, id, status = None, spoiler_text = None, sensitive = None, media_ids = None, poll = None):
1960 """
1961 Edit a status. The meanings of the fields are largely the same as in `status_post()`_,
1962 though not every field can be edited.
1963
1964 Note that editing a poll will reset the votes.
1965 """
1966 return self.__status_internal(
1967 status = status,
1968 media_ids = media_ids,
1969 sensitive = sensitive,
1970 spoiler_text = spoiler_text,
1971 poll = poll,
1972 edit = id
1973 )
1974
1975 @api_version("3.5.0", "3.5.0", __DICT_VERSION_STATUS_EDIT)
1976 def status_history(self, id):
1977 """
1978 Returns the edit history of a status as a list of `status edit dicts`_, starting
1979 from the original form. Note that this means that a status that has been edited
1980 once will have *two* entries in this list, a status that has been edited twice
1981 will have three, and so on.
1982 """
1983 id = self.__unpack_id(id)
1984 return self.__api_request('GET', "/api/v1/statuses/{0}/history".format(str(id)))
1985
1986 def status_source(self, id):
1987 """
1988 Returns the source of a status for editing.
1989
1990 Return value is a dictionary containing exactly the parameters you could pass to
1991 `status_update()`_ to change nothing about the status, except `status` is `text`
1992 instead.
1993 """
1994 id = self.__unpack_id(id)
1995 return self.__api_request('GET', "/api/v1/statuses/{0}/source".format(str(id)))
1996
1943 @api_version("1.0.0", "2.8.0", __DICT_VERSION_STATUS) 1997 @api_version("1.0.0", "2.8.0", __DICT_VERSION_STATUS)
1944 def status_reply(self, to_status, status, in_reply_to_id=None, media_ids=None, 1998 def status_reply(self, to_status, status, in_reply_to_id=None, media_ids=None,
1945 sensitive=False, visibility=None, spoiler_text=None, 1999 sensitive=False, visibility=None, spoiler_text=None,
diff --git a/tests/cassettes/test_status_edit.yaml b/tests/cassettes/test_status_edit.yaml
new file mode 100644
index 0000000..1343b28
--- /dev/null
+++ b/tests/cassettes/test_status_edit.yaml
@@ -0,0 +1,379 @@
1interactions:
2- request:
3 body: status=the+best+editor%3F+why%2C+of+course+it+is+VS+Code
4 headers:
5 Accept:
6 - '*/*'
7 Accept-Encoding:
8 - gzip, deflate
9 Authorization:
10 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
11 Connection:
12 - keep-alive
13 Content-Length:
14 - '56'
15 Content-Type:
16 - application/x-www-form-urlencoded
17 User-Agent:
18 - tests/v311
19 method: POST
20 uri: http://localhost:3000/api/v1/statuses
21 response:
22 body:
23 string: '{"id":"109384054168698393","created_at":"2022-11-21T22:03:29.362Z","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/109384054168698393","url":"http://localhost:3000/@mastodonpy_test/109384054168698393","replies_count":0,"reblogs_count":0,"favourites_count":0,"edited_at":null,"favourited":false,"reblogged":false,"muted":false,"bookmarked":false,"pinned":false,"content":"\u003cp\u003ethe
24 best editor? why, of course it is VS Code\u003c/p\u003e","filtered":[],"reblog":null,"application":{"name":"Mastodon.py
25 test suite","website":null},"account":{"id":"109383687546708201","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-21T00: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":6,"last_status_at":"2022-11-21","noindex":false,"emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null}'
26 headers:
27 Cache-Control:
28 - no-store
29 Content-Security-Policy:
30 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
31 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
32 style-src ''self'' http://localhost:3000 ''nonce-3UDW6mpgnOTfx5Euaa1LQA=='';
33 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
34 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
35 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
36 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
37 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
38 worker-src ''self'' blob: http://localhost:3000'
39 Content-Type:
40 - application/json; charset=utf-8
41 ETag:
42 - W/"8a45eb762bdb11cdd6cd63bfebe39f63"
43 Referrer-Policy:
44 - strict-origin-when-cross-origin
45 Transfer-Encoding:
46 - chunked
47 Vary:
48 - Accept, Origin
49 X-Content-Type-Options:
50 - nosniff
51 X-Download-Options:
52 - noopen
53 X-Frame-Options:
54 - SAMEORIGIN
55 X-Permitted-Cross-Domain-Policies:
56 - none
57 X-RateLimit-Limit:
58 - '300'
59 X-RateLimit-Remaining:
60 - '292'
61 X-RateLimit-Reset:
62 - '2022-11-22T00:00:00.383365Z'
63 X-Request-Id:
64 - e56f662b-28f8-4ba7-9b38-36e71ac7d73c
65 X-Runtime:
66 - '0.033929'
67 X-XSS-Protection:
68 - 1; mode=block
69 status:
70 code: 200
71 message: OK
72- request:
73 body: null
74 headers:
75 Accept:
76 - '*/*'
77 Accept-Encoding:
78 - gzip, deflate
79 Authorization:
80 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
81 Connection:
82 - keep-alive
83 User-Agent:
84 - tests/v311
85 method: GET
86 uri: http://localhost:3000/api/v1/statuses/109384054168698393/history
87 response:
88 body:
89 string: '[]'
90 headers:
91 Cache-Control:
92 - no-store
93 Content-Security-Policy:
94 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
95 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
96 style-src ''self'' http://localhost:3000 ''nonce-oKku/pMs24FqYkpW5MkiGQ=='';
97 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
98 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
99 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
100 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
101 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
102 worker-src ''self'' blob: http://localhost:3000'
103 Content-Type:
104 - application/json; charset=utf-8
105 ETag:
106 - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
107 Referrer-Policy:
108 - strict-origin-when-cross-origin
109 Transfer-Encoding:
110 - chunked
111 Vary:
112 - Accept, Origin
113 X-Content-Type-Options:
114 - nosniff
115 X-Download-Options:
116 - noopen
117 X-Frame-Options:
118 - SAMEORIGIN
119 X-Permitted-Cross-Domain-Policies:
120 - none
121 X-Request-Id:
122 - 4a780264-f947-4745-a5de-7165d8eee3d9
123 X-Runtime:
124 - '0.010494'
125 X-XSS-Protection:
126 - 1; mode=block
127 status:
128 code: 200
129 message: OK
130- request:
131 body: status=the+best+editor%3F+why%2C+of+course+it+is+the+KDE+Advanced+Text+Editor%2C+Kate
132 headers:
133 Accept:
134 - '*/*'
135 Accept-Encoding:
136 - gzip, deflate
137 Authorization:
138 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
139 Connection:
140 - keep-alive
141 Content-Length:
142 - '85'
143 Content-Type:
144 - application/x-www-form-urlencoded
145 User-Agent:
146 - tests/v311
147 method: PUT
148 uri: http://localhost:3000/api/v1/statuses/109384054168698393
149 response:
150 body:
151 string: '{"id":"109384054168698393","created_at":"2022-11-21T22:03:29.362Z","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/109384054168698393","url":"http://localhost:3000/@mastodonpy_test/109384054168698393","replies_count":0,"reblogs_count":0,"favourites_count":0,"edited_at":"2022-11-21T22:03:29.418Z","favourited":false,"reblogged":false,"muted":false,"bookmarked":false,"pinned":false,"content":"\u003cp\u003ethe
152 best editor? why, of course it is the KDE Advanced Text Editor, Kate\u003c/p\u003e","filtered":[],"reblog":null,"application":{"name":"Mastodon.py
153 test suite","website":null},"account":{"id":"109383687546708201","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-21T00: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":6,"last_status_at":"2022-11-21","noindex":false,"emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null}'
154 headers:
155 Cache-Control:
156 - no-store
157 Content-Security-Policy:
158 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
159 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
160 style-src ''self'' http://localhost:3000 ''nonce-11jMbHJPLcAv+qMX8EK9Eg=='';
161 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
162 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
163 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
164 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
165 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
166 worker-src ''self'' blob: http://localhost:3000'
167 Content-Type:
168 - application/json; charset=utf-8
169 ETag:
170 - W/"976b69a807cf9d4601d0c73c8eb249fc"
171 Referrer-Policy:
172 - strict-origin-when-cross-origin
173 Transfer-Encoding:
174 - chunked
175 Vary:
176 - Accept, Origin
177 X-Content-Type-Options:
178 - nosniff
179 X-Download-Options:
180 - noopen
181 X-Frame-Options:
182 - SAMEORIGIN
183 X-Permitted-Cross-Domain-Policies:
184 - none
185 X-RateLimit-Limit:
186 - '300'
187 X-RateLimit-Remaining:
188 - '291'
189 X-RateLimit-Reset:
190 - '2022-11-22T00:00:00.437259Z'
191 X-Request-Id:
192 - 1f4c3ffd-1c13-45ee-a9df-8d7fff11a17c
193 X-Runtime:
194 - '0.033812'
195 X-XSS-Protection:
196 - 1; mode=block
197 status:
198 code: 200
199 message: OK
200- request:
201 body: null
202 headers:
203 Accept:
204 - '*/*'
205 Accept-Encoding:
206 - gzip, deflate
207 Authorization:
208 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
209 Connection:
210 - keep-alive
211 User-Agent:
212 - tests/v311
213 method: GET
214 uri: http://localhost:3000/api/v1/statuses/109384054168698393
215 response:
216 body:
217 string: '{"id":"109384054168698393","created_at":"2022-11-21T22:03:29.362Z","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/109384054168698393","url":"http://localhost:3000/@mastodonpy_test/109384054168698393","replies_count":0,"reblogs_count":0,"favourites_count":0,"edited_at":"2022-11-21T22:03:29.418Z","favourited":false,"reblogged":false,"muted":false,"bookmarked":false,"content":"\u003cp\u003ethe
218 best editor? why, of course it is the KDE Advanced Text Editor, Kate\u003c/p\u003e","filtered":[],"reblog":null,"application":{"name":"Mastodon.py
219 test suite","website":null},"account":{"id":"109383687546708201","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-21T00: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":6,"last_status_at":"2022-11-21","noindex":false,"emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null}'
220 headers:
221 Cache-Control:
222 - no-store
223 Content-Security-Policy:
224 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
225 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
226 style-src ''self'' http://localhost:3000 ''nonce-/HjTa7cbsYkrasMByN5dRw=='';
227 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
228 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
229 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
230 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
231 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
232 worker-src ''self'' blob: http://localhost:3000'
233 Content-Type:
234 - application/json; charset=utf-8
235 ETag:
236 - W/"8d8244c105ccd1fff42ddc2e75976f91"
237 Referrer-Policy:
238 - strict-origin-when-cross-origin
239 Transfer-Encoding:
240 - chunked
241 Vary:
242 - Accept, Origin
243 X-Content-Type-Options:
244 - nosniff
245 X-Download-Options:
246 - noopen
247 X-Frame-Options:
248 - SAMEORIGIN
249 X-Permitted-Cross-Domain-Policies:
250 - none
251 X-Request-Id:
252 - 36c0e7e0-064a-42f1-91e0-82c90ebc4456
253 X-Runtime:
254 - '0.030588'
255 X-XSS-Protection:
256 - 1; mode=block
257 status:
258 code: 200
259 message: OK
260- request:
261 body: null
262 headers:
263 Accept:
264 - '*/*'
265 Accept-Encoding:
266 - gzip, deflate
267 Authorization:
268 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
269 Connection:
270 - keep-alive
271 User-Agent:
272 - tests/v311
273 method: GET
274 uri: http://localhost:3000/api/v1/statuses/109384054168698393/history
275 response:
276 body:
277 string: '[{"content":"\u003cp\u003ethe best editor? why, of course it is VS
278 Code\u003c/p\u003e","spoiler_text":"","sensitive":false,"created_at":"2022-11-21T22:03:29.362Z","account":{"id":"109383687546708201","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-21T00: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":6,"last_status_at":"2022-11-21","noindex":false,"emojis":[],"fields":[]},"media_attachments":[],"emojis":[]},{"content":"\u003cp\u003ethe
279 best editor? why, of course it is the KDE Advanced Text Editor, Kate\u003c/p\u003e","spoiler_text":"","sensitive":false,"created_at":"2022-11-21T22:03:29.418Z","account":{"id":"109383687546708201","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-21T00: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":6,"last_status_at":"2022-11-21","noindex":false,"emojis":[],"fields":[]},"media_attachments":[],"emojis":[]}]'
280 headers:
281 Cache-Control:
282 - no-store
283 Content-Security-Policy:
284 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
285 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
286 style-src ''self'' http://localhost:3000 ''nonce-mn4VRGJCjg55CXsiLcW5tA=='';
287 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
288 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
289 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
290 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
291 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
292 worker-src ''self'' blob: http://localhost:3000'
293 Content-Type:
294 - application/json; charset=utf-8
295 ETag:
296 - W/"e5185ce4a3ebf261210613a8bb85e77e"
297 Referrer-Policy:
298 - strict-origin-when-cross-origin
299 Transfer-Encoding:
300 - chunked
301 Vary:
302 - Accept, Origin
303 X-Content-Type-Options:
304 - nosniff
305 X-Download-Options:
306 - noopen
307 X-Frame-Options:
308 - SAMEORIGIN
309 X-Permitted-Cross-Domain-Policies:
310 - none
311 X-Request-Id:
312 - 17896b84-96a0-4ed4-b3a0-8fca353a3725
313 X-Runtime:
314 - '0.016628'
315 X-XSS-Protection:
316 - 1; mode=block
317 status:
318 code: 200
319 message: OK
320- request:
321 body: null
322 headers:
323 Accept:
324 - '*/*'
325 Accept-Encoding:
326 - gzip, deflate
327 Authorization:
328 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2
329 Connection:
330 - keep-alive
331 User-Agent:
332 - tests/v311
333 method: GET
334 uri: http://localhost:3000/api/v1/statuses/109384054168698393/source
335 response:
336 body:
337 string: '{"id":"109384054168698393","text":"the best editor? why, of course
338 it is the KDE Advanced Text Editor, Kate","spoiler_text":""}'
339 headers:
340 Cache-Control:
341 - no-store
342 Content-Security-Policy:
343 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
344 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
345 style-src ''self'' http://localhost:3000 ''nonce-1CVpCwMC0PSWzPM4QmGGoA=='';
346 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
347 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
348 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
349 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
350 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
351 worker-src ''self'' blob: http://localhost:3000'
352 Content-Type:
353 - application/json; charset=utf-8
354 ETag:
355 - W/"41ed5fd640708627beb7f31b84cb65d3"
356 Referrer-Policy:
357 - strict-origin-when-cross-origin
358 Transfer-Encoding:
359 - chunked
360 Vary:
361 - Accept, Origin
362 X-Content-Type-Options:
363 - nosniff
364 X-Download-Options:
365 - noopen
366 X-Frame-Options:
367 - SAMEORIGIN
368 X-Permitted-Cross-Domain-Policies:
369 - none
370 X-Request-Id:
371 - b5919220-e51e-4496-80f5-5a17e908702f
372 X-Runtime:
373 - '0.016356'
374 X-XSS-Protection:
375 - 1; mode=block
376 status:
377 code: 200
378 message: OK
379version: 1
diff --git a/tests/test_status.py b/tests/test_status.py
index 20e32f2..e747571 100644
--- a/tests/test_status.py
+++ b/tests/test_status.py
@@ -213,3 +213,19 @@ def test_scheduled_status_long_part2(api):
213 if text in status.content: 213 if text in status.content:
214 found_status = True 214 found_status = True
215 assert found_status 215 assert found_status
216
217@pytest.mark.vcr()
218def test_status_edit(api, api2):
219 status = api.status_post("the best editor? why, of course it is VS Code")
220 edit_list_1 = api2.status_history(status)
221 status_edited = api.status_update(status, "the best editor? why, of course it is the KDE Advanced Text Editor, Kate")
222 status_result = api2.status(status)
223 edit_list_2 = api2.status_history(status)
224
225 assert len(edit_list_1) == 0
226 assert len(edit_list_2) == 2
227 assert "the best editor? why, of course it is the KDE Advanced Text Editor, Kate" in status_result.content
228
229 source = api2.status_source(status)
230 assert source.text == "the best editor? why, of course it is the KDE Advanced Text Editor, Kate"
231 \ No newline at end of file
Powered by cgit v1.2.3 (git 2.41.0)