From 35aca1f0582c43b5f6818c8fc00b924247e45881 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 15 Jul 2020 06:09:50 +0200 Subject: Implement rss sync --- src/main.c | 156 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 39 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 11fdc54..eabd755 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include "fileutils.h" #include "stringutils.h" #include "rss.h" +#include "rss_html_common.h" #include "html.h" #include "json.h" @@ -55,16 +56,6 @@ static void usage_sync(void) { exit(1); } -static struct json_value_s* json_object_get_field_by_name(struct json_object_s *json_obj, const char *name) { - struct json_object_element_s *obj_element = json_obj->start; - while(obj_element) { - if(strcmp(obj_element->name->string, name) == 0) - return obj_element->value; - obj_element = obj_element->next; - } - return NULL; -} - typedef void (*DownloadedListCallback)(const char *title, double timestamp, void *userdata); static void data_file_get_downloaded(const char *dir_name, const char *data_filepath, int is_html, DownloadedListCallback callback, void *userdata) { @@ -163,21 +154,23 @@ static void downloaded_list_callback(const char *title, double timestamp, void * static void get_downloaded_items(const char *tracked_dir, int is_html, void *userdata) { struct dirent *dir; DIR *d = opendir(tracked_dir); - if(!d) + if(!d) { + fprintf(stderr, "Failed to open directory: %s\n", tracked_dir); return; + } - char data_filepath[PATH_MAX] = {0}; - strcat(data_filepath, tracked_dir); + char data_filepath[PATH_MAX]; + strcpy(data_filepath, tracked_dir); strcat(data_filepath, "/"); int data_filepath_length = strlen(data_filepath); while((dir = readdir(d)) != NULL) { - /* We dont want hidden files (and . ..) */ - if(dir->d_name[0] == '.') + int filename_len = strlen(dir->d_name); + if((filename_len == 1 && dir->d_name[0] == '.') || (filename_len == 2 && dir->d_name[0] == '.' && dir->d_name[1] == '.')) continue; strcpy(data_filepath + data_filepath_length, dir->d_name); - strcpy(data_filepath + data_filepath_length + strlen(dir->d_name), "/data"); + strcpy(data_filepath + data_filepath_length + filename_len, "/data"); data_file_get_downloaded(dir->d_name, data_filepath, is_html, downloaded_list_callback, userdata); } @@ -265,11 +258,98 @@ static void command_add(int argc, char **argv, char *rss_config_dir, char *html_ } } +sig_atomic_t running = 0; +static void automedia_pid_signal_handler(int signum) { + (void)signum; + running = 0; +} + +static void sync_tracked_rss(char *rss_config_dir) { + char rss_tracked_dir[PATH_MAX]; + strcpy(rss_tracked_dir, rss_config_dir); + strcat(rss_tracked_dir, "/tracked"); + + struct dirent *dir; + DIR *d = opendir(rss_tracked_dir); + if(!d) { + fprintf(stderr, "Failed to open directory: %s\n", rss_tracked_dir); + return; + } + + char *item_filepath = rss_tracked_dir; + strcat(item_filepath, "/"); + int item_filepath_len = strlen(item_filepath); + + while((dir = readdir(d)) != NULL && running) { + int title_len = strlen(dir->d_name); + if((title_len == 1 && dir->d_name[0] == '.') || (title_len == 2 && dir->d_name[0] == '.' && dir->d_name[1] == '.')) + continue; + + strcpy(item_filepath + item_filepath_len, dir->d_name); + + strcpy(item_filepath + item_filepath_len + title_len, "/.in_progress"); + if(file_exists(item_filepath) == 0) { + fprintf(stderr, "Skipping in-progress rss %s\n", dir->d_name); + continue; + } + + strcpy(item_filepath + item_filepath_len + title_len, "/link"); + char *link_file_content = NULL; + long link_file_size = 0; + int has_link = file_get_content(item_filepath, &link_file_content, &link_file_size); + + strcpy(item_filepath + item_filepath_len + title_len, "/data"); + char *data_file_content = NULL; + long data_file_size = 0; + int has_data = file_get_content(item_filepath, &data_file_content, &data_file_size); + + if(has_link != 0 || has_data != 0) { + free(link_file_content); + free(data_file_content); + fprintf(stderr, "Rss corrupt, link or data missing for rss %s\n", dir->d_name); + continue; + } + + struct json_value_s *json_data = json_parse(data_file_content, data_file_size); + free(data_file_content); + if(!json_data || json_data->type != json_type_object) { + free(link_file_content); + free(json_data); + fprintf(stderr, "Rss corrupt for %s\n", dir->d_name); + continue; + } + + TrackedRss tracked_rss; + tracked_rss.title = dir->d_name; + tracked_rss.link = link_file_content; + tracked_rss.json_data = json_value_as_object(json_data); + if(sync_rss(&tracked_rss, rss_config_dir) != 0) + fprintf(stderr, "Failed to sync %s\n", dir->d_name); + + free(link_file_content); + free(json_data); + } + + closedir(d); +} + static void sync_rss_html(char *rss_config_dir, char *html_config_dir, const char *download_dir, int sync_rate_sec) { - (void)rss_config_dir; (void)html_config_dir; - (void)download_dir; - (void)sync_rate_sec; + + if(transmission_is_daemon_running() != 0) { + if(transmission_start_daemon(download_dir) != 0) { + fprintf(stderr, "Failed to start torrent daemon\n"); + exit(2); + } + } + + running = 1; + /* running is set to 0 in SIGINT signal handler (ctrl+c) */ + while(running) { + sync_tracked_rss(rss_config_dir); + if(running) + sleep(sync_rate_sec); + } } static int cmdline_contains_str(const char *cmdline, const char *str) { @@ -285,24 +365,27 @@ static int cmdline_contains_str(const char *cmdline, const char *str) { } } -static void automedia_pid_signal_handler(int signum) { - (void)signum; - unlink("/tmp/automedia.pid"); - exit(1); -} - static void command_sync(int argc, char **argv, char *rss_config_dir, char *html_config_dir) { if(argc < 1) usage_sync(); - const char *download_dir = argv[0]; + char *download_dir = argv[0]; const char automedia_pid_path[] = "/tmp/automedia.pid"; + + if(create_directory_recursive(download_dir) != 0) { + fprintf(stderr, "Failed to create download directory %s\n", download_dir); + exit(1); + } - int pid_file = open(automedia_pid_path, O_CREAT | O_EXCL | O_RDWR); + int pid_file = open(automedia_pid_path, O_CREAT | O_EXCL | O_SYNC | O_RDWR, 0666); if(pid_file == -1 && errno == EEXIST) { char *running_automedia_pid; long running_automedia_pid_size; if(file_get_content(automedia_pid_path, &running_automedia_pid, &running_automedia_pid_size) == 0) { + /* + We have to check the cmdline because another process could theoretically receive the pid + that an old automedia process had + */ char cmdline_file_path[128]; sprintf(cmdline_file_path, "/proc/%s/cmdline", running_automedia_pid); free(running_automedia_pid); @@ -318,11 +401,14 @@ static void command_sync(int argc, char **argv, char *rss_config_dir, char *html } free(cmdline); } else { + fprintf(stderr, "Failed to get content of %s\n", automedia_pid_path); free(running_automedia_pid); + exit(1); } + fprintf(stderr, "Overwriting existing %s\n", automedia_pid_path); remove(automedia_pid_path); - pid_file = open(automedia_pid_path, O_CREAT | O_EXCL | O_RDWR); + pid_file = open(automedia_pid_path, O_CREAT | O_EXCL | O_SYNC | O_RDWR, 0666); } if(pid_file == -1 && errno != EEXIST) { @@ -337,14 +423,14 @@ static void command_sync(int argc, char **argv, char *rss_config_dir, char *html int process_pid_str_len = strlen(process_pid_str); if(write(pid_file, process_pid_str, process_pid_str_len) != process_pid_str_len) { fprintf(stderr, "Failed to write pid to %s\n", automedia_pid_path); - unlink(automedia_pid_path); + remove(automedia_pid_path); exit(1); } close(pid_file); const int sync_rate_sec = 15 * 60; /* every 15 min */ sync_rss_html(rss_config_dir, html_config_dir, download_dir, sync_rate_sec); - unlink(automedia_pid_path); + remove(automedia_pid_path); } static void command_downloaded(const char *rss_config_dir, const char *html_config_dir) { @@ -372,12 +458,7 @@ static void command_downloaded(const char *rss_config_dir, const char *html_conf buffer_deinit(&downloaded_items); } -/* -static void torrent_list_callback(int id, float percentage_finished, const char *name, void *userdata) { - (void)userdata; - fprintf(stderr, "id: |%d|, done: |%g|, name: |%s|\n", id, percentage_finished, name); -} -*/ + int main(int argc, char **argv) { if(argc < 2) usage(); @@ -404,8 +485,5 @@ int main(int argc, char **argv) { usage(); } - /*transmission_get_all_torrents(torrent_list_callback, NULL); - printf("is transmission daemon running? %s\n", transmission_is_daemon_running() == 0 ? "yes" : "no");*/ - return 0; } -- cgit v1.2.3