summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile36
-rw-r--r--TODO.md14
-rw-r--r--src/curl.c177
-rw-r--r--src/curl.h24
-rw-r--r--src/db.c79
-rw-r--r--src/db.h20
-rw-r--r--src/feed.c21
-rw-r--r--src/feed.h13
-rw-r--r--src/main.c47
-rw-r--r--src/util.h20
10 files changed, 451 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3a69811
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,36 @@
+CC = clang
+CFLAGS = -g -DDEBUG -fsanitize=address
+LDFLAGS != pkg-config --libs libcurl sqlite3
+
+BIN=bin/newspaddle
+
+SRC=$(wildcard src/*.c)
+OBJ=$(patsubst src/%.c, obj/%.o, $(SRC))
+
+all: bin/ obj/ $(BIN)
+
+$(BIN): $(OBJ)
+ $(CC) $^ $(LDFLAGS) -fsanitize=address -o $@
+
+obj/%.o: src/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+bin/:
+ mkdir bin
+
+obj/:
+ mkdir obj
+
+run: all
+ ./$(BIN)
+
+debug: all
+ gdb ./$(BIN)
+
+scan:
+ make clean
+ scan-build make
+
+clean:
+ rm -r bin/
+ rm -r obj/
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..c666d56
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,14 @@
+* Connect to miniflux
+* Get newsraft db
+
+# Sync feeds
+* Get list of all newsraft feeds and all miniflux feeds
+* Feeds missing in miniflux should be added
+ Feeds are going to be one way for now, only newsraft -> miniflux.
+* Refresh all feeds on miniflux
+
+* Get all local items, all remote items, compare and mark as read the different ones
+
+# A
+* Update miniflux
+* Update newsraft
diff --git a/src/curl.c b/src/curl.c
new file mode 100644
index 0000000..4046d3d
--- /dev/null
+++ b/src/curl.c
@@ -0,0 +1,177 @@
+#include <string.h>
+#include "util.h"
+#include "curl.h"
+
+const char*
+get_apikey()
+{
+ return check_get_env("MINIFLUX_APIKEY");
+}
+
+const char *
+get_url()
+{
+ return check_get_env("MINIFLUX_URL");
+}
+
+char *
+get_endpoint(char* endpoint)
+{
+ char *url = calloc(sizeof(char), PATH_MAX);
+ snprintf(url, PATH_MAX, "%s/v1/%s", get_url(), endpoint);
+ return url;
+}
+
+bool
+curl_init()
+{
+ curl = curl_easy_init();
+
+ if (!curl) {
+ fprintf(stderr, "Error in curl init\n");
+ return false;
+ }
+
+ api_header = calloc(sizeof(char), MAX_URL);
+ snprintf(api_header, sizeof(char) * MAX_URL, "X-Auth-Token: %s", get_apikey());
+
+#ifdef DEBUG
+ fprintf(stderr, "api: %s\n", api_header);
+#endif
+
+ return true;
+}
+
+size_t
+parse_header_reply(
+ char* ptr, size_t size, size_t nmemb, struct reply *userdata)
+{
+ size_t s = 0;
+ if (sscanf(ptr, "Content-Length: %ld\n", &s) != 0) {
+ userdata->size = s + 1;
+#ifdef DEBUG
+ printf("Len: %ld\n", s);
+#endif
+ }
+ return size * nmemb;
+}
+
+size_t
+parse_body_reply(
+ char *ptr, size_t size, size_t nmemb, struct reply *userdata)
+{
+ if (userdata->size == 0) {
+ return 0;
+ }
+ size_t realsize = size * nmemb;
+ char *tmp = realloc(userdata->data, userdata->size);
+ if (!tmp) {
+ fprintf(stderr, "Not enough memory\n");
+ return 0;
+ } else {
+ userdata->data = tmp;
+ }
+
+ strncat(userdata->data, ptr, realsize);
+ return realsize;
+}
+
+struct feed *
+get_remote_feeds()
+{
+ CURLcode res;
+ struct curl_slist *header = NULL;
+
+ char *url = get_endpoint("feeds");
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ free(url);
+ header = curl_slist_append(header, api_header);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
+
+ struct reply data = {0};
+ data.size = 0;
+ data.data = malloc(1);
+ data.data[0] = '\0';
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &parse_body_reply);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &parse_header_reply);
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, &data);
+
+
+ res = curl_easy_perform(curl);
+ if (res != CURLE_OK) {
+ fprintf(stderr, "Curl failed: %s", curl_easy_strerror(res));
+ return NULL;
+ }
+
+#ifdef DEBUG
+ printf("%s\n", data.data);
+#endif
+
+ struct feed *feeds = calloc(sizeof(struct feed), 1);
+ // TODO: populate feed;
+ free(data.data);
+ curl_slist_free_all(header);
+ return feeds;
+}
+
+void
+curl_clean()
+{
+ curl_easy_cleanup(curl);
+ free(api_header);
+}
+
+size_t
+print_reply(
+ char *ptr, size_t size, size_t nmemb, void *null)
+{
+ printf("%s\n", ptr);
+ return size * nmemb;
+}
+
+void
+remote_add_feed(struct feed feed)
+{
+ char *json = calloc(sizeof(char), 4096);
+ snprintf(json, 4096, "{ \"feed_url\": \"%s\", \"category_id\": 1 }", feed.url);
+ char *url = get_endpoint("feeds");
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
+
+ struct curl_slist *header = NULL;
+ header = curl_slist_append(header, api_header);
+ header = curl_slist_append(header, "Content-Type: application/json");
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &print_reply);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
+
+ curl_easy_perform(curl);
+ free(url);
+ free(json);
+ curl_slist_free_all(header);
+}
+
+bool
+create_category(char *title)
+{
+ char *json = calloc(sizeof(char), 4096);
+ snprintf(json, 4096, "{ \"title\": \"%s\" }", title);
+ char *url = get_endpoint("categories");
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
+ struct curl_slist *header = NULL;
+ header = curl_slist_append(header, api_header);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &print_reply);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
+
+ curl_easy_perform(curl);
+ free(url);
+ free(json);
+ curl_slist_free_all(header);
+
+ return true;
+}
diff --git a/src/curl.h b/src/curl.h
new file mode 100644
index 0000000..d496962
--- /dev/null
+++ b/src/curl.h
@@ -0,0 +1,24 @@
+#ifndef _CURL_H_
+#define _CURL_H_
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <curl/curl.h>
+#include "feed.h"
+
+#define MAX_URL 2048
+static CURL *curl;
+static char *api_header;
+
+struct reply {
+ size_t size;
+ char *data;
+};
+
+bool curl_init();
+void curl_clean();
+struct feed *get_remote_feeds();
+bool create_category(char *title);
+void remote_add_feed(struct feed feed);
+
+#endif
diff --git a/src/db.c b/src/db.c
new file mode 100644
index 0000000..7211b8c
--- /dev/null
+++ b/src/db.c
@@ -0,0 +1,79 @@
+#include <string.h>
+#include "db.h"
+#include "util.h"
+
+const char *
+get_db_path()
+{
+ return check_get_env("NEWSRAFT_DB_PATH");
+}
+
+bool
+db_init()
+{
+ int result = sqlite3_open(get_db_path(), &db);
+ if (result != SQLITE_OK) {
+ fprintf(stderr, "Can't open database: %s", sqlite3_errmsg(db));
+ sqlite3_close(db);
+ return false;
+ }
+ return true;
+}
+
+void
+db_clean()
+{
+ sqlite3_close(db);
+}
+
+struct feed *
+get_db_feeds()
+{
+ char *query;
+ size_t total_feeds = get_feed_count();
+ if (total_feeds == 0) {
+ return NULL;
+ }
+ struct feed *feeds = calloc(sizeof(struct feed), total_feeds);
+
+ query = "select feed_url,title from feeds;";
+ int result = sqlite3_prepare_v2(db, query, -1, &statement, NULL);
+
+ if (result == SQLITE_OK) {
+ for (size_t i = 0; sqlite3_step(statement) != SQLITE_DONE; i++) {
+ char *url = (char*)sqlite3_column_text(statement, 0);
+ char *title = (char*)sqlite3_column_text(statement, 1);
+ feeds[i] = create_feed(url, title);
+ }
+ }
+
+#ifdef DEBUG
+ for (size_t i = 0; i < total_feeds; i++) {
+ printf("%s, %s\n", feeds[i].title, feeds[i].url);
+ }
+#endif
+
+ sqlite3_finalize(statement);
+ return feeds;
+}
+
+size_t
+get_feed_count()
+{
+ char* query = "select count(*) from feeds;";
+ int result = sqlite3_prepare_v2(db, query, -1, &statement, NULL);
+ int total_feeds = 0;
+
+ if (result == SQLITE_OK) {
+ while(sqlite3_step(statement) != SQLITE_DONE) {
+ total_feeds = sqlite3_column_int(statement, 0);
+ printf("%d\n", total_feeds);
+ }
+ }
+
+ sqlite3_finalize(statement);
+ return total_feeds;
+}
+
+//size_t get_item_count() {
+//}
diff --git a/src/db.h b/src/db.h
new file mode 100644
index 0000000..d332365
--- /dev/null
+++ b/src/db.h
@@ -0,0 +1,20 @@
+#ifndef _DB_H_
+#define _DB_H_
+
+#include <sqlite3.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include "feed.h"
+
+static sqlite3 *db;
+static sqlite3_stmt *statement;
+
+bool db_init();
+void db_clean();
+
+struct feed *get_db_feeds();
+size_t get_feed_count();
+//size_t get_item_count();
+
+
+#endif
diff --git a/src/feed.c b/src/feed.c
new file mode 100644
index 0000000..4fa99af
--- /dev/null
+++ b/src/feed.c
@@ -0,0 +1,21 @@
+#include <stdlib.h>
+#include <string.h>
+#include "feed.h"
+
+struct feed create_feed(char *url, char* title) {
+ struct feed feed = { 0 };
+ size_t size = strlen(url);
+ feed.url = calloc(sizeof(char), size);
+ strncpy(feed.url, url, size);
+
+ size = strlen(title);
+ feed.title = calloc(sizeof(char), size);
+ strncpy(feed.title, title, size);
+
+ return feed;
+}
+
+void delete_feed(struct feed *feed) {
+ free(feed->url);
+ free(feed->title);
+}
diff --git a/src/feed.h b/src/feed.h
new file mode 100644
index 0000000..c67d07a
--- /dev/null
+++ b/src/feed.h
@@ -0,0 +1,13 @@
+#ifndef _FEED_H_
+#define _FEED_H_
+
+struct feed {
+ char *url;
+ char *title;
+};
+
+struct feed create_feed(char *url, char* title);
+void delete_feed(struct feed *feed);
+
+#endif
+
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..1794a65
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <sqlite3.h>
+#include <string.h>
+#include <stdlib.h>
+#include <json-c/json.h>
+
+#include "curl.h"
+#include "feed.h"
+#include "db.h"
+
+#define _UTIL_DEF_
+#include "util.h"
+
+static sqlite3 *db;
+
+void init() {
+ if (!curl_init() || !db_init()) {
+ exit(1);
+ }
+}
+
+void clean() {
+ curl_clean();
+ db_clean();
+}
+
+int main(int argc, char **argv) {
+
+ init();
+
+ //struct feed *remote_feeds = get_remote_feeds();
+ struct feed *db_feeds = get_db_feeds();
+
+ for (size_t i = 0; i < get_feed_count(); i++) {
+ remote_add_feed(db_feeds[i]);
+ }
+
+ free(db_feeds);
+
+ //if (!remote_feeds) {
+ //exit(1);
+ //}
+ //free(remote_feeds);
+
+ clean();
+ return 0;
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..4b3bed7
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,20 @@
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+
+const char* check_get_env(char* env);
+
+#ifdef _UTIL_DEF_
+const char* check_get_env(char* env) {
+ char *env_val = getenv(env);
+ if (!env_val) {
+ fprintf(stderr, "%s not set", env);
+ exit(1);
+ }
+ return env_val;
+}
+#endif
+
+#endif