From 1e4f5c64339194e2bda47f495a8cb65c4ae36b9b Mon Sep 17 00:00:00 2001 From: David Rosa Date: Wed, 17 Jan 2024 13:56:18 -0800 Subject: [PATCH] integrations: Create incoming webhook for Patreon. Creates an incoming webhook integration for Patreon. The main use case is getting notifications when new patrons sign up. Fixes #18321. Co-authored-by: Hari Prashant Bhimaraju Co-authored-by: Sudipto Mondal --- .../integrations/bot_avatars/patreon.png | Bin 0 -> 3083 bytes static/images/integrations/logos/patreon.png | Bin 0 -> 60896 bytes static/images/integrations/patreon/001.png | Bin 0 -> 39821 bytes zerver/lib/integrations.py | 2 + zerver/webhooks/patreon/__init__.py | 0 zerver/webhooks/patreon/doc.md | 22 ++ .../patreon/fixtures/members_create.json | 104 ++++++++++ .../patreon/fixtures/members_delete.json | 144 +++++++++++++ .../fixtures/members_pledge_create.json | 117 +++++++++++ .../members_pledge_create_paid_post.json | 144 +++++++++++++ .../fixtures/members_pledge_delete.json | 117 +++++++++++ .../fixtures/members_pledge_update.json | 139 +++++++++++++ .../patreon/fixtures/members_update.json | 170 ++++++++++++++++ zerver/webhooks/patreon/tests.py | 105 ++++++++++ zerver/webhooks/patreon/view.py | 190 ++++++++++++++++++ 15 files changed, 1254 insertions(+) create mode 100644 static/images/integrations/bot_avatars/patreon.png create mode 100644 static/images/integrations/logos/patreon.png create mode 100644 static/images/integrations/patreon/001.png create mode 100644 zerver/webhooks/patreon/__init__.py create mode 100644 zerver/webhooks/patreon/doc.md create mode 100644 zerver/webhooks/patreon/fixtures/members_create.json create mode 100644 zerver/webhooks/patreon/fixtures/members_delete.json create mode 100644 zerver/webhooks/patreon/fixtures/members_pledge_create.json create mode 100644 zerver/webhooks/patreon/fixtures/members_pledge_create_paid_post.json create mode 100644 zerver/webhooks/patreon/fixtures/members_pledge_delete.json create mode 100644 zerver/webhooks/patreon/fixtures/members_pledge_update.json create mode 100644 zerver/webhooks/patreon/fixtures/members_update.json create mode 100644 zerver/webhooks/patreon/tests.py create mode 100644 zerver/webhooks/patreon/view.py diff --git a/static/images/integrations/bot_avatars/patreon.png b/static/images/integrations/bot_avatars/patreon.png new file mode 100644 index 0000000000000000000000000000000000000000..7d60e973a846f7c9ea0165000460a0dff7d52b60 GIT binary patch literal 3083 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 F{~xgahMNEY literal 0 HcmV?d00001 diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index 9b425d0a8f..8c6e8e71d8 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -441,6 +441,7 @@ WEBHOOK_INTEGRATIONS: List[WebhookIntegration] = [ WebhookIntegration("opsgenie", ["meta-integration", "monitoring"]), WebhookIntegration("pagerduty", ["monitoring"], display_name="PagerDuty"), WebhookIntegration("papertrail", ["monitoring"]), + WebhookIntegration("patreon", ["financial"], display_name="Patreon"), WebhookIntegration("pingdom", ["monitoring"]), WebhookIntegration("pivotal", ["project-management"], display_name="Pivotal Tracker"), WebhookIntegration("radarr", ["entertainment"], display_name="Radarr"), @@ -777,6 +778,7 @@ DOC_SCREENSHOT_CONFIG: Dict[str, List[BaseScreenshotConfig]] = { "opsgenie": [ScreenshotConfig("addrecipient.json", image_name="000.png")], "pagerduty": [ScreenshotConfig("trigger_v2.json")], "papertrail": [ScreenshotConfig("short_post.json", payload_as_query_param=True)], + "patreon": [ScreenshotConfig("members_pledge_create.json")], "pingdom": [ScreenshotConfig("http_up_to_down.json", image_name="002.png")], "pivotal": [ScreenshotConfig("v5_type_changed.json")], "radarr": [ScreenshotConfig("radarr_movie_grabbed.json")], diff --git a/zerver/webhooks/patreon/__init__.py b/zerver/webhooks/patreon/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/zerver/webhooks/patreon/doc.md b/zerver/webhooks/patreon/doc.md new file mode 100644 index 0000000000..8df9b4d951 --- /dev/null +++ b/zerver/webhooks/patreon/doc.md @@ -0,0 +1,22 @@ +Get Patreon notifications in Zulip! + + 1. {!create-stream.md!} + +1. {!create-an-incoming-webhook.md!} + +1. {!generate-integration-url.md!} + + You can refer to Patreons's documentation for + [triggers](https://docs.patreon.com/#triggers-v2) and + [webhook events](https://docs.patreon.com/#webhooks). + +1. Login to your Patreon developer account, navigate to your Patreon Portal, and + click on [My Webhooks](https://www.patreon.com/portal/registration/register-webhooks). + +1. Paste the URL constructed above in the webhook URL field, and click the + **plus** (**+**) button. Enable the events you would like to receive + notifications for, and click **Send Test**. + + {!congrats.md!} + + ![](/static/images/integrations/patreon/001.png) diff --git a/zerver/webhooks/patreon/fixtures/members_create.json b/zerver/webhooks/patreon/fixtures/members_create.json new file mode 100644 index 0000000000..06d0c21a4a --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_create.json @@ -0,0 +1,104 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 0, + "email": "kopi@pangea.com", + "full_name": "Kopi", + "is_follower": false, + "is_free_trial": false, + "last_charge_date": null, + "last_charge_status": null, + "lifetime_support_cents": 0, + "next_charge_date": null, + "note": "", + "patron_status": null, + "pledge_cadence": null, + "pledge_relationship_start": "2023-12-29T02:59:46.036+00:00", + "will_pay_amount_cents": 0 + }, + "id": "38c264ba-0612-4bb9-bc33-f9755cc68bb0", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11539233", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11539233" + } + }, + "currently_entitled_tiers": { + "data": [] + }, + "user": { + "data": { + "id": "111836593", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111836593" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2023-12-29T01:11:16.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "is_charged_immediately": true, + "is_monthly": true, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 0, + "pay_per_name": "month", + "pledge_url": "/checkout/11539233", + "published_at": "2023-12-29T01:29:54.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "11539233", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T02:38:24.000+00:00", + "first_name": "Kopi", + "full_name": "Kopi", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "is_creator": false, + "last_name": "", + "like_count": 0, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "url": "https://www.patreon.com/user?u=111836593", + "vanity": null + }, + "id": "111836593", + "type": "user" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/38c264ba-0612-4bb9-bc33-f9755cc68bb0" + } +} diff --git a/zerver/webhooks/patreon/fixtures/members_delete.json b/zerver/webhooks/patreon/fixtures/members_delete.json new file mode 100644 index 0000000000..9b530e9b53 --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_delete.json @@ -0,0 +1,144 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 0, + "email": "kopi@pangea.com", + "full_name": "Kopi", + "is_follower": false, + "is_free_trial": false, + "last_charge_date": null, + "last_charge_status": null, + "lifetime_support_cents": 0, + "next_charge_date": null, + "note": "", + "patron_status": null, + "pledge_cadence": null, + "pledge_relationship_start": "2023-12-29T02:38:24.943+00:00", + "will_pay_amount_cents": 0 + }, + "id": "38c264ba-0612-4bb9-bc33-f9755cc68bb0", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11539233", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11539233" + } + }, + "currently_entitled_tiers": { + "data": [ + { + "id": "21926168", + "type": "tier" + } + ] + }, + "user": { + "data": { + "id": "111836593", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111836593" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2023-12-29T01:11:16.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "is_charged_immediately": true, + "is_monthly": true, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 0, + "pay_per_name": "month", + "pledge_url": "/checkout/11539233", + "published_at": "2023-12-29T01:29:54.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "11539233", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T02:38:24.000+00:00", + "first_name": "Kopi", + "full_name": "Kopi", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "is_creator": false, + "last_name": "", + "like_count": 0, + "social_connections": { + "discord": null, + "facebook": null, + "google": null, + "instagram": null, + "reddit": null, + "spotify": null, + "spotify_open_access": null, + "twitch": null, + "twitter": null, + "vimeo": null, + "youtube": null + }, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "url": "https://www.patreon.com/user?u=111836593", + "vanity": null + }, + "id": "111836593", + "type": "user" + }, + { + "attributes": { + "amount_cents": 0, + "created_at": "2023-12-29T01:11:16.871+00:00", + "description": "", + "discord_role_ids": null, + "edited_at": "2023-12-29T01:11:16.871+00:00", + "image_url": null, + "patron_count": 0, + "post_count": 0, + "published": true, + "published_at": "2023-12-29T01:11:16.871+00:00", + "remaining": null, + "requires_shipping": false, + "title": "Free", + "unpublished_at": null, + "url": "/checkout/11539233?rid=21926168", + "user_limit": null + }, + "id": "21926168", + "type": "tier" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/38c264ba-0612-4bb9-bc33-f9755cc68bb0" + } +} diff --git a/zerver/webhooks/patreon/fixtures/members_pledge_create.json b/zerver/webhooks/patreon/fixtures/members_pledge_create.json new file mode 100644 index 0000000000..f283276642 --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_pledge_create.json @@ -0,0 +1,117 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 500, + "email": "kopi@pangea.com", + "full_name": "Kopi", + "is_follower": false, + "is_free_trial": false, + "last_charge_date": "2023-12-29T05:26:19.000+00:00", + "last_charge_status": "Paid", + "lifetime_support_cents": 0, + "next_charge_date": "2024-01-29T00:00:00.000+00:00", + "note": "", + "patron_status": "active_patron", + "pledge_cadence": 1, + "pledge_relationship_start": "2023-12-29T05:26:17.634+00:00", + "will_pay_amount_cents": 500 + }, + "id": "38c264ba-0612-4bb9-bc33-f9755cc68bb0", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11539233", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11539233" + } + }, + "currently_entitled_tiers": { + "data": [] + }, + "user": { + "data": { + "id": "111836593", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111836593" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2023-12-29T01:11:16.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "is_charged_immediately": true, + "is_monthly": true, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 5, + "pay_per_name": "month", + "pledge_url": "/checkout/11539233", + "published_at": "2023-12-29T01:29:54.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "11539233", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T02:38:24.000+00:00", + "first_name": "Kopi", + "full_name": "Kopi", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "is_creator": false, + "last_name": "", + "like_count": 0, + "social_connections": { + "discord": null, + "facebook": null, + "google": null, + "instagram": null, + "reddit": null, + "spotify": null, + "spotify_open_access": null, + "twitch": null, + "twitter": null, + "vimeo": null, + "youtube": null + }, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "url": "https://www.patreon.com/user?u=111836593", + "vanity": null + }, + "id": "111836593", + "type": "user" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/38c264ba-0612-4bb9-bc33-f9755cc68bb0" + } +} diff --git a/zerver/webhooks/patreon/fixtures/members_pledge_create_paid_post.json b/zerver/webhooks/patreon/fixtures/members_pledge_create_paid_post.json new file mode 100644 index 0000000000..1a7b87e8cd --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_pledge_create_paid_post.json @@ -0,0 +1,144 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 500, + "email": "drrosa@duck.com", + "full_name": "David", + "is_follower": false, + "is_free_trial": false, + "last_charge_date": null, + "last_charge_status": null, + "lifetime_support_cents": 0, + "next_charge_date": "2024-02-01T08:00:00.000+00:00", + "note": "", + "patron_status": "active_patron", + "pledge_cadence": 1, + "pledge_relationship_start": "2024-01-10T22:37:02.731+00:00", + "will_pay_amount_cents": 500 + }, + "id": "359a4862-bc4e-496f-8559-82a0a596ed72", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11579710", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11579710" + } + }, + "currently_entitled_tiers": { + "data": [ + { + "id": "21992054", + "type": "tier" + } + ] + }, + "user": { + "data": { + "id": "111828554", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111828554" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2024-01-06T02:15:31.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11579710/4d4cde3afc3e4caf900f1237f7be1347/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1707004800&token-hash=HVyUX_Jm6Qp4Zy_1uSzi2M8BOV9xkPMNwUHvDu9Mwis%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11579710/4d4cde3afc3e4caf900f1237f7be1347/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1707004800&token-hash=HVyUX_Jm6Qp4Zy_1uSzi2M8BOV9xkPMNwUHvDu9Mwis%3D", + "is_charged_immediately": false, + "is_monthly": false, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 0, + "pay_per_name": "pull request", + "pledge_url": "/checkout/Test2979", + "published_at": "2024-01-10T22:06:53.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/Test2979", + "vanity": "Test2979" + }, + "id": "11579710", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T01:09:55.000+00:00", + "first_name": "David", + "full_name": "David", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111828554/1543482da60f49dda649625e7bdf4e15/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=8SZgxLW0nhdUhKDxEaur_X-rYnZI5Gcu-9m2lC1F18Y%3D", + "is_creator": true, + "last_name": "", + "like_count": 0, + "social_connections": { + "discord": null, + "facebook": null, + "google": null, + "instagram": null, + "reddit": null, + "spotify": null, + "spotify_open_access": null, + "twitch": null, + "twitter": null, + "vimeo": null, + "youtube": null + }, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111828554/1543482da60f49dda649625e7bdf4e15/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=8SZgxLW0nhdUhKDxEaur_X-rYnZI5Gcu-9m2lC1F18Y%3D", + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "111828554", + "type": "user" + }, + { + "attributes": { + "amount_cents": 500, + "created_at": "2024-01-06T02:16:24.443+00:00", + "description": "Access to exclusive content and more", + "discord_role_ids": null, + "edited_at": "2024-01-06T02:16:24.443+00:00", + "image_url": null, + "patron_count": 1, + "post_count": 0, + "published": true, + "published_at": "2024-01-06T02:16:24.443+00:00", + "remaining": null, + "requires_shipping": false, + "title": "", + "unpublished_at": null, + "url": "/checkout/Test2979?rid=21992054", + "user_limit": null + }, + "id": "21992054", + "type": "tier" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/359a4862-bc4e-496f-8559-82a0a596ed72" + } + } diff --git a/zerver/webhooks/patreon/fixtures/members_pledge_delete.json b/zerver/webhooks/patreon/fixtures/members_pledge_delete.json new file mode 100644 index 0000000000..25740aeaa2 --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_pledge_delete.json @@ -0,0 +1,117 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 0, + "email": "kopi@pangea.com", + "full_name": "Kopi", + "is_follower": false, + "is_free_trial": false, + "last_charge_date": "2023-12-29T05:26:19.000+00:00", + "last_charge_status": "Deleted", + "lifetime_support_cents": 0, + "next_charge_date": "2024-01-29T00:00:00.000+00:00", + "note": "", + "patron_status": "former_patron", + "pledge_cadence": 1, + "pledge_relationship_start": "2023-12-29T05:26:17.634+00:00", + "will_pay_amount_cents": 0 + }, + "id": "38c264ba-0612-4bb9-bc33-f9755cc68bb0", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11539233", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11539233" + } + }, + "currently_entitled_tiers": { + "data": [] + }, + "user": { + "data": { + "id": "111836593", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111836593" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2023-12-29T01:11:16.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "is_charged_immediately": true, + "is_monthly": true, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 4, + "pay_per_name": "month", + "pledge_url": "/checkout/11539233", + "published_at": "2023-12-29T01:29:54.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "11539233", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T02:38:24.000+00:00", + "first_name": "Kopi", + "full_name": "Kopi", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "is_creator": false, + "last_name": "", + "like_count": 0, + "social_connections": { + "discord": null, + "facebook": null, + "google": null, + "instagram": null, + "reddit": null, + "spotify": null, + "spotify_open_access": null, + "twitch": null, + "twitter": null, + "vimeo": null, + "youtube": null + }, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "url": "https://www.patreon.com/user?u=111836593", + "vanity": null + }, + "id": "111836593", + "type": "user" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/38c264ba-0612-4bb9-bc33-f9755cc68bb0" + } +} diff --git a/zerver/webhooks/patreon/fixtures/members_pledge_update.json b/zerver/webhooks/patreon/fixtures/members_pledge_update.json new file mode 100644 index 0000000000..8492f3c584 --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_pledge_update.json @@ -0,0 +1,139 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 1000, + "email": "kopi@pangea.com", + "full_name": "Kopi", + "is_follower": false, + "is_free_trial": false, + "last_charge_date": "2023-12-29T05:26:19.000+00:00", + "last_charge_status": "Paid", + "lifetime_support_cents": 0, + "next_charge_date": "2024-01-29T00:00:00.000+00:00", + "note": "", + "patron_status": "active_patron", + "pledge_cadence": 1, + "pledge_relationship_start": "2023-12-29T05:26:17.634+00:00", + "will_pay_amount_cents": 1000 + }, + "id": "38c264ba-0612-4bb9-bc33-f9755cc68bb0", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11539233", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11539233" + } + }, + "currently_entitled_tiers": { + "data": [] + }, + "user": { + "data": { + "id": "111836593", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111836593" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2023-12-29T01:11:16.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "is_charged_immediately": true, + "is_monthly": true, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 5, + "pay_per_name": "month", + "pledge_url": "/checkout/11539233", + "published_at": "2023-12-29T01:29:54.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "11539233", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T02:38:24.000+00:00", + "first_name": "Kopi", + "full_name": "Kopi", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "is_creator": false, + "last_name": "", + "like_count": 0, + "social_connections": { + "discord": null, + "facebook": null, + "google": null, + "instagram": null, + "reddit": null, + "spotify": null, + "spotify_open_access": null, + "twitch": null, + "twitter": null, + "vimeo": null, + "youtube": null + }, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "url": "https://www.patreon.com/user?u=111836593", + "vanity": null + }, + "id": "111836593", + "type": "user" + }, + { + "attributes": { + "amount_cents": 0, + "created_at": "2023-12-29T01:11:16.871+00:00", + "description": "", + "discord_role_ids": null, + "edited_at": "2023-12-29T01:11:16.871+00:00", + "image_url": null, + "patron_count": 5, + "post_count": 0, + "published": true, + "published_at": "2023-12-29T01:11:16.871+00:00", + "remaining": null, + "requires_shipping": false, + "title": "Free", + "unpublished_at": null, + "url": "/checkout/11539233?rid=21926168", + "user_limit": null + }, + "id": "21926168", + "type": "tier" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/38c264ba-0612-4bb9-bc33-f9755cc68bb0" + } +} diff --git a/zerver/webhooks/patreon/fixtures/members_update.json b/zerver/webhooks/patreon/fixtures/members_update.json new file mode 100644 index 0000000000..12fa2902cf --- /dev/null +++ b/zerver/webhooks/patreon/fixtures/members_update.json @@ -0,0 +1,170 @@ +{ + "data": { + "attributes": { + "campaign_lifetime_support_cents": 0, + "currently_entitled_amount_cents": 100, + "email": "kopi@pangea.com", + "full_name": "Kopi", + "is_follower": false, + "is_free_trial": true, + "last_charge_date": null, + "last_charge_status": null, + "lifetime_support_cents": 0, + "next_charge_date": null, + "note": "", + "patron_status": "active_patron", + "pledge_cadence": null, + "pledge_relationship_start": "2023-12-29T03:40:28.000+00:00", + "will_pay_amount_cents": 0 + }, + "id": "38c264ba-0612-4bb9-bc33-f9755cc68bb0", + "relationships": { + "address": { + "data": null + }, + "campaign": { + "data": { + "id": "11539233", + "type": "campaign" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/campaigns/11539233" + } + }, + "currently_entitled_tiers": { + "data": [ + { + "id": "21926235", + "type": "tier" + }, + { + "id": "21926168", + "type": "tier" + } + ] + }, + "user": { + "data": { + "id": "111836593", + "type": "user" + }, + "links": { + "related": "https://www.patreon.com/api/oauth2/v2/user/111836593" + } + } + }, + "type": "member" + }, + "included": [ + { + "attributes": { + "created_at": "2023-12-29T01:11:16.000+00:00", + "creation_name": "", + "discord_server_id": null, + "google_analytics_id": null, + "has_rss": false, + "has_sent_rss_notify": false, + "image_small_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/campaign/11539233/e1a083b0bf3a44d399523f2f08e59d9c/eyJ3IjoxOTIwLCJ3ZSI6MX0%3D/1.png?token-time=1704326400&token-hash=Qb6nRUM96w1o5QgxEpHevoF7TZ5LjFVPAxpQBOLKHas%3D", + "is_charged_immediately": true, + "is_monthly": true, + "is_nsfw": false, + "main_video_embed": null, + "main_video_url": null, + "one_liner": null, + "patron_count": 0, + "pay_per_name": "month", + "pledge_url": "/checkout/11539233", + "published_at": "2023-12-29T01:29:54.000+00:00", + "rss_artwork_url": null, + "rss_feed_title": null, + "summary": null, + "thanks_embed": null, + "thanks_msg": null, + "thanks_video_url": null, + "url": "https://www.patreon.com/user?u=111828554", + "vanity": null + }, + "id": "11539233", + "type": "campaign" + }, + { + "attributes": { + "about": null, + "created": "2023-12-29T02:38:24.000+00:00", + "first_name": "Kopi", + "full_name": "Kopi", + "hide_pledges": true, + "image_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "is_creator": false, + "last_name": "", + "like_count": 0, + "social_connections": { + "discord": null, + "facebook": null, + "google": null, + "instagram": null, + "reddit": null, + "spotify": null, + "spotify_open_access": null, + "twitch": null, + "twitter": null, + "vimeo": null, + "youtube": null + }, + "thumb_url": "https://c10.patreonusercontent.com/4/patreon-media/p/user/111836593/7e238b05a88548e2ac1afed4e0f95b74/eyJ3IjoyMDB9/1.png?token-time=2145916800&token-hash=NI0mVHbv2rxc8cQ1qGsRCOFHPbHe4Le_0L1OLKZJsYo%3D", + "url": "https://www.patreon.com/user?u=111836593", + "vanity": null + }, + "id": "111836593", + "type": "user" + }, + { + "attributes": { + "amount_cents": 100, + "created_at": "2023-12-29T01:22:12.268+00:00", + "description": "Access to exclusive content and more", + "discord_role_ids": null, + "edited_at": "2023-12-29T01:23:06.534+00:00", + "image_url": null, + "patron_count": 1, + "post_count": 0, + "published": true, + "published_at": "2023-12-29T01:22:12.268+00:00", + "remaining": null, + "requires_shipping": false, + "title": "Paid", + "unpublished_at": null, + "url": "/checkout/11539233?rid=21926235", + "user_limit": null + }, + "id": "21926235", + "type": "tier" + }, + { + "attributes": { + "amount_cents": 0, + "created_at": "2023-12-29T01:11:16.871+00:00", + "description": "", + "discord_role_ids": null, + "edited_at": "2023-12-29T01:11:16.871+00:00", + "image_url": null, + "patron_count": 0, + "post_count": 0, + "published": true, + "published_at": "2023-12-29T01:11:16.871+00:00", + "remaining": null, + "requires_shipping": false, + "title": "Free", + "unpublished_at": null, + "url": "/checkout/11539233?rid=21926168", + "user_limit": null + }, + "id": "21926168", + "type": "tier" + } + ], + "links": { + "self": "https://www.patreon.com/api/oauth2/v2/members/38c264ba-0612-4bb9-bc33-f9755cc68bb0" + } +} diff --git a/zerver/webhooks/patreon/tests.py b/zerver/webhooks/patreon/tests.py new file mode 100644 index 0000000000..9110f0969c --- /dev/null +++ b/zerver/webhooks/patreon/tests.py @@ -0,0 +1,105 @@ +from unittest.mock import patch + +import orjson + +from zerver.lib.test_classes import WebhookTestCase + +EXPECTED_TOPIC = "membership notifications" +IGNORED_EVENTS = [ + "pledges:create", + "pledges:update", + "pledges:delete", +] + + +class PatreonHookTests(WebhookTestCase): + STREAM_NAME = "Patreon" + URL_TEMPLATE = "/api/v1/external/patreon?&api_key={api_key}&stream={stream}" + WEBHOOK_DIR_NAME = "patreon" + + def test_patreon_members_create(self) -> None: + expected_message = "Kopi has joined as a member!" + self.check_webhook( + "members_create", + EXPECTED_TOPIC, + expected_message, + ) + + def test_patreon_members_update(self) -> None: + expected_message = "Kopi's membership has been updated to active patron." + self.check_webhook( + "members_update", + EXPECTED_TOPIC, + expected_message, + ) + + def test_patreon_members_delete(self) -> None: + expected_message = "Kopi's membership has ended." + self.check_webhook( + "members_delete", + EXPECTED_TOPIC, + expected_message, + ) + + def test_patreon_members_pledge_create(self) -> None: + expected_message = "Kopi has pledged $5.00 per month. :tada:\nTotal number of patrons: 5" + self.check_webhook( + "members_pledge_create", + EXPECTED_TOPIC, + expected_message, + ) + + def test_patreon_members_pledge_update(self) -> None: + expected_message = "Kopi has updated their pledge to $10.00 per month. :gear:" + self.check_webhook( + "members_pledge_update", + EXPECTED_TOPIC, + expected_message, + ) + + def test_patreon_members_pledge_delete(self) -> None: + expected_message = ( + "Kopi's pledge has been cancelled. :cross_mark:\nTotal number of patrons: 4" + ) + self.check_webhook( + "members_pledge_delete", + EXPECTED_TOPIC, + expected_message, + ) + + def test_ignored_events(self) -> None: + # The payload for these events never gets looked at in the + # webhook itself; it only needs to be valid JSON. + payload = "{}" + + for event in IGNORED_EVENTS: + self.verify_post_is_ignored(payload, event) + + def test_ignored_payloads(self) -> None: + payload = orjson.loads(self.get_body("members_create")) + payload["data"]["attributes"]["last_charge_status"] = "Declined" + payload["data"]["attributes"]["patron_status"] = "declined_patron" + + event_types = [ + "members:create", + "members:update", + "members:delete", + "members:pledge:create", + "members:pledge:update", + "members:pledge:delete", + ] + + for event in event_types: + self.verify_post_is_ignored(orjson.dumps(payload).decode(), event) + + def verify_post_is_ignored(self, payload: str, http_x_patreon_event: str) -> None: + with patch("zerver.webhooks.patreon.view.check_send_webhook_message") as m: + result = self.client_post( + self.url, + payload, + HTTP_X_PATREON_EVENT=http_x_patreon_event, + content_type="application/json", + ) + if http_x_patreon_event in IGNORED_EVENTS: + self.assertFalse(m.called) + self.assert_json_success(result) diff --git a/zerver/webhooks/patreon/view.py b/zerver/webhooks/patreon/view.py new file mode 100644 index 0000000000..c28308e0ef --- /dev/null +++ b/zerver/webhooks/patreon/view.py @@ -0,0 +1,190 @@ +from typing import Callable, Dict, Optional + +from django.http import HttpRequest, HttpResponse + +from zerver.decorator import webhook_view +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError +from zerver.lib.response import json_success +from zerver.lib.typed_endpoint import JsonBodyPayload, typed_endpoint +from zerver.lib.validator import WildValue, check_int, check_none_or, check_string +from zerver.lib.webhooks.common import ( + check_send_webhook_message, + validate_extract_webhook_http_header, +) +from zerver.models import UserProfile + + +# The events for this integration contain the ":" character, which is not appropriate in a +# filename and requires us to deviate from the common `get_http_headers_from_filename` method +# from zerver.lib.webhooks.common. +def get_custom_http_headers_from_filename(http_header_key: str) -> Callable[[str], Dict[str, str]]: + def fixture_to_headers(filename: str) -> Dict[str, str]: + event_type = filename.replace("_", ":") + return {http_header_key: event_type} + + return fixture_to_headers + + +fixture_to_headers = get_custom_http_headers_from_filename("HTTP_X_PATREON_EVENT") + + +def get_members_create_body(payload: WildValue) -> Optional[str]: + last_charge_status = get_last_charge_status(payload) + patron_status = get_patron_status(payload) + # null values indicate the member has never pledged + if last_charge_status is None and patron_status is None: + template = "{user_name} has joined as a member!" + return template.format( + user_name=get_user_name(payload), + ).rstrip() + return None + + +def get_members_update_body(payload: WildValue) -> Optional[str]: + last_charge_status = get_last_charge_status(payload) + patron_status = get_patron_status(payload) + if last_charge_status in ("Paid", None) and patron_status in ("active_patron", "former_patron"): + template = "{user_name}'s membership has been updated to {patron_status}." + return template.format( + user_name=get_user_name(payload), + patron_status=str(patron_status).replace("_", " "), + ).rstrip() + return None + + +def get_members_delete_body(payload: WildValue) -> Optional[str]: + last_charge_status = get_last_charge_status(payload) + patron_status = get_patron_status(payload) + # null value indicates the member has never pledged + if last_charge_status in ("Paid", None) and patron_status != "declined_patron": + template = "{user_name}'s membership has ended." + return template.format( + user_name=get_user_name(payload), + ).rstrip() + return None + + +def get_members_pledge_create_body(payload: WildValue) -> Optional[str]: + last_charge_status = get_last_charge_status(payload) + pledge_amount = get_pledge_amount(payload) + # The only successful charge status is "Paid". null if not yet charged. + if last_charge_status in ("Paid", None) and pledge_amount > 0: + template = "{user_name} has pledged ${pledge_amount:.2f} per {pay_per_name}. :tada:\nTotal number of patrons: {patron_count}" + return template.format( + user_name=get_user_name(payload), + pledge_amount=pledge_amount, + pay_per_name=get_pay_per_name(payload), + patron_count=get_patron_count(payload), + ).rstrip() + return None + + +def get_members_pledge_update_body(payload: WildValue) -> Optional[str]: + last_charge_status = get_last_charge_status(payload) + pledge_amount = get_pledge_amount(payload) + # The only successful charge status is "Paid". null if not yet charged. + if last_charge_status in ("Paid", None) and pledge_amount > 0: + template = "{user_name} has updated their pledge to ${pledge_amount:.2f} per {pay_per_name}. :gear:" + return template.format( + user_name=get_user_name(payload), + pledge_amount=pledge_amount, + pay_per_name=get_pay_per_name(payload), + ).rstrip() + return None + + +def get_members_pledge_delete_body(payload: WildValue) -> Optional[str]: + last_charge_status = get_last_charge_status(payload) + if last_charge_status in ("Paid", "Deleted", None): + template = "{user_name}'s pledge has been cancelled. :cross_mark:\nTotal number of patrons: {patron_count}" + return template.format( + user_name=get_user_name(payload), + patron_count=get_patron_count(payload), + ).rstrip() + return None + + +def get_last_charge_status(payload: WildValue) -> Optional[str]: + return payload["data"]["attributes"]["last_charge_status"].tame(check_none_or(check_string)) + + +def get_patron_status(payload: WildValue) -> Optional[str]: + return payload["data"]["attributes"]["patron_status"].tame(check_none_or(check_string)) + + +def get_user_name(payload: WildValue) -> str: + return payload["data"]["attributes"]["full_name"].tame(check_string) + + +def get_pledge_amount(payload: WildValue) -> float: + return payload["data"]["attributes"]["currently_entitled_amount_cents"].tame(check_int) / 100 + + +def get_patron_count(payload: WildValue) -> int: + return payload["included"][0]["attributes"]["patron_count"].tame(check_int) + + +def get_pay_per_name(payload: WildValue) -> str: + return payload["included"][0]["attributes"]["pay_per_name"].tame(check_string) + + +EVENT_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Optional[str]]] = { + "members:create": get_members_create_body, + "members:update": get_members_update_body, + "members:delete": get_members_delete_body, + "members:pledge:create": get_members_pledge_create_body, + "members:pledge:update": get_members_pledge_update_body, + "members:pledge:delete": get_members_pledge_delete_body, +} + +# deprecated events +IGNORED_EVENTS = [ + "pledges:create", + "pledges:update", + "pledges:delete", +] + +ALL_EVENT_TYPES = list(EVENT_FUNCTION_MAPPER.keys()) + + +@webhook_view("Patreon", all_event_types=ALL_EVENT_TYPES) +@typed_endpoint +def api_patreon_webhook( + request: HttpRequest, + user_profile: UserProfile, + *, + payload: JsonBodyPayload[WildValue], +) -> HttpResponse: + header_event = validate_extract_webhook_http_header(request, "X-Patreon-Event", "Patreon") + + event_name = get_zulip_event_name(header_event, payload) + if event_name is None: + # See IGNORED_EVENTS. + return json_success(request) + topic = "membership notifications" + + body_function = EVENT_FUNCTION_MAPPER[event_name] + body = body_function(payload) + + if body is None: + # None for payloads that are valid, + # but where we intentionally do not send a message. + return json_success(request) + + check_send_webhook_message(request, user_profile, topic, body, event_name) + return json_success(request) + + +def get_zulip_event_name( + header_event: str, + payload: WildValue, +) -> Optional[str]: + """ + Usually, we return an event name that is a key in EVENT_FUNCTION_MAPPER. + We return None for an event that we know we don't want to handle. + """ + if header_event in EVENT_FUNCTION_MAPPER: + return header_event + elif header_event in IGNORED_EVENTS: + return None + raise UnsupportedWebhookEventTypeError(header_event)