commit 2af9481

Stefano Marinelli  ·  2024-01-12 08:54:14 +0000 UTC
parent adf5623
Added support for ntfy notifications. You can configure either a self-hosted server or use the official ntfy.sh, and you have the option to use a private token to protect access and topics.
5 files changed,  +89, -1
M data.c
M html.c
M snac.h
+41, -1
 1@@ -800,8 +800,23 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
 2         objid = actor;
 3 
 4     notify_add(snac, type, utype, actor, objid != NULL ? objid : id);
 5-}
 6 
 7+    /* ntfy */
 8+    char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
 9+    char *ntfy_token  = xs_dict_get(snac->config, "ntfy_token");
10+
11+    if (!xs_is_null(ntfy_server) && *ntfy_server )
12+        enqueue_ntfy(body, ntfy_server, ntfy_token);
13+
14+    /* finally, store it in the notification folder */
15+    if (strcmp(type, "Follow") == 0)
16+        objid = id;
17+    else
18+    if (strcmp(utype, "Follow") == 0)
19+        objid = actor;
20+
21+    notify_add(snac, type, utype, actor, objid != NULL ? objid : id);
22+}
23 
24 /** messages **/
25 
26@@ -2133,6 +2148,31 @@ void process_queue_item(xs_dict *q_item)
27         srv_debug(0, xs_fmt("telegram post %d", status));
28     }
29     else
30+    if (strcmp(type, "ntfy") == 0) {
31+        /* send this via ntfy */
32+        char *ntfy_server   = xs_dict_get(q_item, "ntfy_server");
33+        char *msg   = xs_dict_get(q_item, "message");
34+        char *ntfy_token   = xs_dict_get(q_item, "ntfy_token");
35+        int status  = 0;
36+
37+        xs *url  = xs_fmt("%s", ntfy_server);
38+        //xs *body = xs_fmt("\"text\":\"%s\"}", msg);
39+        xs *body = xs_fmt("%s", msg);
40+
41+        xs *headers = xs_dict_new();
42+        headers = xs_dict_append(headers, "content-type", "text/plain");
43+        // Append the Authorization header only if ntfy_token is not NULL
44+         if (ntfy_token != NULL) {
45+             headers = xs_dict_append(headers, "Authorization", xs_fmt("Bearer %s", ntfy_token));
46+             }
47+
48+        xs *rsp = xs_http_request("POST", url, headers,
49+                                   body, strlen(body), &status, NULL, NULL, 0);
50+        rsp = xs_free(rsp);
51+
52+        srv_debug(0, xs_fmt("ntfy post %d", status));
53+    }
54+    else
55     if (strcmp(type, "purge") == 0) {
56         srv_log(xs_dup("purge start"));
57 
M data.c
+15, -0
 1@@ -2232,6 +2232,21 @@ void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id)
 2     srv_debug(1, xs_fmt("enqueue_telegram %s %s", bot, chat_id));
 3 }
 4 
 5+void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token)
 6+/* enqueues a message to be sent via ntfy */
 7+{
 8+    xs *qmsg   = _new_qmsg("ntfy", msg, 0);
 9+    char *ntid = xs_dict_get(qmsg, "ntid");
10+    xs *fn     = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
11+
12+    qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server);
13+    qmsg = xs_dict_append(qmsg, "ntfy_token",  ntfy_token);
14+
15+
16+    qmsg = _enqueue_put(fn, qmsg);
17+
18+    srv_debug(1, xs_fmt("enqueue_ntfy %s %s", ntfy_server, ntfy_token));
19+}
20 
21 void enqueue_message(snac *snac, const xs_dict *msg)
22 /* enqueues an output message */
+6, -0
 1@@ -93,6 +93,12 @@ a Telegram channel and a bot for this; the process is rather
 2 cumbersome but it's documented everywhere. The Bot API key
 3 is a long string of alphanumeric characters and the chat id
 4 is a big, negative number.
 5+.It ntfy notifications
 6+To enable notifications via ntfy (both self-hosted or
 7+standard ntfy.sh server), fill the two provided
 8+fields (ntfy server/topic and, if protected, the token).
 9+You need to refer to the https://ntfy.sh web site for
10+more information on this process.
11 .It Maximum days to keep posts
12 This numeric value specifies the number of days to pass before
13 posts (yours and others') will be purged. This value overrides
M html.c
+26, -0
 1@@ -853,6 +853,14 @@ xs_html *html_top_controls(snac *snac)
 2     if (xs_is_null(telegram_chat_id))
 3         telegram_chat_id = "";
 4 
 5+    char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
 6+    if (xs_is_null(ntfy_server))
 7+        ntfy_server = "";
 8+
 9+    char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
10+    if (xs_is_null(ntfy_token))
11+        ntfy_token = "";
12+
13     char *purge_days = xs_dict_get(snac->config, "purge_days");
14     if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER)
15         purge_days = (char *)xs_number_str(purge_days);
16@@ -946,6 +954,20 @@ xs_html *html_top_controls(snac *snac)
17                         xs_html_attr("name", "telegram_chat_id"),
18                         xs_html_attr("value", telegram_chat_id),
19                         xs_html_attr("placeholder", "Chat id"))),
20+                xs_html_tag("p",
21+                    xs_html_text(L("ntfy notifications (ntfy server and token):")),
22+                    xs_html_sctag("br", NULL),
23+                    xs_html_sctag("input",
24+                        xs_html_attr("type", "text"),
25+                        xs_html_attr("name", "ntfy_server"),
26+                        xs_html_attr("value", ntfy_server),
27+                        xs_html_attr("placeholder", "ntfy server - full URL (example: https://ntfy.sh/YourTopic)")),
28+                    xs_html_text(" "),
29+                    xs_html_sctag("input",
30+                        xs_html_attr("type", "text"),
31+                        xs_html_attr("name", "ntfy_token"),
32+                        xs_html_attr("value", ntfy_token),
33+                        xs_html_attr("placeholder", "ntfy token - if needed"))),
34                 xs_html_tag("p",
35                     xs_html_text(L("Maximum days to keep posts (0: server settings):")),
36                     xs_html_sctag("br", NULL),
37@@ -2890,6 +2912,10 @@ int html_post_handler(const xs_dict *req, const char *q_path,
38             snac.config = xs_dict_set(snac.config, "telegram_bot", v);
39         if ((v = xs_dict_get(p_vars, "telegram_chat_id")) != NULL)
40             snac.config = xs_dict_set(snac.config, "telegram_chat_id", v);
41+        if ((v = xs_dict_get(p_vars, "ntfy_server")) != NULL)
42+            snac.config = xs_dict_set(snac.config, "ntfy_server", v);
43+        if ((v = xs_dict_get(p_vars, "ntfy_token")) != NULL)
44+            snac.config = xs_dict_set(snac.config, "ntfy_token", v);
45         if ((v = xs_dict_get(p_vars, "purge_days")) != NULL) {
46             xs *days    = xs_number_new(atof(v));
47             snac.config = xs_dict_set(snac.config, "purge_days", days);
M snac.h
+1, -0
1@@ -204,6 +204,7 @@ void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_
2 void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries);
3 void enqueue_email(xs_str *msg, int retries);
4 void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id);
5+void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token);
6 void enqueue_message(snac *snac, const xs_dict *msg);
7 void enqueue_close_question(snac *user, const char *id, int end_secs);
8 void enqueue_request_replies(snac *user, const char *id);