From 60b16577ae4ae8cfc768be7e1923d2b65a8984bc Mon Sep 17 00:00:00 2001 From: mr-boneman Date: Tue, 20 Aug 2024 13:19:47 +0200 Subject: [PATCH] parse and aggregate --- Containerfile | 2 ++ config.nims | 1 + rssmix.nimble | 19 +++++++++++ src/rssmix.nim | 80 ++++++++++++++++++++++++++++++++++++++++++++++ src/tomlToJson.nim | 52 ++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 Containerfile create mode 100644 config.nims create mode 100644 rssmix.nimble create mode 100644 src/rssmix.nim create mode 100644 src/tomlToJson.nim diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..0dfefc1 --- /dev/null +++ b/Containerfile @@ -0,0 +1,2 @@ +ARG fedoraVersion=40 +FROM quay.io/fedora/fedora-minimal:${fedoraVersion} \ No newline at end of file diff --git a/config.nims b/config.nims new file mode 100644 index 0000000..ca97df1 --- /dev/null +++ b/config.nims @@ -0,0 +1 @@ +switch("d", "ssl") \ No newline at end of file diff --git a/rssmix.nimble b/rssmix.nimble new file mode 100644 index 0000000..d1ec1ce --- /dev/null +++ b/rssmix.nimble @@ -0,0 +1,19 @@ +# Package + +version = "0.1.0" +author = "mr-boneman" +description = "mix rss feeds" +license = "MIT" +srcDir = "src" +bin = @["rssmix"] + + +# Dependencies + +requires "nim >= 2.0.8" +requires "mummy" +requires "parsetoml" +requires "jsony" +requires "rssatom" +requires "puppy" +requires "pretty" \ No newline at end of file diff --git a/src/rssmix.nim b/src/rssmix.nim new file mode 100644 index 0000000..3f60da9 --- /dev/null +++ b/src/rssmix.nim @@ -0,0 +1,80 @@ +import std/[algorithm, json, xmltree, times, options, sequtils] +import pkg/[mummy, rssatom, puppy, pretty] + +const + atomTimeFormat {.strdefine.} = "yyyy-MM-dd'T'HH:mm:ss'Z'" + rssv2TimeFormat {.strdefine.} = "ddd',' dd MMM yyyy HH:mm:ss ZZZ" + +type RssFeed = object # name:string + url: string + kind: FeedType + +proc parseAtomTime(s: string): DateTime = + parse(s, atomTimeFormat) + +proc parseRSSv2Time(s: string): DateTime = + parse(s, rssv2TimeFormat) + +proc getrssv2Time(r:RssItem):DateTime= + result = dateTime(0, Month.low, MonthdayRange.low) + if r.pubDate.isSome(): + result = parseRssv2Time(r.pubDate.get()) + + +proc getTime(r: RssItem): DateTime = + result = dateTime(0, Month.low, MonthdayRange.low) + if r.updated.isSome(): + result = parseAtomTime(r.updated.get()) + elif r.pubDate.isSome(): + result = parseAtomTime(r.pubDate.get()) + +proc cmpRssItem(x, y: RssItem): int = + cmp(x.getTime(), y.getTime()) + +proc mixRssFeeds(feeds: seq[RssFeed]): RSS = + result = RSS() + result.id = "https://example.com/".some() + result.title = "This is a test".some() + result.link = "link.com".some() + result.author.name = "Samuel R.".some() + result.description = "this is a test for this and that".some() + var entries: seq[RSS] + for feed in feeds: + case feed.kind + of Atom: + entries.add parseAtom(fetch(feed.url)) + of RSSv2: + entries.add parseRss(fetch(feed.url)) + + entries[^1].items = entries[^1].items.mapIt( + block: + var item = it + item.pubdate = some(getRssv2Time(item).format(atomTimeFormat)) + item + ) + + for feed in entries: + result.items.add feed.items + + result.items.sort(cmp = cmpRssItem, order = Descending) + +proc assembleAtom(r: RSS): XmlNode = + result = buildAtom(r) + result.attrs = { + "xmlns": "http://www.w3.org/2005/Atom", + "xmlns:thr": "http://purl.org/syndication/thread/1.0", + "xml:lang": "en-EN" + }.toXmlAttributes() + + discard + +echo assembleAtom( + mixRssFeeds( + @[ + RssFeed(kind: Atom, url: "https://github.com/nim-lang/Nim/releases.atom"), + RssFeed(kind: Atom, url: "https://github.com/fatedier/frp/releases.atom"), + RssFeed(kind: RSSv2, url: "https://fedoramagazine.org/rss"), + RssFeed(kind: RSSv2, url: "http://communityblog.fedoraproject.org/?feed=rss2"), + ] + ) +) diff --git a/src/tomlToJson.nim b/src/tomlToJson.nim new file mode 100644 index 0000000..d66ad39 --- /dev/null +++ b/src/tomlToJson.nim @@ -0,0 +1,52 @@ +import std/[json, math, tables, sequtils] +import pkg/parsetoml + +proc customToJson*(table: parsetoml.TomlTableRef): JsonNode + +proc customToJson*(value: parsetoml.TomlValueRef): JsonNode = + case value.kind + of TomlValueKind.Int: + %*value.intVal + of TomlValueKind.Float: + if classify(value.floatVal) == fcNan: + if value.forcedSign != Pos: + %*value.floatVal + else: + %*value.floatVal + else: + %*value.floatVal + of TomlValueKind.Bool: + %* $value.boolVal + of TomlValueKind.Datetime: + if value.dateTimeVal.shift == false: + %*value.dateTimeVal + else: + %*value.dateTimeVal + of TomlValueKind.Date: + %*value.dateVal + of TomlValueKind.Time: + %*value.timeVal + of TomlValueKind.String: + %*value.stringVal + of TomlValueKind.Array: + if value.arrayVal.len == 0: + when defined(newtestsuite): + %[] + else: + %*[] + elif value.arrayVal[0].kind == TomlValueKind.Table: + %value.arrayVal.map(customToJson) + else: + when defined(newtestsuite): + %*value.arrayVal.map(customToJson) + else: + %*value.arrayVal.map(customToJson) + of TomlValueKind.Table: + value.tableVal.customToJson() + of TomlValueKind.None: + %*{"type": "ERROR"} + +proc customToJson*(table: parsetoml.TomlTableRef): JsonNode = + result = newJObject() + for key, value in pairs(table): + result[key] = value.customToJson