Skip to content

Commit

Permalink
Accept webhooks for Patreon
Browse files Browse the repository at this point in the history
  • Loading branch information
Rosuav committed Nov 15, 2024
1 parent e8a9c14 commit 9586f80
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
2 changes: 1 addition & 1 deletion modules/http/chan_integrations.pike
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ __async__ mapping get_chan_state(object channel, string grp, string|void id) {
//If there's a bot handover during that time, the login will have to be restarted.
@"is_mod": mapping wscmd_patreonlogin(object channel, mapping(string:mixed) conn, mapping(string:mixed) msg) {
string tok = String.string2hex(random_string(8));
G->G->patreon_csrf_states[tok] = (["timestamp": time(), "channel": channel->login]);
G->G->patreon_csrf_states[tok] = (["timestamp": time(), "channel": channel->userid]);
object uri = Standards.URI("https://www.patreon.com/oauth2/authorize");
uri->set_query_variables(([
"response_type": "code",
Expand Down
31 changes: 28 additions & 3 deletions modules/http/patreon.pike
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ inherit http_websocket;
@retain: mapping patreon_csrf_states = ([]);

__async__ mapping(string:mixed)|string http_request(Protocols.HTTP.Server.Request req) {
if (req->request_type == "POST") {
//Might be a web hook
if (string other = !is_active_bot() && get_active_bot()) {
werror("Patreon integration - forwarding...\n");
Concurrent.Future fwd = Protocols.HTTP.Promise.post_url("https://" + other + req->not_query,
Protocols.HTTP.Promise.Arguments((["headers": (["content-type": req->request_headers["content-type"]]), "data": req->body_raw])));
//As in chan_integrations, not currently awaiting the promise. Should we?
return "Passing it along.";
}
object signer = Crypto.MD5.HMAC("DufWFHQgjKSat_KRmIUFyTiCFS0WfQCtQHGZc3SugDNCLsQQeeQJFXsQdiH1_DRB");
if (req->request_headers["x-patreon-signature"] != String.string2hex(signer(req->body_raw)))
return (["error": 418, "data": "My teapot thinks your signature is wrong."]);
mapping body = Standards.JSON.decode_utf8(req->body_raw);
return "Thanks!";
}
mapping state = m_delete(patreon_csrf_states, req->variables->state);
if (!state) return "Unable to login, please close this window and try again";
object res = await(Protocols.HTTP.Promise.post_url("https://www.patreon.com/api/oauth2/token",
Expand All @@ -20,13 +35,23 @@ __async__ mapping(string:mixed)|string http_request(Protocols.HTTP.Server.Reques
]))]))
));
mapping auth = Standards.JSON.decode_utf8(res->get());
res = await(Protocols.HTTP.Promise.get_url("https://www.patreon.com/api/oauth2/v2/identity",
object channel = G->G->irc->id[state->channel];
if (!channel) return "Something's wrong, but we got this";
await(G->G->DB->mutate_config(channel->userid, "patreon") {mapping cfg = __ARGS__[0];
cfg->auth = auth;
});
res = await(Protocols.HTTP.Promise.get_url("https://www.patreon.com/api/oauth2/v2/webhooks",
Protocols.HTTP.Promise.Arguments((["headers": ([
"Authorization": "Bearer " + auth->access_token,
])]))
));
werror("Identity: %O\n", Standards.JSON.decode_utf8(res->get()));
return "Testing";
mapping hooks = Standards.JSON.decode_utf8(res->get());
if (!sizeof(hooks->data)) {
//No hooks yet; establish one.
}
return "Awesome!";
}

//TODO: Periodically check for near-to-expiration credentials and refresh them

protected void create(string name) {::create(name);}

0 comments on commit 9586f80

Please sign in to comment.