summaryrefslogtreecommitdiff
path: root/src/RSS.cpp
diff options
context:
space:
mode:
authorPhysick <96335032+DegustatorPonos@users.noreply.github.com>2026-05-10 18:06:16 +0500
committerPhysick <96335032+DegustatorPonos@users.noreply.github.com>2026-05-10 18:06:16 +0500
commit838eaa77fa389203a4c41751b36993575bbbfe04 (patch)
tree706fb459923e590978bbacdde5fe2fb3bacf4b74 /src/RSS.cpp
Initial evening
Diffstat (limited to 'src/RSS.cpp')
-rw-r--r--src/RSS.cpp81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/RSS.cpp b/src/RSS.cpp
new file mode 100644
index 0000000..a1c0dde
--- /dev/null
+++ b/src/RSS.cpp
@@ -0,0 +1,81 @@
+#include "RSS.hpp"
+#include <iomanip>
+#include <iostream>
+#include <ctime>
+#include <memory>
+#include <stdexcept>
+#include <curl/curl.h>
+
+RSS::RSS(std::string url) {
+ URL = url;
+ channelInfo = ChannelInfo(url);
+ parse(request());
+}
+
+size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
+ size_t totalSize = size * nmemb;
+ userp->append((char*)contents, totalSize);
+ return totalSize;
+}
+
+std::string RSS::request() {
+ std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> curl (
+ curl_easy_init(), &curl_easy_cleanup);
+
+ if (!curl) {
+ throw std::runtime_error("Failed to initialize CURL");
+ }
+
+ std::string data;
+
+ curl_easy_setopt(curl.get(), CURLOPT_URL, URL.c_str());
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &data);
+ curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1L);
+
+ auto res = curl_easy_perform(curl.get());
+ if (res != CURLE_OK) {
+ throw std::runtime_error(std::string("CURL request failed: ") + curl_easy_strerror(res));
+ }
+
+ curl_easy_cleanup(curl.get());
+ return data;
+}
+
+void RSS::parse(std::string contents) {
+ // std::cout << "starting tokenization..." << std::endl;
+ try {
+ auto leaf = XML_leaf(contents).GetChild("channel");
+ if (leaf.Raw == "<>")
+ throw new std::runtime_error("The feed does not contain <channel> element");
+
+ this->channelInfo.Title = leaf.GetChild("title").Value;
+
+ auto items = leaf.GetChildren("item");
+ for (auto item : items)
+ Entries.push_back(RSS_Entry(item));
+ } catch (const char *err) {
+ std::cout << "Failed to parse feed '" << URL << "' :" << err << std::endl;
+ return;
+ }
+}
+
+RSS_Entry::RSS_Entry(XML_leaf node) {
+ Title = node.GetChild("title").GetValue();
+ URL = node.GetChild("link").GetValue();
+ Contents = node.GetChild("description").GetValue();
+
+ // auto pubDateField = node.GetChild("pubDate");
+ // if (pubDateField.Value.length() == 0) return;
+ // std::cout << "pub date" << pubDateField.Value << std::endl;
+ // strptime(pubDateField.Value.c_str(), "%Y-%m-%dT%H:%M:%SZ", &pubDate);
+}
+
+void RSS_Entry::print() {
+ std::cout
+ << "==============================\n"
+ << Title << '\n'
+ // << std::put_time(&pubDate, "%Y-%m-%d %H:%M:%S") << '\n'
+ << Contents << '\n'
+ << URL<< '\n';
+}