diff options
Diffstat (limited to 'mastodon')
-rw-r--r-- | mastodon/Mastodon.py | 218 |
1 files changed, 136 insertions, 82 deletions
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, |