diff options
| author | 2025-05-28 09:07:19 +0200 | |
|---|---|---|
| committer | 2025-05-28 09:07:19 +0200 | |
| commit | a1369b39c1bd3d2036af12368997648454ca5564 (patch) | |
| tree | fb18610c75bbda7b80b6726ebd80373fedd606c9 | |
| parent | Don't prepend a # before a hashtag that is really an URL. (diff) | |
| download | penes-snac2-a1369b39c1bd3d2036af12368997648454ca5564.tar.gz penes-snac2-a1369b39c1bd3d2036af12368997648454ca5564.tar.xz penes-snac2-a1369b39c1bd3d2036af12368997648454ca5564.zip | |
Activated hashtag RSS polling.
| -rw-r--r-- | activitypub.c | 4 | ||||
| -rw-r--r-- | html.c | 3 | ||||
| -rw-r--r-- | httpd.c | 42 | ||||
| -rw-r--r-- | rss.c | 9 | ||||
| -rw-r--r-- | snac.h | 2 |
5 files changed, 43 insertions, 17 deletions
diff --git a/activitypub.c b/activitypub.c index 0cc7bcb..2cffeac 100644 --- a/activitypub.c +++ b/activitypub.c | |||
| @@ -3050,6 +3050,10 @@ void process_queue_item(xs_dict *q_item) | |||
| 3050 | } | 3050 | } |
| 3051 | } | 3051 | } |
| 3052 | else | 3052 | else |
| 3053 | if (strcmp(type, "rss_poll") == 0) { | ||
| 3054 | rss_poll_hashtags(); | ||
| 3055 | } | ||
| 3056 | else | ||
| 3053 | srv_log(xs_fmt("unexpected q_item type '%s'", type)); | 3057 | srv_log(xs_fmt("unexpected q_item type '%s'", type)); |
| 3054 | } | 3058 | } |
| 3055 | 3059 | ||
| @@ -1601,7 +1601,8 @@ xs_html *html_top_controls(snac *user) | |||
| 1601 | xs_html_attr("name", "followed_hashtags"), | 1601 | xs_html_attr("name", "followed_hashtags"), |
| 1602 | xs_html_attr("cols", "40"), | 1602 | xs_html_attr("cols", "40"), |
| 1603 | xs_html_attr("rows", "4"), | 1603 | xs_html_attr("rows", "4"), |
| 1604 | xs_html_attr("placeholder", "#cats\n#windowfriday\n#classicalmusic"), | 1604 | xs_html_attr("placeholder", "#cats\n#windowfriday\n#classicalmusic\nhttps:/" |
| 1605 | "/mastodon.social/tags/dogs"), | ||
| 1605 | xs_html_text(followed_hashtags)), | 1606 | xs_html_text(followed_hashtags)), |
| 1606 | 1607 | ||
| 1607 | xs_html_tag("br", NULL), | 1608 | xs_html_tag("br", NULL), |
| @@ -705,34 +705,36 @@ static pthread_cond_t sleep_cond; | |||
| 705 | static void *background_thread(void *arg) | 705 | static void *background_thread(void *arg) |
| 706 | /* background thread (queue management and other things) */ | 706 | /* background thread (queue management and other things) */ |
| 707 | { | 707 | { |
| 708 | time_t purge_time; | 708 | time_t t, purge_time, rss_time; |
| 709 | 709 | ||
| 710 | (void)arg; | 710 | (void)arg; |
| 711 | 711 | ||
| 712 | t = time(NULL); | ||
| 713 | |||
| 712 | /* first purge time */ | 714 | /* first purge time */ |
| 713 | purge_time = time(NULL) + 10 * 60; | 715 | purge_time = t + 10 * 60; |
| 716 | |||
| 717 | /* first RSS polling time */ | ||
| 718 | rss_time = t + 15 * 60; | ||
| 714 | 719 | ||
| 715 | srv_log(xs_fmt("background thread started")); | 720 | srv_log(xs_fmt("background thread started")); |
| 716 | 721 | ||
| 717 | while (p_state->srv_running) { | 722 | while (p_state->srv_running) { |
| 718 | time_t t; | ||
| 719 | int cnt = 0; | 723 | int cnt = 0; |
| 720 | 724 | ||
| 721 | p_state->th_state[0] = THST_QUEUE; | 725 | p_state->th_state[0] = THST_QUEUE; |
| 722 | 726 | ||
| 723 | { | 727 | { |
| 724 | xs *list = user_list(); | 728 | xs *list = user_list(); |
| 725 | char *p; | ||
| 726 | const char *uid; | 729 | const char *uid; |
| 727 | 730 | ||
| 728 | /* process queues for all users */ | 731 | /* process queues for all users */ |
| 729 | p = list; | 732 | xs_list_foreach(list, uid) { |
| 730 | while (xs_list_iter(&p, &uid)) { | 733 | snac user; |
| 731 | snac snac; | ||
| 732 | 734 | ||
| 733 | if (user_open(&snac, uid)) { | 735 | if (user_open(&user, uid)) { |
| 734 | cnt += process_user_queue(&snac); | 736 | cnt += process_user_queue(&user); |
| 735 | user_free(&snac); | 737 | user_free(&user); |
| 736 | } | 738 | } |
| 737 | } | 739 | } |
| 738 | } | 740 | } |
| @@ -740,8 +742,10 @@ static void *background_thread(void *arg) | |||
| 740 | /* global queue */ | 742 | /* global queue */ |
| 741 | cnt += process_queue(); | 743 | cnt += process_queue(); |
| 742 | 744 | ||
| 745 | t = time(NULL); | ||
| 746 | |||
| 743 | /* time to purge? */ | 747 | /* time to purge? */ |
| 744 | if ((t = time(NULL)) > purge_time) { | 748 | if (t > purge_time) { |
| 745 | /* next purge time is tomorrow */ | 749 | /* next purge time is tomorrow */ |
| 746 | purge_time = t + 24 * 60 * 60; | 750 | purge_time = t + 24 * 60 * 60; |
| 747 | 751 | ||
| @@ -750,6 +754,22 @@ static void *background_thread(void *arg) | |||
| 750 | job_post(q_item, 0); | 754 | job_post(q_item, 0); |
| 751 | } | 755 | } |
| 752 | 756 | ||
| 757 | /* time to poll the RSS? */ | ||
| 758 | if (t > rss_time) { | ||
| 759 | /* next RSS poll time */ | ||
| 760 | int hours = xs_number_get(xs_dict_get_def(srv_config, "rss_poll_hours", "4")); | ||
| 761 | |||
| 762 | /* don't hammer servers too much */ | ||
| 763 | if (hours < 1) | ||
| 764 | hours = 1; | ||
| 765 | |||
| 766 | rss_time = t + 60 * 60 * hours; | ||
| 767 | |||
| 768 | xs *q_item = xs_dict_new(); | ||
| 769 | q_item = xs_dict_append(q_item, "type", "rss_poll"); | ||
| 770 | job_post(q_item, 0); | ||
| 771 | } | ||
| 772 | |||
| 753 | if (cnt == 0) { | 773 | if (cnt == 0) { |
| 754 | /* sleep 3 seconds */ | 774 | /* sleep 3 seconds */ |
| 755 | 775 | ||
| @@ -110,6 +110,9 @@ xs_str *rss_from_timeline(snac *user, const xs_list *timeline, | |||
| 110 | void rss_to_timeline(snac *user, const char *url) | 110 | void rss_to_timeline(snac *user, const char *url) |
| 111 | /* reads an RSS and inserts all ActivityPub posts into the user's timeline */ | 111 | /* reads an RSS and inserts all ActivityPub posts into the user's timeline */ |
| 112 | { | 112 | { |
| 113 | if (!xs_startswith(url, "https:/") && !xs_startswith(url, "http:/")) | ||
| 114 | return; | ||
| 115 | |||
| 113 | xs *hdrs = xs_dict_new(); | 116 | xs *hdrs = xs_dict_new(); |
| 114 | hdrs = xs_dict_set(hdrs, "accept", "application/rss+xml"); | 117 | hdrs = xs_dict_set(hdrs, "accept", "application/rss+xml"); |
| 115 | hdrs = xs_dict_set(hdrs, "user-agent", USER_AGENT); | 118 | hdrs = xs_dict_set(hdrs, "user-agent", USER_AGENT); |
| @@ -204,10 +207,9 @@ void rss_to_timeline(snac *user, const char *url) | |||
| 204 | } | 207 | } |
| 205 | 208 | ||
| 206 | 209 | ||
| 207 | void rss_process(void) | 210 | void rss_poll_hashtags(void) |
| 208 | /* parses all RSS from all users */ | 211 | /* parses all RSS from all users */ |
| 209 | { | 212 | { |
| 210 | #if 0 | ||
| 211 | xs *list = user_list(); | 213 | xs *list = user_list(); |
| 212 | const char *uid; | 214 | const char *uid; |
| 213 | 215 | ||
| @@ -215,7 +217,7 @@ void rss_process(void) | |||
| 215 | snac user; | 217 | snac user; |
| 216 | 218 | ||
| 217 | if (user_open(&user, uid)) { | 219 | if (user_open(&user, uid)) { |
| 218 | const xs_list *rss = xs_dict_get(user.config, "rss"); | 220 | const xs_list *rss = xs_dict_get(user.config, "followed_hashtags"); |
| 219 | 221 | ||
| 220 | if (xs_is_list(rss)) { | 222 | if (xs_is_list(rss)) { |
| 221 | const char *url; | 223 | const char *url; |
| @@ -227,5 +229,4 @@ void rss_process(void) | |||
| 227 | user_free(&user); | 229 | user_free(&user); |
| 228 | } | 230 | } |
| 229 | } | 231 | } |
| 230 | #endif | ||
| 231 | } | 232 | } |
| @@ -464,4 +464,4 @@ const char *lang_str(const char *str, const snac *user); | |||
| 464 | xs_str *rss_from_timeline(snac *user, const xs_list *timeline, | 464 | xs_str *rss_from_timeline(snac *user, const xs_list *timeline, |
| 465 | const char *title, const char *link, const char *desc); | 465 | const char *title, const char *link, const char *desc); |
| 466 | void rss_to_timeline(snac *user, const char *url); | 466 | void rss_to_timeline(snac *user, const char *url); |
| 467 | void rss_process(void); | 467 | void rss_poll_hashtags(void); |