diff --git a/alertik.h b/alertik.h index 9575df6..9193b0f 100644 --- a/alertik.h +++ b/alertik.h @@ -12,6 +12,5 @@ extern char *get_formatted_time(time_t time, char *time_str); extern void log_msg(const char *fmt, ...); - extern int send_telegram_notification(const char *msg); #endif /* ALERTIK_H */ diff --git a/notifiers.c b/notifiers.c index c5c054b..cf78f77 100644 --- a/notifiers.c +++ b/notifiers.c @@ -50,15 +50,14 @@ int is_within_notify_threshold(void) { * * @param hnd CURL handle. * @param url Request URL. - * @return Returns CURLE_OK if successful, otherwise a CURLcode error. + * @return Returns 0. */ -static void setopts_get_curl(CURL *hnd, const char *url) +static int setopts_get_curl(CURL *hnd, const char *url) { curl_easy_setopt(hnd, CURLOPT_URL, url); curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(hnd, CURLOPT_USERAGENT, CURL_USER_AGENT); curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 3L); - curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, libcurl_noop_cb); #ifdef CURL_VERBOSE curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); @@ -66,14 +65,16 @@ static void setopts_get_curl(CURL *hnd, const char *url) #ifndef VALIDATE_CERTS curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); #endif + return 0; } /** * */ -static void do_curl_cleanup(CURL *hnd, char *escape) +static void do_curl_cleanup(CURL *hnd, char *escape, struct curl_slist *slist) { curl_free(escape); + curl_slist_free_all(slist); if (hnd) curl_easy_cleanup(hnd); } @@ -81,7 +82,7 @@ static void do_curl_cleanup(CURL *hnd, char *escape) /** * */ -static CURLcode do_curl(CURL *hnd, char *escape) +static CURLcode do_curl(CURL *hnd, char *escape, struct curl_slist *slist) { CURLcode ret_curl = !CURLE_OK; @@ -97,7 +98,7 @@ static CURLcode do_curl(CURL *hnd, char *escape) ret_curl = CURLE_OK; error: - do_curl_cleanup(hnd, escape); + do_curl_cleanup(hnd, escape, slist); return ret_curl; } @@ -105,17 +106,80 @@ error: * @brief Initializes and configures the CURL handle for sending a POST * request with a JSON payload. * - * @param hnd CURL handle. - * @param url Request URL. - * @param payload Payload data in JSON format. + * @param hnd CURL handle. + * @param url Request URL. + * @param json_payload Payload data in JSON format. * - * @return Returns CURLE_OK if successful, otherwise a CURLcode error. + * @return Returns 0 if successful, 1 otherwise. */ -static void setopts_post_json_curl(CURL *hnd, const char *url, - const char *payload) +static int setopts_post_json_curl(CURL *hnd, const char *url, + const char *json_payload, struct curl_slist **slist) { + struct curl_slist *s = *slist; + + s = NULL; + s = curl_slist_append(s, "Content-Type: application/json"); + s = curl_slist_append(s, "Accept: application/json"); + if (!s) { + *slist = s; + return 1; + } + + curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, s); + curl_easy_setopt(hnd, CURLOPT_URL, url); + curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(hnd, CURLOPT_USERAGENT, CURL_USER_AGENT); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 3L); + curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, libcurl_noop_cb); +#ifdef CURL_VERBOSE + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); +#endif +#ifndef VALIDATE_CERTS + curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); +#endif + curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, json_payload); + *slist = s; + return 0; } +/** + * + */ +static int send_generic_webhook(const char *url, const char *text) +{ + CURL *hnd = NULL; + struct curl_slist *s = NULL; + char payload_data[4096] = {0}; + + if (!(hnd = curl_easy_init())) { + log_msg("Failed to initialize libcurl!\n"); + return 1; + } + + snprintf( + payload_data, + sizeof payload_data - 1, + "{\"text\":\"%s\"}", + text + ); + + + #if 0 + TODO: + - escape "" in the payload, otherwise it will silently + escape from the {"text": } + - think about the return code from the request and + emmit some message if not 200 + #endif + + if (setopts_post_json_curl(hnd, url, payload_data, &s)) + return 1; + + log_msg("> Sending notification!\n"); + return do_curl(hnd, NULL, s); +} + + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////// TELEGRAM ////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -143,7 +207,7 @@ void setup_telegram(void) setup = 1; } -int send_telegram_notification(const char *msg) +static int send_telegram_notification(const char *msg) { char full_request_url[4096] = {0}; char *escaped_msg = NULL; @@ -157,7 +221,7 @@ int send_telegram_notification(const char *msg) escaped_msg = curl_easy_escape(hnd, msg, 0); if (!escaped_msg) { log_msg("> Unable to escape notification message...\n"); - do_curl_cleanup(hnd, escaped_msg); + do_curl_cleanup(hnd, escaped_msg, NULL); } snprintf( @@ -167,11 +231,36 @@ int send_telegram_notification(const char *msg) telegram_bot_token, telegram_chat_id, escaped_msg); setopts_get_curl(hnd, full_request_url); - log_msg("> Sending notification!\n"); - - return do_curl(hnd, escaped_msg); + return do_curl(hnd, escaped_msg, NULL); } + +//////////////////////////////////////////////////////////////////////////////// +////////////////////////////////// SLACK /////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/* Slack settings. */ +static char *slack_webhook_url; + +void setup_slack(void) +{ + static int setup = 0; + if (setup) + return; + + slack_webhook_url = getenv("SLACK_WEBHOOK_URL"); + if (!slack_webhook_url) { + panic("Unable to find env vars for, please check if you have set\n" + "the SLACK_WEBHOOK_URL!!\n"); + } + setup = 1; +} + +static int send_slack_notification(const char *msg) { + return send_generic_webhook(slack_webhook_url, msg); +} + + ////////////////////////////////// END //////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -185,5 +274,10 @@ struct notifier notifiers[] = { { .setup = setup_telegram, .send_notification = send_telegram_notification + }, + /* Slack. */ + { + .setup = setup_slack, + .send_notification = send_slack_notification } };