commit c0a48f1
default
·
2023-04-11 19:07:47 +0000 UTC
parent 036be9d
Added support for likes and boosts.
2 files changed,
+138,
-30
M
httpd.c
M
httpd.c
+3,
-3
1@@ -188,15 +188,15 @@ void httpd_connection(FILE *f)
2 else
3 if (strcmp(method, "POST") == 0) {
4 if (status == 0)
5- status = activitypub_post_handler(req, q_path,
6+ status = oauth_post_handler(req, q_path,
7 payload, p_size, &body, &b_size, &ctype);
8
9 if (status == 0)
10- status = oauth_post_handler(req, q_path,
11+ status = mastoapi_post_handler(req, q_path,
12 payload, p_size, &body, &b_size, &ctype);
13
14 if (status == 0)
15- status = mastoapi_post_handler(req, q_path,
16+ status = activitypub_post_handler(req, q_path,
17 payload, p_size, &body, &b_size, &ctype);
18
19 if (status == 0)
+135,
-27
1@@ -596,25 +596,11 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
2 }
3
4
5-int mastoapi_get_handler(const xs_dict *req, const char *q_path,
6- char **body, int *b_size, char **ctype)
7+int process_auth_token(snac *snac, const xs_dict *req)
8+/* processes an authorization token, if there is one */
9 {
10- if (!xs_startswith(q_path, "/api/v1/"))
11- return 0;
12-
13- srv_debug(0, xs_fmt("mastoapi_get_handler %s", q_path));
14-/* {
15- xs *j = xs_json_dumps_pp(req, 4);
16- printf("mastoapi get:\n%s\n", j);
17- }*/
18-
19- int status = 404;
20- xs_dict *args = xs_dict_get(req, "q_vars");
21- xs *cmd = xs_replace(q_path, "/api/v1", "");
22- char *v;
23-
24- snac snac = {0};
25 int logged_in = 0;
26+ char *v;
27
28 /* if there is an authorization field, try to validate it */
29 if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) {
30@@ -624,7 +610,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
31 if (token != NULL) {
32 const char *uid = xs_dict_get(token, "uid");
33
34- if (!xs_is_null(uid) && user_open(&snac, uid)) {
35+ if (!xs_is_null(uid) && user_open(snac, uid)) {
36 logged_in = 1;
37 srv_debug(0, xs_fmt("mastoapi auth: valid token for user %s", uid));
38 }
39@@ -635,6 +621,29 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
40 srv_log(xs_fmt("mastoapi auth: invalid token %s", tokid));
41 }
42
43+ return logged_in;
44+}
45+
46+
47+int mastoapi_get_handler(const xs_dict *req, const char *q_path,
48+ char **body, int *b_size, char **ctype)
49+{
50+ if (!xs_startswith(q_path, "/api/v1/"))
51+ return 0;
52+
53+ srv_debug(0, xs_fmt("mastoapi_get_handler %s", q_path));
54+/* {
55+ xs *j = xs_json_dumps_pp(req, 4);
56+ printf("mastoapi get:\n%s\n", j);
57+ }*/
58+
59+ int status = 404;
60+ xs_dict *args = xs_dict_get(req, "q_vars");
61+ xs *cmd = xs_replace(q_path, "/api/v1", "");
62+
63+ snac snac = {0};
64+ int logged_in = process_auth_token(&snac, req);;
65+
66 if (strcmp(cmd, "/accounts/verify_credentials") == 0) {
67 if (logged_in) {
68 xs *acct = xs_dict_new();
69@@ -946,28 +955,31 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
70 }
71
72 int status = 404;
73- xs *msg = NULL;
74+ xs *args = NULL;
75 char *i_ctype = xs_dict_get(req, "content-type");
76
77- if (xs_startswith(i_ctype, "application/json"))
78- msg = xs_json_loads(payload);
79+ if (i_ctype && xs_startswith(i_ctype, "application/json"))
80+ args = xs_json_loads(payload);
81 else
82- msg = xs_dup(xs_dict_get(req, "p_vars"));
83+ args = xs_dup(xs_dict_get(req, "p_vars"));
84
85- if (msg == NULL)
86+ if (args == NULL)
87 return 400;
88
89 {
90- xs *j = xs_json_dumps_pp(msg, 4);
91+ xs *j = xs_json_dumps_pp(args, 4);
92 printf("%s\n", j);
93 }
94
95 xs *cmd = xs_replace(q_path, "/api/v1", "");
96
97+ snac snac = {0};
98+ int logged_in = process_auth_token(&snac, req);;
99+
100 if (strcmp(cmd, "/apps") == 0) {
101- const char *name = xs_dict_get(msg, "client_name");
102- const char *ruri = xs_dict_get(msg, "redirect_uris");
103- const char *scope = xs_dict_get(msg, "scope");
104+ const char *name = xs_dict_get(args, "client_name");
105+ const char *ruri = xs_dict_get(args, "redirect_uris");
106+ const char *scope = xs_dict_get(args, "scope");
107
108 if (xs_type(ruri) == XSTYPE_LIST)
109 ruri = xs_dict_get(ruri, 0);
110@@ -1000,6 +1012,102 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
111 srv_debug(0, xs_fmt("mastoapi apps: new app %s", cid));
112 }
113 }
114+ else
115+ if (strcmp(cmd, "/statuses") == 0) {
116+ if (logged_in) {
117+ /* post a new Note */
118+ /* TBD */
119+ }
120+ else
121+ status = 401;
122+ }
123+ else
124+ if (xs_startswith(cmd, "/statuses")) {
125+ if (logged_in) {
126+ /* operations on a status */
127+ xs *l = xs_split(cmd, "/");
128+ const char *mid = xs_list_get(l, 2);
129+ const char *op = xs_list_get(l, 3);
130+
131+ if (!xs_is_null(mid)) {
132+ xs *msg = NULL;
133+ xs *out = NULL;
134+
135+ /* skip the fake part of the id (the date) */
136+ mid += 14;
137+
138+ if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) {
139+ char *id = xs_dict_get(msg, "id");
140+
141+ if (op == NULL) {
142+ /* no operation (?) */
143+ }
144+ else
145+ if (strcmp(op, "favourite") == 0) {
146+ xs *n_msg = msg_admiration(&snac, id, "Like");
147+
148+ if (n_msg != NULL) {
149+ enqueue_message(&snac, n_msg);
150+ timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 1);
151+
152+ out = mastoapi_status(&snac, msg);
153+ }
154+ }
155+ else
156+ if (strcmp(op, "unfavourite") == 0) {
157+ /* snac does not support Undo+Like */
158+ }
159+ else
160+ if (strcmp(op, "reblog") == 0) {
161+ xs *n_msg = msg_admiration(&snac, id, "Announce");
162+
163+ if (n_msg != NULL) {
164+ enqueue_message(&snac, n_msg);
165+ timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 0);
166+
167+ out = mastoapi_status(&snac, msg);
168+ }
169+ }
170+ else
171+ if (strcmp(op, "unreblog") == 0) {
172+ /* snac does not support Undo+Announce */
173+ }
174+ else
175+ if (strcmp(op, "bookmark") == 0) {
176+ /* snac does not support bookmarks */
177+ }
178+ else
179+ if (strcmp(op, "unbookmark") == 0) {
180+ /* snac does not support bookmarks */
181+ }
182+ else
183+ if (strcmp(op, "pin") == 0) {
184+ /* snac does not support pinning */
185+ }
186+ else
187+ if (strcmp(op, "unpin") == 0) {
188+ /* snac does not support pinning */
189+ }
190+ else
191+ if (strcmp(op, "mute") == 0) {
192+ /* Mastodon's mute is snac's hide */
193+ }
194+ else
195+ if (strcmp(op, "unmute") == 0) {
196+ /* Mastodon's unmute is snac's unhide */
197+ }
198+ }
199+
200+ if (out != NULL) {
201+ *body = xs_json_dumps_pp(out, 4);
202+ *ctype = "application/json";
203+ status = 200;
204+ }
205+ }
206+ }
207+ else
208+ status = 401;
209+ }
210
211 return status;
212 }