Newer
Older
cartastraccia / source / cartastraccia / config.d
@GallaFrancesco GallaFrancesco on 22 Sep 2019 1 KB no more busy waiting
module cartastraccia.config;

import pegged.grammar;
import sumtype;

import core.time;
import std.datetime;
import std.conv : to;
import std.algorithm : filter;
import std.range;

mixin(grammar(ConfigFileParser));

/**
 * Specify grammar for config file in the form:
 * ...
 * [feed_name] [refresh_time] [feed_address]
 * ...
*/
immutable string ConfigFileParser = `
	ConfigFile:

		ConfigFile <- Feed+

		Feed <- Name space* Refresh space* Address Newline

		Name <- identifier

		Refresh <- Number Timeunit

		Address <- ~([A-Za-z]+ "://" ( !Newline !">" . )+)

		Number 	<-  ~([0-9]+)

		Timeunit <- [mshd]

		Newline <- endOfLine / endOfInput
`;

alias RSSFeedList = SumType!(RSSFeed[], InvalidFeeds);


struct InvalidFeeds
{
	string msg;
}

struct RSSFeed
{
	string name;
	Duration refresh;
	string path;

	this(string[] props) @safe
	{
		name = props[0];
		path = props[3];

		switch(props[2][0]) {
			case 's':
				refresh = dur!"seconds"(props[1].to!uint);
				break;
			case 'm':
				refresh = dur!"minutes"(props[1].to!uint);
				break;
			case 'h':
				refresh = dur!"hours"(props[1].to!uint);
				break;
			case 'd':
				refresh = dur!"days"(props[1].to!uint);
				break;
			default:
				assert(false, "should not get here");
		}
	}

}

RSSFeedList processFeeds(ParseTree pt) @trusted
{
	RSSFeed[] feeds;

	foreach(ref conf; pt.children) {
		foreach(ref feed; conf.children) {
			feeds ~= RSSFeed(feed.matches
						.filter!((immutable s) => s != "\n" && s != " ")
						.array
					);
		}
	}
	if(feeds.empty) return RSSFeedList(InvalidFeeds("No feeds found"));
	else return RSSFeedList(feeds);
}