diff options
| -rw-r--r-- | activitypub.c | 110 | ||||
| -rw-r--r-- | data.c | 19 | ||||
| -rw-r--r-- | main.c | 11 | ||||
| -rw-r--r-- | mastoapi.c | 8 | ||||
| -rw-r--r-- | snac.h | 4 | ||||
| -rw-r--r-- | utils.c | 12 |
6 files changed, 150 insertions, 14 deletions
diff --git a/activitypub.c b/activitypub.c index 09da229..2c0aa98 100644 --- a/activitypub.c +++ b/activitypub.c | |||
| @@ -1021,6 +1021,107 @@ void collect_replies(snac *user, const char *id) | |||
| 1021 | } | 1021 | } |
| 1022 | 1022 | ||
| 1023 | 1023 | ||
| 1024 | void collect_outbox(snac *user, const char *actor_id) | ||
| 1025 | /* gets an actor's outbox and inserts a bunch of posts in a user's timeline */ | ||
| 1026 | { | ||
| 1027 | int status; | ||
| 1028 | xs *actor = NULL; | ||
| 1029 | |||
| 1030 | if (!valid_status(status = actor_request(user, actor_id, &actor))) { | ||
| 1031 | snac_debug(user, 1, xs_fmt("collect_outbox: cannot get actor object '%s' %d", actor_id, status)); | ||
| 1032 | return; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | xs *outbox = NULL; | ||
| 1036 | const char *outbox_url = xs_dict_get(actor, "outbox"); | ||
| 1037 | |||
| 1038 | if (!xs_is_string(outbox_url)) | ||
| 1039 | return; | ||
| 1040 | |||
| 1041 | if (!valid_status(status = activitypub_request(user, outbox_url, &outbox))) { | ||
| 1042 | snac_debug(user, 1, xs_fmt("collect_outbox: cannot get actor outbox '%s' %d", outbox_url, status)); | ||
| 1043 | return; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | const xs_list *ordered_items = xs_dict_get(outbox, "orderedItems"); | ||
| 1047 | |||
| 1048 | if (!xs_is_list(ordered_items)) { | ||
| 1049 | /* the list is not here; does it have a 'first'? */ | ||
| 1050 | const char *first = xs_dict_get(outbox, "first"); | ||
| 1051 | |||
| 1052 | if (xs_is_string(first)) { | ||
| 1053 | /* download this instead */ | ||
| 1054 | xs *first2 = xs_dup(first); | ||
| 1055 | xs_free(outbox); | ||
| 1056 | |||
| 1057 | if (!valid_status(status = activitypub_request(user, first2, &outbox))) { | ||
| 1058 | snac_debug(user, 1, xs_fmt("collect_outbox: cannot get first page of outbox '%s' %d", first2, status)); | ||
| 1059 | return; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | /* last chance */ | ||
| 1063 | ordered_items = xs_dict_get(outbox, "orderedItems"); | ||
| 1064 | } | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | if (!xs_is_list(ordered_items)) { | ||
| 1068 | snac_debug(user, 1, xs_fmt("collect_outbox: cannot get list of posts for actor '%s' outbox", actor_id)); | ||
| 1069 | return; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | /* well, ok, then */ | ||
| 1073 | int max = 4; | ||
| 1074 | const xs_val *v; | ||
| 1075 | |||
| 1076 | xs_list_foreach(ordered_items, v) { | ||
| 1077 | if (max == 0) | ||
| 1078 | break; | ||
| 1079 | |||
| 1080 | xs *post = NULL; | ||
| 1081 | |||
| 1082 | if (xs_is_string(v)) { | ||
| 1083 | /* it's probably the post url */ | ||
| 1084 | if (!valid_status(activitypub_request(user, v, &post))) | ||
| 1085 | continue; | ||
| 1086 | } | ||
| 1087 | else | ||
| 1088 | if (xs_is_dict(v)) | ||
| 1089 | post = xs_dup(v); | ||
| 1090 | |||
| 1091 | if (post == NULL) | ||
| 1092 | continue; | ||
| 1093 | |||
| 1094 | const char *type = xs_dict_get(post, "type"); | ||
| 1095 | |||
| 1096 | if (!xs_is_string(type) || strcmp(type, "Create")) { | ||
| 1097 | /* not a post */ | ||
| 1098 | continue; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | const xs_dict *object = xs_dict_get(post, "object"); | ||
| 1102 | |||
| 1103 | if (!xs_is_dict(object)) | ||
| 1104 | continue; | ||
| 1105 | |||
| 1106 | type = xs_dict_get(object, "type"); | ||
| 1107 | const char *id = xs_dict_get(object, "id"); | ||
| 1108 | const char *attr_to = get_atto(object); | ||
| 1109 | |||
| 1110 | if (!xs_is_string(type) || !xs_is_string(id) || !xs_is_string(attr_to)) | ||
| 1111 | continue; | ||
| 1112 | |||
| 1113 | if (!timeline_here(user, id)) { | ||
| 1114 | timeline_add(user, id, object); | ||
| 1115 | snac_log(user, xs_fmt("new '%s' (collect_outbox) %s %s", type, attr_to, id)); | ||
| 1116 | } | ||
| 1117 | else | ||
| 1118 | snac_debug(user, 1, xs_fmt("collect_outbox: post '%s' already here", id)); | ||
| 1119 | |||
| 1120 | max--; | ||
| 1121 | } | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | |||
| 1024 | void notify(snac *snac, const char *type, const char *utype, const char *actor, const xs_dict *msg) | 1125 | void notify(snac *snac, const char *type, const char *utype, const char *actor, const xs_dict *msg) |
| 1025 | /* notifies the user of relevant events */ | 1126 | /* notifies the user of relevant events */ |
| 1026 | { | 1127 | { |
| @@ -2487,6 +2588,9 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) | |||
| 2487 | if (following_check(snac, actor)) { | 2588 | if (following_check(snac, actor)) { |
| 2488 | following_add(snac, actor, msg); | 2589 | following_add(snac, actor, msg); |
| 2489 | snac_log(snac, xs_fmt("confirmed follow from %s", actor)); | 2590 | snac_log(snac, xs_fmt("confirmed follow from %s", actor)); |
| 2591 | |||
| 2592 | /* request a bit of this fellow's outbox */ | ||
| 2593 | enqueue_collect_outbox(snac, actor); | ||
| 2490 | } | 2594 | } |
| 2491 | else | 2595 | else |
| 2492 | snac_log(snac, xs_fmt("spurious follow accept from %s", actor)); | 2596 | snac_log(snac, xs_fmt("spurious follow accept from %s", actor)); |
| @@ -2979,6 +3083,12 @@ void process_user_queue_item(snac *user, xs_dict *q_item) | |||
| 2979 | collect_replies(user, post); | 3083 | collect_replies(user, post); |
| 2980 | } | 3084 | } |
| 2981 | else | 3085 | else |
| 3086 | if (strcmp(type, "collect_outbox") == 0) { | ||
| 3087 | const char *actor_id = xs_dict_get(q_item, "message"); | ||
| 3088 | |||
| 3089 | collect_outbox(user, actor_id); | ||
| 3090 | } | ||
| 3091 | else | ||
| 2982 | snac_log(user, xs_fmt("unexpected user q_item type '%s'", type)); | 3092 | snac_log(user, xs_fmt("unexpected user q_item type '%s'", type)); |
| 2983 | } | 3093 | } |
| 2984 | 3094 | ||
| @@ -2429,8 +2429,8 @@ xs_list *list_timeline(snac *user, const char *list, int skip, int show) | |||
| 2429 | } | 2429 | } |
| 2430 | 2430 | ||
| 2431 | 2431 | ||
| 2432 | xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op) | 2432 | xs_val *list_members(snac *user, const char *list, const char *actor_md5, int op) |
| 2433 | /* list content management */ | 2433 | /* list member management */ |
| 2434 | { | 2434 | { |
| 2435 | xs_val *l = NULL; | 2435 | xs_val *l = NULL; |
| 2436 | 2436 | ||
| @@ -2443,7 +2443,7 @@ xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op | |||
| 2443 | xs *fn = xs_fmt("%s/list/%s.lst", user->basedir, list); | 2443 | xs *fn = xs_fmt("%s/list/%s.lst", user->basedir, list); |
| 2444 | 2444 | ||
| 2445 | switch (op) { | 2445 | switch (op) { |
| 2446 | case 0: /** list content **/ | 2446 | case 0: /** list members **/ |
| 2447 | l = index_list(fn, XS_ALL); | 2447 | l = index_list(fn, XS_ALL); |
| 2448 | 2448 | ||
| 2449 | break; | 2449 | break; |
| @@ -3589,6 +3589,19 @@ void enqueue_collect_replies(snac *user, const char *post) | |||
| 3589 | } | 3589 | } |
| 3590 | 3590 | ||
| 3591 | 3591 | ||
| 3592 | void enqueue_collect_outbox(snac *user, const char *actor_id) | ||
| 3593 | /* enqueues a collect outbox request */ | ||
| 3594 | { | ||
| 3595 | xs *qmsg = _new_qmsg("collect_outbox", actor_id, 0); | ||
| 3596 | const char *ntid = xs_dict_get(qmsg, "ntid"); | ||
| 3597 | xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid); | ||
| 3598 | |||
| 3599 | qmsg = _enqueue_put(fn, qmsg); | ||
| 3600 | |||
| 3601 | snac_debug(user, 1, xs_fmt("enqueue_collect_outbox %s", actor_id)); | ||
| 3602 | } | ||
| 3603 | |||
| 3604 | |||
| 3592 | int was_question_voted(snac *user, const char *id) | 3605 | int was_question_voted(snac *user, const char *id) |
| 3593 | /* returns true if the user voted in this poll */ | 3606 | /* returns true if the user voted in this poll */ |
| 3594 | { | 3607 | { |
| @@ -355,7 +355,7 @@ int main(int argc, char *argv[]) | |||
| 355 | xs *lid = list_maint(&snac, url, 4); | 355 | xs *lid = list_maint(&snac, url, 4); |
| 356 | 356 | ||
| 357 | if (lid != NULL) { | 357 | if (lid != NULL) { |
| 358 | xs *lcont = list_content(&snac, lid, NULL, 0); | 358 | xs *lcont = list_members(&snac, lid, NULL, 0); |
| 359 | const char *md5; | 359 | const char *md5; |
| 360 | 360 | ||
| 361 | xs_list_foreach(lcont, md5) { | 361 | xs_list_foreach(lcont, md5) { |
| @@ -411,7 +411,7 @@ int main(int argc, char *argv[]) | |||
| 411 | if (valid_status(webfinger_request(account, &actor, &uid))) { | 411 | if (valid_status(webfinger_request(account, &actor, &uid))) { |
| 412 | xs *md5 = xs_md5_hex(actor, strlen(actor)); | 412 | xs *md5 = xs_md5_hex(actor, strlen(actor)); |
| 413 | 413 | ||
| 414 | list_content(&snac, lid, md5, 1); | 414 | list_members(&snac, lid, md5, 1); |
| 415 | printf("Actor %s (%s) added to list '%s' (%s)\n", actor, uid, url, lid); | 415 | printf("Actor %s (%s) added to list '%s' (%s)\n", actor, uid, url, lid); |
| 416 | } | 416 | } |
| 417 | else | 417 | else |
| @@ -434,7 +434,7 @@ int main(int argc, char *argv[]) | |||
| 434 | if (lid != NULL) { | 434 | if (lid != NULL) { |
| 435 | xs *md5 = xs_md5_hex(account, strlen(account)); | 435 | xs *md5 = xs_md5_hex(account, strlen(account)); |
| 436 | 436 | ||
| 437 | list_content(&snac, lid, md5, 2); | 437 | list_members(&snac, lid, md5, 2); |
| 438 | printf("Actor %s deleted from list '%s' (%s)\n", account, url, lid); | 438 | printf("Actor %s deleted from list '%s' (%s)\n", account, url, lid); |
| 439 | } | 439 | } |
| 440 | else | 440 | else |
| @@ -739,6 +739,11 @@ int main(int argc, char *argv[]) | |||
| 739 | return 0; | 739 | return 0; |
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | if (strcmp(cmd, "collect_outbox") == 0) { /** **/ | ||
| 743 | enqueue_collect_outbox(&snac, url); | ||
| 744 | return 0; | ||
| 745 | } | ||
| 746 | |||
| 742 | if (strcmp(cmd, "insert") == 0) { /** **/ | 747 | if (strcmp(cmd, "insert") == 0) { /** **/ |
| 743 | int status; | 748 | int status; |
| 744 | xs *data = NULL; | 749 | xs *data = NULL; |
| @@ -1560,7 +1560,7 @@ xs_list *mastoapi_account_lists(snac *user, const char *uid) | |||
| 1560 | const char *list_id = xs_list_get(li, 0); | 1560 | const char *list_id = xs_list_get(li, 0); |
| 1561 | const char *list_title = xs_list_get(li, 1); | 1561 | const char *list_title = xs_list_get(li, 1); |
| 1562 | if (uid) { | 1562 | if (uid) { |
| 1563 | xs *users = list_content(user, list_id, NULL, 0); | 1563 | xs *users = list_members(user, list_id, NULL, 0); |
| 1564 | if (xs_list_in(users, actor_md5) == -1) | 1564 | if (xs_list_in(users, actor_md5) == -1) |
| 1565 | continue; | 1565 | continue; |
| 1566 | } | 1566 | } |
| @@ -2087,7 +2087,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 2087 | p = xs_list_get(l, -2); | 2087 | p = xs_list_get(l, -2); |
| 2088 | 2088 | ||
| 2089 | if (p && xs_is_hex(p)) { | 2089 | if (p && xs_is_hex(p)) { |
| 2090 | xs *actors = list_content(&snac1, p, NULL, 0); | 2090 | xs *actors = list_members(&snac1, p, NULL, 0); |
| 2091 | xs *out = xs_list_new(); | 2091 | xs *out = xs_list_new(); |
| 2092 | int c = 0; | 2092 | int c = 0; |
| 2093 | const char *v; | 2093 | const char *v; |
| @@ -3297,7 +3297,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 3297 | const char *v; | 3297 | const char *v; |
| 3298 | 3298 | ||
| 3299 | while (xs_list_next(accts, &v, &c)) { | 3299 | while (xs_list_next(accts, &v, &c)) { |
| 3300 | list_content(&snac, id, v, 1); | 3300 | list_members(&snac, id, v, 1); |
| 3301 | } | 3301 | } |
| 3302 | 3302 | ||
| 3303 | xs *out = xs_dict_new(); | 3303 | xs *out = xs_dict_new(); |
| @@ -3507,7 +3507,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, | |||
| 3507 | const char *v; | 3507 | const char *v; |
| 3508 | 3508 | ||
| 3509 | while (xs_list_next(accts, &v, &c)) { | 3509 | while (xs_list_next(accts, &v, &c)) { |
| 3510 | list_content(&snac, p, v, 2); | 3510 | list_members(&snac, p, v, 2); |
| 3511 | } | 3511 | } |
| 3512 | } | 3512 | } |
| 3513 | else { | 3513 | else { |
| @@ -233,7 +233,7 @@ xs_list *tag_search(const char *tag, int skip, int show); | |||
| 233 | xs_val *list_maint(snac *user, const char *list, int op); | 233 | xs_val *list_maint(snac *user, const char *list, int op); |
| 234 | xs_str *list_timeline_fn(snac *user, const char *list); | 234 | xs_str *list_timeline_fn(snac *user, const char *list); |
| 235 | xs_list *list_timeline(snac *user, const char *list, int skip, int show); | 235 | xs_list *list_timeline(snac *user, const char *list, int skip, int show); |
| 236 | xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op); | 236 | xs_val *list_members(snac *user, const char *list_id, const char *actor_md5, int op); |
| 237 | void list_distribute(snac *user, const char *who, const xs_dict *post); | 237 | void list_distribute(snac *user, const char *who, const xs_dict *post); |
| 238 | 238 | ||
| 239 | int actor_add(const char *actor, const xs_dict *msg); | 239 | int actor_add(const char *actor, const xs_dict *msg); |
| @@ -298,6 +298,7 @@ void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs); | |||
| 298 | void enqueue_webmention(const xs_dict *msg); | 298 | void enqueue_webmention(const xs_dict *msg); |
| 299 | void enqueue_notify_webhook(snac *user, const xs_dict *noti, int retries); | 299 | void enqueue_notify_webhook(snac *user, const xs_dict *noti, int retries); |
| 300 | void enqueue_collect_replies(snac *user, const char *post); | 300 | void enqueue_collect_replies(snac *user, const char *post); |
| 301 | void enqueue_collect_outbox(snac *user, const char *actor_id); | ||
| 301 | 302 | ||
| 302 | int was_question_voted(snac *user, const char *id); | 303 | int was_question_voted(snac *user, const char *id); |
| 303 | 304 | ||
| @@ -336,6 +337,7 @@ const char *default_avatar_base64(void); | |||
| 336 | xs_str *process_tags(snac *snac, const char *content, xs_list **tag); | 337 | xs_str *process_tags(snac *snac, const char *content, xs_list **tag); |
| 337 | 338 | ||
| 338 | void collect_replies(snac *user, const char *id); | 339 | void collect_replies(snac *user, const char *id); |
| 340 | void collect_outbox(snac *user, const char *actor_id); | ||
| 339 | 341 | ||
| 340 | const char *get_atto(const xs_dict *msg); | 342 | const char *get_atto(const xs_dict *msg); |
| 341 | const char *get_in_reply_to(const xs_dict *msg); | 343 | const char *get_in_reply_to(const xs_dict *msg); |
| @@ -229,6 +229,9 @@ int snac_init(const char *basedir) | |||
| 229 | xs *ibdir = xs_fmt("%s/inbox", srv_basedir); | 229 | xs *ibdir = xs_fmt("%s/inbox", srv_basedir); |
| 230 | mkdirx(ibdir); | 230 | mkdirx(ibdir); |
| 231 | 231 | ||
| 232 | xs *langdir = xs_fmt("%s/lang", srv_basedir); | ||
| 233 | mkdirx(langdir); | ||
| 234 | |||
| 232 | xs *gfn = xs_fmt("%s/greeting.html", srv_basedir); | 235 | xs *gfn = xs_fmt("%s/greeting.html", srv_basedir); |
| 233 | if ((f = fopen(gfn, "w")) == NULL) { | 236 | if ((f = fopen(gfn, "w")) == NULL) { |
| 234 | printf("ERROR: cannot create '%s'\n", gfn); | 237 | printf("ERROR: cannot create '%s'\n", gfn); |
| @@ -253,7 +256,10 @@ int snac_init(const char *basedir) | |||
| 253 | xs_json_dump(srv_config, 4, f); | 256 | xs_json_dump(srv_config, 4, f); |
| 254 | fclose(f); | 257 | fclose(f); |
| 255 | 258 | ||
| 256 | printf("Done.\n"); | 259 | printf("Done.\n\n"); |
| 260 | |||
| 261 | printf("Wanted web UI language files (.po) must be copied manually to %s\n", langdir); | ||
| 262 | |||
| 257 | return 0; | 263 | return 0; |
| 258 | } | 264 | } |
| 259 | 265 | ||
| @@ -681,7 +687,7 @@ void export_csv(snac *user) | |||
| 681 | const char *lid = xs_list_get(li, 0); | 687 | const char *lid = xs_list_get(li, 0); |
| 682 | const char *ltitle = xs_list_get(li, 1); | 688 | const char *ltitle = xs_list_get(li, 1); |
| 683 | 689 | ||
| 684 | xs *actors = list_content(user, lid, NULL, 0); | 690 | xs *actors = list_members(user, lid, NULL, 0); |
| 685 | const char *md5; | 691 | const char *md5; |
| 686 | 692 | ||
| 687 | xs_list_foreach(actors, md5) { | 693 | xs_list_foreach(actors, md5) { |
| @@ -907,7 +913,7 @@ void import_list_csv(snac *user, const char *ifn) | |||
| 907 | if (valid_status(webfinger_request(acct, &url, &uid))) { | 913 | if (valid_status(webfinger_request(acct, &url, &uid))) { |
| 908 | xs *actor_md5 = xs_md5_hex(url, strlen(url)); | 914 | xs *actor_md5 = xs_md5_hex(url, strlen(url)); |
| 909 | 915 | ||
| 910 | list_content(user, list_id, actor_md5, 1); | 916 | list_members(user, list_id, actor_md5, 1); |
| 911 | snac_log(user, xs_fmt("Added %s to list %s", url, lname)); | 917 | snac_log(user, xs_fmt("Added %s to list %s", url, lname)); |
| 912 | 918 | ||
| 913 | if (!following_check(user, url)) { | 919 | if (!following_check(user, url)) { |