From 388306d4a36f6c838661197aed3ba5d3d625937e Mon Sep 17 00:00:00 2001 From: Will Brown Date: Sat, 23 Nov 2024 14:17:15 -0500 Subject: [PATCH] Move insert logic from add command into feed_info.c --- feed_info.c | 76 ++++++++++++++++++++++++++++++++++++++++++----------- feed_info.h | 9 +++++-- main.c | 32 +++------------------- 3 files changed, 70 insertions(+), 47 deletions(-) diff --git a/feed_info.c b/feed_info.c index a4c68b8..8f42160 100644 --- a/feed_info.c +++ b/feed_info.c @@ -15,23 +15,18 @@ #include "config.h" #include "feed_info.h" +static const char *ZBLOCK_FEED_INFO_ERRORS[] = { + "OK", + "Invalid arguments provided", + "An error was encountered with the feed database", + "The feed already exists", + "The feed does not exist" +}; +static_assert(sizeof(ZBLOCK_FEED_INFO_ERRORS) / sizeof(*ZBLOCK_FEED_INFO_ERRORS) == ZBLOCK_FEED_INFO_ERRORCOUNT, "Not all feed info errors implemented"); + // returns a string about the result of a feed_info function const char *zblock_feed_info_strerror(zblock_feed_info_err error) { - static_assert(ZBLOCK_FEED_INFO_ERRORCOUNT == 3, "Not all feed info errors implemented"); - switch (error) { - case ZBLOCK_FEED_INFO_OK: { - return "OK"; - } - case ZBLOCK_FEED_INFO_NULL: { - return "No feed info was provided"; - } - case ZBLOCK_FEED_INFO_POSTGRES: { - return "An error was encountered with the feed database"; - } - default: { - return "Unspecified error"; - } - } + return error < 0 || error >= ZBLOCK_FEED_INFO_ERRORCOUNT ? "Unspecified error" : ZBLOCK_FEED_INFO_ERRORS[error]; } // format string for for the time format of pubDate @@ -45,7 +40,56 @@ time_t pubDate_to_time_t(char *s) { return mktime(&tm); } +// check if the feed currently exists. the result is in the exists pointer. +zblock_feed_info_err zblock_feed_info_exists(PGconn *conn, const char *url, u64snowflake channel_id, int *exists) { + if (!conn || !exists) return ZBLOCK_FEED_INFO_INVALID_ARGS; + + char channel_id_str[21]; // hold a 64-bit int in decimal form + snprintf(channel_id_str, sizeof(channel_id_str), "%ld", channel_id); + + const char *const params[] = {url, channel_id_str}; + PGresult *res = PQexecParams(conn, "SELECT COUNT(1) FROM feeds WHERE url = $1 AND channel_id = $2", 2, NULL, params, NULL, NULL, 0); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + PQclear(res); + return ZBLOCK_FEED_INFO_DBERROR; + } + + *exists = *(int *) PQgetvalue(res, 0, 0); + PQclear(res); + return ZBLOCK_FEED_INFO_OK; +} + // Insert new feed into the database zblock_feed_info_err zblock_feed_info_insert(PGconn *conn, zblock_feed_info *feed) { - assert(0 && "not implemented yet"); + if (!conn || !feed) return ZBLOCK_FEED_INFO_INVALID_ARGS; + + // check if the feed already exists + { + int feed_exists = 0; + zblock_feed_info_err exists_error = zblock_feed_info_exists(conn, feed->url, feed->channel_id, &feed_exists); + if (exists_error) { + return exists_error; + } else if (feed_exists) { + return ZBLOCK_FEED_INFO_EXISTS; + } + } + + // I don't want to deal with the extra fuss that is sending these in binary format + char channel_id_str[21]; + snprintf(channel_id_str, sizeof(channel_id_str), "%ld", feed->channel_id); + char guild_id_str[21]; + snprintf(guild_id_str, sizeof(guild_id_str), "%ld", feed->guild_id); + const char *const insert_params[] = {feed->url, feed->last_pubDate, channel_id_str, feed->title, guild_id_str}; + PGresult *insert_res = PQexecParams(conn, + "INSERT INTO feeds (url, last_pubDate, channel_id, title, guild_id) VALUES ($1, $2, $3, $4, $5)", + 5, NULL, insert_params, NULL, NULL, 0 + ); + + zblock_feed_info_err result = ZBLOCK_FEED_INFO_OK; + if (PQresultStatus(insert_res) != PGRES_COMMAND_OK) { + result = ZBLOCK_FEED_INFO_DBERROR; + } + + PQclear(insert_res); + return result; } diff --git a/feed_info.h b/feed_info.h index ca260d5..0aaf539 100644 --- a/feed_info.h +++ b/feed_info.h @@ -23,8 +23,10 @@ typedef struct { typedef enum { ZBLOCK_FEED_INFO_OK, - ZBLOCK_FEED_INFO_NULL, - ZBLOCK_FEED_INFO_POSTGRES, + ZBLOCK_FEED_INFO_INVALID_ARGS, + ZBLOCK_FEED_INFO_DBERROR, + ZBLOCK_FEED_INFO_EXISTS, + ZBLOCK_FEED_INFO_NOT_EXIST, ZBLOCK_FEED_INFO_ERRORCOUNT } zblock_feed_info_err; @@ -34,6 +36,9 @@ time_t pubDate_to_time_t(char *s); // returns a string about the result of a feed_info function const char *zblock_feed_info_strerror(zblock_feed_info_err error); +// check if the feed currently exists. the result is in the exists pointer. +zblock_feed_info_err zblock_feed_info_exists(PGconn *conn, const char *url, u64snowflake channel_id, int *exists); + // Insert new feed into the database zblock_feed_info_err zblock_feed_info_insert(PGconn *conn, zblock_feed_info *feed); diff --git a/main.c b/main.c index 5c951ed..f92d25b 100644 --- a/main.c +++ b/main.c @@ -217,25 +217,6 @@ static void bot_command_add(struct discord *client, const struct discord_interac feed.channel_id = event->channel_id; feed.guild_id = event->guild_id; - // check if it already exists - char channel_id_str[21]; // hold a 64-bit int in decimal form - snprintf(channel_id_str, sizeof(channel_id_str), "%ld", feed.channel_id); - - const char *const select_params[] = {feed.url, channel_id_str}; - PGresult *select_res = PQexecParams(database_conn, "SELECT * from feeds WHERE url = $1 AND channel_id = $2", 2, NULL, select_params, NULL, NULL, 0); - if (PQresultStatus(select_res) != PGRES_TUPLES_OK) { - snprintf(msg, sizeof(msg), "Error adding feed: %s", PQresultErrorMessage(select_res)); - PQclear(select_res); - } - - if (PQntuples(select_res) > 0) { - PQclear(select_res); - snprintf(msg, sizeof(msg), "Error adding feed: it has already been added to this channel"); - goto send_msg; - } else { - PQclear(select_res); // don't actually do anything with the contents of the query - } - mrss_t *mrss_feed; mrss_error_t mrss_error = mrss_parse_url(feed.url, &mrss_feed); if (mrss_error) { @@ -246,22 +227,15 @@ static void bot_command_add(struct discord *client, const struct discord_interac feed.title = mrss_feed->title; feed.last_pubDate = mrss_feed->item->pubDate; - char guild_id_str[21]; - snprintf(guild_id_str, sizeof(guild_id_str), "%ld", feed.guild_id); - const char *const insert_params[] = {feed.url, feed.last_pubDate, channel_id_str, feed.title, guild_id_str}; - PGresult *insert_res = PQexecParams(database_conn, - "INSERT INTO feeds (url, last_pubDate, channel_id, title, guild_id) VALUES ($1, $2, $3, $4, $5)", - 5, NULL, insert_params, NULL, NULL, 0 - ); - if (PQresultStatus(insert_res) != PGRES_COMMAND_OK) { + zblock_feed_info_err insert_res = zblock_feed_info_insert(database_conn, &feed); + if (insert_res) { // write error message - snprintf(msg, sizeof(msg), "Error adding feed: %s", PQresultErrorMessage(insert_res)); + snprintf(msg, sizeof(msg), "Error adding feed: %s", zblock_feed_info_strerror(insert_res)); } else { // write the confirmation message snprintf(msg, sizeof(msg), "The following feed has been successfully added to this channel:\n`%s`", feed.url); } - PQclear(insert_res); mrss_free(mrss_feed); send_msg: