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.

This commit is contained in:
Stefano Marinelli 2024-01-12 09:54:14 +01:00
parent adf5623044
commit 2af9481837
5 changed files with 89 additions and 1 deletions

View file

@ -800,8 +800,23 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
objid = actor; objid = actor;
notify_add(snac, type, utype, actor, objid != NULL ? objid : id); notify_add(snac, type, utype, actor, objid != NULL ? objid : id);
}
/* ntfy */
char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
if (!xs_is_null(ntfy_server) && *ntfy_server )
enqueue_ntfy(body, ntfy_server, ntfy_token);
/* finally, store it in the notification folder */
if (strcmp(type, "Follow") == 0)
objid = id;
else
if (strcmp(utype, "Follow") == 0)
objid = actor;
notify_add(snac, type, utype, actor, objid != NULL ? objid : id);
}
/** messages **/ /** messages **/
@ -2133,6 +2148,31 @@ void process_queue_item(xs_dict *q_item)
srv_debug(0, xs_fmt("telegram post %d", status)); srv_debug(0, xs_fmt("telegram post %d", status));
} }
else else
if (strcmp(type, "ntfy") == 0) {
/* send this via ntfy */
char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
char *msg = xs_dict_get(q_item, "message");
char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
int status = 0;
xs *url = xs_fmt("%s", ntfy_server);
//xs *body = xs_fmt("\"text\":\"%s\"}", msg);
xs *body = xs_fmt("%s", msg);
xs *headers = xs_dict_new();
headers = xs_dict_append(headers, "content-type", "text/plain");
// Append the Authorization header only if ntfy_token is not NULL
if (ntfy_token != NULL) {
headers = xs_dict_append(headers, "Authorization", xs_fmt("Bearer %s", ntfy_token));
}
xs *rsp = xs_http_request("POST", url, headers,
body, strlen(body), &status, NULL, NULL, 0);
rsp = xs_free(rsp);
srv_debug(0, xs_fmt("ntfy post %d", status));
}
else
if (strcmp(type, "purge") == 0) { if (strcmp(type, "purge") == 0) {
srv_log(xs_dup("purge start")); srv_log(xs_dup("purge start"));

15
data.c
View file

@ -2232,6 +2232,21 @@ void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id)
srv_debug(1, xs_fmt("enqueue_telegram %s %s", bot, chat_id)); srv_debug(1, xs_fmt("enqueue_telegram %s %s", bot, chat_id));
} }
void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token)
/* enqueues a message to be sent via ntfy */
{
xs *qmsg = _new_qmsg("ntfy", msg, 0);
char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server);
qmsg = xs_dict_append(qmsg, "ntfy_token", ntfy_token);
qmsg = _enqueue_put(fn, qmsg);
srv_debug(1, xs_fmt("enqueue_ntfy %s %s", ntfy_server, ntfy_token));
}
void enqueue_message(snac *snac, const xs_dict *msg) void enqueue_message(snac *snac, const xs_dict *msg)
/* enqueues an output message */ /* enqueues an output message */

View file

@ -93,6 +93,12 @@ a Telegram channel and a bot for this; the process is rather
cumbersome but it's documented everywhere. The Bot API key cumbersome but it's documented everywhere. The Bot API key
is a long string of alphanumeric characters and the chat id is a long string of alphanumeric characters and the chat id
is a big, negative number. is a big, negative number.
.It ntfy notifications
To enable notifications via ntfy (both self-hosted or
standard ntfy.sh server), fill the two provided
fields (ntfy server/topic and, if protected, the token).
You need to refer to the https://ntfy.sh web site for
more information on this process.
.It Maximum days to keep posts .It Maximum days to keep posts
This numeric value specifies the number of days to pass before This numeric value specifies the number of days to pass before
posts (yours and others') will be purged. This value overrides posts (yours and others') will be purged. This value overrides

26
html.c
View file

@ -853,6 +853,14 @@ xs_html *html_top_controls(snac *snac)
if (xs_is_null(telegram_chat_id)) if (xs_is_null(telegram_chat_id))
telegram_chat_id = ""; telegram_chat_id = "";
char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
if (xs_is_null(ntfy_server))
ntfy_server = "";
char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
if (xs_is_null(ntfy_token))
ntfy_token = "";
char *purge_days = xs_dict_get(snac->config, "purge_days"); char *purge_days = xs_dict_get(snac->config, "purge_days");
if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER) if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER)
purge_days = (char *)xs_number_str(purge_days); purge_days = (char *)xs_number_str(purge_days);
@ -946,6 +954,20 @@ xs_html *html_top_controls(snac *snac)
xs_html_attr("name", "telegram_chat_id"), xs_html_attr("name", "telegram_chat_id"),
xs_html_attr("value", telegram_chat_id), xs_html_attr("value", telegram_chat_id),
xs_html_attr("placeholder", "Chat id"))), xs_html_attr("placeholder", "Chat id"))),
xs_html_tag("p",
xs_html_text(L("ntfy notifications (ntfy server and token):")),
xs_html_sctag("br", NULL),
xs_html_sctag("input",
xs_html_attr("type", "text"),
xs_html_attr("name", "ntfy_server"),
xs_html_attr("value", ntfy_server),
xs_html_attr("placeholder", "ntfy server - full URL (example: https://ntfy.sh/YourTopic)")),
xs_html_text(" "),
xs_html_sctag("input",
xs_html_attr("type", "text"),
xs_html_attr("name", "ntfy_token"),
xs_html_attr("value", ntfy_token),
xs_html_attr("placeholder", "ntfy token - if needed"))),
xs_html_tag("p", xs_html_tag("p",
xs_html_text(L("Maximum days to keep posts (0: server settings):")), xs_html_text(L("Maximum days to keep posts (0: server settings):")),
xs_html_sctag("br", NULL), xs_html_sctag("br", NULL),
@ -2890,6 +2912,10 @@ int html_post_handler(const xs_dict *req, const char *q_path,
snac.config = xs_dict_set(snac.config, "telegram_bot", v); snac.config = xs_dict_set(snac.config, "telegram_bot", v);
if ((v = xs_dict_get(p_vars, "telegram_chat_id")) != NULL) if ((v = xs_dict_get(p_vars, "telegram_chat_id")) != NULL)
snac.config = xs_dict_set(snac.config, "telegram_chat_id", v); snac.config = xs_dict_set(snac.config, "telegram_chat_id", v);
if ((v = xs_dict_get(p_vars, "ntfy_server")) != NULL)
snac.config = xs_dict_set(snac.config, "ntfy_server", v);
if ((v = xs_dict_get(p_vars, "ntfy_token")) != NULL)
snac.config = xs_dict_set(snac.config, "ntfy_token", v);
if ((v = xs_dict_get(p_vars, "purge_days")) != NULL) { if ((v = xs_dict_get(p_vars, "purge_days")) != NULL) {
xs *days = xs_number_new(atof(v)); xs *days = xs_number_new(atof(v));
snac.config = xs_dict_set(snac.config, "purge_days", days); snac.config = xs_dict_set(snac.config, "purge_days", days);

1
snac.h
View file

@ -204,6 +204,7 @@ void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_
void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries); void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries);
void enqueue_email(xs_str *msg, int retries); void enqueue_email(xs_str *msg, int retries);
void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id); void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id);
void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token);
void enqueue_message(snac *snac, const xs_dict *msg); void enqueue_message(snac *snac, const xs_dict *msg);
void enqueue_close_question(snac *user, const char *id, int end_secs); void enqueue_close_question(snac *user, const char *id, int end_secs);
void enqueue_request_replies(snac *user, const char *id); void enqueue_request_replies(snac *user, const char *id);