commit 99375a7
grunfink
·
2026-01-10 20:29:32 +0000 UTC
parent fdd2217
New command-line option top_ten.
5 files changed,
+102,
-9
M
Makefile
+4,
-4
1@@ -46,7 +46,7 @@ update-po:
2 xgettext --omit-header -j -o $$a --language=C --keyword=L --from-code=utf-8 *.c ; \
3 done
4
5-activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_mime.h \
6+activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_url.h xs_mime.h \
7 xs_openssl.h xs_regex.h xs_time.h xs_set.h xs_match.h xs_unicode.h \
8 xs_webmention.h xs_http.h xs_http_codes.h snac.h
9 data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \
10@@ -68,16 +68,16 @@ mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \
11 xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \
12 xs_unicode.h xs_http.h xs_http_codes.h snac.h
13 rss.o: rss.c xs.h xs_html.h xs_regex.h xs_time.h xs_match.h xs_curl.h \
14- xs_openssl.h xs_json.h xs_http.h xs_http_codes.h snac.h
15+ xs_openssl.h xs_json.h xs_http.h xs_http_codes.h xs_unicode.h snac.h
16 sandbox.o: sandbox.c xs.h snac.h
17 snac.o: snac.c xs.h xs_hex.h xs_io.h xs_unicode_tbl.h xs_unicode.h \
18 xs_json.h xs_curl.h xs_openssl.h xs_socket.h xs_unix_socket.h xs_url.h \
19 xs_http.h xs_http_codes.h xs_httpd.h xs_mime.h xs_regex.h xs_set.h \
20 xs_time.h xs_glob.h xs_random.h xs_match.h xs_fcgi.h xs_html.h xs_po.h \
21- xs_webmention.h snac.h
22+ xs_webmention.h xs_list_tools.h snac.h
23 upgrade.o: upgrade.c xs.h xs_io.h xs_json.h xs_glob.h snac.h
24 utils.o: utils.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h \
25 xs_random.h xs_glob.h xs_curl.h xs_regex.h xs_http.h xs_http_codes.h \
26- snac.h
27+ xs_list_tools.h xs_set.h snac.h
28 webfinger.o: webfinger.c xs.h xs_json.h xs_curl.h xs_mime.h xs_http.h \
29 xs_http_codes.h snac.h
+4,
-4
1@@ -35,7 +35,7 @@ uninstall:
2 rm $(PREFIX_MAN)/man5/snac.5
3 rm $(PREFIX_MAN)/man8/snac.8
4
5-activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_mime.h \
6+activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_url.h xs_mime.h \
7 xs_openssl.h xs_regex.h xs_time.h xs_set.h xs_match.h xs_unicode.h \
8 xs_webmention.h xs_http.h xs_http_codes.h snac.h
9 data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \
10@@ -57,16 +57,16 @@ mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \
11 xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \
12 xs_unicode.h xs_http.h xs_http_codes.h snac.h
13 rss.o: rss.c xs.h xs_html.h xs_regex.h xs_time.h xs_match.h xs_curl.h \
14- xs_openssl.h xs_json.h xs_http.h xs_http_codes.h snac.h
15+ xs_openssl.h xs_json.h xs_http.h xs_http_codes.h xs_unicode.h snac.h
16 sandbox.o: sandbox.c xs.h snac.h
17 snac.o: snac.c xs.h xs_hex.h xs_io.h xs_unicode_tbl.h xs_unicode.h \
18 xs_json.h xs_curl.h xs_openssl.h xs_socket.h xs_unix_socket.h xs_url.h \
19 xs_http.h xs_http_codes.h xs_httpd.h xs_mime.h xs_regex.h xs_set.h \
20 xs_time.h xs_glob.h xs_random.h xs_match.h xs_fcgi.h xs_html.h xs_po.h \
21- xs_webmention.h snac.h
22+ xs_webmention.h xs_list_tools.h snac.h
23 upgrade.o: upgrade.c xs.h xs_io.h xs_json.h xs_glob.h snac.h
24 utils.o: utils.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h \
25 xs_random.h xs_glob.h xs_curl.h xs_regex.h xs_http.h xs_http_codes.h \
26- snac.h
27+ xs_list_tools.h xs_set.h snac.h
28 webfinger.o: webfinger.c xs.h xs_json.h xs_curl.h xs_mime.h xs_http.h \
29 xs_http_codes.h snac.h
M
main.c
+20,
-1
1@@ -76,7 +76,8 @@ int usage(const char *cmd)
2 "list_create {basedir} {uid} {name} Creates a new list\n"
3 "list_remove {basedir} {uid} {name} Removes an existing list\n"
4 "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n"
5- "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n";
6+ "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"
7+ "top_ten {basedir} {uid} [{N}] Prints the most popular posts\n";
8
9 if (cmd == NULL)
10 printf("%s", cmds);
11@@ -350,6 +351,24 @@ int main(int argc, char *argv[])
12 return 0;
13 }
14
15+ if (strcmp(cmd, "top_ten") == 0) { /** **/
16+ int count = 10;
17+ const char *n = GET_ARGV();
18+ if (xs_is_string(n))
19+ count = atoi(n);
20+
21+ xs *l = user_top_ten(&snac, count);
22+ const xs_list *i;
23+
24+ xs_list_foreach(l, i) {
25+ printf("%s %ld★ %ld↺\n", xs_list_get(i, 0),
26+ xs_number_get_l(xs_list_get(i, 1)),
27+ xs_number_get_l(xs_list_get(i, 2)));
28+ }
29+
30+ return 0;
31+ }
32+
33 if ((url = GET_ARGV()) == NULL)
34 return usage(cmd);
35
M
snac.h
+2,
-0
1@@ -494,3 +494,5 @@ void rss_to_timeline(snac *user, const char *url);
2 void rss_poll_hashtags(void);
3
4 void data_fsck(void);
5+
6+xs_list *user_top_ten(snac *user, int count);
M
utils.c
+72,
-0
1@@ -11,6 +11,8 @@
2 #include "xs_curl.h"
3 #include "xs_regex.h"
4 #include "xs_http.h"
5+#include "xs_list_tools.h"
6+#include "xs_set.h"
7
8 #include "snac.h"
9
10@@ -1002,6 +1004,76 @@ void import_csv(snac *user)
11 snac_log(user, xs_fmt("Cannot open file %s", fn));
12 }
13
14+
15+static int top_ten_sort(const void *v1, const void *v2)
16+{
17+ const xs_list *l1 = *(const xs_list **)v1;
18+ const xs_list *l2 = *(const xs_list **)v2;
19+
20+ const char *c1 = xs_list_get(l1, 3);
21+ const char *c2 = xs_list_get(l2, 3);
22+
23+ return xs_cmp(c2, c1);
24+}
25+
26+
27+xs_list *user_top_ten(snac *user, int count)
28+/* returns the top ten more popular posts by a user */
29+{
30+ xs *idx = xs_fmt("%s/private.idx", user->basedir);
31+ xs *list = index_list(idx, XS_ALL);
32+ xs *u_list = xs_list_new();
33+ xs_set u;
34+
35+ xs_set_init(&u);
36+
37+ const char *md5;
38+
39+ xs_list_foreach(list, md5) {
40+ xs *obj = NULL;
41+
42+ if (!valid_status(object_get_by_md5(md5, &obj)))
43+ continue;
44+
45+ const char *id = xs_dict_get_def(obj, "id", "-");
46+
47+ if (!is_msg_mine(user, id))
48+ continue;
49+
50+ if (xs_set_add(&u, id) != 1)
51+ continue;
52+
53+ /* get metrics */
54+ int ls = object_likes_len(id);
55+ int as = object_announces_len(id);
56+
57+ /* build the entry and convert to list */
58+ xs *s = xs_fmt("%s\t%d\t%d\t%010d", id, ls, as, ls + as);
59+ xs *l = xs_split(s, "\t");
60+
61+ u_list = xs_list_append(u_list, l);
62+ }
63+
64+ /* sort by the sum of likes and boosts */
65+ xs *s_list = xs_list_sort(u_list, top_ten_sort);
66+
67+ xs_list *r = xs_list_new();
68+ const xs_list *i;
69+
70+ xs_list_foreach(s_list, i) {
71+ r = xs_list_append(r, i);
72+
73+ if (--count <= 0)
74+ break;
75+ }
76+
77+ xs_set_free(&u);
78+
79+ return r;
80+}
81+
82+
83+
84 static const struct {
85 const char *proto;
86 unsigned short default_port;