diff --git a/Makefile b/Makefile index 33e1d46..8ea5b99 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -Wall -Wextra -std=gnu99 -O2 +CFLAGS = -Wall -Wextra -std=gnu11 -O2 LDFLAGS = -lpthread -lcurl -lmrss SRC = $(wildcard *.c) diff --git a/config.c b/config.c new file mode 100644 index 0000000..2dfdc97 --- /dev/null +++ b/config.c @@ -0,0 +1,11 @@ +#include + +#include "config.h" + +struct zblock_config zblock_config; + +int zblock_config_load(struct discord *client) { + // TODO: actually load config + zblock_config.database_path = "feeds"; + return 0; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..44caa1d --- /dev/null +++ b/config.h @@ -0,0 +1,13 @@ +#ifndef ZBLOCK_CONFIG_H +#define ZBLOCK_CONFIG_H + +#include + +// the current zblock config +extern struct zblock_config { + char *database_path; +} zblock_config; + +int zblock_config_load(struct discord *client); + +#endif diff --git a/feed_info.c b/feed_info.c new file mode 100644 index 0000000..36159a7 --- /dev/null +++ b/feed_info.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "config.h" +#include "feed_info.h" + +void feed_info_free(feed_info *feed) { + free(feed->title); + free(feed->url); + free(feed->last_pubDate); + free(feed); +} + +const char *feed_info_strerror(feed_info_err error) { + static_assert(FEED_INFO_ERRORCOUNT == 3, "Not all feed info errors implemented"); + switch (error) { + case FEED_INFO_OK: { + return "OK"; + } + case FEED_INFO_FILEERROR: { + return strerror(errno); + } + case FEED_INFO_NULL: { + return "No feed info was provided"; + } + default: { + return "Unspecified error"; + } + } +} + +/* + * Reads feed info for given information from file and puts it in the provided struct + */ +feed_info_err feed_info_save_file(feed_info *feed) { + if (!feed) return FEED_INFO_NULL; + + char file_path[PATH_MAX]; + // maybe check if we ran out of characters for path? + snprintf(file_path, sizeof(file_path), "%s/%lu/%lu/%x", zblock_config.database_path, feed->guild_id, feed->channel_id, feed->feed_id); + + FILE *fp = fopen(file_path, "w"); + if (!fp) return FEED_INFO_FILEERROR; + fprintf(fp, "title=%s\nurl=%s\nlast_pubDate=%s\n", feed->title, feed->url, feed->last_pubDate); + fclose(fp); +} + +feed_info_err feed_info_load_file(u64snowflake guild_id, u64snowflake channel_id, unsigned feed_id, feed_info *feed) { + assert(0 && "not implemented yet"); +} diff --git a/feed_info.h b/feed_info.h new file mode 100644 index 0000000..4ebfb0a --- /dev/null +++ b/feed_info.h @@ -0,0 +1,44 @@ +#ifndef ZBLOCK_FEED_INFO_H +#define ZBLOCK_FEED_INFO_H + +#include + +// TODO: last_pubDate doesn't actually work properly yet +typedef struct feed_info { + char *title; + char *url; + char *last_pubDate; + u64snowflake guild_id; + u64snowflake channel_id; + unsigned timer_id; + unsigned feed_id; +} feed_info; + +typedef enum { + FEED_INFO_OK, + FEED_INFO_NULL, + FEED_INFO_FILEERROR, + FEED_INFO_ERRORCOUNT +} feed_info_err; + +/* + * Free the feed info struct + */ +void feed_info_free(struct feed_info *feed); + +/* + * Get a string explaining a feed info error + */ +const char *feed_info_strerror(feed_info_err error); + +/* + * Saves feed info to given file + */ +feed_info_err feed_info_save_file(feed_info *feed); + +/* + * Reads feed info for given information from file and puts it in the provided struct + */ +feed_info_err feed_info_load_file(u64snowflake guild_id, u64snowflake channel_id, unsigned feed_id, feed_info *feed); + +#endif diff --git a/main.c b/main.c index a952855..1f3d8dd 100644 --- a/main.c +++ b/main.c @@ -15,6 +15,9 @@ #include +#include "config.h" +#include "feed_info.h" + // Function pointer type for commands typedef void (*command_func)(struct discord *, const struct discord_interaction *); @@ -39,25 +42,6 @@ struct bot_command { discord_create_interaction_response(client, event->id, event->token, &res, NULL); \ } while (0) -struct feed_info { - char *title; - char *url; - char *last_pubDate; - u64snowflake guild_id; - u64snowflake channel_id; - unsigned timer_id; - unsigned feed_id; -}; - -void feed_info_free(struct feed_info *feed) { - free(feed->title); - free(feed->url); - free(feed->last_pubDate); - free(feed); -} - -static const char *database_path = "feeds"; - // format string for for the time format of pubDate #define PUBDATE_FMT "%a, %d %b %Y %T %z" @@ -98,6 +82,7 @@ static void timer_retrieve_feeds(struct discord *client, struct discord_timer *t if (update_pubDate) { free(feed->last_pubDate); feed->last_pubDate = strdup(mrss_feed->item->pubDate); + // TODO: save the updated pubDate to disk once that's implemented } mrss_free(mrss_feed); @@ -128,30 +113,23 @@ static void bot_command_add(struct discord *client, const struct discord_interac feed->title = mrss_feed->title; feed->last_pubDate = mrss_feed->item->pubDate; feed->feed_id = rand(); + feed->guild_id = event->guild_id; + feed->channel_id = event->channel_id; - char file_path[PATH_MAX]; - // maybe check if we ran out of characters for path? - snprintf(file_path, sizeof(file_path), "%s/%lu/%lu/%x", database_path, event->guild_id, event->channel_id, feed->feed_id); - - FILE *fp = fopen(file_path, "w"); - if (!fp) { - snprintf(msg, sizeof(msg), "Error adding feed: %s", strerror(errno)); - mrss_free(mrss_feed); - feed_info_free(feed); - goto send_msg; + feed_info_err feed_error = feed_info_save_file(feed); + if (feed_error) { + // write error message + snprintf(msg, sizeof(msg), "Error adding feed: %s", feed_info_strerror(feed_error)); + } else { + // spawn the timer for this feed + feed->timer_id = discord_timer_interval(client, timer_retrieve_feeds, NULL, feed, 0, TIMER_INTERVAL, -1); + // write the confirmation message + snprintf(msg, sizeof(msg), "The following feed has been successfully added to this channel:\n`%s`", feed->url); } - fprintf(fp, "title=%s\nurl=%s\nlast_pubDate=%s\n", feed->title, feed->url, feed->last_pubDate); - fclose(fp); - - // spawn the timer for this feed - feed->timer_id = discord_timer_interval(client, timer_retrieve_feeds, NULL, feed, 0, TIMER_INTERVAL, -1); - + mrss_free(mrss_feed); - // send the confirmation message - snprintf(msg, sizeof(msg), "The following feed has been successfully added to this channel:\n`%s`", feed->url); - send_msg: struct discord_interaction_response res = { .type = DISCORD_INTERACTION_CHANNEL_MESSAGE_WITH_SOURCE, @@ -263,6 +241,7 @@ static void on_interaction(struct discord *client, const struct discord_interact int main(void) { srand(time(NULL)); struct discord *client = discord_config_init("config.json"); + zblock_config_load(client); discord_set_on_ready(client, &on_ready); discord_set_on_interaction_create(client, &on_interaction); discord_run(client);