commit 79224ca

default  ·  2023-04-11 07:50:12 +0000 UTC
parent 7c9846e
New function mastodon_status().
3 files changed,  +182, -171
M snac.h
+3, -3
 1@@ -242,7 +242,7 @@ int send_to_actor(snac *snac, char *actor, char *msg, d_char **payload, int *p_s
 2 }
 3 
 4 
 5-d_char *recipient_list(snac *snac, char *msg, int expand_public)
 6+xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public)
 7 /* returns the list of recipients for a message */
 8 {
 9     char *to = xs_dict_get(msg, "to");
10@@ -285,7 +285,7 @@ d_char *recipient_list(snac *snac, char *msg, int expand_public)
11 }
12 
13 
14-int is_msg_public(snac *snac, xs_dict *msg)
15+int is_msg_public(snac *snac, const xs_dict *msg)
16 /* checks if a message is public */
17 {
18     xs *rcpts = recipient_list(snac, msg, 0);
19@@ -294,7 +294,7 @@ int is_msg_public(snac *snac, xs_dict *msg)
20 }
21 
22 
23-int is_msg_for_me(snac *snac, xs_dict *c_msg)
24+int is_msg_for_me(snac *snac, const xs_dict *c_msg)
25 /* checks if this message is for me */
26 {
27     const char *type = xs_dict_get(c_msg, "type");
+177, -166
  1@@ -403,7 +403,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
  2 xs_str *mastoapi_id(const xs_dict *msg)
  3 /* returns a somewhat Mastodon-compatible status id */
  4 {
  5-    char tmp[256] = "";
  6+    char tmp[15] = "";
  7     int n = 0;
  8     const char *id        = xs_dict_get(msg, "id");
  9     const char *published = xs_dict_get(msg, "published");
 10@@ -424,6 +424,178 @@ xs_str *mastoapi_id(const xs_dict *msg)
 11 }
 12 
 13 
 14+xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
 15+/* converts an ActivityPub note to a Mastodon status */
 16+{
 17+    xs *actor = NULL;
 18+    actor_get(snac, xs_dict_get(msg, "attributedTo"), &actor);
 19+
 20+    /* if the author is not here, discard */
 21+    if (actor == NULL)
 22+        return NULL;
 23+
 24+    /** shave the yak converting an ActivityPub Note to a Mastodon status **/
 25+
 26+    xs *acct = xs_dict_new();
 27+
 28+    const char *display_name = xs_dict_get(actor, "name");
 29+    if (xs_is_null(display_name) || *display_name == '\0')
 30+        display_name = xs_dict_get(actor, "preferredUsername");
 31+
 32+    const char *id  = xs_dict_get(actor, "id");
 33+    const char *pub = xs_dict_get(actor, "published");
 34+    xs *acct_md5 = xs_md5_hex(id, strlen(id));
 35+    acct = xs_dict_append(acct, "id",           acct_md5);
 36+    acct = xs_dict_append(acct, "username",     xs_dict_get(actor, "preferredUsername"));
 37+    acct = xs_dict_append(acct, "acct",         xs_dict_get(actor, "preferredUsername"));
 38+    acct = xs_dict_append(acct, "display_name", display_name);
 39+
 40+    if (pub)
 41+        acct = xs_dict_append(acct, "created_at", pub);
 42+
 43+    acct = xs_dict_append(acct, "note",         xs_dict_get(actor, "summary"));
 44+    acct = xs_dict_append(acct, "url",          id);
 45+
 46+    xs *avatar  = NULL;
 47+    xs_dict *av = xs_dict_get(actor, "icon");
 48+
 49+    if (xs_type(av) == XSTYPE_DICT)
 50+        avatar = xs_dup(xs_dict_get(av, "url"));
 51+    else
 52+        avatar = xs_fmt("%s/susie.png", srv_baseurl);
 53+
 54+    acct = xs_dict_append(acct, "avatar", avatar);
 55+
 56+    xs *f   = xs_val_new(XSTYPE_FALSE);
 57+    xs *t   = xs_val_new(XSTYPE_TRUE);
 58+    xs *n   = xs_val_new(XSTYPE_NULL);
 59+    xs *el  = xs_list_new();
 60+    xs *idx = NULL;
 61+    xs *ixc = NULL;
 62+
 63+    char *tmp;
 64+    id = xs_dict_get(msg, "id");
 65+    xs *mid = mastoapi_id(msg);
 66+
 67+    xs_dict *st = xs_dict_new();
 68+
 69+    st = xs_dict_append(st, "id",           mid);
 70+    st = xs_dict_append(st, "uri",          id);
 71+    st = xs_dict_append(st, "url",          id);
 72+    st = xs_dict_append(st, "created_at",   xs_dict_get(msg, "published"));
 73+    st = xs_dict_append(st, "account",      acct);
 74+    st = xs_dict_append(st, "content",      xs_dict_get(msg, "content"));
 75+
 76+    st = xs_dict_append(st, "visibility",
 77+        is_msg_public(snac, msg) ? "public" : "private");
 78+
 79+    tmp = xs_dict_get(msg, "sensitive");
 80+    if (xs_is_null(tmp))
 81+        tmp = f;
 82+
 83+    st = xs_dict_append(st, "sensitive",    tmp);
 84+
 85+    tmp = xs_dict_get(msg, "summary");
 86+    if (xs_is_null(tmp))
 87+        tmp = "";
 88+
 89+    st = xs_dict_append(st, "spoiler_text", tmp);
 90+
 91+    /* create the list of attachments */
 92+    xs *matt = xs_list_new();
 93+    xs_list *att = xs_dict_get(msg, "attachment");
 94+    xs_str *aobj;
 95+
 96+    while (xs_list_iter(&att, &aobj)) {
 97+        const char *mtype = xs_dict_get(aobj, "mediaType");
 98+
 99+        if (!xs_is_null(mtype) && xs_startswith(mtype, "image/")) {
100+            xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
101+            xs *matte   = xs_dict_new();
102+
103+            matte = xs_dict_append(matte, "id",          matteid);
104+            matte = xs_dict_append(matte, "type",        "image");
105+            matte = xs_dict_append(matte, "url",         xs_dict_get(aobj, "url"));
106+            matte = xs_dict_append(matte, "preview_url", xs_dict_get(aobj, "url"));
107+            matte = xs_dict_append(matte, "remote_url",  xs_dict_get(aobj, "url"));
108+            matte = xs_dict_append(matte, "description", xs_dict_get(aobj, "name"));
109+
110+            matt = xs_list_append(matt, matte);
111+        }
112+    }
113+
114+    st = xs_dict_append(st, "media_attachments", matt);
115+
116+    st = xs_dict_append(st, "mentions",          el);
117+    st = xs_dict_append(st, "tags",              el);
118+    st = xs_dict_append(st, "emojis",            el);
119+
120+    xs_free(idx);
121+    xs_free(ixc);
122+    idx = object_likes(id);
123+    ixc = xs_number_new(xs_list_len(idx));
124+
125+    st = xs_dict_append(st, "favourites_count", ixc);
126+    st = xs_dict_append(st, "favourited",
127+        xs_list_in(idx, snac->md5) != -1 ? t : f);
128+
129+    xs_free(idx);
130+    xs_free(ixc);
131+    idx = object_announces(id);
132+    ixc = xs_number_new(xs_list_len(idx));
133+
134+    st = xs_dict_append(st, "reblogs_count", ixc);
135+    st = xs_dict_append(st, "reblogged",
136+        xs_list_in(idx, snac->md5) != -1 ? t : f);
137+
138+    xs_free(idx);
139+    xs_free(ixc);
140+    idx = object_children(id);
141+    ixc = xs_number_new(xs_list_len(idx));
142+
143+    st = xs_dict_append(st, "replies_count", ixc);
144+
145+    /* default in_reply_to values */
146+    st = xs_dict_append(st, "in_reply_to_id",         n);
147+    st = xs_dict_append(st, "in_reply_to_account_id", n);
148+
149+    tmp = xs_dict_get(msg, "inReplyTo");
150+    if (!xs_is_null(tmp)) {
151+        xs *irto = NULL;
152+
153+        if (valid_status(object_get(tmp, &irto))) {
154+            xs *irt_mid = mastoapi_id(irto);
155+            st = xs_dict_set(st, "in_reply_to_id", irt_mid);
156+
157+            char *at = NULL;
158+            if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) {
159+                xs *at_md5 = xs_md5_hex(at, strlen(at));
160+                st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
161+            }
162+        }
163+    }
164+
165+    st = xs_dict_append(st, "reblog",   n);
166+    st = xs_dict_append(st, "poll",     n);
167+    st = xs_dict_append(st, "card",     n);
168+    st = xs_dict_append(st, "language", n);
169+
170+    tmp = xs_dict_get(msg, "sourceContent");
171+    if (xs_is_null(tmp))
172+        tmp = "";
173+
174+    st = xs_dict_append(st, "text", tmp);
175+
176+    tmp = xs_dict_get(msg, "updated");
177+    if (xs_is_null(tmp))
178+        tmp = n;
179+
180+    st = xs_dict_append(st, "edited_at", tmp);
181+
182+    return st;
183+}
184+
185+
186 int mastoapi_get_handler(const xs_dict *req, const char *q_path,
187                          char **body, int *b_size, char **ctype)
188 {
189@@ -548,172 +720,11 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
190                 if (strcmp(xs_dict_get(msg, "type"), "Note") != 0)
191                     continue;
192 
193-                xs *actor = NULL;
194-                actor_get(&snac, xs_dict_get(msg, "attributedTo"), &actor);
195-
196-                /* if the author is not here, discard */
197-                if (actor == NULL)
198-                    continue;
199-
200-                /** shave the yak converting an ActivityPub Note to a Mastodon status **/
201-
202-                xs *acct = xs_dict_new();
203-
204-                const char *display_name = xs_dict_get(actor, "name");
205-                if (xs_is_null(display_name) || *display_name == '\0')
206-                    display_name = xs_dict_get(actor, "preferredUsername");
207-
208-                const char *id  = xs_dict_get(actor, "id");
209-                const char *pub = xs_dict_get(actor, "published");
210-                xs *acct_md5 = xs_md5_hex(id, strlen(id));
211-                acct = xs_dict_append(acct, "id",           acct_md5);
212-                acct = xs_dict_append(acct, "username",     xs_dict_get(actor, "preferredUsername"));
213-                acct = xs_dict_append(acct, "acct",         xs_dict_get(actor, "preferredUsername"));
214-                acct = xs_dict_append(acct, "display_name", display_name);
215-
216-                if (pub)
217-                    acct = xs_dict_append(acct, "created_at", pub);
218-
219-                acct = xs_dict_append(acct, "note",         xs_dict_get(actor, "summary"));
220-                acct = xs_dict_append(acct, "url",          id);
221-
222-                xs *avatar  = NULL;
223-                xs_dict *av = xs_dict_get(actor, "icon");
224-
225-                if (xs_type(av) == XSTYPE_DICT)
226-                    avatar = xs_dup(xs_dict_get(av, "url"));
227-                else
228-                    avatar = xs_fmt("%s/susie.png", srv_baseurl);
229-
230-                acct = xs_dict_append(acct, "avatar", avatar);
231-
232-                xs *f   = xs_val_new(XSTYPE_FALSE);
233-                xs *t   = xs_val_new(XSTYPE_TRUE);
234-                xs *n   = xs_val_new(XSTYPE_NULL);
235-                xs *el  = xs_list_new();
236-                xs *idx = NULL;
237-                xs *ixc = NULL;
238-
239-                char *tmp;
240-                id = xs_dict_get(msg, "id");
241-                xs *mid = mastoapi_id(msg);
242-
243-                xs *st = xs_dict_new();
244-
245-                st = xs_dict_append(st, "id",           mid);
246-                st = xs_dict_append(st, "uri",          id);
247-                st = xs_dict_append(st, "url",          id);
248-                st = xs_dict_append(st, "created_at",   xs_dict_get(msg, "published"));
249-                st = xs_dict_append(st, "account",      acct);
250-                st = xs_dict_append(st, "content",      xs_dict_get(msg, "content"));
251-
252-                st = xs_dict_append(st, "visibility",
253-                    is_msg_public(&snac, msg) ? "public" : "private");
254-
255-                tmp = xs_dict_get(msg, "sensitive");
256-                if (xs_is_null(tmp))
257-                    tmp = f;
258-
259-                st = xs_dict_append(st, "sensitive",    tmp);
260-
261-                tmp = xs_dict_get(msg, "summary");
262-                if (xs_is_null(tmp))
263-                    tmp = "";
264-
265-                st = xs_dict_append(st, "spoiler_text", tmp);
266-
267-                /* create the list of attachments */
268-                xs *matt = xs_list_new();
269-                xs_list *att = xs_dict_get(msg, "attachment");
270-                xs_str *aobj;
271-
272-                while (xs_list_iter(&att, &aobj)) {
273-                    const char *mtype = xs_dict_get(aobj, "mediaType");
274-
275-                    if (!xs_is_null(mtype) && xs_startswith(mtype, "image/")) {
276-                        xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
277-                        xs *matte   = xs_dict_new();
278-
279-                        matte = xs_dict_append(matte, "id",          matteid);
280-                        matte = xs_dict_append(matte, "type",        "image");
281-                        matte = xs_dict_append(matte, "url",         xs_dict_get(aobj, "url"));
282-                        matte = xs_dict_append(matte, "preview_url", xs_dict_get(aobj, "url"));
283-                        matte = xs_dict_append(matte, "remote_url",  xs_dict_get(aobj, "url"));
284-                        matte = xs_dict_append(matte, "description", xs_dict_get(aobj, "name"));
285-
286-                        matt = xs_list_append(matt, matte);
287-                    }
288-                }
289-
290-                st = xs_dict_append(st, "media_attachments", matt);
291-
292-                st = xs_dict_append(st, "mentions",          el);
293-                st = xs_dict_append(st, "tags",              el);
294-                st = xs_dict_append(st, "emojis",            el);
295-
296-                xs_free(idx);
297-                xs_free(ixc);
298-                idx = object_likes(id);
299-                ixc = xs_number_new(xs_list_len(idx));
300-
301-                st = xs_dict_append(st, "favourites_count", ixc);
302-                st = xs_dict_append(st, "favourited",
303-                    xs_list_in(idx, snac.md5) != -1 ? t : f);
304-
305-                xs_free(idx);
306-                xs_free(ixc);
307-                idx = object_announces(id);
308-                ixc = xs_number_new(xs_list_len(idx));
309-
310-                st = xs_dict_append(st, "reblogs_count", ixc);
311-                st = xs_dict_append(st, "reblogged",
312-                    xs_list_in(idx, snac.md5) != -1 ? t : f);
313-
314-                xs_free(idx);
315-                xs_free(ixc);
316-                idx = object_children(id);
317-                ixc = xs_number_new(xs_list_len(idx));
318-
319-                st = xs_dict_append(st, "replies_count", ixc);
320-
321-                /* default in_reply_to values */
322-                st = xs_dict_append(st, "in_reply_to_id",         n);
323-                st = xs_dict_append(st, "in_reply_to_account_id", n);
324-
325-                tmp = xs_dict_get(msg, "inReplyTo");
326-                if (!xs_is_null(tmp)) {
327-                    xs *irto = NULL;
328-
329-                    if (valid_status(object_get(tmp, &irto))) {
330-                        xs *irt_mid = mastoapi_id(irto);
331-                        st = xs_dict_set(st, "in_reply_to_id", irt_mid);
332-
333-                        char *at = NULL;
334-                        if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) {
335-                            xs *at_md5 = xs_md5_hex(at, strlen(at));
336-                            st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
337-                        }
338-                    }
339-                }
340-
341-                st = xs_dict_append(st, "reblog",   n);
342-                st = xs_dict_append(st, "poll",     n);
343-                st = xs_dict_append(st, "card",     n);
344-                st = xs_dict_append(st, "language", n);
345-
346-                tmp = xs_dict_get(msg, "sourceContent");
347-                if (xs_is_null(tmp))
348-                    tmp = "";
349-
350-                st = xs_dict_append(st, "text", tmp);
351-
352-                tmp = xs_dict_get(msg, "updated");
353-                if (xs_is_null(tmp))
354-                    tmp = n;
355-
356-                st = xs_dict_append(st, "edited_at", tmp);
357+                /* convert the Note into a Mastodon status */
358+                xs *st = mastoapi_status(&snac, msg);
359 
360-                out = xs_list_append(out, st);
361+                if (st != NULL)
362+                    out = xs_list_append(out, st);
363 
364                 cnt++;
365             }
M snac.h
+2, -2
 1@@ -196,8 +196,8 @@ int send_to_inbox(snac *snac, const xs_str *inbox, const xs_dict *msg,
 2                   xs_val **payload, int *p_size, int timeout);
 3 d_char *get_actor_inbox(snac *snac, char *actor);
 4 int send_to_actor(snac *snac, char *actor, char *msg, d_char **payload, int *p_size, int timeout);
 5-int is_msg_public(snac *snac, xs_dict *msg);
 6-int is_msg_for_me(snac *snac, xs_dict *msg);
 7+int is_msg_public(snac *snac, const xs_dict *msg);
 8+int is_msg_for_me(snac *snac, const xs_dict *msg);
 9 
10 int process_user_queue(snac *snac);
11 void process_queue_item(xs_dict *q_item);