mirror of
https://github.com/WCBROW01/zblock.git
synced 2025-12-12 04:28:07 -05:00
Extract feed_info struct and save routine to its own file
Also start creating basic framework for config
This commit is contained in:
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
|||||||
CFLAGS = -Wall -Wextra -std=gnu99 -O2
|
CFLAGS = -Wall -Wextra -std=gnu11 -O2
|
||||||
LDFLAGS = -lpthread -lcurl -lmrss
|
LDFLAGS = -lpthread -lcurl -lmrss
|
||||||
|
|
||||||
SRC = $(wildcard *.c)
|
SRC = $(wildcard *.c)
|
||||||
|
|||||||
11
config.c
Normal file
11
config.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <concord/discord.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
13
config.h
Normal file
13
config.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef ZBLOCK_CONFIG_H
|
||||||
|
#define ZBLOCK_CONFIG_H
|
||||||
|
|
||||||
|
#include <concord/discord.h>
|
||||||
|
|
||||||
|
// the current zblock config
|
||||||
|
extern struct zblock_config {
|
||||||
|
char *database_path;
|
||||||
|
} zblock_config;
|
||||||
|
|
||||||
|
int zblock_config_load(struct discord *client);
|
||||||
|
|
||||||
|
#endif
|
||||||
56
feed_info.c
Normal file
56
feed_info.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <concord/discord.h>
|
||||||
|
#include <concord/log.h>
|
||||||
|
|
||||||
|
#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");
|
||||||
|
}
|
||||||
44
feed_info.h
Normal file
44
feed_info.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef ZBLOCK_FEED_INFO_H
|
||||||
|
#define ZBLOCK_FEED_INFO_H
|
||||||
|
|
||||||
|
#include <concord/discord.h>
|
||||||
|
|
||||||
|
// 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
|
||||||
51
main.c
51
main.c
@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
#include <mrss.h>
|
#include <mrss.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "feed_info.h"
|
||||||
|
|
||||||
// Function pointer type for commands
|
// Function pointer type for commands
|
||||||
typedef void (*command_func)(struct discord *, const struct discord_interaction *);
|
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); \
|
discord_create_interaction_response(client, event->id, event->token, &res, NULL); \
|
||||||
} while (0)
|
} 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
|
// format string for for the time format of pubDate
|
||||||
#define PUBDATE_FMT "%a, %d %b %Y %T %z"
|
#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) {
|
if (update_pubDate) {
|
||||||
free(feed->last_pubDate);
|
free(feed->last_pubDate);
|
||||||
feed->last_pubDate = strdup(mrss_feed->item->pubDate);
|
feed->last_pubDate = strdup(mrss_feed->item->pubDate);
|
||||||
|
// TODO: save the updated pubDate to disk once that's implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
mrss_free(mrss_feed);
|
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->title = mrss_feed->title;
|
||||||
feed->last_pubDate = mrss_feed->item->pubDate;
|
feed->last_pubDate = mrss_feed->item->pubDate;
|
||||||
feed->feed_id = rand();
|
feed->feed_id = rand();
|
||||||
|
feed->guild_id = event->guild_id;
|
||||||
|
feed->channel_id = event->channel_id;
|
||||||
|
|
||||||
|
|
||||||
char file_path[PATH_MAX];
|
feed_info_err feed_error = feed_info_save_file(feed);
|
||||||
// maybe check if we ran out of characters for path?
|
if (feed_error) {
|
||||||
snprintf(file_path, sizeof(file_path), "%s/%lu/%lu/%x", database_path, event->guild_id, event->channel_id, feed->feed_id);
|
// write error message
|
||||||
|
snprintf(msg, sizeof(msg), "Error adding feed: %s", feed_info_strerror(feed_error));
|
||||||
FILE *fp = fopen(file_path, "w");
|
} else {
|
||||||
if (!fp) {
|
|
||||||
snprintf(msg, sizeof(msg), "Error adding feed: %s", strerror(errno));
|
|
||||||
mrss_free(mrss_feed);
|
|
||||||
feed_info_free(feed);
|
|
||||||
goto send_msg;
|
|
||||||
}
|
|
||||||
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
|
// spawn the timer for this feed
|
||||||
feed->timer_id = discord_timer_interval(client, timer_retrieve_feeds, NULL, feed, 0, TIMER_INTERVAL, -1);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
mrss_free(mrss_feed);
|
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:
|
send_msg:
|
||||||
struct discord_interaction_response res = {
|
struct discord_interaction_response res = {
|
||||||
.type = DISCORD_INTERACTION_CHANNEL_MESSAGE_WITH_SOURCE,
|
.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) {
|
int main(void) {
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
struct discord *client = discord_config_init("config.json");
|
struct discord *client = discord_config_init("config.json");
|
||||||
|
zblock_config_load(client);
|
||||||
discord_set_on_ready(client, &on_ready);
|
discord_set_on_ready(client, &on_ready);
|
||||||
discord_set_on_interaction_create(client, &on_interaction);
|
discord_set_on_interaction_create(client, &on_interaction);
|
||||||
discord_run(client);
|
discord_run(client);
|
||||||
|
|||||||
Reference in New Issue
Block a user