diff options
Diffstat (limited to 'mastoapi.c')
| -rw-r--r-- | mastoapi.c | 342 |
1 files changed, 270 insertions, 72 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* snac - A simple, minimalistic ActivityPub instance */ | 1 | /* snac - A simple, minimalistic ActivityPub instance */ |
| 2 | /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ | 2 | /* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ |
| 3 | 3 | ||
| 4 | #ifndef NO_MASTODON_API | 4 | #ifndef NO_MASTODON_API |
| 5 | 5 | ||
| @@ -1158,6 +1158,103 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 1158 | st = xs_dict_append(st, "tags", htl); | 1158 | st = xs_dict_append(st, "tags", htl); |
| 1159 | st = xs_dict_append(st, "emojis", eml); | 1159 | st = xs_dict_append(st, "emojis", eml); |
| 1160 | } | 1160 | } |
| 1161 | { | ||
| 1162 | xs *rl = object_get_emoji_reacts(id); | ||
| 1163 | xs *frl = xs_list_new(); /* final */ | ||
| 1164 | xs *sfrl = xs_dict_new(); /* seen */ | ||
| 1165 | int c = 0; | ||
| 1166 | const char *v; | ||
| 1167 | |||
| 1168 | while (xs_list_next(rl, &v, &c)) { | ||
| 1169 | xs *msg = NULL; | ||
| 1170 | if (valid_status(object_get_by_md5(v, &msg))) { | ||
| 1171 | const char *content = xs_dict_get(msg, "content"); | ||
| 1172 | const char *actor = xs_dict_get(msg, "actor"); | ||
| 1173 | const xs_list *contentl = xs_dict_get(sfrl, content); | ||
| 1174 | |||
| 1175 | if ((snac && is_muted(snac, actor)) || is_instance_blocked(actor)) | ||
| 1176 | continue; | ||
| 1177 | |||
| 1178 | /* NOTE: idk when there are no actor, but i encountered that bug. | ||
| 1179 | * Probably because of one of my previous attempts. | ||
| 1180 | * Keeping this just in case, can remove later */ | ||
| 1181 | const char *me = actor && snac && strcmp(actor, snac->actor) == 0 ? | ||
| 1182 | xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE); | ||
| 1183 | int count = 1; | ||
| 1184 | |||
| 1185 | if (contentl) { | ||
| 1186 | count = atoi(xs_list_get(contentl, 0)) + 1; | ||
| 1187 | if (strncmp(xs_list_get(contentl, 1), xs_stock(XSTYPE_TRUE), 1) == 0) | ||
| 1188 | me = xs_stock(XSTYPE_TRUE); | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | xs *fl = xs_list_new(); | ||
| 1192 | xs *c1 = xs_fmt("%d", count); | ||
| 1193 | fl = xs_list_append(fl, c1, me); | ||
| 1194 | sfrl = xs_dict_append(sfrl, content, fl); | ||
| 1195 | } | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | c = 0; | ||
| 1199 | |||
| 1200 | while (xs_list_next(rl, &v, &c)) { | ||
| 1201 | xs *msg = NULL; | ||
| 1202 | if (valid_status(object_get_by_md5(v, &msg))) { | ||
| 1203 | xs *d1 = xs_dict_new(); | ||
| 1204 | |||
| 1205 | const xs_dict *icon = xs_dict_get(xs_list_get(xs_dict_get(msg, "tag"), 0), "icon"); | ||
| 1206 | const char *o_url = xs_dict_get(icon, "url"); | ||
| 1207 | const char *name = xs_dict_get(msg, "content"); | ||
| 1208 | const char *actor = xs_dict_get(msg, "actor"); | ||
| 1209 | |||
| 1210 | xs *nm = xs_dup(name); | ||
| 1211 | xs *url = NULL; | ||
| 1212 | |||
| 1213 | if (!xs_is_null(o_url)) { | ||
| 1214 | if (actor && snac && !strcmp(actor, snac->actor)) | ||
| 1215 | url = make_url(o_url, NULL, 1); | ||
| 1216 | else | ||
| 1217 | url = xs_dup(o_url); | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | xs *accounts = xs_list_new(); | ||
| 1221 | if (actor) { | ||
| 1222 | xs *d2 = xs_dict_new(); | ||
| 1223 | object_get(actor, &d2); | ||
| 1224 | xs *e_acct = mastoapi_account(snac, d2); | ||
| 1225 | accounts = xs_list_append(accounts, e_acct); | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | const xs_list *item = xs_dict_get(sfrl, nm); | ||
| 1229 | const xs_str *nb = xs_list_get(item, 0); | ||
| 1230 | const xs_val *me = xs_list_get(item, 1); | ||
| 1231 | if (item == NULL) | ||
| 1232 | continue; | ||
| 1233 | |||
| 1234 | if (nm && strcmp(nm, "")) { | ||
| 1235 | if (url && strcmp(url, "")) { | ||
| 1236 | d1 = xs_dict_append(d1, "name", nm); | ||
| 1237 | d1 = xs_dict_append(d1, "shortcode", nm); | ||
| 1238 | d1 = xs_dict_append(d1, "accounts", accounts); | ||
| 1239 | d1 = xs_dict_append(d1, "me", me); | ||
| 1240 | d1 = xs_dict_append(d1, "url", url); | ||
| 1241 | d1 = xs_dict_append(d1, "static_url", url); | ||
| 1242 | d1 = xs_dict_append(d1, "visible_in_picker", xs_stock(XSTYPE_TRUE)); | ||
| 1243 | d1 = xs_dict_append(d1, "count", nb); | ||
| 1244 | } else { | ||
| 1245 | d1 = xs_dict_append(d1, "name", nm); | ||
| 1246 | d1 = xs_dict_append(d1, "count", nb); | ||
| 1247 | d1 = xs_dict_append(d1, "me", me); | ||
| 1248 | d1 = xs_dict_append(d1, "visible_in_picker", xs_stock(XSTYPE_TRUE)); | ||
| 1249 | } | ||
| 1250 | sfrl = xs_dict_del(sfrl, nm); | ||
| 1251 | frl = xs_list_append(frl, d1); | ||
| 1252 | } | ||
| 1253 | } | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | st = xs_dict_append(st, "reactions", frl); | ||
| 1257 | } | ||
| 1161 | 1258 | ||
| 1162 | xs_free(idx); | 1259 | xs_free(idx); |
| 1163 | xs_free(ixc); | 1260 | xs_free(ixc); |
| @@ -1712,6 +1809,37 @@ xs_list *mastoapi_account_lists(snac *user, const char *uid) | |||
| 1712 | } | 1809 | } |
| 1713 | 1810 | ||
| 1714 | 1811 | ||
| 1812 | xs_list *build_childrens(const xs_dict *msg, snac *snac1) { | ||
| 1813 | xs_list *ret = xs_list_new(); | ||
| 1814 | xs *children = object_children(xs_dict_get(msg, "id")); | ||
| 1815 | char *p = children; | ||
| 1816 | const xs_str *v; | ||
| 1817 | |||
| 1818 | while (xs_list_iter(&p, &v)) { | ||
| 1819 | xs *m2 = NULL; | ||
| 1820 | |||
| 1821 | if (valid_status(timeline_get_by_md5(snac1, v, &m2))) { | ||
| 1822 | if (xs_is_null(xs_dict_get(m2, "name"))) { | ||
| 1823 | xs *st = mastoapi_status(snac1, m2); | ||
| 1824 | |||
| 1825 | if (st) { | ||
| 1826 | /* childrens children */ | ||
| 1827 | xs *childs = build_childrens(m2, snac1); | ||
| 1828 | ret = xs_list_append(ret, st); | ||
| 1829 | if (xs_list_len(childs)) { | ||
| 1830 | char *p2 = childs; | ||
| 1831 | while (xs_list_iter(&p2, &v)) | ||
| 1832 | ret = xs_list_append(ret, v); | ||
| 1833 | |||
| 1834 | } | ||
| 1835 | } | ||
| 1836 | } | ||
| 1837 | } | ||
| 1838 | } | ||
| 1839 | return ret; | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | |||
| 1715 | int mastoapi_get_handler(const xs_dict *req, const char *q_path, | 1843 | int mastoapi_get_handler(const xs_dict *req, const char *q_path, |
| 1716 | char **body, int *b_size, char **ctype, xs_str **link) | 1844 | char **body, int *b_size, char **ctype, xs_str **link) |
| 1717 | { | 1845 | { |
| @@ -1892,60 +2020,64 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1892 | } | 2020 | } |
| 1893 | else | 2021 | else |
| 1894 | if (strcmp(opt, "statuses") == 0) { /** **/ | 2022 | if (strcmp(opt, "statuses") == 0) { /** **/ |
| 1895 | /* the public list of posts of a user */ | 2023 | if (logged_in || xs_type(xs_dict_get(snac2.config, "private")) == XSTYPE_FALSE) { |
| 1896 | const char *limit_s = xs_dict_get(args, "limit"); | 2024 | /* the public list of posts of a user */ |
| 1897 | const char *o_max_id = xs_dict_get(args, "max_id"); | 2025 | const char *limit_s = xs_dict_get(args, "limit"); |
| 1898 | int limit = limit_s ? atoi(limit_s) : 20; | 2026 | const char *o_max_id = xs_dict_get(args, "max_id"); |
| 1899 | xs *max_id = o_max_id ? xs_tolower_i(xs_dup(o_max_id)) : NULL; | 2027 | int limit = limit_s ? atoi(limit_s) : 20; |
| 2028 | xs *max_id = o_max_id ? xs_tolower_i(xs_dup(o_max_id)) : NULL; | ||
| 1900 | 2029 | ||
| 1901 | srv_debug(1, xs_fmt("account statuses: max_id=%s limit=%d", max_id ? max_id : "(null)", limit)); | 2030 | srv_debug(1, xs_fmt("account statuses: max_id=%s limit=%d", max_id ? max_id : "(null)", limit)); |
| 1902 | 2031 | ||
| 1903 | xs *timeline = timeline_simple_list(&snac2, "public", 0, 256, NULL); | 2032 | xs *timeline = timeline_simple_list(&snac2, "public", 0, 256, NULL); |
| 1904 | xs_list *p = timeline; | 2033 | xs_list *p = timeline; |
| 1905 | const xs_str *v; | 2034 | const xs_str *v; |
| 1906 | xs_set seen; | 2035 | xs_set seen; |
| 1907 | int cnt = 0; | 2036 | int cnt = 0; |
| 1908 | int skip_until_max = max_id != NULL; | 2037 | int skip_until_max = max_id != NULL; |
| 1909 | 2038 | ||
| 1910 | out = xs_list_new(); | 2039 | out = xs_list_new(); |
| 1911 | xs_set_init(&seen); | 2040 | xs_set_init(&seen); |
| 1912 | 2041 | ||
| 1913 | while (xs_list_iter(&p, &v) && cnt < limit) { | 2042 | while (xs_list_iter(&p, &v) && cnt < limit) { |
| 1914 | xs *msg = NULL; | 2043 | xs *msg = NULL; |
| 1915 | 2044 | ||
| 1916 | if (valid_status(timeline_get_by_md5(&snac2, v, &msg))) { | 2045 | if (valid_status(timeline_get_by_md5(&snac2, v, &msg))) { |
| 1917 | const char *msg_id = xs_dict_get(msg, "id"); | 2046 | const char *msg_id = xs_dict_get(msg, "id"); |
| 1918 | 2047 | ||
| 1919 | /* add only posts by the author */ | 2048 | /* add only posts by the author */ |
| 1920 | if (!xs_is_null(msg_id) && | 2049 | if (!xs_is_null(msg_id) && |
| 1921 | strcmp(xs_dict_get(msg, "type"), "Note") == 0 && | 2050 | strcmp(xs_dict_get(msg, "type"), "Note") == 0 && |
| 1922 | xs_startswith(xs_dict_get(msg, "id"), snac2.actor) && is_msg_public(msg)) { | 2051 | is_msg_mine(&snac2, xs_dict_get(msg, "id")) && is_msg_public(msg)) { |
| 1923 | 2052 | ||
| 1924 | /* if max_id is set, skip entries until we find it */ | 2053 | /* if max_id is set, skip entries until we find it */ |
| 1925 | if (skip_until_max) { | 2054 | if (skip_until_max) { |
| 1926 | xs *mid = mastoapi_id(msg); | 2055 | xs *mid = mastoapi_id(msg); |
| 1927 | if (strcmp(mid, max_id) == 0) { | 2056 | if (strcmp(mid, max_id) == 0) { |
| 1928 | skip_until_max = 0; | 2057 | skip_until_max = 0; |
| 1929 | srv_debug(2, xs_fmt("account statuses: found max_id, starting from next post")); | 2058 | srv_debug(2, xs_fmt("account statuses: found max_id, starting from next post")); |
| 2059 | } | ||
| 2060 | continue; | ||
| 1930 | } | 2061 | } |
| 1931 | continue; | ||
| 1932 | } | ||
| 1933 | 2062 | ||
| 1934 | /* deduplicate by message id */ | 2063 | /* deduplicate by message id */ |
| 1935 | if (xs_set_add(&seen, msg_id) == 1) { | 2064 | if (xs_set_add(&seen, msg_id) == 1) { |
| 1936 | xs *st = mastoapi_status(&snac2, msg); | 2065 | xs *st = mastoapi_status(&snac2, msg); |
| 1937 | 2066 | ||
| 1938 | if (st) { | 2067 | if (st) { |
| 1939 | out = xs_list_append(out, st); | 2068 | out = xs_list_append(out, st); |
| 1940 | cnt++; | 2069 | cnt++; |
| 2070 | } | ||
| 1941 | } | 2071 | } |
| 1942 | } | 2072 | } |
| 1943 | } | 2073 | } |
| 1944 | } | 2074 | } |
| 1945 | } | ||
| 1946 | 2075 | ||
| 1947 | srv_debug(1, xs_fmt("account statuses: returning %d posts (requested %d)", cnt, limit)); | 2076 | srv_debug(1, xs_fmt("account statuses: returning %d posts (requested %d)", cnt, limit)); |
| 1948 | xs_set_free(&seen); | 2077 | xs_set_free(&seen); |
| 2078 | } | ||
| 2079 | else | ||
| 2080 | status = HTTP_STATUS_UNAUTHORIZED; | ||
| 1949 | } | 2081 | } |
| 1950 | else | 2082 | else |
| 1951 | if (strcmp(opt, "featured_tags") == 0) { | 2083 | if (strcmp(opt, "featured_tags") == 0) { |
| @@ -2202,15 +2334,24 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2202 | if (noti == NULL) | 2334 | if (noti == NULL) |
| 2203 | continue; | 2335 | continue; |
| 2204 | 2336 | ||
| 2337 | const xs_dict *tag = xs_list_get(xs_dict_get_path(noti, "msg.tag"), 0); | ||
| 2338 | |||
| 2205 | const char *type = xs_dict_get(noti, "type"); | 2339 | const char *type = xs_dict_get(noti, "type"); |
| 2206 | const char *utype = xs_dict_get(noti, "utype"); | 2340 | const char *utype = xs_dict_get(noti, "utype"); |
| 2207 | const char *objid = xs_dict_get(noti, "objid"); | 2341 | const char *objid = xs_dict_get(noti, "objid"); |
| 2208 | const char *id = xs_dict_get(noti, "id"); | 2342 | const char *id = xs_dict_get(noti, "id"); |
| 2209 | const char *actid = xs_dict_get(noti, "actor"); | 2343 | const char *actid = xs_dict_get(noti, "actor"); |
| 2344 | |||
| 2345 | int isEmoji = 0; | ||
| 2346 | |||
| 2210 | xs *fid = xs_replace(id, ".", ""); | 2347 | xs *fid = xs_replace(id, ".", ""); |
| 2211 | xs *actor = NULL; | 2348 | xs *actor = NULL; |
| 2212 | xs *entry = NULL; | 2349 | xs *entry = NULL; |
| 2213 | 2350 | ||
| 2351 | if (tag) { | ||
| 2352 | isEmoji = strcmp(xs_dict_get(tag, "type"), "Emoji") ? 0 : 1; | ||
| 2353 | } | ||
| 2354 | |||
| 2214 | if (!valid_status(actor_get(actid, &actor))) | 2355 | if (!valid_status(actor_get(actid, &actor))) |
| 2215 | continue; | 2356 | continue; |
| 2216 | 2357 | ||
| @@ -2234,9 +2375,12 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2234 | } | 2375 | } |
| 2235 | 2376 | ||
| 2236 | /* convert the type */ | 2377 | /* convert the type */ |
| 2237 | if (strcmp(type, "Like") == 0 || strcmp(type, "EmojiReact") == 0) | 2378 | if (strcmp(type, "Like") == 0 && !isEmoji) |
| 2238 | type = "favourite"; | 2379 | type = "favourite"; |
| 2239 | else | 2380 | else |
| 2381 | if (isEmoji || strcmp(type, "EmojiReact") == 0) | ||
| 2382 | type = "reaction"; | ||
| 2383 | else | ||
| 2240 | if (strcmp(type, "Announce") == 0) | 2384 | if (strcmp(type, "Announce") == 0) |
| 2241 | type = "reblog"; | 2385 | type = "reblog"; |
| 2242 | else | 2386 | else |
| @@ -2277,8 +2421,31 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2277 | if (strcmp(type, "follow") != 0 && !xs_is_null(objid)) { | 2421 | if (strcmp(type, "follow") != 0 && !xs_is_null(objid)) { |
| 2278 | xs *st = mastoapi_status(&snac1, entry); | 2422 | xs *st = mastoapi_status(&snac1, entry); |
| 2279 | 2423 | ||
| 2280 | if (st) | 2424 | if (st) { |
| 2281 | mn = xs_dict_append(mn, "status", st); | 2425 | mn = xs_dict_append(mn, "status", st); |
| 2426 | |||
| 2427 | if (strcmp(type, "reaction") == 0 && !xs_is_null(objid)) { | ||
| 2428 | const char *eid = NULL; | ||
| 2429 | const char *url = NULL; | ||
| 2430 | int utf = 0; | ||
| 2431 | |||
| 2432 | const xs_dict *tag = xs_list_get(xs_dict_get_path(noti, "msg.tag"), 0); | ||
| 2433 | const char *content = xs_dict_get_path(noti, "msg.content"); | ||
| 2434 | |||
| 2435 | url = xs_dict_get(xs_dict_get(tag, "icon"), "url"); | ||
| 2436 | eid = xs_dict_get(tag, "name"); | ||
| 2437 | |||
| 2438 | if (eid && url) { | ||
| 2439 | mn = xs_dict_append(mn, "emoji", eid); | ||
| 2440 | mn = xs_dict_append(mn, "emoji_url", url); | ||
| 2441 | } | ||
| 2442 | |||
| 2443 | if (xs_is_emoji((utf = xs_utf8_dec(&content)))) { | ||
| 2444 | xs *s1 = xs_fmt("&#%d;", utf); | ||
| 2445 | mn = xs_dict_append(mn, "name", s1); | ||
| 2446 | } | ||
| 2447 | } | ||
| 2448 | } | ||
| 2282 | } | 2449 | } |
| 2283 | 2450 | ||
| 2284 | out = xs_list_append(out, mn); | 2451 | out = xs_list_append(out, mn); |
| @@ -2480,19 +2647,33 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2480 | if (strcmp(cmd, "/v1/custom_emojis") == 0) { /** **/ | 2647 | if (strcmp(cmd, "/v1/custom_emojis") == 0) { /** **/ |
| 2481 | xs *emo = emojis(); | 2648 | xs *emo = emojis(); |
| 2482 | xs *list = xs_list_new(); | 2649 | xs *list = xs_list_new(); |
| 2483 | int c = 0; | ||
| 2484 | const xs_str *k; | 2650 | const xs_str *k; |
| 2485 | const xs_val *v; | 2651 | const xs_val *v; |
| 2486 | while(xs_dict_next(emo, &k, &v, &c)) { | 2652 | xs_dict_foreach(emo, k, v) { |
| 2487 | xs *current = xs_dict_new(); | 2653 | xs *current = xs_dict_new(); |
| 2488 | if (xs_startswith(v, "https://") && xs_startswith((xs_mime_by_ext(v)), "image/")) { | 2654 | if ((xs_startswith(v, "https://") && xs_startswith((xs_mime_by_ext(v)), "image/")) || xs_type(v) == XSTYPE_DICT) { |
| 2489 | /* remove first and last colon */ | 2655 | /* remove first and last colon */ |
| 2490 | xs *shortcode = xs_replace(k, ":", ""); | 2656 | if (xs_type(v) == XSTYPE_DICT) { |
| 2491 | current = xs_dict_append(current, "shortcode", shortcode); | 2657 | const char *v2; |
| 2492 | current = xs_dict_append(current, "url", v); | 2658 | const char *cat = k; |
| 2493 | current = xs_dict_append(current, "static_url", v); | 2659 | xs_dict_foreach(v, k, v2) { |
| 2494 | current = xs_dict_append(current, "visible_in_picker", xs_stock(XSTYPE_TRUE)); | 2660 | xs *shortcode = xs_replace(k, ":", ""); |
| 2495 | list = xs_list_append(list, current); | 2661 | current = xs_dict_append(current, "shortcode", shortcode); |
| 2662 | current = xs_dict_append(current, "url", v2); | ||
| 2663 | current = xs_dict_append(current, "static_url", v2); | ||
| 2664 | current = xs_dict_append(current, "visible_in_picker", xs_stock(XSTYPE_TRUE)); | ||
| 2665 | current = xs_dict_append(current, "category", cat); | ||
| 2666 | list = xs_list_append(list, current); | ||
| 2667 | } | ||
| 2668 | } | ||
| 2669 | else { | ||
| 2670 | xs *shortcode = xs_replace(k, ":", ""); | ||
| 2671 | current = xs_dict_append(current, "shortcode", shortcode); | ||
| 2672 | current = xs_dict_append(current, "url", v); | ||
| 2673 | current = xs_dict_append(current, "static_url", v); | ||
| 2674 | current = xs_dict_append(current, "visible_in_picker", xs_stock(XSTYPE_TRUE)); | ||
| 2675 | list = xs_list_append(list, current); | ||
| 2676 | } | ||
| 2496 | } | 2677 | } |
| 2497 | } | 2678 | } |
| 2498 | *body = xs_json_dumps(list, 0); | 2679 | *body = xs_json_dumps(list, 0); |
| @@ -2594,6 +2775,11 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2594 | "\"max_expiration\":2629746," | 2775 | "\"max_expiration\":2629746," |
| 2595 | "\"max_options\":8,\"min_expiration\":300}"); | 2776 | "\"max_options\":8,\"min_expiration\":300}"); |
| 2596 | cfg = xs_dict_append(cfg, "polls", d14); | 2777 | cfg = xs_dict_append(cfg, "polls", d14); |
| 2778 | |||
| 2779 | |||
| 2780 | xs *d15 = xs_json_loads("{\"max_reactions\":50}"); | ||
| 2781 | cfg = xs_dict_append(cfg, "reactions", d15); | ||
| 2782 | |||
| 2597 | } | 2783 | } |
| 2598 | 2784 | ||
| 2599 | ins = xs_dict_append(ins, "configuration", cfg); | 2785 | ins = xs_dict_append(ins, "configuration", cfg); |
| @@ -2680,8 +2866,6 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2680 | /* return ancestors and children */ | 2866 | /* return ancestors and children */ |
| 2681 | xs *anc = xs_list_new(); | 2867 | xs *anc = xs_list_new(); |
| 2682 | xs *des = xs_list_new(); | 2868 | xs *des = xs_list_new(); |
| 2683 | xs_list *p; | ||
| 2684 | const xs_str *v; | ||
| 2685 | char pid[MD5_HEX_SIZE]; | 2869 | char pid[MD5_HEX_SIZE]; |
| 2686 | 2870 | ||
| 2687 | /* build the [grand]parent list, moving up */ | 2871 | /* build the [grand]parent list, moving up */ |
| @@ -2701,21 +2885,9 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2701 | } | 2885 | } |
| 2702 | 2886 | ||
| 2703 | /* build the children list */ | 2887 | /* build the children list */ |
| 2704 | xs *children = object_children(xs_dict_get(msg, "id")); | 2888 | xs *childs = build_childrens(msg, &snac1); |
| 2705 | p = children; | 2889 | if (xs_list_len(childs) > 0) |
| 2706 | 2890 | des = xs_list_cat(des, childs); | |
| 2707 | while (xs_list_iter(&p, &v)) { | ||
| 2708 | xs *m2 = NULL; | ||
| 2709 | |||
| 2710 | if (valid_status(timeline_get_by_md5(&snac1, v, &m2))) { | ||
| 2711 | if (xs_is_null(xs_dict_get(m2, "name"))) { | ||
| 2712 | xs *st = mastoapi_status(&snac1, m2); | ||
| 2713 | |||
| 2714 | if (st) | ||
| 2715 | des = xs_list_append(des, st); | ||
| 2716 | } | ||
| 2717 | } | ||
| 2718 | } | ||
| 2719 | 2891 | ||
| 2720 | out = xs_dict_new(); | 2892 | out = xs_dict_new(); |
| 2721 | out = xs_dict_append(out, "ancestors", anc); | 2893 | out = xs_dict_append(out, "ancestors", anc); |
| @@ -3044,7 +3216,10 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 3044 | xs *app = xs_dict_new(); | 3216 | xs *app = xs_dict_new(); |
| 3045 | xs *id = xs_replace_i(tid(0), ".", ""); | 3217 | xs *id = xs_replace_i(tid(0), ".", ""); |
| 3046 | xs *csec = random_str(); | 3218 | xs *csec = random_str(); |
| 3047 | xs *vkey = random_str(); | 3219 | xs *vkey = xs_dup(xs_dict_get(srv_config, "vkey")); |
| 3220 | if (vkey == NULL) | ||
| 3221 | vkey = random_str(); | ||
| 3222 | |||
| 3048 | xs *cid = NULL; | 3223 | xs *cid = NULL; |
| 3049 | 3224 | ||
| 3050 | /* pick a non-existent random cid */ | 3225 | /* pick a non-existent random cid */ |
| @@ -3216,7 +3391,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 3216 | 3391 | ||
| 3217 | if (n_msg != NULL) { | 3392 | if (n_msg != NULL) { |
| 3218 | enqueue_message(&snac, n_msg); | 3393 | enqueue_message(&snac, n_msg); |
| 3219 | timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 1); | 3394 | timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 1, msg); |
| 3220 | 3395 | ||
| 3221 | out = mastoapi_status(&snac, msg); | 3396 | out = mastoapi_status(&snac, msg); |
| 3222 | } | 3397 | } |
| @@ -3232,12 +3407,35 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 3232 | } | 3407 | } |
| 3233 | } | 3408 | } |
| 3234 | else | 3409 | else |
| 3410 | if (strcmp(op, "react") == 0) { /** **/ | ||
| 3411 | const char *eid = xs_list_get(l, 5); | ||
| 3412 | xs *n_msg = msg_emoji_init(&snac, id, eid); | ||
| 3413 | if (n_msg) | ||
| 3414 | out = mastoapi_status(&snac, n_msg); | ||
| 3415 | } | ||
| 3416 | else | ||
| 3417 | if (strcmp(op, "unreact") == 0) { /** **/ | ||
| 3418 | const char *eid = xs_list_get(l, 5); | ||
| 3419 | xs *content = xs_fmt("%s", eid); | ||
| 3420 | |||
| 3421 | if (eid) { | ||
| 3422 | xs *n_msg = msg_emoji_unreact(&snac, id, content); | ||
| 3423 | |||
| 3424 | if (n_msg != NULL) { | ||
| 3425 | enqueue_message(&snac, n_msg); | ||
| 3426 | |||
| 3427 | out = mastoapi_status(&snac, msg); | ||
| 3428 | } | ||
| 3429 | } | ||
| 3430 | } | ||
| 3431 | |||
| 3432 | else | ||
| 3235 | if (strcmp(op, "reblog") == 0) { /** **/ | 3433 | if (strcmp(op, "reblog") == 0) { /** **/ |
| 3236 | xs *n_msg = msg_admiration(&snac, id, "Announce"); | 3434 | xs *n_msg = msg_admiration(&snac, id, "Announce"); |
| 3237 | 3435 | ||
| 3238 | if (n_msg != NULL) { | 3436 | if (n_msg != NULL) { |
| 3239 | enqueue_message(&snac, n_msg); | 3437 | enqueue_message(&snac, n_msg); |
| 3240 | timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 0); | 3438 | timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 0, msg); |
| 3241 | 3439 | ||
| 3242 | out = mastoapi_status(&snac, msg); | 3440 | out = mastoapi_status(&snac, msg); |
| 3243 | } | 3441 | } |
| @@ -3824,7 +4022,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, | |||
| 3824 | if (valid_status(object_get_by_md5(p, &obj))) { | 4022 | if (valid_status(object_get_by_md5(p, &obj))) { |
| 3825 | const char *id = xs_dict_get(obj, "id"); | 4023 | const char *id = xs_dict_get(obj, "id"); |
| 3826 | 4024 | ||
| 3827 | if (xs_is_string(id) && xs_startswith(id, snac.actor)) { | 4025 | if (xs_is_string(id) && is_msg_mine(&snac, id)) { |
| 3828 | xs *out = mastoapi_status(&snac, obj); | 4026 | xs *out = mastoapi_status(&snac, obj); |
| 3829 | 4027 | ||
| 3830 | xs *msg = msg_delete(&snac, id); | 4028 | xs *msg = msg_delete(&snac, id); |