commit b993e26
default
·
2025-01-16 13:20:07 +0000 UTC
parent ba4c350
Implemented Mastodon-like /authorize_interaction.
M
html.c
+61,
-0
1@@ -3124,6 +3124,21 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2 else
3 return HTTP_STATUS_NOT_FOUND;
4 }
5+ else
6+ if (strcmp(v, "auth-int-bridge") == 0) {
7+ const char *login = xs_dict_get(q_vars, "login");
8+ const char *id = xs_dict_get(q_vars, "id");
9+ const char *action = xs_dict_get(q_vars, "action");
10+
11+ if (xs_is_string(login) && xs_is_string(id) && xs_is_string(action)) {
12+ *body = xs_fmt("%s/%s/authorize_interaction?action=%s&id=%s",
13+ srv_baseurl, login, action, id);
14+
15+ return HTTP_STATUS_SEE_OTHER;
16+ }
17+ else
18+ return HTTP_STATUS_NOT_FOUND;
19+ }
20
21 uid = xs_dup(v);
22
23@@ -3695,6 +3710,52 @@ int html_get_handler(const xs_dict *req, const char *q_path,
24 status = HTTP_STATUS_SEE_OTHER;
25 }
26 }
27+ else
28+ if (strcmp(p_path, "authorize_interaction") == 0) { /** follow, like or boost from Mastodon **/
29+ if (!login(&snac, req)) {
30+ *body = xs_dup(uid);
31+ status = HTTP_STATUS_UNAUTHORIZED;
32+ }
33+ else {
34+ status = HTTP_STATUS_NOT_FOUND;
35+
36+ const char *id = xs_dict_get(q_vars, "id");
37+ const char *action = xs_dict_get(q_vars, "action");
38+
39+ if (xs_is_string(id) && xs_is_string(action)) {
40+ if (strcmp(action, "Follow") == 0) {
41+ xs *msg = msg_follow(&snac, id);
42+
43+ if (msg != NULL) {
44+ const char *actor = xs_dict_get(msg, "object");
45+
46+ following_add(&snac, actor, msg);
47+
48+ enqueue_output_by_actor(&snac, msg, actor, 0);
49+
50+ status = HTTP_STATUS_SEE_OTHER;
51+ }
52+ }
53+ else
54+ if (xs_match(action, "Like|Boost|Announce")) {
55+ /* bring the post */
56+ xs *msg = msg_admiration(&snac, id, *action == 'L' ? "Like" : "Announce");
57+
58+ if (msg != NULL) {
59+ enqueue_message(&snac, msg);
60+ timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, *action == 'L' ? 1 : 0);
61+
62+ status = HTTP_STATUS_SEE_OTHER;
63+ }
64+ }
65+ }
66+
67+ if (status == HTTP_STATUS_SEE_OTHER) {
68+ *body = xs_fmt("%s/admin", snac.actor);
69+ *b_size = strlen(*body);
70+ }
71+ }
72+ }
73 else
74 status = HTTP_STATUS_NOT_FOUND;
75
M
httpd.c
+42,
-0
1@@ -182,6 +182,29 @@ const char *share_page = ""
2 "";
3
4
5+const char *authorize_interaction_page = ""
6+"<!DOCTYPE html>\n"
7+"<html>\n"
8+"<head>\n"
9+"<title>%s - snac</title>\n"
10+"<meta content=\"width=device-width, initial-scale=1, minimum-scale=1, user-scalable=no\" name=\"viewport\">\n"
11+"<link rel=\"stylesheet\" type=\"text/css\" href=\"%s/style.css\"/>\n"
12+"<style>:root {color-scheme: light dark}</style>\n"
13+"</head>\n"
14+"<body><h1>%s authorize interaction</h1>\n"
15+"<form method=\"get\" action=\"%s/auth-int-bridge\">\n"
16+"<select name=\"action\">\n"
17+"<option value=\"Follow\">Follow</option>\n"
18+"<option value=\"Like\">Like</option>\n"
19+"<option value=\"Boost\">Boost</option>\n"
20+"</select> %s\n"
21+"<input type=\"hidden\" name=\"id\" value=\"%s\">\n"
22+"<p>Login: <input type=\"text\" name=\"login\" autocapitalize=\"off\" required=\"required\"></p>\n"
23+"<input type=\"submit\" value=\"OK\">\n"
24+"</form><p>%s</p></body></html>\n"
25+"";
26+
27+
28 int server_get_handler(xs_dict *req, const char *q_path,
29 char **body, int *b_size, char **ctype)
30 /* basic server services */
31@@ -318,6 +341,25 @@ int server_get_handler(xs_dict *req, const char *q_path,
32 USER_AGENT
33 );
34 }
35+ else
36+ if (strcmp(q_path, "/authorize_interaction") == 0) {
37+ const xs_dict *q_vars = xs_dict_get(req, "q_vars");
38+ const char *uri = xs_dict_get(q_vars, "uri");
39+
40+ if (xs_is_string(uri)) {
41+ status = HTTP_STATUS_OK;
42+ *ctype = "text/html; charset=utf-8";
43+ *body = xs_fmt(authorize_interaction_page,
44+ xs_dict_get(srv_config, "host"),
45+ srv_baseurl,
46+ xs_dict_get(srv_config, "host"),
47+ srv_baseurl,
48+ uri,
49+ uri,
50+ USER_AGENT
51+ );
52+ }
53+ }
54
55 if (status != 0)
56 srv_debug(1, xs_fmt("server_get_handler serving '%s' %d", q_path, status));