readr

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

feeds.c (3041B)


      1 #include "feeds.h"
      2 
      3 #include <string.h>
      4 #include <mrss.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <pthread.h>
      8 #include <curl/curl.h>
      9 
     10 #include "config.h"
     11 #include "utils.h"
     12 #include "http.h"
     13 
     14 static void parse_feed(feed_t*, char*, char*);
     15 static void populate_feed(feed_t*);
     16 
     17 app_t
     18 load_app(char* contents_feeds)
     19 {
     20 	CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
     21 	if (res) panic("Curl init error %d", res);
     22 	pthread_t t[MAX_FEEDS];
     23 	char* lines[MAX_FEEDS];
     24 	int feed_count = 0;
     25 
     26 	app_t app = {
     27 		.feeds_cap = FEEDS_CAP,
     28 		.feeds = ecalloc(FEEDS_CAP, sizeof(feed_t*)),
     29 	};
     30 
     31 	remove_all_chars(contents_feeds, '\r');
     32 	char* line = strtok(contents_feeds, "\n");
     33 
     34 	while (line != NULL) {
     35 		lines[feed_count] = strdup(line);
     36 
     37 		/* threads out --> */
     38 		pthread_create(&t[feed_count], NULL, threaded_fetch, lines[feed_count]);
     39 		/* threads out --> */
     40 
     41 		feed_count++;
     42 		if (feed_count > MAX_FEEDS) {
     43 			fprintf(stderr, "WARNING exeeded number of feeds %d\n", MAX_FEEDS);
     44 			break;
     45 		}
     46 		line = strtok(NULL, "\n");
     47 	}
     48 
     49 	for (int i = 0; i < feed_count; i++) {
     50 		void* ret;
     51 
     52 		/* <-- thread join */
     53 		pthread_join(t[i], &ret);
     54 		/* <-- thread join */
     55 
     56 		http_blob* httpblob = (http_blob*)ret;
     57 		feed_t* feed = (feed_t*)ecalloc(1, sizeof(feed_t));
     58 		if (!httpblob) continue;
     59 		parse_feed(feed, lines[i], httpblob->data);
     60 		populate_feed(feed);
     61 		free(lines[i]);
     62 		http_blob_free(ret);
     63 
     64 		if (app.feeds_cap == app.feeds_len) {
     65 			app.feeds_cap *= 2;
     66 			app.feeds = realloc(app.feeds, app.feeds_cap * sizeof(feed_t*));
     67 		}
     68 		app.feeds[app.feeds_len++] = feed;
     69 	}
     70 
     71 	free(line);
     72 	curl_global_cleanup();
     73 	return app;
     74 }
     75 
     76 static void
     77 parse_feed(feed_t* feed, char* url, char* http_body)
     78 {
     79 	mrss_t* rss = NULL;
     80 
     81 	*feed = (feed_t) { .url = url };
     82 	feed->title = (char*)ecalloc(FEED_CAP, sizeof(char));
     83 
     84 	/* process feed from given buffer */
     85 	mrss_error_t rc = mrss_parse_buffer(http_body, strlen(http_body), &rss);
     86 
     87 	if (rc != MRSS_OK || rss == NULL) {
     88 		snprintf(feed->title, FEED_CAP, "%s%s ", "(bad) ", url ? url : "(unknown feed url)");
     89 		return;
     90 	}
     91 
     92 	feed->website_url = strdup(rss->link);
     93 
     94 	snprintf(feed->title, FEED_CAP, "%s", rss->title ? rss->title : "(unknown feedtitle)");
     95 
     96 	for (mrss_item_t* it = rss->item; it; it = it->next) {
     97 		char* title = (it->title && *it->title) ? it->title : "";
     98 		char* link = (it->link && *it->link) ? it->link : "";
     99 		char* comments = (it->comments && *it->comments) ? it->comments : "";
    100 		char* desc = (it->description && *it->description) ? it->description : "";
    101 		char* date = (it->pubDate && *it->pubDate) ? it->pubDate : "";
    102 
    103 		remove_all_tags(desc);
    104 
    105 		db_post_t db_post = {
    106 			.title = title,
    107 			.link = link,
    108 			.comments = comments,
    109 			.pub_date = date,
    110 			.summary = desc,
    111 			.feed_url = url,
    112 		};
    113 
    114 		db_insert_post(db_post);
    115 	}
    116 
    117 	mrss_free(rss);
    118 	printf(".");
    119 	fflush(stdout);
    120 }
    121 
    122 static void
    123 populate_feed(feed_t* feed)
    124 {
    125 	const char* url = feed->url;
    126 	db_fetch_post_t dbposts = db_fetch_posts(url);
    127 	if (!dbposts.success) return;
    128 	feed->posts = dbposts.posts;
    129 	feed->posts_len = dbposts.count;
    130 }