Pogger/src/Feed.cpp

333 lines
5.4 KiB
C++
Raw Normal View History

2020-12-30 22:07:54 -06:00
/*
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "Feed.h"
#include <tinyxml2.h>
2020-12-30 22:07:54 -06:00
#include "App.h"
#include "Entry.h"
#include "Config.h"
#include "Util.h"
2020-12-30 22:07:54 -06:00
Feed::Feed(BString path)
{
2020-12-30 22:07:54 -06:00
title = BString("Untitled Feed");
description = BString("Nondescript, N/A.");
homeUrl = BString("");
xmlUrl = BString("");
updated = true;
fetched = false;
inputPath = path;
2020-12-30 22:07:54 -06:00
SetCachePath(path);
}
2020-12-30 22:07:54 -06:00
2021-01-09 16:53:39 -06:00
Feed::Feed(Feed* feed)
: Feed()
{
SetCachePath(feed->GetCachePath());
}
2020-12-30 22:07:54 -06:00
Feed::Feed()
{
title = BString("");
description = BString("");
homeUrl = BString("");
xmlUrl = BString("");
}
2020-08-14 14:00:07 -05:00
void
2020-12-30 22:07:54 -06:00
Feed::Parse()
2020-08-14 14:00:07 -05:00
{
2020-12-30 22:07:54 -06:00
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_ONLY);
2020-08-14 14:00:07 -05:00
BDateTime attrLastDate = BDateTime();
2020-12-30 22:07:54 -06:00
time_t tt_lastDate = 0;
2020-08-14 14:00:07 -05:00
2020-12-30 22:07:54 -06:00
feedFile->ReadAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate,
sizeof(time_t));
if (tt_lastDate > 0 && ((App*)be_app)->cfg->updateFeeds == true) {
attrLastDate.SetTime_t(tt_lastDate);
2020-08-14 14:00:07 -05:00
minDate = attrLastDate;
}
}
// Download a remote feed's XML to the cache path.
BString
2020-12-30 22:07:54 -06:00
Feed::FetchRemoteFeed()
{
2020-12-30 22:07:54 -06:00
BUrl givenUrl = BUrl(inputPath);
2020-08-14 01:59:15 -05:00
time_t tt_lastDate = 0;
BDateTime* lastDate = new BDateTime();
BString* newHash = new BString();
char oldHash[41];
2020-12-30 22:07:54 -06:00
BFile* cacheFile = new BFile(GetCachePath(), B_READ_WRITE | B_CREATE_FILE);
2020-07-13 12:31:52 -05:00
2020-12-30 22:07:54 -06:00
cacheFile->ReadAttr("LastHash", B_STRING_TYPE, 0, oldHash, 41);
2020-12-30 22:07:54 -06:00
if (((App*)be_app)->cfg->verbose)
printf("Saving %s...\n", inputPath.String());
2020-12-30 22:07:54 -06:00
webFetch(BUrl(inputPath), cacheFile, newHash);
2020-12-30 22:07:54 -06:00
cacheFile->WriteAttr("LastHash", B_STRING_TYPE, 0,
newHash->String(), newHash->CountChars());
2020-12-30 22:07:54 -06:00
if (*(newHash) == BString(oldHash))
updated = false;
2020-07-13 12:31:52 -05:00
fetched = true;
return GetCachePath();
2020-07-13 12:31:52 -05:00
}
// return whether or not the feed's given URI/path is remote.
bool
2020-12-30 22:07:54 -06:00
Feed::IsRemote ()
{
2020-12-30 22:07:54 -06:00
return isRemotePath(inputPath);
}
2020-12-30 22:07:54 -06:00
// return whether or not the feed seems to have been updated
bool
2020-12-30 22:07:54 -06:00
Feed::IsUpdated ()
{
return updated;
}
2020-12-30 22:07:54 -06:00
// return whether or not feed is RSS
bool
2020-12-30 22:07:54 -06:00
Feed::IsRss ()
{
EnsureCached();
tinyxml2::XMLDocument xml;
2020-12-30 22:07:54 -06:00
xml.LoadFile(GetCachePath().String());
2020-12-30 22:07:54 -06:00
if (xml.FirstChildElement("rss"))
return true;
return false;
}
2020-12-30 22:07:54 -06:00
// return whether or not feed is Atom
bool
2020-12-30 22:07:54 -06:00
Feed::IsAtom ()
{
tinyxml2::XMLDocument xml;
2020-12-30 22:07:54 -06:00
xml.LoadFile(GetCachePath().String());
2020-12-30 22:07:54 -06:00
if (xml.FirstChildElement("feed"))
return true;
return false;
}
// ensure the feed XML is available at the cache path.
// if necessary, download it.
void
2020-12-30 22:07:54 -06:00
Feed::EnsureCached ()
{
2020-12-30 22:07:54 -06:00
if (IsRemote() && fetched == false)
FetchRemoteFeed();
}
2020-12-30 22:07:54 -06:00
// Return the 'cachePath' (location of XML file locally)
BString
2020-12-30 22:07:54 -06:00
Feed::GetCachePath ()
{
2020-12-30 22:07:54 -06:00
if (cachePath == NULL)
SetCachePath(inputPath);
return cachePath;
}
2020-12-30 22:07:54 -06:00
// Select a 'cachePath' (location of XML file locally)
// For remote files, a cache file is created in ~/config/cache/Pogger/ by default
// For local files, the same local file is used.
BString
2020-12-30 22:07:54 -06:00
Feed::SetCachePath (BString givenPath)
{
2020-12-30 22:07:54 -06:00
BUrl givenUrl = BUrl(givenPath);
BString protocol = givenUrl.Protocol().String();
2020-12-30 22:07:54 -06:00
if (protocol == NULL && givenUrl.UrlString() != NULL) {
cachePath = givenPath;
return givenPath;
}
2020-12-30 22:07:54 -06:00
BString splitName = givenUrl.Host();
splitName.Append(givenUrl.Path());
splitName.ReplaceAll("/", "_");
BString filename = ((App*)be_app)->cfg->cacheDir;
filename.Append(splitName);
cachePath = filename;
return filename;
}
2021-01-09 16:53:39 -06:00
// Count the amount of siblings to an element of given type name
int
2020-12-30 22:07:54 -06:00
Feed::xmlCountSiblings (tinyxml2::XMLElement* xsibling, const char* sibling_name)
{
int count = 0;
2020-12-30 22:07:54 -06:00
while (xsibling) {
count++;
xsibling = xsibling->NextSiblingElement(sibling_name);
}
return count;
}
2021-01-09 16:53:39 -06:00
// Add the given entry to the feed, if appropriate
2020-08-14 01:59:15 -05:00
bool
2020-12-30 22:07:54 -06:00
Feed::AddEntry (Entry* newEntry)
2020-08-14 01:59:15 -05:00
{
Config* cfg = ((App*)be_app)->cfg;
2020-12-30 22:07:54 -06:00
if (!withinDateRange(cfg->minDate, newEntry->date, cfg->maxDate) ||
!withinDateRange(minDate, newEntry->date, maxDate))
2020-08-14 01:59:15 -05:00
return false;
2020-12-30 22:07:54 -06:00
if (cfg->verbose == true)
printf("\t%s\n", newEntry->title.String());
entries.AddItem(newEntry);
2020-08-14 01:59:15 -05:00
return true;
}
2020-12-30 22:07:54 -06:00
BList
Feed::GetEntries()
{
return entries;
}
bool
Feed::SetTitle(const char* titleStr)
{
if (titleStr != NULL)
title = BString(titleStr);
else return false;
return true;
}
2020-12-30 22:07:54 -06:00
bool
Feed::SetTitle(tinyxml2::XMLElement* elem)
{
if (elem != NULL)
return SetTitle(elem->GetText());
else return false;
}
2020-12-30 22:07:54 -06:00
BString
Feed::GetTitle()
{
return title;
}
bool
Feed::SetDesc(const char* descStr)
{
if (descStr != NULL)
description = BString(descStr);
else return false;
return true;
}
2020-12-30 22:07:54 -06:00
bool
Feed::SetDesc(tinyxml2::XMLElement* elem)
{
if (elem != NULL)
return SetDesc(elem->GetText());
else return false;
}
2020-12-30 22:07:54 -06:00
BString
Feed::GetDesc()
{
return description;
}
// set a feed's «home URL»
2020-12-30 22:07:54 -06:00
bool
Feed::SetHomeUrl(const char* homepageStr)
{
if (homepageStr != NULL)
homeUrl = BString(homepageStr);
else return false;
return true;
}
2020-12-30 22:07:54 -06:00
bool
Feed::SetHomeUrl(tinyxml2::XMLElement* elem)
{
if (elem != NULL)
return SetHomeUrl(elem->GetText());
else return false;
}
2020-12-30 22:07:54 -06:00
BString
Feed::GetHomeUrl()
{
return homeUrl;
}
2021-01-09 16:53:39 -06:00
BString
Feed::GetXmlUrl()
{
return xmlUrl;
}
// set the update time for a feed
2020-12-30 22:07:54 -06:00
bool
Feed::SetDate(const char* dateCStr)
{
if (dateCStr == NULL)
return false;
2020-12-30 22:07:54 -06:00
BDateTime newDate = feedDateToBDate(dateCStr);
if (newDate == NULL)
return false;
date = newDate;
return true;
}
2020-12-30 22:07:54 -06:00
bool
Feed::SetDate(tinyxml2::XMLElement* elem)
{
if (elem != NULL)
return SetDate(elem->GetText());
else return false;
}
2020-12-30 22:07:54 -06:00
BDateTime
Feed::GetDate()
{
return date;
}