diff options
Diffstat (limited to 'utils.c')
| -rw-r--r-- | utils.c | 74 |
1 files changed, 73 insertions, 1 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 | #include "xs.h" | 4 | #include "xs.h" |
| 5 | #include "xs_io.h" | 5 | #include "xs_io.h" |
| @@ -11,6 +11,8 @@ | |||
| 11 | #include "xs_curl.h" | 11 | #include "xs_curl.h" |
| 12 | #include "xs_regex.h" | 12 | #include "xs_regex.h" |
| 13 | #include "xs_http.h" | 13 | #include "xs_http.h" |
| 14 | #include "xs_list_tools.h" | ||
| 15 | #include "xs_set.h" | ||
| 14 | 16 | ||
| 15 | #include "snac.h" | 17 | #include "snac.h" |
| 16 | 18 | ||
| @@ -1002,6 +1004,76 @@ void import_csv(snac *user) | |||
| 1002 | snac_log(user, xs_fmt("Cannot open file %s", fn)); | 1004 | snac_log(user, xs_fmt("Cannot open file %s", fn)); |
| 1003 | } | 1005 | } |
| 1004 | 1006 | ||
| 1007 | |||
| 1008 | static int top_ten_sort(const void *v1, const void *v2) | ||
| 1009 | { | ||
| 1010 | const xs_list *l1 = *(const xs_list **)v1; | ||
| 1011 | const xs_list *l2 = *(const xs_list **)v2; | ||
| 1012 | |||
| 1013 | const char *c1 = xs_list_get(l1, 3); | ||
| 1014 | const char *c2 = xs_list_get(l2, 3); | ||
| 1015 | |||
| 1016 | return xs_cmp(c2, c1); | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | |||
| 1020 | xs_list *user_top_ten(snac *user, int count) | ||
| 1021 | /* returns the top ten more popular posts by a user */ | ||
| 1022 | { | ||
| 1023 | xs *idx = xs_fmt("%s/private.idx", user->basedir); | ||
| 1024 | xs *list = index_list(idx, XS_ALL); | ||
| 1025 | xs *u_list = xs_list_new(); | ||
| 1026 | xs_set u; | ||
| 1027 | |||
| 1028 | xs_set_init(&u); | ||
| 1029 | |||
| 1030 | const char *md5; | ||
| 1031 | |||
| 1032 | xs_list_foreach(list, md5) { | ||
| 1033 | xs *obj = NULL; | ||
| 1034 | |||
| 1035 | if (!valid_status(object_get_by_md5(md5, &obj))) | ||
| 1036 | continue; | ||
| 1037 | |||
| 1038 | const char *id = xs_dict_get_def(obj, "id", "-"); | ||
| 1039 | |||
| 1040 | if (!is_msg_mine(user, id)) | ||
| 1041 | continue; | ||
| 1042 | |||
| 1043 | if (xs_set_add(&u, id) != 1) | ||
| 1044 | continue; | ||
| 1045 | |||
| 1046 | /* get metrics */ | ||
| 1047 | int ls = object_likes_len(id); | ||
| 1048 | int as = object_announces_len(id); | ||
| 1049 | |||
| 1050 | /* build the entry and convert to list */ | ||
| 1051 | xs *s = xs_fmt("%s\t%d\t%d\t%010d", id, ls, as, ls + as); | ||
| 1052 | xs *l = xs_split(s, "\t"); | ||
| 1053 | |||
| 1054 | u_list = xs_list_append(u_list, l); | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | /* sort by the sum of likes and boosts */ | ||
| 1058 | xs *s_list = xs_list_sort(u_list, top_ten_sort); | ||
| 1059 | |||
| 1060 | xs_list *r = xs_list_new(); | ||
| 1061 | const xs_list *i; | ||
| 1062 | |||
| 1063 | xs_list_foreach(s_list, i) { | ||
| 1064 | r = xs_list_append(r, i); | ||
| 1065 | |||
| 1066 | if (--count <= 0) | ||
| 1067 | break; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | xs_set_free(&u); | ||
| 1071 | |||
| 1072 | return r; | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | |||
| 1076 | |||
| 1005 | static const struct { | 1077 | static const struct { |
| 1006 | const char *proto; | 1078 | const char *proto; |
| 1007 | unsigned short default_port; | 1079 | unsigned short default_port; |