commit 97ff66116b7633066375bbc6cc88be5b8587453b
parent 859de583d9b575a830bab92a6379f77c70910a93
Author: grunfink <grunfink@comam.es>
Date: Wed, 28 May 2025 07:48:47 +0200
New file rss.c.
Diffstat:
M | Makefile | | | 9 | +++++---- |
M | Makefile.NetBSD | | | 9 | +++++---- |
M | html.c | | | 97 | ------------------------------------------------------------------------------- |
A | rss.c | | | 105 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | snac.h | | | 5 | +++-- |
5 files changed, 118 insertions(+), 107 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,7 +5,7 @@ CFLAGS?=-g -Wall -Wextra -pedantic
all: snac
snac: snac.o main.o sandbox.o data.o http.o httpd.o webfinger.o \
- activitypub.o html.o utils.o format.o upgrade.o mastoapi.o
+ activitypub.o html.o utils.o format.o upgrade.o mastoapi.o rss.o
$(CC) $(CFLAGS) -L$(PREFIX)/lib *.o -lcurl -lcrypto $(LDFLAGS) -pthread -o $@
test: tests/smtp
@@ -48,12 +48,12 @@ update-po:
activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_mime.h \
xs_openssl.h xs_regex.h xs_time.h xs_set.h xs_match.h xs_unicode.h \
- snac.h http_codes.h
+ xs_webmention.h snac.h http_codes.h
data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \
xs_set.h xs_time.h xs_regex.h xs_match.h xs_unicode.h xs_random.h \
xs_po.h snac.h http_codes.h
format.o: format.c xs.h xs_regex.h xs_mime.h xs_html.h xs_json.h \
- xs_time.h xs_match.h snac.h http_codes.h
+ xs_time.h xs_match.h xs_unicode.h snac.h http_codes.h
html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \
xs_time.h xs_mime.h xs_match.h xs_html.h xs_curl.h xs_unicode.h xs_url.h \
xs_random.h snac.h http_codes.h
@@ -66,7 +66,8 @@ main.o: main.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h xs_match.h \
snac.h http_codes.h
mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \
xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \
- snac.h http_codes.h
+ xs_unicode.h snac.h http_codes.h
+rss.o: rss.c xs.h xs_html.h xs_regex.h xs_time.h snac.h http_codes.h
sandbox.o: sandbox.c xs.h snac.h http_codes.h
snac.o: snac.c xs.h xs_hex.h xs_io.h xs_unicode_tbl.h xs_unicode.h \
xs_json.h xs_curl.h xs_openssl.h xs_socket.h xs_unix_socket.h xs_url.h \
diff --git a/Makefile.NetBSD b/Makefile.NetBSD
@@ -6,7 +6,7 @@ LDFLAGS=-lrt
all: snac
snac: snac.o main.o sandbox.o data.o http.o httpd.o webfinger.o \
- activitypub.o html.o utils.o format.o upgrade.o mastoapi.o
+ activitypub.o html.o utils.o format.o upgrade.o mastoapi.o rss.o
$(CC) $(CFLAGS) -L/usr/pkg/lib *.o -lcurl -lcrypto -pthread $(LDFLAGS) -Wl,-rpath,/usr/lib -Wl,-rpath,/usr/pkg/lib -o $@
@@ -37,12 +37,12 @@ uninstall:
activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_mime.h \
xs_openssl.h xs_regex.h xs_time.h xs_set.h xs_match.h xs_unicode.h \
- snac.h http_codes.h
+ xs_webmention.h snac.h http_codes.h
data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \
xs_set.h xs_time.h xs_regex.h xs_match.h xs_unicode.h xs_random.h \
xs_po.h snac.h http_codes.h
format.o: format.c xs.h xs_regex.h xs_mime.h xs_html.h xs_json.h \
- xs_time.h xs_match.h snac.h http_codes.h
+ xs_time.h xs_match.h xs_unicode.h snac.h http_codes.h
html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \
xs_time.h xs_mime.h xs_match.h xs_html.h xs_curl.h xs_unicode.h xs_url.h \
xs_random.h snac.h http_codes.h
@@ -55,7 +55,8 @@ main.o: main.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h xs_match.h \
snac.h http_codes.h
mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \
xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \
- snac.h http_codes.h
+ xs_unicode.h snac.h http_codes.h
+rss.o: rss.c xs.h xs_html.h xs_regex.h xs_time.h snac.h http_codes.h
sandbox.o: sandbox.c xs.h snac.h http_codes.h
snac.o: snac.c xs.h xs_hex.h xs_io.h xs_unicode_tbl.h xs_unicode.h \
xs_json.h xs_curl.h xs_openssl.h xs_socket.h xs_unix_socket.h xs_url.h \
diff --git a/html.c b/html.c
@@ -5020,100 +5020,3 @@ int html_post_handler(const xs_dict *req, const char *q_path,
return status;
}
-
-
-xs_str *rss_from_timeline(snac *user, const xs_list *timeline,
- const char *title, const char *link, const char *desc)
-/* converts a timeline to rss */
-{
- xs_html *rss = xs_html_tag("rss",
- xs_html_attr("xmlns:content", "http:/" "/purl.org/rss/1.0/modules/content/"),
- xs_html_attr("version", "2.0"),
- xs_html_attr("xmlns:atom", "http:/" "/www.w3.org/2005/Atom"));
-
- xs_html *channel = xs_html_tag("channel",
- xs_html_tag("title",
- xs_html_text(title)),
- xs_html_tag("language",
- xs_html_text("en")),
- xs_html_tag("link",
- xs_html_text(link)),
- xs_html_sctag("atom:link",
- xs_html_attr("href", link),
- xs_html_attr("rel", "self"),
- xs_html_attr("type", "application/rss+xml")),
- xs_html_tag("generator",
- xs_html_text(USER_AGENT)),
- xs_html_tag("description",
- xs_html_text(desc)));
-
- xs_html_add(rss, channel);
-
- int cnt = 0;
- const char *v;
-
- xs_list_foreach(timeline, v) {
- xs *msg = NULL;
-
- if (user) {
- if (!valid_status(timeline_get_by_md5(user, v, &msg)))
- continue;
- }
- else {
- if (!valid_status(object_get_by_md5(v, &msg)))
- continue;
- }
-
- const char *id = xs_dict_get(msg, "id");
- const char *content = xs_dict_get(msg, "content");
- const char *published = xs_dict_get(msg, "published");
-
- if (user && !xs_startswith(id, user->actor))
- continue;
-
- if (!id || !content || !published)
- continue;
-
- /* create a title with the first line of the content */
- xs *title = xs_replace(content, "<br>", "\n");
- title = xs_regex_replace_i(title, "<[^>]+>", " ");
- title = xs_regex_replace_i(title, "&[^;]+;", " ");
- int i;
-
- for (i = 0; title[i] && title[i] != '\n' && i < 50; i++);
-
- if (title[i] != '\0') {
- title[i] = '\0';
- title = xs_str_cat(title, "...");
- }
-
- title = xs_strip_i(title);
-
- /* convert the date */
- time_t t = xs_parse_iso_date(published, 0);
- xs *rss_date = xs_str_utctime(t, "%a, %d %b %Y %T +0000");
-
- /* if it's the first one, add it to the header */
- if (cnt == 0)
- xs_html_add(channel,
- xs_html_tag("lastBuildDate",
- xs_html_text(rss_date)));
-
- xs_html_add(channel,
- xs_html_tag("item",
- xs_html_tag("title",
- xs_html_text(title)),
- xs_html_tag("link",
- xs_html_text(id)),
- xs_html_tag("guid",
- xs_html_text(id)),
- xs_html_tag("pubDate",
- xs_html_text(rss_date)),
- xs_html_tag("description",
- xs_html_text(content))));
-
- cnt++;
- }
-
- return xs_html_render_s(rss, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-}
diff --git a/rss.c b/rss.c
@@ -0,0 +1,105 @@
+/* snac - A simple, minimalistic ActivityPub instance */
+/* copyright (c) 2025 grunfink et al. / MIT license */
+
+#include "xs.h"
+#include "xs_html.h"
+#include "xs_regex.h"
+#include "xs_time.h"
+
+#include "snac.h"
+
+xs_str *rss_from_timeline(snac *user, const xs_list *timeline,
+ const char *title, const char *link, const char *desc)
+/* converts a timeline to rss */
+{
+ xs_html *rss = xs_html_tag("rss",
+ xs_html_attr("xmlns:content", "http:/" "/purl.org/rss/1.0/modules/content/"),
+ xs_html_attr("version", "2.0"),
+ xs_html_attr("xmlns:atom", "http:/" "/www.w3.org/2005/Atom"));
+
+ xs_html *channel = xs_html_tag("channel",
+ xs_html_tag("title",
+ xs_html_text(title)),
+ xs_html_tag("language",
+ xs_html_text("en")),
+ xs_html_tag("link",
+ xs_html_text(link)),
+ xs_html_sctag("atom:link",
+ xs_html_attr("href", link),
+ xs_html_attr("rel", "self"),
+ xs_html_attr("type", "application/rss+xml")),
+ xs_html_tag("generator",
+ xs_html_text(USER_AGENT)),
+ xs_html_tag("description",
+ xs_html_text(desc)));
+
+ xs_html_add(rss, channel);
+
+ int cnt = 0;
+ const char *v;
+
+ xs_list_foreach(timeline, v) {
+ xs *msg = NULL;
+
+ if (user) {
+ if (!valid_status(timeline_get_by_md5(user, v, &msg)))
+ continue;
+ }
+ else {
+ if (!valid_status(object_get_by_md5(v, &msg)))
+ continue;
+ }
+
+ const char *id = xs_dict_get(msg, "id");
+ const char *content = xs_dict_get(msg, "content");
+ const char *published = xs_dict_get(msg, "published");
+
+ if (user && !xs_startswith(id, user->actor))
+ continue;
+
+ if (!id || !content || !published)
+ continue;
+
+ /* create a title with the first line of the content */
+ xs *title = xs_replace(content, "<br>", "\n");
+ title = xs_regex_replace_i(title, "<[^>]+>", " ");
+ title = xs_regex_replace_i(title, "&[^;]+;", " ");
+ int i;
+
+ for (i = 0; title[i] && title[i] != '\n' && i < 50; i++);
+
+ if (title[i] != '\0') {
+ title[i] = '\0';
+ title = xs_str_cat(title, "...");
+ }
+
+ title = xs_strip_i(title);
+
+ /* convert the date */
+ time_t t = xs_parse_iso_date(published, 0);
+ xs *rss_date = xs_str_utctime(t, "%a, %d %b %Y %T +0000");
+
+ /* if it's the first one, add it to the header */
+ if (cnt == 0)
+ xs_html_add(channel,
+ xs_html_tag("lastBuildDate",
+ xs_html_text(rss_date)));
+
+ xs_html_add(channel,
+ xs_html_tag("item",
+ xs_html_tag("title",
+ xs_html_text(title)),
+ xs_html_tag("link",
+ xs_html_text(id)),
+ xs_html_tag("guid",
+ xs_html_text(id)),
+ xs_html_tag("pubDate",
+ xs_html_text(rss_date)),
+ xs_html_tag("description",
+ xs_html_text(content))));
+
+ cnt++;
+ }
+
+ return xs_html_render_s(rss, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+}
diff --git a/snac.h b/snac.h
@@ -395,8 +395,6 @@ int html_get_handler(const xs_dict *req, const char *q_path,
int html_post_handler(const xs_dict *req, const char *q_path,
char *payload, int p_size,
char **body, int *b_size, char **ctype);
-xs_str *rss_from_timeline(snac *user, const xs_list *timeline,
- const char *title, const char *link, const char *desc);
int write_default_css(void);
int snac_init(const char *_basedir);
@@ -462,3 +460,6 @@ int badlogin_check(const char *user, const char *addr);
void badlogin_inc(const char *user, const char *addr);
const char *lang_str(const char *str, const snac *user);
+
+xs_str *rss_from_timeline(snac *user, const xs_list *timeline,
+ const char *title, const char *link, const char *desc);