diff options
-rw-r--r-- | CHANGELOG.rst | 1 | ||||
-rw-r--r-- | TODO.md | 2 | ||||
-rw-r--r-- | mastodon/Mastodon.py | 14 | ||||
-rw-r--r-- | tests/cassettes/test_push_set.yaml | 24 | ||||
-rw-r--r-- | tests/test_instance.py | 2 | ||||
-rw-r--r-- | tests/test_push.py | 11 |
6 files changed, 36 insertions, 18 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index da22ae1..fb69ded 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst | |||
@@ -7,6 +7,7 @@ v1.6.3 | |||
7 | * Add server rules API (`instance_rules`) | 7 | * Add server rules API (`instance_rules`) |
8 | * Add confirmation email resend API (`email_resend_confirmation`) | 8 | * Add confirmation email resend API (`email_resend_confirmation`) |
9 | * Add account lookup API (`account_lookup`) | 9 | * Add account lookup API (`account_lookup`) |
10 | * Add `policy` param to control notification sources for `push_subscription_set` | ||
10 | 11 | ||
11 | v1.6.2 | 12 | v1.6.2 |
12 | ------ | 13 | ------ |
@@ -32,7 +32,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m | |||
32 | * [x] Add server rules | 32 | * [x] Add server rules |
33 | * [x] Add POST /api/v1/emails/confirmations to REST API | 33 | * [x] Add POST /api/v1/emails/confirmations to REST API |
34 | * [x] Add GET /api/v1/accounts/lookup to REST API | 34 | * [x] Add GET /api/v1/accounts/lookup to REST API |
35 | * [ ] Add policy param to POST /api/v1/push/subscriptions in REST API | 35 | * [x] Add policy param to POST /api/v1/push/subscriptions in REST API |
36 | * [ ] Add details to error response for POST /api/v1/accounts in REST API | 36 | * [ ] Add details to error response for POST /api/v1/accounts in REST API |
37 | 37 | ||
38 | 3.4.2 | 38 | 3.4.2 |
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 6e5bc29..12a054a 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py | |||
@@ -2756,7 +2756,7 @@ class Mastodon: | |||
2756 | def push_subscription_set(self, endpoint, encrypt_params, follow_events=None, | 2756 | def push_subscription_set(self, endpoint, encrypt_params, follow_events=None, |
2757 | favourite_events=None, reblog_events=None, | 2757 | favourite_events=None, reblog_events=None, |
2758 | mention_events=None, poll_events=None, | 2758 | mention_events=None, poll_events=None, |
2759 | follow_request_events=None): | 2759 | follow_request_events=None, status_events=None, policy='all'): |
2760 | """ | 2760 | """ |
2761 | Sets up or modifies the push subscription the logged-in user has for this app. | 2761 | Sets up or modifies the push subscription the logged-in user has for this app. |
2762 | 2762 | ||
@@ -2766,10 +2766,16 @@ class Mastodon: | |||
2766 | You can generate this as well as the corresponding private key using the | 2766 | You can generate this as well as the corresponding private key using the |
2767 | `push_subscription_generate_keys()`_ function. | 2767 | `push_subscription_generate_keys()`_ function. |
2768 | 2768 | ||
2769 | `policy` controls what sources will generate webpush events. Valid values are | ||
2770 | `all`, `none`, `follower` and `followed`. | ||
2771 | |||
2769 | The rest of the parameters controls what kind of events you wish to subscribe to. | 2772 | The rest of the parameters controls what kind of events you wish to subscribe to. |
2770 | 2773 | ||
2771 | Returns a `push subscription dict`_. | 2774 | Returns a `push subscription dict`_. |
2772 | """ | 2775 | """ |
2776 | if not policy in ['all', 'none', 'follower', 'followed']: | ||
2777 | raise MastodonIllegalArgumentError("Valid values for policy are 'all', 'none', 'follower' or 'followed'.") | ||
2778 | |||
2773 | endpoint = Mastodon.__protocolize(endpoint) | 2779 | endpoint = Mastodon.__protocolize(endpoint) |
2774 | 2780 | ||
2775 | push_pubkey_b64 = base64.b64encode(encrypt_params['pubkey']) | 2781 | push_pubkey_b64 = base64.b64encode(encrypt_params['pubkey']) |
@@ -2778,7 +2784,8 @@ class Mastodon: | |||
2778 | params = { | 2784 | params = { |
2779 | 'subscription[endpoint]': endpoint, | 2785 | 'subscription[endpoint]': endpoint, |
2780 | 'subscription[keys][p256dh]': push_pubkey_b64, | 2786 | 'subscription[keys][p256dh]': push_pubkey_b64, |
2781 | 'subscription[keys][auth]': push_auth_b64 | 2787 | 'subscription[keys][auth]': push_auth_b64, |
2788 | 'policy': policy | ||
2782 | } | 2789 | } |
2783 | 2790 | ||
2784 | if follow_events != None: | 2791 | if follow_events != None: |
@@ -2799,6 +2806,9 @@ class Mastodon: | |||
2799 | if follow_request_events != None: | 2806 | if follow_request_events != None: |
2800 | params['data[alerts][follow_request]'] = follow_request_events | 2807 | params['data[alerts][follow_request]'] = follow_request_events |
2801 | 2808 | ||
2809 | if follow_request_events != None: | ||
2810 | params['data[alerts][status]'] = status_events | ||
2811 | |||
2802 | # Canonicalize booleans | 2812 | # Canonicalize booleans |
2803 | params = self.__generate_params(params) | 2813 | params = self.__generate_params(params) |
2804 | 2814 | ||
diff --git a/tests/cassettes/test_push_set.yaml b/tests/cassettes/test_push_set.yaml index dd3089e..4995277 100644 --- a/tests/cassettes/test_push_set.yaml +++ b/tests/cassettes/test_push_set.yaml | |||
@@ -1,6 +1,6 @@ | |||
1 | interactions: | 1 | interactions: |
2 | - request: | 2 | - request: |
3 | body: subscription%5Bendpoint%5D=https%3A%2F%2Fexample.com&subscription%5Bkeys%5D%5Bp256dh%5D=BMGJORRZ33ebUVNTfhh5ONpJiYo1Qq6k%2FIv21xcIFzbR25IC2q7AE7RLc4x%2Ba5Rix8nZtyJ2QqVuBj5ScKvZvGQ%3D&subscription%5Bkeys%5D%5Bauth%5D=y6Jq8wK%2F5bnDIGR40sENrw%3D%3D | 3 | body: subscription%5Bendpoint%5D=https%3A%2F%2Fexample.com&subscription%5Bkeys%5D%5Bp256dh%5D=BKFO5w6Uf%2B%2F2wo89ovbphk5Zrb0mcAKjZrIyrX66f2IAijRtuXx4yK6J9hR%2FemKnF2DyQcyx7%2F4IGhKHBk0OTEk%3D&subscription%5Bkeys%5D%5Bauth%5D=6T8gVmd01DhQUbejRj%2Bxmg%3D%3D&policy=none&data%5Balerts%5D%5Bfollow%5D=1&data%5Balerts%5D%5Bfavourite%5D=1&data%5Balerts%5D%5Breblog%5D=1&data%5Balerts%5D%5Bmention%5D=1&data%5Balerts%5D%5Bpoll%5D=1&data%5Balerts%5D%5Bfollow_request%5D=1&data%5Balerts%5D%5Bstatus%5D=1 |
4 | headers: | 4 | headers: |
5 | Accept: | 5 | Accept: |
6 | - '*/*' | 6 | - '*/*' |
@@ -11,7 +11,7 @@ interactions: | |||
11 | Connection: | 11 | Connection: |
12 | - keep-alive | 12 | - keep-alive |
13 | Content-Length: | 13 | Content-Length: |
14 | - '246' | 14 | - '489' |
15 | Content-Type: | 15 | Content-Type: |
16 | - application/x-www-form-urlencoded | 16 | - application/x-www-form-urlencoded |
17 | User-Agent: | 17 | User-Agent: |
@@ -20,14 +20,14 @@ interactions: | |||
20 | uri: http://localhost:3000/api/v1/push/subscription | 20 | uri: http://localhost:3000/api/v1/push/subscription |
21 | response: | 21 | response: |
22 | body: | 22 | body: |
23 | string: '{"id":1,"endpoint":"https://example.com","alerts":{},"server_key":"BIX7IY8wYrdPf5wfG59B5B4CBbpQWmOBr_SI9zEsCDfMGDx8KmPuu-3WP7b-amaekv2NZj3ZSNst9OaqoxXvC1s="}' | 23 | string: '{"id":5,"endpoint":"https://example.com","alerts":{"mention":true,"status":true,"reblog":true,"follow":true,"follow_request":true,"favourite":true,"poll":true},"server_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}' |
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-IWpo+b1yj3qq43HAmklp8w==''; | 30 | style-src ''self'' http://localhost:3000 ''nonce-bz+9uelNbajqElylgkM2Gg==''; |
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/"07d4ac937919cd871dc7bf1552440cdd" | 40 | - W/"083c3b807a4d145ec452ffd03c768d76" |
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,9 @@ 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 | - 095b046e-1a89-4d2c-8d0d-9af1c13fee60 | 56 | - abb4aec7-a93a-4a99-ba4c-5a290bbbf782 |
57 | X-Runtime: | 57 | X-Runtime: |
58 | - '0.019991' | 58 | - '0.027761' |
59 | X-XSS-Protection: | 59 | X-XSS-Protection: |
60 | - 1; mode=block | 60 | - 1; mode=block |
61 | status: | 61 | status: |
@@ -78,14 +78,14 @@ interactions: | |||
78 | uri: http://localhost:3000/api/v1/push/subscription | 78 | uri: http://localhost:3000/api/v1/push/subscription |
79 | response: | 79 | response: |
80 | body: | 80 | body: |
81 | string: '{"id":1,"endpoint":"https://example.com","alerts":{},"server_key":"BIX7IY8wYrdPf5wfG59B5B4CBbpQWmOBr_SI9zEsCDfMGDx8KmPuu-3WP7b-amaekv2NZj3ZSNst9OaqoxXvC1s="}' | 81 | string: '{"id":5,"endpoint":"https://example.com","alerts":{"mention":true,"status":true,"reblog":true,"follow":true,"follow_request":true,"favourite":true,"poll":true},"server_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}' |
82 | headers: | 82 | headers: |
83 | Cache-Control: | 83 | Cache-Control: |
84 | - no-store | 84 | - no-store |
85 | Content-Security-Policy: | 85 | Content-Security-Policy: |
86 | - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src | 86 | - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src |
87 | ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000; | 87 | ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000; |
88 | style-src ''self'' http://localhost:3000 ''nonce-F8ntBeTNhe2yPZYi1hFWAQ==''; | 88 | style-src ''self'' http://localhost:3000 ''nonce-4kBQ0XWCASsxXi+/Z0W5jA==''; |
89 | media-src ''self'' https: data: http://localhost:3000; frame-src ''self'' | 89 | media-src ''self'' https: data: http://localhost:3000; frame-src ''self'' |
90 | https:; manifest-src ''self'' http://localhost:3000; connect-src ''self'' | 90 | https:; manifest-src ''self'' http://localhost:3000; connect-src ''self'' |
91 | data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000 | 91 | data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000 |
@@ -95,7 +95,7 @@ interactions: | |||
95 | Content-Type: | 95 | Content-Type: |
96 | - application/json; charset=utf-8 | 96 | - application/json; charset=utf-8 |
97 | ETag: | 97 | ETag: |
98 | - W/"07d4ac937919cd871dc7bf1552440cdd" | 98 | - W/"083c3b807a4d145ec452ffd03c768d76" |
99 | Referrer-Policy: | 99 | Referrer-Policy: |
100 | - strict-origin-when-cross-origin | 100 | - strict-origin-when-cross-origin |
101 | Transfer-Encoding: | 101 | Transfer-Encoding: |
@@ -111,9 +111,9 @@ interactions: | |||
111 | X-Permitted-Cross-Domain-Policies: | 111 | X-Permitted-Cross-Domain-Policies: |
112 | - none | 112 | - none |
113 | X-Request-Id: | 113 | X-Request-Id: |
114 | - 1fc1f34c-9edb-4647-a1b9-935865e14630 | 114 | - eeb007da-a24b-4e31-b962-30ef0ba3bc16 |
115 | X-Runtime: | 115 | X-Runtime: |
116 | - '0.007914' | 116 | - '0.008203' |
117 | X-XSS-Protection: | 117 | X-XSS-Protection: |
118 | - 1; mode=block | 118 | - 1; mode=block |
119 | status: | 119 | status: |
diff --git a/tests/test_instance.py b/tests/test_instance.py index 5f451c7..8f3f142 100644 --- a/tests/test_instance.py +++ b/tests/test_instance.py | |||
@@ -42,7 +42,7 @@ def test_health(api): | |||
42 | 42 | ||
43 | @pytest.mark.vcr() | 43 | @pytest.mark.vcr() |
44 | def test_server_time(api): | 44 | def test_server_time(api): |
45 | # present date... | 45 | # present date... |
46 | present_time = api.get_approx_server_time() | 46 | present_time = api.get_approx_server_time() |
47 | # hahahahaha | 47 | # hahahahaha |
48 | 48 | ||
diff --git a/tests/test_push.py b/tests/test_push.py index 0479191..daa99c7 100644 --- a/tests/test_push.py +++ b/tests/test_push.py | |||
@@ -26,11 +26,18 @@ def test_decrypt(api): | |||
26 | @pytest.mark.vcr(match_on=['path']) | 26 | @pytest.mark.vcr(match_on=['path']) |
27 | def test_push_set(api): | 27 | def test_push_set(api): |
28 | priv, pub = api.push_subscription_generate_keys() | 28 | priv, pub = api.push_subscription_generate_keys() |
29 | sub = api.push_subscription_set("example.com", pub) | 29 | sub = api.push_subscription_set("example.com", pub, follow_events=True, favourite_events=True, reblog_events=True, mention_events=True, poll_events=True, follow_request_events=True, status_events=True, policy='none') |
30 | |||
31 | assert sub == api.push_subscription() | 30 | assert sub == api.push_subscription() |
32 | assert sub.endpoint == "https://example.com" | 31 | assert sub.endpoint == "https://example.com" |
33 | 32 | ||
33 | should_throw = False | ||
34 | try: | ||
35 | sub = api.push_subscription_set("example.com", pub, follow_events=True, favourite_events=True, reblog_events=True, mention_events=True, poll_events=True, follow_request_events=True, status_events=True, policy='not a valid value') | ||
36 | should_throw = True | ||
37 | except: | ||
38 | pass | ||
39 | assert not should_throw | ||
40 | |||
34 | @pytest.mark.vcr(match_on=['path']) | 41 | @pytest.mark.vcr(match_on=['path']) |
35 | def test_push_update(api): | 42 | def test_push_update(api): |
36 | priv, pub = api.push_subscription_generate_keys() | 43 | priv, pub = api.push_subscription_generate_keys() |