diff options
-rw-r--r-- | mastodon/Mastodon.py | 35 | ||||
-rw-r--r-- | tests/cassettes/test_server_time.yaml | 63 | ||||
-rw-r--r-- | tests/test_instance.py | 7 | ||||
-rw-r--r-- | tests/test_notifications.py | 1 | ||||
-rw-r--r-- | tests/test_status.py | 1 |
5 files changed, 96 insertions, 11 deletions
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 05ebaaa..44e3b52 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -481,8 +481,7 @@ class Mastodon: | |||
481 | # instance() was added in 1.1.0, so our best guess is 1.0.0. | 481 | # instance() was added in 1.1.0, so our best guess is 1.0.0. |
482 | version_str = "1.0.0" | 482 | version_str = "1.0.0" |
483 | 483 | ||
484 | self.mastodon_major, self.mastodon_minor, self.mastodon_patch = parse_version_string( | 484 | self.mastodon_major, self.mastodon_minor, self.mastodon_patch = parse_version_string(version_str) |
485 | version_str) | ||
486 | return version_str | 485 | return version_str |
487 | 486 | ||
488 | def verify_minimum_version(self, version_str, cached=False): | 487 | def verify_minimum_version(self, version_str, cached=False): |
@@ -503,7 +502,24 @@ class Mastodon: | |||
503 | elif major == self.mastodon_major and minor == self.mastodon_minor and patch > self.mastodon_patch: | 502 | elif major == self.mastodon_major and minor == self.mastodon_minor and patch > self.mastodon_patch: |
504 | return False | 503 | return False |
505 | return True | 504 | return True |
505 | |||
506 | def get_approx_server_time(self): | ||
507 | """ | ||
508 | Retrieve the approximate server time | ||
509 | |||
510 | We parse this from the hopefully present "Date" header, but make no effort to compensate for latency. | ||
511 | """ | ||
512 | response = self.__api_request("HEAD", "/", return_response_object=True) | ||
513 | print(response.headers) | ||
514 | if 'Date' in response.headers: | ||
515 | server_time_datetime = dateutil.parser.parse(response.headers['Date']) | ||
506 | 516 | ||
517 | # Make sure we're in local time | ||
518 | epoch_time = self.__datetime_to_epoch(server_time_datetime) | ||
519 | return datetime.datetime.fromtimestamp(epoch_time) | ||
520 | else: | ||
521 | raise MastodonAPIError("No server time in response.") | ||
522 | |||
507 | @staticmethod | 523 | @staticmethod |
508 | def get_supported_version(): | 524 | def get_supported_version(): |
509 | """ | 525 | """ |
@@ -937,7 +953,7 @@ class Mastodon: | |||
937 | 953 | ||
938 | Returns a `card dict`_. | 954 | Returns a `card dict`_. |
939 | """ | 955 | """ |
940 | if self.verify_minimum_version("3.0.0"): | 956 | if self.verify_minimum_version("3.0.0", cached=True): |
941 | return self.status(id).card | 957 | return self.status(id).card |
942 | else: | 958 | else: |
943 | id = self.__unpack_id(id) | 959 | id = self.__unpack_id(id) |
@@ -2139,7 +2155,7 @@ class Mastodon: | |||
2139 | """ | 2155 | """ |
2140 | id = self.__unpack_id(id) | 2156 | id = self.__unpack_id(id) |
2141 | 2157 | ||
2142 | if self.verify_minimum_version("2.9.2"): | 2158 | if self.verify_minimum_version("2.9.2", cached=True): |
2143 | url = '/api/v1/notifications/{0}/dismiss'.format(str(id)) | 2159 | url = '/api/v1/notifications/{0}/dismiss'.format(str(id)) |
2144 | self.__api_request('POST', url) | 2160 | self.__api_request('POST', url) |
2145 | else: | 2161 | else: |
@@ -2590,14 +2606,14 @@ class Mastodon: | |||
2590 | focus = str(focus[0]) + "," + str(focus[1]) | 2606 | focus = str(focus[0]) + "," + str(focus[1]) |
2591 | 2607 | ||
2592 | if not thumbnail is None: | 2608 | if not thumbnail is None: |
2593 | if not self.verify_minimum_version("3.2.0"): | 2609 | if not self.verify_minimum_version("3.2.0", cached=True): |
2594 | raise MastodonVersionError( | 2610 | raise MastodonVersionError( |
2595 | 'Thumbnail requires version > 3.2.0') | 2611 | 'Thumbnail requires version > 3.2.0') |
2596 | files["thumbnail"] = self.__load_media_file( | 2612 | files["thumbnail"] = self.__load_media_file( |
2597 | thumbnail, thumbnail_mime_type) | 2613 | thumbnail, thumbnail_mime_type) |
2598 | 2614 | ||
2599 | # Disambiguate URL by version | 2615 | # Disambiguate URL by version |
2600 | if self.verify_minimum_version("3.1.4"): | 2616 | if self.verify_minimum_version("3.1.4", cached=True): |
2601 | ret_dict = self.__api_request( | 2617 | ret_dict = self.__api_request( |
2602 | 'POST', '/api/v2/media', files=files, params={'description': description, 'focus': focus}) | 2618 | 'POST', '/api/v2/media', files=files, params={'description': description, 'focus': focus}) |
2603 | else: | 2619 | else: |
@@ -2637,7 +2653,7 @@ class Mastodon: | |||
2637 | locals(), ['id', 'thumbnail', 'thumbnail_mime_type']) | 2653 | locals(), ['id', 'thumbnail', 'thumbnail_mime_type']) |
2638 | 2654 | ||
2639 | if not thumbnail is None: | 2655 | if not thumbnail is None: |
2640 | if not self.verify_minimum_version("3.2.0"): | 2656 | if not self.verify_minimum_version("3.2.0", cached=True): |
2641 | raise MastodonVersionError( | 2657 | raise MastodonVersionError( |
2642 | 'Thumbnail requires version > 3.2.0') | 2658 | 'Thumbnail requires version > 3.2.0') |
2643 | files = {"thumbnail": self.__load_media_file( | 2659 | files = {"thumbnail": self.__load_media_file( |
@@ -3359,8 +3375,7 @@ class Mastodon: | |||
3359 | else: | 3375 | else: |
3360 | date_time_utc = date_time.astimezone(pytz.utc) | 3376 | date_time_utc = date_time.astimezone(pytz.utc) |
3361 | 3377 | ||
3362 | epoch_utc = datetime.datetime.utcfromtimestamp( | 3378 | epoch_utc = datetime.datetime.utcfromtimestamp(0).replace(tzinfo=pytz.utc) |
3363 | 0).replace(tzinfo=pytz.utc) | ||
3364 | 3379 | ||
3365 | return (date_time_utc - epoch_utc).total_seconds() | 3380 | return (date_time_utc - epoch_utc).total_seconds() |
3366 | 3381 | ||
@@ -3632,7 +3647,7 @@ class Mastodon: | |||
3632 | response_object.status_code, | 3647 | response_object.status_code, |
3633 | response_object.reason, | 3648 | response_object.reason, |
3634 | error_msg) | 3649 | error_msg) |
3635 | 3650 | ||
3636 | if return_response_object: | 3651 | if return_response_object: |
3637 | return response_object | 3652 | return response_object |
3638 | 3653 | ||
diff --git a/tests/cassettes/test_server_time.yaml b/tests/cassettes/test_server_time.yaml new file mode 100644 index 0000000..a94b3aa --- /dev/null +++ b/tests/cassettes/test_server_time.yaml | |||
@@ -0,0 +1,63 @@ | |||
1 | interactions: | ||
2 | - request: | ||
3 | body: null | ||
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 | User-Agent: | ||
14 | - tests/v311 | ||
15 | method: HEAD | ||
16 | uri: http://localhost:3000/ | ||
17 | response: | ||
18 | body: | ||
19 | string: '' | ||
20 | headers: | ||
21 | Cache-Control: | ||
22 | - max-age=0, public | ||
23 | Content-Security-Policy: | ||
24 | - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src | ||
25 | ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000; | ||
26 | style-src ''self'' http://localhost:3000 ''nonce-2+ENJYUdR8BJrDBHHtp0Iw==''; | ||
27 | media-src ''self'' https: data: http://localhost:3000; frame-src ''self'' | ||
28 | https:; manifest-src ''self'' http://localhost:3000; connect-src ''self'' | ||
29 | data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000 | ||
30 | ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline'' | ||
31 | ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000; | ||
32 | worker-src ''self'' blob: http://localhost:3000' | ||
33 | Content-Type: | ||
34 | - text/html; charset=utf-8 | ||
35 | Date: | ||
36 | - Thu, 17 Nov 2022 20:42:32 GMT | ||
37 | ETag: | ||
38 | - W/"9bb3b62cb5fb0388ee3b972a95ee0633" | ||
39 | Referrer-Policy: | ||
40 | - origin | ||
41 | Set-Cookie: | ||
42 | - _mastodon_session=S%2F25BrjlEMmL38vg%2FCMcsvHcd8%2BW45HbUkMBwTiqvTgNnzQ%2FhKVYvwORXtqZ5IgNVXl7gMcJ7SxG9y1ks1LN%2Bw3rvgb%2FxECYIlBWY7C3m%2B0aWsWG%2F8iNJsZfHvXlEY3xQxDzenmA2Mw35wRyPiT%2FSUJvwM9I5RtY1iUDsaCPzUbhGFcw3aoGUTdeag37%2FfGsJuG%2F9JsR0jj%2FCgWAlokV8%2Freu8XPUBFFDmjV9SdyFfzsIvP8%2Bd7cAebpCpaqp2DPngNSm8k6xgqXCuMCqpNc09slWQHzfDVqtWPTCMc95SmGpO0DOethwA44F8WbsfX1x5HGml8%3D--x1Ipi2xI5V5ct712--m3eM1Vf8f4oi87fjm0LEvw%3D%3D; | ||
43 | path=/; HttpOnly; SameSite=Lax | ||
44 | Vary: | ||
45 | - Accept | ||
46 | X-Content-Type-Options: | ||
47 | - nosniff | ||
48 | X-Download-Options: | ||
49 | - noopen | ||
50 | X-Frame-Options: | ||
51 | - SAMEORIGIN | ||
52 | X-Permitted-Cross-Domain-Policies: | ||
53 | - none | ||
54 | X-Request-Id: | ||
55 | - 9d6b0c84-dff7-481a-a975-c669b8469976 | ||
56 | X-Runtime: | ||
57 | - '0.691929' | ||
58 | X-XSS-Protection: | ||
59 | - 1; mode=block | ||
60 | status: | ||
61 | code: 200 | ||
62 | message: OK | ||
63 | version: 1 | ||
diff --git a/tests/test_instance.py b/tests/test_instance.py index 2762ecb..5de61f6 100644 --- a/tests/test_instance.py +++ b/tests/test_instance.py | |||
@@ -1,6 +1,7 @@ | |||
1 | import pytest | 1 | import pytest |
2 | 2 | ||
3 | from mastodon.Mastodon import MastodonVersionError | 3 | from mastodon.Mastodon import MastodonVersionError |
4 | import datetime | ||
4 | 5 | ||
5 | @pytest.mark.vcr() | 6 | @pytest.mark.vcr() |
6 | def test_instance(api): | 7 | def test_instance(api): |
@@ -36,7 +37,11 @@ def test_emoji(api): | |||
36 | @pytest.mark.vcr() | 37 | @pytest.mark.vcr() |
37 | def test_health(api): | 38 | def test_health(api): |
38 | assert api.instance_health() == True | 39 | assert api.instance_health() == True |
39 | 40 | ||
41 | @pytest.mark.vcr() | ||
42 | def test_server_time(api): | ||
43 | assert isinstance(api.get_approx_server_time(), datetime.datetime) | ||
44 | |||
40 | @pytest.mark.vcr() | 45 | @pytest.mark.vcr() |
41 | def test_nodeinfo(api): | 46 | def test_nodeinfo(api): |
42 | nodeinfo = api.instance_nodeinfo() | 47 | nodeinfo = api.instance_nodeinfo() |
diff --git a/tests/test_notifications.py b/tests/test_notifications.py index 0be81c6..6e761ce 100644 --- a/tests/test_notifications.py +++ b/tests/test_notifications.py | |||
@@ -26,6 +26,7 @@ def test_notifications_dismiss_pre_2_9_2(api, api2): | |||
26 | try: | 26 | try: |
27 | status = api2.status_post('@mastodonpy_test hello!') | 27 | status = api2.status_post('@mastodonpy_test hello!') |
28 | notifications = api.notifications() | 28 | notifications = api.notifications() |
29 | api.verify_minimum_version("2.9.2", cached=False) | ||
29 | api.notifications_dismiss(notifications[0]) | 30 | api.notifications_dismiss(notifications[0]) |
30 | finally: | 31 | finally: |
31 | if not status is None: | 32 | if not status is None: |
diff --git a/tests/test_status.py b/tests/test_status.py index 7e30362..f45634f 100644 --- a/tests/test_status.py +++ b/tests/test_status.py | |||
@@ -53,6 +53,7 @@ def test_status_card_pre_2_9_2(api): | |||
53 | import time | 53 | import time |
54 | status = api.status_post("http://example.org/") | 54 | status = api.status_post("http://example.org/") |
55 | time.sleep(5) # Card generation may take time | 55 | time.sleep(5) # Card generation may take time |
56 | api.verify_minimum_version("2.9.2", cached=False) | ||
56 | card = api.status_card(status['id']) | 57 | card = api.status_card(status['id']) |
57 | try: | 58 | try: |
58 | assert card | 59 | assert card |