readr

Minimal Terminal RSS Reader
Log | Files | Refs | README | LICENSE

feeds.c (3041B)



#include "feeds.h"

#include <string.h>
#include <mrss.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>

#include "config.h"
#include "utils.h"
#include "http.h"

static void parse_feed(feed_t*, char*, char*);
static void populate_feed(feed_t*);

app_t
load_app(char* contents_feeds)
{
	CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
	if (res) panic("Curl init error %d", res);
	pthread_t t[MAX_FEEDS];
	char* lines[MAX_FEEDS];
	int feed_count = 0;

	app_t app = {
		.feeds_cap = FEEDS_CAP,
		.feeds = ecalloc(FEEDS_CAP, sizeof(feed_t*)),
	};

	remove_all_chars(contents_feeds, '\r');
	char* line = strtok(contents_feeds, "\n");

	while (line != NULL) {
		lines[feed_count] = strdup(line);

		/* threads out --> */
		pthread_create(&t[feed_count], NULL, threaded_fetch, lines[feed_count]);
		/* threads out --> */

		feed_count++;
		if (feed_count > MAX_FEEDS) {
			fprintf(stderr, "WARNING exeeded number of feeds %d\n", MAX_FEEDS);
			break;
		}
		line = strtok(NULL, "\n");
	}

	for (int i = 0; i < feed_count; i++) {
		void* ret;

		/* <-- thread join */
		pthread_join(t[i], &ret);
		/* <-- thread join */

		http_blob* httpblob = (http_blob*)ret;
		feed_t* feed = (feed_t*)ecalloc(1, sizeof(feed_t));
		if (!httpblob) continue;
		parse_feed(feed, lines[i], httpblob->data);
		populate_feed(feed);
		free(lines[i]);
		http_blob_free(ret);

		if (app.feeds_cap == app.feeds_len) {
			app.feeds_cap *= 2;
			app.feeds = realloc(app.feeds, app.feeds_cap * sizeof(feed_t*));
		}
		app.feeds[app.feeds_len++] = feed;
	}

	free(line);
	curl_global_cleanup();
	return app;
}

static void
parse_feed(feed_t* feed, char* url, char* http_body)
{
	mrss_t* rss = NULL;

	*feed = (feed_t) { .url = url };
	feed->title = (char*)ecalloc(FEED_CAP, sizeof(char));

	/* process feed from given buffer */
	mrss_error_t rc = mrss_parse_buffer(http_body, strlen(http_body), &rss);

	if (rc != MRSS_OK || rss == NULL) {
		snprintf(feed->title, FEED_CAP, "%s%s ", "(bad) ", url ? url : "(unknown feed url)");
		return;
	}

	feed->website_url = strdup(rss->link);

	snprintf(feed->title, FEED_CAP, "%s", rss->title ? rss->title : "(unknown feedtitle)");

	for (mrss_item_t* it = rss->item; it; it = it->next) {
		char* title = (it->title && *it->title) ? it->title : "";
		char* link = (it->link && *it->link) ? it->link : "";
		char* comments = (it->comments && *it->comments) ? it->comments : "";
		char* desc = (it->description && *it->description) ? it->description : "";
		char* date = (it->pubDate && *it->pubDate) ? it->pubDate : "";

		remove_all_tags(desc);

		db_post_t db_post = {
			.title = title,
			.link = link,
			.comments = comments,
			.pub_date = date,
			.summary = desc,
			.feed_url = url,
		};

		db_insert_post(db_post);
	}

	mrss_free(rss);
	printf(".");
	fflush(stdout);
}

static void
populate_feed(feed_t* feed)
{
	const char* url = feed->url;
	db_fetch_post_t dbposts = db_fetch_posts(url);
	if (!dbposts.success) return;
	feed->posts = dbposts.posts;
	feed->posts_len = dbposts.count;
}