diff options
| author | 2022-12-02 19:14:59 +0100 | |
|---|---|---|
| committer | 2022-12-02 19:14:59 +0100 | |
| commit | c00e3afcdc8cf1503439a174621090b133ad329f (patch) | |
| tree | 3738fb8d555a55878011cc70a33a05733e2322e8 | |
| parent | Updated RELEASE_NOTES. (diff) | |
| download | snac2-c00e3afcdc8cf1503439a174621090b133ad329f.tar.gz snac2-c00e3afcdc8cf1503439a174621090b133ad329f.tar.xz snac2-c00e3afcdc8cf1503439a174621090b133ad329f.zip | |
Big data storage change.
| -rw-r--r-- | activitypub.c | 6 | ||||
| -rw-r--r-- | data.c | 77 | ||||
| -rw-r--r-- | html.c | 142 | ||||
| -rw-r--r-- | main.c | 2 | ||||
| -rw-r--r-- | snac.h | 12 |
5 files changed, 131 insertions, 108 deletions
diff --git a/activitypub.c b/activitypub.c index 7f63310..8e173c5 100644 --- a/activitypub.c +++ b/activitypub.c | |||
| @@ -879,7 +879,7 @@ int process_message(snac *snac, char *msg, char *req) | |||
| 879 | if (xs_type(object) == XSTYPE_DICT) | 879 | if (xs_type(object) == XSTYPE_DICT) |
| 880 | object = xs_dict_get(object, "id"); | 880 | object = xs_dict_get(object, "id"); |
| 881 | 881 | ||
| 882 | timeline_admire(snac, object, actor, 1); | 882 | timeline_admire(snac, msg, object, actor, 1); |
| 883 | snac_log(snac, xs_fmt("new 'Like' %s %s", actor, object)); | 883 | snac_log(snac, xs_fmt("new 'Like' %s %s", actor, object)); |
| 884 | do_notify = 1; | 884 | do_notify = 1; |
| 885 | } | 885 | } |
| @@ -900,7 +900,7 @@ int process_message(snac *snac, char *msg, char *req) | |||
| 900 | xs *who_o = NULL; | 900 | xs *who_o = NULL; |
| 901 | 901 | ||
| 902 | if (valid_status(actor_request(snac, who, &who_o))) { | 902 | if (valid_status(actor_request(snac, who, &who_o))) { |
| 903 | timeline_admire(snac, object, actor, 0); | 903 | timeline_admire(snac, msg, object, actor, 0); |
| 904 | snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); | 904 | snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); |
| 905 | do_notify = 1; | 905 | do_notify = 1; |
| 906 | } | 906 | } |
| @@ -1094,7 +1094,7 @@ int activitypub_get_handler(d_char *req, char *q_path, | |||
| 1094 | else | 1094 | else |
| 1095 | if (strcmp(p_path, "outbox") == 0) { | 1095 | if (strcmp(p_path, "outbox") == 0) { |
| 1096 | xs *id = xs_fmt("%s/outbox", snac.actor); | 1096 | xs *id = xs_fmt("%s/outbox", snac.actor); |
| 1097 | xs *elems = local_list(&snac, 20); | 1097 | xs *elems = timeline_list(&snac, "public", 20); |
| 1098 | xs *list = xs_list_new(); | 1098 | xs *list = xs_list_new(); |
| 1099 | msg = msg_collection(&snac, id); | 1099 | msg = msg_collection(&snac, id); |
| 1100 | char *p, *v; | 1100 | char *p, *v; |
| @@ -116,6 +116,7 @@ void user_free(snac *snac) | |||
| 116 | xs_free(snac->config); | 116 | xs_free(snac->config); |
| 117 | xs_free(snac->key); | 117 | xs_free(snac->key); |
| 118 | xs_free(snac->actor); | 118 | xs_free(snac->actor); |
| 119 | xs_free(snac->md5); | ||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | 122 | ||
| @@ -154,6 +155,7 @@ int user_open(snac *snac, char *uid) | |||
| 154 | 155 | ||
| 155 | if ((snac->key = xs_json_loads(key_data)) != NULL) { | 156 | if ((snac->key = xs_json_loads(key_data)) != NULL) { |
| 156 | snac->actor = xs_fmt("%s/%s", srv_baseurl, uid); | 157 | snac->actor = xs_fmt("%s/%s", srv_baseurl, uid); |
| 158 | snac->md5 = xs_md5_hex(snac->actor, strlen(snac->actor)); | ||
| 157 | ret = 1; | 159 | ret = 1; |
| 158 | } | 160 | } |
| 159 | else | 161 | else |
| @@ -566,14 +568,31 @@ int object_del_if_unref(const char *id) | |||
| 566 | } | 568 | } |
| 567 | 569 | ||
| 568 | 570 | ||
| 571 | d_char *_object_metadata(const char *id, const char *idxsfx) | ||
| 572 | /* returns the content of a metadata index */ | ||
| 573 | { | ||
| 574 | xs *fn = _object_fn(id); | ||
| 575 | fn = xs_replace_i(fn, ".json", idxsfx); | ||
| 576 | return index_list(fn, XS_ALL); | ||
| 577 | } | ||
| 578 | |||
| 579 | |||
| 569 | d_char *object_children(const char *id) | 580 | d_char *object_children(const char *id) |
| 570 | /* returns the list of an object's children */ | 581 | /* returns the list of an object's children */ |
| 571 | { | 582 | { |
| 572 | xs *fn = _object_fn(id); | 583 | return _object_metadata(id, "_c.idx"); |
| 584 | } | ||
| 573 | 585 | ||
| 574 | fn = xs_replace_i(fn, ".json", "_c.idx"); | ||
| 575 | 586 | ||
| 576 | return index_list(fn, XS_ALL); | 587 | d_char *object_likes(const char *id) |
| 588 | { | ||
| 589 | return _object_metadata(id, "_l.idx"); | ||
| 590 | } | ||
| 591 | |||
| 592 | |||
| 593 | d_char *object_announces(const char *id) | ||
| 594 | { | ||
| 595 | return _object_metadata(id, "_a.idx"); | ||
| 577 | } | 596 | } |
| 578 | 597 | ||
| 579 | 598 | ||
| @@ -818,35 +837,6 @@ d_char *timeline_get(snac *snac, char *fn) | |||
| 818 | } | 837 | } |
| 819 | 838 | ||
| 820 | 839 | ||
| 821 | d_char *_timeline_list(snac *snac, char *directory, int max) | ||
| 822 | /* returns a list of the timeline filenames */ | ||
| 823 | { | ||
| 824 | xs *spec = xs_fmt("%s/%s/" "*.json", snac->basedir, directory); | ||
| 825 | int c_max; | ||
| 826 | |||
| 827 | /* maximum number of items in the timeline */ | ||
| 828 | c_max = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); | ||
| 829 | |||
| 830 | /* never more timeline entries than the configured maximum */ | ||
| 831 | if (max > c_max) | ||
| 832 | max = c_max; | ||
| 833 | |||
| 834 | return xs_glob_n(spec, 0, 1, max); | ||
| 835 | } | ||
| 836 | |||
| 837 | |||
| 838 | d_char *timeline_list(snac *snac, int max) | ||
| 839 | { | ||
| 840 | return _timeline_list(snac, "timeline", max); | ||
| 841 | } | ||
| 842 | |||
| 843 | |||
| 844 | d_char *local_list(snac *snac, int max) | ||
| 845 | { | ||
| 846 | return _timeline_list(snac, "local", max); | ||
| 847 | } | ||
| 848 | |||
| 849 | |||
| 850 | d_char *_timeline_new_fn(snac *snac, char *id) | 840 | d_char *_timeline_new_fn(snac *snac, char *id) |
| 851 | /* creates a new filename */ | 841 | /* creates a new filename */ |
| 852 | { | 842 | { |
| @@ -1050,7 +1040,7 @@ int timeline_add(snac *snac, char *id, char *o_msg, char *parent, char *referrer | |||
| 1050 | } | 1040 | } |
| 1051 | 1041 | ||
| 1052 | 1042 | ||
| 1053 | d_char *timeline_top_level(snac *snac, d_char *list) | 1043 | d_char *timeline_top_level(d_char *list) |
| 1054 | /* returns the top level md5 entries from this index */ | 1044 | /* returns the top level md5 entries from this index */ |
| 1055 | { | 1045 | { |
| 1056 | d_char *tl = xs_list_new(); | 1046 | d_char *tl = xs_list_new(); |
| @@ -1094,7 +1084,26 @@ d_char *timeline_top_level(snac *snac, d_char *list) | |||
| 1094 | } | 1084 | } |
| 1095 | 1085 | ||
| 1096 | 1086 | ||
| 1097 | void timeline_admire(snac *snac, char *id, char *admirer, int like) | 1087 | d_char *timeline_list(snac *snac, const char *idx_name, int max) |
| 1088 | /* returns a timeline */ | ||
| 1089 | { | ||
| 1090 | int c_max; | ||
| 1091 | |||
| 1092 | /* maximum number of items in the timeline */ | ||
| 1093 | c_max = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); | ||
| 1094 | |||
| 1095 | /* never more timeline entries than the configured maximum */ | ||
| 1096 | if (max > c_max) | ||
| 1097 | max = c_max; | ||
| 1098 | |||
| 1099 | xs *idx = xs_fmt("%s/%s.idx", snac->basedir, idx_name); | ||
| 1100 | xs *list = index_list_desc(idx, max); | ||
| 1101 | |||
| 1102 | return timeline_top_level(list); | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | |||
| 1106 | void timeline_admire(snac *snac, char *o_msg, char *id, char *admirer, int like) | ||
| 1098 | /* updates a timeline entry with a new admiration */ | 1107 | /* updates a timeline entry with a new admiration */ |
| 1099 | { | 1108 | { |
| 1100 | xs *ofn = _timeline_find_fn(snac, id); | 1109 | xs *ofn = _timeline_find_fn(snac, id); |
| @@ -386,7 +386,8 @@ d_char *html_entry_controls(snac *snac, d_char *os, char *msg, int num) | |||
| 386 | { | 386 | { |
| 387 | char *id = xs_dict_get(msg, "id"); | 387 | char *id = xs_dict_get(msg, "id"); |
| 388 | char *actor = xs_dict_get(msg, "attributedTo"); | 388 | char *actor = xs_dict_get(msg, "attributedTo"); |
| 389 | char *meta = xs_dict_get(msg, "_snac"); | 389 | xs *likes = object_likes(id); |
| 390 | xs *boosts = object_announces(id); | ||
| 390 | 391 | ||
| 391 | xs *s = xs_str_new(NULL); | 392 | xs *s = xs_str_new(NULL); |
| 392 | xs *md5 = xs_md5_hex(id, strlen(id)); | 393 | xs *md5 = xs_md5_hex(id, strlen(id)); |
| @@ -407,20 +408,14 @@ d_char *html_entry_controls(snac *snac, d_char *os, char *msg, int num) | |||
| 407 | s = xs_str_cat(s, s1); | 408 | s = xs_str_cat(s, s1); |
| 408 | } | 409 | } |
| 409 | 410 | ||
| 410 | { | 411 | if (xs_list_in(likes, snac->md5) == -1) { |
| 411 | char *l; | 412 | /* not already liked; add button */ |
| 412 | 413 | s = html_button(s, "like", L("Like")); | |
| 413 | l = xs_dict_get(meta, "liked_by"); | 414 | } |
| 414 | if (xs_list_in(l, snac->actor) == -1) { | ||
| 415 | /* not already liked; add button */ | ||
| 416 | s = html_button(s, "like", L("Like")); | ||
| 417 | } | ||
| 418 | 415 | ||
| 419 | l = xs_dict_get(meta, "announced_by"); | 416 | if (strcmp(actor, snac->actor) == 0 || xs_list_in(boosts, snac->md5) == -1) { |
| 420 | if (strcmp(actor, snac->actor) == 0 || xs_list_in(l, snac->actor) == -1) { | 417 | /* not already boosted or us; add button */ |
| 421 | /* not already boosted or us; add button */ | 418 | s = html_button(s, "boost", L("Boost")); |
| 422 | s = html_button(s, "boost", L("Boost")); | ||
| 423 | } | ||
| 424 | } | 419 | } |
| 425 | 420 | ||
| 426 | if (strcmp(actor, snac->actor) != 0) { | 421 | if (strcmp(actor, snac->actor) != 0) { |
| @@ -477,23 +472,20 @@ d_char *html_entry_controls(snac *snac, d_char *os, char *msg, int num) | |||
| 477 | } | 472 | } |
| 478 | 473 | ||
| 479 | 474 | ||
| 480 | d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, int level, int *num) | 475 | d_char *html_entry(snac *snac, d_char *os, char *msg, int local, int level, int *num) |
| 481 | { | 476 | { |
| 482 | char *id = xs_dict_get(msg, "id"); | 477 | char *id = xs_dict_get(msg, "id"); |
| 483 | char *type = xs_dict_get(msg, "type"); | 478 | char *type = xs_dict_get(msg, "type"); |
| 484 | char *meta = xs_dict_get(msg, "_snac"); | ||
| 485 | char *actor; | 479 | char *actor; |
| 486 | int sensitive = 0; | 480 | int sensitive = 0; |
| 487 | char *v; | 481 | char *v; |
| 482 | xs *likes = NULL; | ||
| 483 | xs *boosts = NULL; | ||
| 488 | 484 | ||
| 489 | /* do not show non-public messages in the public timeline */ | 485 | /* do not show non-public messages in the public timeline */ |
| 490 | if (local && !is_msg_public(snac, msg)) | 486 | if (local && !is_msg_public(snac, msg)) |
| 491 | return os; | 487 | return os; |
| 492 | 488 | ||
| 493 | /* return if already seen */ | ||
| 494 | if (xs_set_add(seen, id) == 0) | ||
| 495 | return os; | ||
| 496 | |||
| 497 | xs *s = xs_str_new(NULL); | 489 | xs *s = xs_str_new(NULL); |
| 498 | 490 | ||
| 499 | /* top wrap */ | 491 | /* top wrap */ |
| @@ -522,6 +514,14 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 522 | 514 | ||
| 523 | return xs_str_cat(os, s); | 515 | return xs_str_cat(os, s); |
| 524 | } | 516 | } |
| 517 | else | ||
| 518 | if (strcmp(type, "Note") != 0) { | ||
| 519 | s = xs_str_cat(s, "<div class=\"snac-post\">\n"); | ||
| 520 | |||
| 521 | xs *s1 = xs_fmt("<p>%s</p>\n", type); | ||
| 522 | |||
| 523 | return xs_str_cat(os, s); | ||
| 524 | } | ||
| 525 | 525 | ||
| 526 | /* bring the main actor */ | 526 | /* bring the main actor */ |
| 527 | if ((actor = xs_dict_get(msg, "attributedTo")) == NULL) | 527 | if ((actor = xs_dict_get(msg, "attributedTo")) == NULL) |
| @@ -536,14 +536,14 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 536 | 536 | ||
| 537 | /* if this is our post, add the score */ | 537 | /* if this is our post, add the score */ |
| 538 | if (xs_startswith(id, snac->actor)) { | 538 | if (xs_startswith(id, snac->actor)) { |
| 539 | int likes = xs_list_len(xs_dict_get(meta, "liked_by")); | 539 | likes = object_likes(id); |
| 540 | int boosts = xs_list_len(xs_dict_get(meta, "announced_by")); | 540 | boosts = object_announces(id); |
| 541 | 541 | ||
| 542 | /* alternate emojis: %d 👍 %d 🔁 */ | 542 | /* alternate emojis: %d 👍 %d 🔁 */ |
| 543 | 543 | ||
| 544 | xs *s1 = xs_fmt( | 544 | xs *s1 = xs_fmt( |
| 545 | "<div class=\"snac-score\">%d ★ %d ↺</div>\n", | 545 | "<div class=\"snac-score\">%d ★ %d ↺</div>\n", |
| 546 | likes, boosts); | 546 | xs_list_len(likes), xs_list_len(boosts)); |
| 547 | 547 | ||
| 548 | s = xs_str_cat(s, s1); | 548 | s = xs_str_cat(s, s1); |
| 549 | } | 549 | } |
| @@ -553,28 +553,46 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 553 | 553 | ||
| 554 | s = xs_str_cat(s, "<div class=\"snac-post\">\n"); | 554 | s = xs_str_cat(s, "<div class=\"snac-post\">\n"); |
| 555 | 555 | ||
| 556 | /* print the origin of the post, if any */ | 556 | if (boosts == NULL) |
| 557 | if (!xs_is_null(p = xs_dict_get(meta, "referrer"))) { | 557 | boosts = object_announces(id); |
| 558 | |||
| 559 | if (xs_list_len(boosts)) { | ||
| 560 | /* if somebody boosted this, show as origin */ | ||
| 561 | p = xs_list_get(boosts, 0); | ||
| 558 | xs *actor_r = NULL; | 562 | xs *actor_r = NULL; |
| 559 | 563 | ||
| 560 | if (valid_status(actor_get(snac, p, &actor_r))) { | 564 | if (xs_list_in(boosts, snac->md5) != -1) { |
| 565 | /* we boosted this */ | ||
| 566 | xs *s1 = xs_fmt( | ||
| 567 | "<div class=\"snac-origin\">" | ||
| 568 | "<a href=\"%s\">%s</a> %s</a></div>", | ||
| 569 | snac->actor, xs_dict_get(snac->config, "name"), L("boosted") | ||
| 570 | ); | ||
| 571 | |||
| 572 | s = xs_str_cat(s, s1); | ||
| 573 | } | ||
| 574 | else | ||
| 575 | if (valid_status(object_get_by_md5(p, &actor_r, NULL))) { | ||
| 561 | char *name; | 576 | char *name; |
| 562 | 577 | ||
| 563 | if ((name = xs_dict_get(actor_r, "name")) == NULL) | 578 | if ((name = xs_dict_get(actor_r, "name")) == NULL) |
| 564 | name = xs_dict_get(actor_r, "preferredUsername"); | 579 | name = xs_dict_get(actor_r, "preferredUsername"); |
| 565 | 580 | ||
| 566 | xs *s1 = xs_fmt( | 581 | if (!xs_is_null(name)) { |
| 567 | "<div class=\"snac-origin\">" | 582 | xs *s1 = xs_fmt( |
| 568 | "<a href=\"%s\">%s</a> %s</div>\n", | 583 | "<div class=\"snac-origin\">" |
| 569 | xs_dict_get(actor_r, "id"), | 584 | "<a href=\"%s\">%s</a> %s</div>\n", |
| 570 | name, | 585 | xs_dict_get(actor_r, "id"), |
| 571 | L("boosted") | 586 | name, |
| 572 | ); | 587 | L("boosted") |
| 588 | ); | ||
| 573 | 589 | ||
| 574 | s = xs_str_cat(s, s1); | 590 | s = xs_str_cat(s, s1); |
| 591 | } | ||
| 575 | } | 592 | } |
| 576 | } | 593 | } |
| 577 | else | 594 | |
| 595 | #if 0 | ||
| 578 | if (!xs_is_null((p = xs_dict_get(meta, "parent"))) && *p) { | 596 | if (!xs_is_null((p = xs_dict_get(meta, "parent"))) && *p) { |
| 579 | /* this may happen if any of the autor or the parent aren't here */ | 597 | /* this may happen if any of the autor or the parent aren't here */ |
| 580 | xs *s1 = xs_fmt( | 598 | xs *s1 = xs_fmt( |
| @@ -586,18 +604,6 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 586 | s = xs_str_cat(s, s1); | 604 | s = xs_str_cat(s, s1); |
| 587 | } | 605 | } |
| 588 | else | 606 | else |
| 589 | if (!xs_is_null((p = xs_dict_get(meta, "announced_by"))) && | ||
| 590 | xs_list_in(p, snac->actor) != -1) { | ||
| 591 | /* we boosted this */ | ||
| 592 | xs *s1 = xs_fmt( | ||
| 593 | "<div class=\"snac-origin\">" | ||
| 594 | "<a href=\"%s\">%s</a> %s</a></div>", | ||
| 595 | snac->actor, xs_dict_get(snac->config, "name"), L("boosted") | ||
| 596 | ); | ||
| 597 | |||
| 598 | s = xs_str_cat(s, s1); | ||
| 599 | } | ||
| 600 | else | ||
| 601 | if (!xs_is_null((p = xs_dict_get(meta, "liked_by"))) && | 607 | if (!xs_is_null((p = xs_dict_get(meta, "liked_by"))) && |
| 602 | xs_list_in(p, snac->actor) != -1) { | 608 | xs_list_in(p, snac->actor) != -1) { |
| 603 | /* we liked this */ | 609 | /* we liked this */ |
| @@ -609,6 +615,7 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 609 | 615 | ||
| 610 | s = xs_str_cat(s, s1); | 616 | s = xs_str_cat(s, s1); |
| 611 | } | 617 | } |
| 618 | #endif | ||
| 612 | } | 619 | } |
| 613 | else | 620 | else |
| 614 | s = xs_str_cat(s, "<div class=\"snac-child\">\n"); | 621 | s = xs_str_cat(s, "<div class=\"snac-child\">\n"); |
| @@ -717,12 +724,11 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 717 | s = html_entry_controls(snac, s, msg, *num); | 724 | s = html_entry_controls(snac, s, msg, *num); |
| 718 | 725 | ||
| 719 | /** children **/ | 726 | /** children **/ |
| 720 | 727 | xs *children = object_children(id); | |
| 721 | char *children = xs_dict_get(meta, "children"); | 728 | int left = xs_list_len(children); |
| 722 | int left = xs_list_len(children); | ||
| 723 | 729 | ||
| 724 | if (left) { | 730 | if (left) { |
| 725 | char *id; | 731 | char *p, *cmd5; |
| 726 | 732 | ||
| 727 | if (level < 4) | 733 | if (level < 4) |
| 728 | s = xs_str_cat(s, "<div class=\"snac-children\">\n"); | 734 | s = xs_str_cat(s, "<div class=\"snac-children\">\n"); |
| @@ -732,16 +738,18 @@ d_char *html_entry(snac *snac, d_char *os, char *msg, xs_set *seen, int local, i | |||
| 732 | if (left > 3) | 738 | if (left > 3) |
| 733 | s = xs_str_cat(s, "<details><summary>...</summary>\n"); | 739 | s = xs_str_cat(s, "<details><summary>...</summary>\n"); |
| 734 | 740 | ||
| 735 | while (xs_list_iter(&children, &id)) { | 741 | p = children; |
| 736 | xs *chd = timeline_find(snac, id); | 742 | while (xs_list_iter(&p, &cmd5)) { |
| 743 | xs *chd = NULL; | ||
| 744 | object_get_by_md5(cmd5, &chd, NULL); | ||
| 737 | 745 | ||
| 738 | if (left == 3) | 746 | if (left == 3) |
| 739 | s = xs_str_cat(s, "</details>\n"); | 747 | s = xs_str_cat(s, "</details>\n"); |
| 740 | 748 | ||
| 741 | if (chd != NULL) | 749 | if (chd != NULL) |
| 742 | s = html_entry(snac, s, chd, seen, local, level + 1, num); | 750 | s = html_entry(snac, s, chd, local, level + 1, num); |
| 743 | else | 751 | else |
| 744 | snac_debug(snac, 2, xs_fmt("cannot read from timeline child %s", id)); | 752 | snac_debug(snac, 2, xs_fmt("cannot read from timeline child %s", cmd5)); |
| 745 | 753 | ||
| 746 | left--; | 754 | left--; |
| 747 | } | 755 | } |
| @@ -773,13 +781,10 @@ d_char *html_timeline(snac *snac, char *list, int local) | |||
| 773 | /* returns the HTML for the timeline */ | 781 | /* returns the HTML for the timeline */ |
| 774 | { | 782 | { |
| 775 | d_char *s = xs_str_new(NULL); | 783 | d_char *s = xs_str_new(NULL); |
| 776 | xs_set seen; | ||
| 777 | char *v; | 784 | char *v; |
| 778 | double t = ftime(); | 785 | double t = ftime(); |
| 779 | int num = 0; | 786 | int num = 0; |
| 780 | 787 | ||
| 781 | xs_set_init(&seen); | ||
| 782 | |||
| 783 | s = html_user_header(snac, s, local); | 788 | s = html_user_header(snac, s, local); |
| 784 | 789 | ||
| 785 | if (!local) | 790 | if (!local) |
| @@ -789,9 +794,12 @@ d_char *html_timeline(snac *snac, char *list, int local) | |||
| 789 | s = xs_str_cat(s, "<div class=\"snac-posts\">\n"); | 794 | s = xs_str_cat(s, "<div class=\"snac-posts\">\n"); |
| 790 | 795 | ||
| 791 | while (xs_list_iter(&list, &v)) { | 796 | while (xs_list_iter(&list, &v)) { |
| 792 | xs *msg = timeline_get(snac, v); | 797 | xs *msg = NULL; |
| 798 | |||
| 799 | if (!valid_status(object_get_by_md5(v, &msg, NULL))) | ||
| 800 | continue; | ||
| 793 | 801 | ||
| 794 | s = html_entry(snac, s, msg, &seen, local, 0, &num); | 802 | s = html_entry(snac, s, msg, local, 0, &num); |
| 795 | } | 803 | } |
| 796 | 804 | ||
| 797 | s = xs_str_cat(s, "</div>\n"); | 805 | s = xs_str_cat(s, "</div>\n"); |
| @@ -830,8 +838,6 @@ d_char *html_timeline(snac *snac, char *list, int local) | |||
| 830 | 838 | ||
| 831 | s = xs_str_cat(s, "</body>\n</html>\n"); | 839 | s = xs_str_cat(s, "</body>\n</html>\n"); |
| 832 | 840 | ||
| 833 | xs_set_free(&seen); | ||
| 834 | |||
| 835 | return s; | 841 | return s; |
| 836 | } | 842 | } |
| 837 | 843 | ||
| @@ -1007,7 +1013,7 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * | |||
| 1007 | status = 200; | 1013 | status = 200; |
| 1008 | } | 1014 | } |
| 1009 | else { | 1015 | else { |
| 1010 | xs *list = local_list(&snac, XS_ALL); | 1016 | xs *list = timeline_list(&snac, "public", XS_ALL); |
| 1011 | 1017 | ||
| 1012 | *body = html_timeline(&snac, list, 1); | 1018 | *body = html_timeline(&snac, list, 1); |
| 1013 | *b_size = strlen(*body); | 1019 | *b_size = strlen(*body); |
| @@ -1033,7 +1039,9 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * | |||
| 1033 | else { | 1039 | else { |
| 1034 | snac_debug(&snac, 1, xs_fmt("building timeline")); | 1040 | snac_debug(&snac, 1, xs_fmt("building timeline")); |
| 1035 | 1041 | ||
| 1036 | xs *list = timeline_list(&snac, XS_ALL); | 1042 | xs *list = timeline_list(&snac, "private", XS_ALL); |
| 1043 | |||
| 1044 | printf("--> %d\n", xs_list_len(list)); | ||
| 1037 | 1045 | ||
| 1038 | *body = html_timeline(&snac, list, 0); | 1046 | *body = html_timeline(&snac, list, 0); |
| 1039 | *b_size = strlen(*body); | 1047 | *b_size = strlen(*body); |
| @@ -1098,7 +1106,7 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * | |||
| 1098 | if (strcmp(p_path, ".rss") == 0) { | 1106 | if (strcmp(p_path, ".rss") == 0) { |
| 1099 | /* public timeline in RSS format */ | 1107 | /* public timeline in RSS format */ |
| 1100 | d_char *rss; | 1108 | d_char *rss; |
| 1101 | xs *elems = local_list(&snac, 20); | 1109 | xs *elems = timeline_list(&snac, "public", 20); |
| 1102 | xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio")); | 1110 | xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio")); |
| 1103 | char *p, *v; | 1111 | char *p, *v; |
| 1104 | 1112 | ||
| @@ -1281,13 +1289,13 @@ int html_post_handler(d_char *req, char *q_path, d_char *payload, int p_size, | |||
| 1281 | if (strcmp(action, L("Like")) == 0) { | 1289 | if (strcmp(action, L("Like")) == 0) { |
| 1282 | xs *msg = msg_admiration(&snac, id, "Like"); | 1290 | xs *msg = msg_admiration(&snac, id, "Like"); |
| 1283 | post(&snac, msg); | 1291 | post(&snac, msg); |
| 1284 | timeline_admire(&snac, id, snac.actor, 1); | 1292 | timeline_admire(&snac, msg, id, snac.actor, 1); |
| 1285 | } | 1293 | } |
| 1286 | else | 1294 | else |
| 1287 | if (strcmp(action, L("Boost")) == 0) { | 1295 | if (strcmp(action, L("Boost")) == 0) { |
| 1288 | xs *msg = msg_admiration(&snac, id, "Announce"); | 1296 | xs *msg = msg_admiration(&snac, id, "Announce"); |
| 1289 | post(&snac, msg); | 1297 | post(&snac, msg); |
| 1290 | timeline_admire(&snac, id, snac.actor, 0); | 1298 | timeline_admire(&snac, msg, id, snac.actor, 0); |
| 1291 | } | 1299 | } |
| 1292 | else | 1300 | else |
| 1293 | if (strcmp(action, L("MUTE")) == 0) { | 1301 | if (strcmp(action, L("MUTE")) == 0) { |
| @@ -167,7 +167,7 @@ int main(int argc, char *argv[]) | |||
| 167 | 167 | ||
| 168 | xs *idx = xs_fmt("%s/private.idx", snac.basedir); | 168 | xs *idx = xs_fmt("%s/private.idx", snac.basedir); |
| 169 | xs *list = index_list_desc(idx, 256); | 169 | xs *list = index_list_desc(idx, 256); |
| 170 | xs *tl = timeline_top_level(&snac, list); | 170 | xs *tl = timeline_top_level(list); |
| 171 | 171 | ||
| 172 | xs *j = xs_json_dumps_pp(tl, 4); | 172 | xs *j = xs_json_dumps_pp(tl, 4); |
| 173 | printf("%s\n", j); | 173 | printf("%s\n", j); |
| @@ -33,6 +33,7 @@ typedef struct _snac { | |||
| 33 | d_char *config; /* user configuration */ | 33 | d_char *config; /* user configuration */ |
| 34 | d_char *key; /* keypair */ | 34 | d_char *key; /* keypair */ |
| 35 | d_char *actor; /* actor url */ | 35 | d_char *actor; /* actor url */ |
| 36 | d_char *md5; /* actor url md5 */ | ||
| 36 | } snac; | 37 | } snac; |
| 37 | 38 | ||
| 38 | int user_open(snac *snac, char *uid); | 39 | int user_open(snac *snac, char *uid); |
| @@ -59,9 +60,14 @@ int index_first(const char *fn, char *buf, int size); | |||
| 59 | d_char *index_list(const char *fn, int max); | 60 | d_char *index_list(const char *fn, int max); |
| 60 | d_char *index_list_desc(const char *fn, int max); | 61 | d_char *index_list_desc(const char *fn, int max); |
| 61 | 62 | ||
| 63 | int object_get_by_md5(const char *md5, d_char **obj, const char *type); | ||
| 62 | int object_del(const char *id); | 64 | int object_del(const char *id); |
| 63 | int object_del_if_unref(const char *id); | 65 | int object_del_if_unref(const char *id); |
| 64 | 66 | ||
| 67 | d_char *object_children(const char *id); | ||
| 68 | d_char *object_likes(const char *id); | ||
| 69 | d_char *object_announces(const char *id); | ||
| 70 | |||
| 65 | int follower_add(snac *snac, const char *actor); | 71 | int follower_add(snac *snac, const char *actor); |
| 66 | int follower_del(snac *snac, const char *actor); | 72 | int follower_del(snac *snac, const char *actor); |
| 67 | int follower_check(snac *snac, const char *actor); | 73 | int follower_check(snac *snac, const char *actor); |
| @@ -73,11 +79,11 @@ d_char *_timeline_find_fn(snac *snac, char *id); | |||
| 73 | d_char *timeline_find(snac *snac, char *id); | 79 | d_char *timeline_find(snac *snac, char *id); |
| 74 | int timeline_del(snac *snac, char *id); | 80 | int timeline_del(snac *snac, char *id); |
| 75 | d_char *timeline_get(snac *snac, char *fn); | 81 | d_char *timeline_get(snac *snac, char *fn); |
| 76 | d_char *timeline_list(snac *snac, int max); | 82 | d_char *timeline_list(snac *snac, const char *idx_name, int max); |
| 77 | int timeline_add(snac *snac, char *id, char *o_msg, char *parent, char *referrer); | 83 | int timeline_add(snac *snac, char *id, char *o_msg, char *parent, char *referrer); |
| 78 | void timeline_admire(snac *snac, char *id, char *admirer, int like); | 84 | void timeline_admire(snac *snac, char *o_msg, char *id, char *admirer, int like); |
| 79 | 85 | ||
| 80 | d_char *timeline_top_level(snac *snac, d_char *list); | 86 | d_char *timeline_top_level(d_char *list); |
| 81 | 87 | ||
| 82 | d_char *local_list(snac *snac, int max); | 88 | d_char *local_list(snac *snac, int max); |
| 83 | 89 | ||