Direly needed reformatting
This commit is contained in:
parent
f46a53fdc5
commit
85923f2cc2
19
Makefile
19
Makefile
|
@ -29,17 +29,18 @@ APP_MIME_SIG = application/x-vnd.Pogger
|
|||
# same name (source.c or source.cpp) are included from different directories.
|
||||
# Also note that spaces in folder names do not work well with this Makefile.
|
||||
SRCS = \
|
||||
src/Feed.cpp, \
|
||||
src/Entry.cpp, \
|
||||
src/AtomFeed.cpp, \
|
||||
src/RssFeed.cpp, \
|
||||
src/PrefWindow.cpp, \
|
||||
src/ProtocolListener.cpp, \
|
||||
src/Mimetypes.cpp, \
|
||||
src/Config.cpp, \
|
||||
src/Util.cpp, \
|
||||
src/App.cpp, \
|
||||
src/AtomFeed.cpp, \
|
||||
src/Config.cpp, \
|
||||
src/Entry.cpp, \
|
||||
src/Feed.cpp, \
|
||||
src/FeedView.cpp, \
|
||||
src/Invocation.cpp \
|
||||
src/MainWindow.cpp, \
|
||||
src/Mimetypes.cpp, \
|
||||
src/ProtocolListener.cpp, \
|
||||
src/RssFeed.cpp, \
|
||||
src/Util.cpp
|
||||
|
||||
# Specify the resource definition files to use. Full or relative paths can be
|
||||
# used.
|
||||
|
|
|
@ -112,5 +112,5 @@ Sry bby, i'm trying <3
|
|||
BORING INFO
|
||||
--------------------------------------------------
|
||||
Pogger is under the MIT license.
|
||||
https://git.xwx.moe/pogger.git
|
||||
https://git.feneas.org/detruota/pogger
|
||||
jadedctrl@teknik.io
|
||||
|
|
41
src/App.cpp
41
src/App.cpp
|
@ -1,20 +1,28 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "App.h"
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "AtomFeed.h"
|
||||
#include "RssFeed.h"
|
||||
#include "Feed.h"
|
||||
#include "Entry.h"
|
||||
#include "Mimetypes.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "App.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Entry.h"
|
||||
#include "Feed.h"
|
||||
#include "Invocation.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Mimetypes.h"
|
||||
#include "RssFeed.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
int
|
||||
main ( int argc, char** argv )
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
App* app = new App();
|
||||
usageMsg.ReplaceAll("%app%", "Pogger");
|
||||
|
@ -24,10 +32,10 @@ main ( int argc, char** argv )
|
|||
app->cfg->Load();
|
||||
|
||||
|
||||
if ( argc == 1 )
|
||||
if (argc == 1)
|
||||
app->Run();
|
||||
else
|
||||
cliStart( argc, argv );
|
||||
cliStart(argc, argv);
|
||||
|
||||
|
||||
if ( app->cfg->will_save == true )
|
||||
|
@ -36,25 +44,22 @@ main ( int argc, char** argv )
|
|||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
void
|
||||
cliStart ( int argc, char** argv )
|
||||
cliStart(int argc, char** argv)
|
||||
{
|
||||
invocation( argc, argv );
|
||||
((App*)be_app)->cfg->targetFeeds.DoForEach( &processFeed );
|
||||
invocation(argc, argv);
|
||||
((App*)be_app)->cfg->targetFeeds.DoForEach(&processFeed);
|
||||
}
|
||||
|
||||
App::App ( )
|
||||
: BApplication("application/x-vnd.Pogger")
|
||||
|
||||
App::App() : BApplication("application/x-vnd.Pogger")
|
||||
{
|
||||
MainWindow* mainWin = new MainWindow();
|
||||
mainWin->Show();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const char* configPath = "/boot/home/config/settings/Pogger/";
|
||||
BString usageMsg =
|
||||
"Usage: %app% [-hvDus] [-tT datetime] [-cCO path] \n"
|
||||
|
|
19
src/App.h
19
src/App.h
|
@ -1,9 +1,16 @@
|
|||
#ifndef APPP_H
|
||||
#define APPP_H
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef APP_H
|
||||
#define APP_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <Application.h>
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
class Config;
|
||||
|
||||
|
||||
class App : public BApplication
|
||||
|
@ -13,14 +20,14 @@ public:
|
|||
Config* cfg;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main ( int, char** );
|
||||
void cliStart ( int, char** );
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern const char* configPath;
|
||||
|
||||
extern BString usageMsg;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
119
src/AtomFeed.cpp
119
src/AtomFeed.cpp
|
@ -1,11 +1,19 @@
|
|||
#include <tinyxml2.h>
|
||||
#include "Entry.h"
|
||||
#include "App.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "AtomFeed.h"
|
||||
|
||||
AtomFeed::AtomFeed ( )
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include "App.h"
|
||||
#include "Config.h"
|
||||
#include "Entry.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
AtomFeed::AtomFeed()
|
||||
{
|
||||
title = BString("Untitled Feed");
|
||||
description = BString("");
|
||||
|
@ -15,32 +23,37 @@ AtomFeed::AtomFeed ( )
|
|||
outputDir = ((App*)be_app)->cfg->outDir;
|
||||
}
|
||||
|
||||
AtomFeed::AtomFeed ( Feed* feed ) : AtomFeed::AtomFeed()
|
||||
{ SetCachePath( feed->GetCachePath() ); }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
AtomFeed::AtomFeed(Feed* feed)
|
||||
: AtomFeed::AtomFeed()
|
||||
{
|
||||
SetCachePath(feed->GetCachePath());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AtomFeed::Parse ( )
|
||||
AtomFeed::Parse ()
|
||||
{
|
||||
entries = BList();
|
||||
tinyxml2::XMLDocument xml;
|
||||
xml.LoadFile( GetCachePath().String() );
|
||||
tinyxml2::XMLDocument xml;
|
||||
xml.LoadFile(GetCachePath().String());
|
||||
|
||||
Feed::Parse();
|
||||
|
||||
tinyxml2::XMLElement* xfeed = xml.FirstChildElement("feed");
|
||||
|
||||
RootParse( xfeed );
|
||||
ParseEntries( xfeed );
|
||||
RootParse(xfeed);
|
||||
ParseEntries(xfeed);
|
||||
|
||||
BFile* feedFile = new BFile( GetCachePath().String(), B_READ_WRITE );
|
||||
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_WRITE);
|
||||
time_t tt_lastDate = lastDate.Time_t();
|
||||
feedFile->WriteAttr( "LastDate", B_TIME_TYPE, 0, &tt_lastDate, sizeof(time_t) );
|
||||
feedFile->WriteAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate,
|
||||
sizeof(time_t));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AtomFeed::RootParse( tinyxml2::XMLElement* xfeed )
|
||||
AtomFeed::RootParse(tinyxml2::XMLElement* xfeed)
|
||||
{
|
||||
tinyxml2::XMLElement* xauthor = xfeed->FirstChildElement("author");
|
||||
tinyxml2::XMLElement* xentry = xfeed->FirstChildElement("entry");
|
||||
|
@ -49,70 +62,80 @@ AtomFeed::RootParse( tinyxml2::XMLElement* xfeed )
|
|||
|
||||
bool set = false;
|
||||
|
||||
SetTitle( xfeed->FirstChildElement("title") );
|
||||
SetDesc( xfeed->FirstChildElement("description") );
|
||||
SetTitle(xfeed->FirstChildElement("title"));
|
||||
SetDesc( xfeed->FirstChildElement("description"));
|
||||
|
||||
set = SetDate( xfeed->FirstChildElement("updated") );
|
||||
if ( !set ) set = SetDate( xfeed->FirstChildElement("published") );
|
||||
if ( !set && xentry ) set = SetDate( xentry->FirstChildElement("updated") );
|
||||
if ( !set && xentry ) set = SetDate( xentry->FirstChildElement("published") );
|
||||
set = SetDate(xfeed->FirstChildElement("updated"));
|
||||
if (!set)
|
||||
set = SetDate(xfeed->FirstChildElement("published"));
|
||||
if (!set && xentry)
|
||||
set = SetDate(xentry->FirstChildElement("updated"));
|
||||
if (!set && xentry)
|
||||
set = SetDate(xentry->FirstChildElement("published"));
|
||||
|
||||
set = SetHomeUrl( xlink->Attribute( "href" ) );
|
||||
if ( !set && xauthor ) set = SetHomeUrl( xauthor->FirstChildElement("uri") );
|
||||
if ( !set && xauthlink ) set = SetHomeUrl( xauthlink->Attribute( "href" ) );
|
||||
set = SetHomeUrl(xlink->Attribute("href"));
|
||||
if (!set && xauthor)
|
||||
set = SetHomeUrl(xauthor->FirstChildElement("uri"));
|
||||
if (!set && xauthlink)
|
||||
set = SetHomeUrl(xauthlink->Attribute("href"));
|
||||
|
||||
if ( ((App*)be_app)->cfg->verbose )
|
||||
if (((App*)be_app)->cfg->verbose)
|
||||
printf("Channel '%s' at '%s':\n", title.String(), homeUrl.String());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AtomFeed::EntryParse ( tinyxml2::XMLElement* xentry )
|
||||
AtomFeed::EntryParse(tinyxml2::XMLElement* xentry)
|
||||
{
|
||||
Entry* newEntry= (Entry*)malloc( sizeof(Entry) );
|
||||
newEntry = new Entry( outputDir );
|
||||
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
|
||||
newEntry = new Entry(outputDir);
|
||||
|
||||
tinyxml2::XMLElement* xcontent = xentry->FirstChildElement("content");
|
||||
tinyxml2::XMLElement* xmedia = xentry->FirstChildElement("media:group");
|
||||
tinyxml2::XMLPrinter xprinter;
|
||||
|
||||
newEntry->SetTitle( xentry->FirstChildElement("title") );
|
||||
newEntry->SetPostUrl( xentry->FirstChildElement("link")->Attribute("href") );
|
||||
newEntry->SetFeedTitle( title );
|
||||
newEntry->SetTitle(xentry->FirstChildElement("title"));
|
||||
newEntry->SetPostUrl(xentry->FirstChildElement("link")->Attribute("href"));
|
||||
newEntry->SetFeedTitle(title);
|
||||
|
||||
bool set = false;
|
||||
set = newEntry->SetDesc( xentry->FirstChildElement("summary") );
|
||||
if ( !set ) set = newEntry->SetDesc( xentry->FirstChildElement("description"));
|
||||
if ( !set && xmedia ) set = newEntry->SetDesc( xmedia->FirstChildElement("media:description"));
|
||||
set = newEntry->SetDesc(xentry->FirstChildElement("summary"));
|
||||
if (!set)
|
||||
set = newEntry->SetDesc(xentry->FirstChildElement("description"));
|
||||
if (!set && xmedia)
|
||||
set = newEntry->SetDesc(xmedia->FirstChildElement("media:description"));
|
||||
|
||||
set = newEntry->SetDate( xentry->FirstChildElement("updated") );
|
||||
if ( !set ) set = newEntry->SetDate( xentry->FirstChildElement("published") );
|
||||
set = newEntry->SetDate(xentry->FirstChildElement("updated"));
|
||||
if (!set)
|
||||
set = newEntry->SetDate(xentry->FirstChildElement("published"));
|
||||
|
||||
if ( lastDate == NULL || lastDate < newEntry->date )
|
||||
if (lastDate == NULL || lastDate < newEntry->date)
|
||||
lastDate = newEntry->date;
|
||||
|
||||
if ( xcontent ) {
|
||||
xcontent->Accept( &xprinter );
|
||||
newEntry->SetContent( xprinter.CStr() );
|
||||
if (xcontent) {
|
||||
xcontent->Accept(&xprinter);
|
||||
newEntry->SetContent(xprinter.CStr());
|
||||
}
|
||||
|
||||
AddEntry( newEntry );
|
||||
AddEntry(newEntry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AtomFeed::ParseEntries ( tinyxml2::XMLElement* xfeed )
|
||||
AtomFeed::ParseEntries(tinyxml2::XMLElement* xfeed)
|
||||
{
|
||||
tinyxml2::XMLElement* xentry;
|
||||
|
||||
xentry = xfeed->FirstChildElement("entry");
|
||||
|
||||
int entryCount = xmlCountSiblings( xentry, "entry" );
|
||||
int entryCount = xmlCountSiblings(xentry, "entry");
|
||||
entries = BList(entryCount);
|
||||
|
||||
if ( ((App*)be_app)->cfg->verbose )
|
||||
if (((App*)be_app)->cfg->verbose)
|
||||
printf("\t-%i entries-\n", entryCount);
|
||||
|
||||
while ( xentry ) {
|
||||
EntryParse( xentry );
|
||||
while (xentry) {
|
||||
EntryParse(xentry);
|
||||
xentry = xentry->NextSiblingElement("entry");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef ATOM_FEED_H
|
||||
#define ATOM_FEED_H
|
||||
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <DateTime.h>
|
||||
#include <String.h>
|
||||
#include <List.h>
|
||||
#include <Url.h>
|
||||
#include "Config.h"
|
||||
|
||||
#include "Feed.h"
|
||||
|
||||
|
||||
class AtomFeed: public Feed {
|
||||
public:
|
||||
AtomFeed ( );
|
||||
AtomFeed ( Feed* );
|
||||
AtomFeed();
|
||||
AtomFeed(Feed*);
|
||||
|
||||
void Parse ( );
|
||||
void RootParse ( tinyxml2::XMLElement* );
|
||||
void EntryParse ( tinyxml2::XMLElement* );
|
||||
void ParseEntries ( tinyxml2::XMLElement* );
|
||||
void Parse();
|
||||
void RootParse(tinyxml2::XMLElement*);
|
||||
void EntryParse(tinyxml2::XMLElement*);
|
||||
void ParseEntries(tinyxml2::XMLElement*);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,70 +1,83 @@
|
|||
#include <iostream>
|
||||
#include <String.h>
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
Config::Config () {
|
||||
verbose = false;
|
||||
daemon = true;
|
||||
will_save = false;
|
||||
updateFeeds = false;
|
||||
#include <String.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
Config::Config() {
|
||||
verbose = false;
|
||||
daemon = true;
|
||||
will_save = false;
|
||||
updateFeeds = false;
|
||||
}
|
||||
|
||||
Config::Config ( Config* cfg ) {
|
||||
verbose = cfg->verbose;
|
||||
daemon = cfg->daemon;
|
||||
will_save = cfg->will_save;
|
||||
updateFeeds = cfg->updateFeeds;
|
||||
minDate = cfg->minDate;
|
||||
maxDate = cfg->maxDate;
|
||||
|
||||
Config::Config(Config* cfg) {
|
||||
verbose = cfg->verbose;
|
||||
daemon = cfg->daemon;
|
||||
will_save = cfg->will_save;
|
||||
updateFeeds = cfg->updateFeeds;
|
||||
minDate = cfg->minDate;
|
||||
maxDate = cfg->maxDate;
|
||||
}
|
||||
|
||||
|
||||
// !! handle file status
|
||||
void
|
||||
Config::Load ()
|
||||
Config::Load()
|
||||
{
|
||||
if ( configDir == NULL )
|
||||
configDir = BString( "/boot/home/config/settings/Pogger/" );
|
||||
if (configDir == NULL)
|
||||
configDir = BString("/boot/home/config/settings/Pogger/");
|
||||
|
||||
BString filename = BString(configDir);
|
||||
filename.Append("settings");
|
||||
BFile* file = new BFile( filename.String(), B_READ_ONLY );
|
||||
BFile* file = new BFile(filename.String(), B_READ_ONLY);
|
||||
status_t result = file->InitCheck();
|
||||
|
||||
BMessage storage;
|
||||
storage.Unflatten( file );
|
||||
storage.Unflatten(file);
|
||||
|
||||
if ( outDir == NULL)
|
||||
outDir = BString( storage.GetString("outDir", "/boot/home/feeds/") );
|
||||
if ( cacheDir == NULL)
|
||||
cacheDir = BString( storage.GetString("cacheDir", "/boot/home/config/cache/Pogger/") );
|
||||
if (outDir == NULL)
|
||||
outDir = BString(storage.GetString("outDir", "/boot/home/feeds/"));
|
||||
if (cacheDir == NULL)
|
||||
cacheDir = BString(storage.GetString("cacheDir",
|
||||
"/boot/home/config/cache/Pogger/"));
|
||||
delete file;
|
||||
}
|
||||
|
||||
|
||||
// !! handle file status
|
||||
void
|
||||
Config::Save ()
|
||||
{
|
||||
if ( configDir == NULL )
|
||||
configDir = BString( "/boot/home/config/settings/Pogger/" );
|
||||
if (configDir == NULL)
|
||||
configDir = BString("/boot/home/config/settings/Pogger/");
|
||||
|
||||
BPath* cfgPath = new BPath( configDir.String(), NULL, true );
|
||||
BEntry* cfgEntry = new BEntry( cfgPath->Path() );
|
||||
BDirectory* cfgDir = new BDirectory;
|
||||
BPath* cfgPath = new BPath(configDir.String(), NULL, true);
|
||||
BEntry* cfgEntry = new BEntry(cfgPath->Path());
|
||||
BDirectory* cfgDir = new BDirectory;
|
||||
|
||||
cfgDir->CreateDirectory(cfgPath->Path(), NULL);
|
||||
|
||||
if ( cfgEntry->Exists() == false )
|
||||
cfgDir->CreateDirectory( cfgPath->Path(), NULL );
|
||||
if (cfgEntry->Exists() == false)
|
||||
cfgDir->CreateDirectory(cfgPath->Path(), NULL);
|
||||
|
||||
BMessage storage;
|
||||
BString filename = BString( configDir ).Append("/settings");
|
||||
BString filename = BString(configDir).Append("/settings");
|
||||
|
||||
BFile* file = new BFile( filename.String(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE );
|
||||
BFile* file = new BFile(filename.String(), B_WRITE_ONLY | B_CREATE_FILE
|
||||
| B_ERASE_FILE);
|
||||
status_t result = file->InitCheck();
|
||||
|
||||
storage.AddString( "outDir", outDir.String() );
|
||||
storage.AddString( "cacheDir", cacheDir.String() );
|
||||
storage.AddString("outDir", outDir.String());
|
||||
storage.AddString("cacheDir", cacheDir.String());
|
||||
|
||||
storage.Flatten( file );
|
||||
storage.Flatten(file);
|
||||
}
|
||||
|
||||
|
|
18
src/Config.h
18
src/Config.h
|
@ -1,14 +1,23 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
#include <DateTime.h>
|
||||
#include <String.h>
|
||||
#include <StorageKit.h>
|
||||
|
||||
|
||||
class Config {
|
||||
public:
|
||||
Config ( );
|
||||
Config ( Config* );
|
||||
Config();
|
||||
Config(Config*);
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
bool verbose;
|
||||
bool daemon;
|
||||
|
@ -23,9 +32,8 @@ public:
|
|||
bool will_save;
|
||||
|
||||
bool updateFeeds;
|
||||
|
||||
void Load ( );
|
||||
void Save ( );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
168
src/Entry.cpp
168
src/Entry.cpp
|
@ -1,12 +1,20 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "Entry.h"
|
||||
|
||||
#include <StorageKit.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <tinyxml2.h>
|
||||
#include <StorageKit.h>
|
||||
|
||||
#include "Config.h"
|
||||
#include "Entry.h"
|
||||
#include "Util.h"
|
||||
|
||||
Entry::Entry ( BString outputPath )
|
||||
|
||||
Entry::Entry(BString outputPath)
|
||||
{
|
||||
title = BString("");
|
||||
description = BString("");
|
||||
|
@ -16,90 +24,134 @@ Entry::Entry ( BString outputPath )
|
|||
outputDir = outputPath;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Entry::Filetize ( bool onlyIfNew = false )
|
||||
Entry::Filetize(bool onlyIfNew = false)
|
||||
{
|
||||
BDirectory* dir = new BDirectory( outputDir );
|
||||
BFile* file = new BFile( title.String(), B_READ_WRITE );
|
||||
BDirectory* dir = new BDirectory(outputDir);
|
||||
BFile* file = new BFile(title.String(), B_READ_WRITE);
|
||||
time_t tt_date = date.Time_t();
|
||||
|
||||
dir->CreateFile( title.String(), file );
|
||||
dir->CreateFile(title.String(), file);
|
||||
|
||||
BString betype = BString("text/x-feed-entry");
|
||||
file->WriteAttr( "BEOS:TYPE", B_MIME_STRING_TYPE, 0,
|
||||
betype.String(), betype.CountChars() + 1 );
|
||||
file->WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, betype.String(),
|
||||
betype.CountChars() + 1);
|
||||
|
||||
file->WriteAttr( "FEED:name", B_STRING_TYPE, 0,
|
||||
title.String(), title.CountChars() );
|
||||
file->WriteAttr( "FEED:description", B_STRING_TYPE, 0,
|
||||
description.String(), description.CountChars() );
|
||||
file->WriteAttr( "FEED:source", B_STRING_TYPE, 0,
|
||||
feedTitle.String(), feedTitle.CountChars() );
|
||||
file->WriteAttr( "META:url", B_STRING_TYPE, 0,
|
||||
postUrl.String(), postUrl.CountChars() );
|
||||
if ( date != NULL ) {
|
||||
file->WriteAttr( "FEED:when", B_TIME_TYPE, 0,
|
||||
&tt_date, sizeof(time_t) );
|
||||
file->WriteAttr("FEED:name", B_STRING_TYPE, 0,
|
||||
title.String(), title.CountChars());
|
||||
file->WriteAttr("FEED:description", B_STRING_TYPE, 0,
|
||||
description.String(), description.CountChars());
|
||||
file->WriteAttr("FEED:source", B_STRING_TYPE, 0,
|
||||
feedTitle.String(), feedTitle.CountChars());
|
||||
file->WriteAttr("META:url", B_STRING_TYPE, 0, postUrl.String(),
|
||||
postUrl.CountChars());
|
||||
|
||||
if (date != NULL) {
|
||||
file->WriteAttr("FEED:when", B_TIME_TYPE, 0, &tt_date, sizeof(time_t));
|
||||
}
|
||||
|
||||
file->Write(content.String(), content.Length());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entry::SetTitle ( const char* titleStr ) {
|
||||
if ( titleStr != NULL ) title = BString( titleStr );
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Entry::SetTitle ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetTitle( elem->GetText() );
|
||||
return false;
|
||||
}
|
||||
bool Entry::SetDesc ( const char* descStr ) {
|
||||
if ( descStr != NULL ) description = BString( descStr );
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Entry::SetDesc ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetDesc( elem->GetText() );
|
||||
return false;
|
||||
}
|
||||
bool Entry::SetFeedTitle ( BString titleStr ) {
|
||||
if ( titleStr != NULL ) feedTitle = titleStr;
|
||||
|
||||
bool
|
||||
Entry::SetTitle(const char* titleStr) {
|
||||
if (titleStr != NULL)
|
||||
title = BString(titleStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Entry::SetContent ( const char* contentStr ) {
|
||||
if ( contentStr != NULL ) content = BString( contentStr );
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Entry::SetContent ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetContent( elem->GetText() );
|
||||
|
||||
bool
|
||||
Entry::SetTitle(tinyxml2::XMLElement* elem) {
|
||||
if (elem != NULL)
|
||||
return SetTitle(elem->GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entry::SetPostUrl ( const char* urlStr ) {
|
||||
if ( urlStr != NULL ) postUrl = BString( urlStr );
|
||||
|
||||
bool
|
||||
Entry::SetDesc(const char* descStr) {
|
||||
if (descStr != NULL)
|
||||
description = BString(descStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Entry::SetPostUrl ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetPostUrl( elem->GetText() );
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetDesc(tinyxml2::XMLElement* elem) {
|
||||
if (elem != NULL)
|
||||
return SetDesc(elem->GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entry::SetDate ( const char* dateStr ) {
|
||||
if ( dateStr == NULL )
|
||||
|
||||
bool
|
||||
Entry::SetFeedTitle(BString titleStr) {
|
||||
if (titleStr != NULL)
|
||||
feedTitle = titleStr;
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetContent(const char* contentStr)
|
||||
{
|
||||
if (contentStr != NULL)
|
||||
content = BString(contentStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetContent(tinyxml2::XMLElement* elem)
|
||||
{
|
||||
if (elem != NULL)
|
||||
return SetContent(elem->GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetPostUrl(const char* urlStr) {
|
||||
if (urlStr != NULL)
|
||||
postUrl = BString(urlStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetPostUrl(tinyxml2::XMLElement* elem) {
|
||||
if (elem != NULL)
|
||||
return SetPostUrl(elem->GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetDate(const char* dateStr) {
|
||||
if (dateStr == NULL)
|
||||
return false;
|
||||
BDateTime newDate = feedDateToBDate( dateStr );
|
||||
if ( newDate == NULL )
|
||||
BDateTime newDate = feedDateToBDate(dateStr);
|
||||
if (newDate == NULL)
|
||||
return false;
|
||||
date = newDate;
|
||||
return true;
|
||||
}
|
||||
bool Entry::SetDate ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetDate( elem->GetText() );
|
||||
|
||||
|
||||
bool
|
||||
Entry::SetDate(tinyxml2::XMLElement* elem) {
|
||||
if (elem != NULL)
|
||||
return SetDate(elem->GetText());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
46
src/Entry.h
46
src/Entry.h
|
@ -1,14 +1,40 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef ENTRY_H
|
||||
#define ENTRY_H
|
||||
|
||||
|
||||
#include <DateTime.h>
|
||||
#include <String.h>
|
||||
#include <List.h>
|
||||
#include <String.h>
|
||||
#include <Url.h>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
|
||||
Entry(BString);
|
||||
|
||||
bool Filetize(bool);
|
||||
|
||||
bool SetTitle(const char*);
|
||||
bool SetTitle(tinyxml2::XMLElement*);
|
||||
bool SetDesc(const char*);
|
||||
bool SetDesc(tinyxml2::XMLElement*);
|
||||
bool SetFeedTitle(BString);
|
||||
bool SetContent(const char*);
|
||||
bool SetContent(tinyxml2::XMLElement*);
|
||||
bool SetPostUrl(const char*);
|
||||
bool SetPostUrl(tinyxml2::XMLElement*);
|
||||
bool SetDate(const char*);
|
||||
bool SetDate(tinyxml2::XMLElement*);
|
||||
|
||||
BString title;
|
||||
BString description;
|
||||
BString feedTitle;
|
||||
|
@ -16,22 +42,8 @@ public:
|
|||
BString postUrl;
|
||||
BString content;
|
||||
BString outputDir;
|
||||
|
||||
Entry ( BString );
|
||||
|
||||
bool Filetize ( bool );
|
||||
|
||||
bool SetTitle ( const char* );
|
||||
bool SetTitle ( tinyxml2::XMLElement* );
|
||||
bool SetDesc ( const char* );
|
||||
bool SetDesc ( tinyxml2::XMLElement* );
|
||||
bool SetFeedTitle ( BString );
|
||||
bool SetContent ( const char* );
|
||||
bool SetContent ( tinyxml2::XMLElement* );
|
||||
bool SetPostUrl ( const char* );
|
||||
bool SetPostUrl ( tinyxml2::XMLElement* );
|
||||
bool SetDate ( const char* );
|
||||
bool SetDate ( tinyxml2::XMLElement* );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
244
src/Feed.cpp
244
src/Feed.cpp
|
@ -1,23 +1,32 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "Feed.h"
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include "App.h"
|
||||
#include "Entry.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "Feed.h"
|
||||
|
||||
Feed::Feed ( BString path )
|
||||
|
||||
Feed::Feed(BString path)
|
||||
{
|
||||
title = BString( "Untitled Feed" );
|
||||
description = BString( "Nondescript, N/A." );
|
||||
title = BString("Untitled Feed");
|
||||
description = BString("Nondescript, N/A.");
|
||||
homeUrl = BString("");
|
||||
xmlUrl = BString("");
|
||||
updated = true;
|
||||
fetched = false;
|
||||
inputPath = path;
|
||||
SetCachePath( path );
|
||||
SetCachePath(path);
|
||||
}
|
||||
|
||||
Feed::Feed ( )
|
||||
|
||||
Feed::Feed()
|
||||
{
|
||||
title = BString("");
|
||||
description = BString("");
|
||||
|
@ -25,132 +34,133 @@ Feed::Feed ( )
|
|||
xmlUrl = BString("");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
Feed::Parse ( )
|
||||
Feed::Parse()
|
||||
{
|
||||
BFile* feedFile = new BFile( GetCachePath().String(), B_READ_ONLY );
|
||||
time_t tt_lastDate = 0;
|
||||
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_ONLY);
|
||||
BDateTime attrLastDate = BDateTime();
|
||||
time_t tt_lastDate = 0;
|
||||
|
||||
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 );
|
||||
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);
|
||||
minDate = attrLastDate;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
// Download a remote feed's XML to the cache path.
|
||||
BString
|
||||
Feed::FetchRemoteFeed ( )
|
||||
Feed::FetchRemoteFeed()
|
||||
{
|
||||
BUrl givenUrl = BUrl( inputPath );
|
||||
BUrl givenUrl = BUrl(inputPath);
|
||||
time_t tt_lastDate = 0;
|
||||
BDateTime* lastDate = new BDateTime();
|
||||
BString* newHash = new BString();
|
||||
char oldHash[41];
|
||||
|
||||
BFile* cacheFile = new BFile( GetCachePath(), B_READ_WRITE | B_CREATE_FILE );
|
||||
BFile* cacheFile = new BFile(GetCachePath(), B_READ_WRITE | B_CREATE_FILE);
|
||||
|
||||
cacheFile->ReadAttr( "LastHash", B_STRING_TYPE, 0, oldHash, 41 );
|
||||
cacheFile->ReadAttr("LastHash", B_STRING_TYPE, 0, oldHash, 41);
|
||||
|
||||
if ( ((App*)be_app)->cfg->verbose )
|
||||
printf( "Saving %s...\n", inputPath.String() );
|
||||
if (((App*)be_app)->cfg->verbose)
|
||||
printf("Saving %s...\n", inputPath.String());
|
||||
|
||||
webFetch( BUrl(inputPath), cacheFile, newHash );
|
||||
webFetch(BUrl(inputPath), cacheFile, newHash);
|
||||
|
||||
cacheFile->WriteAttr( "LastHash", B_STRING_TYPE, 0,
|
||||
newHash->String(), newHash->CountChars() );
|
||||
cacheFile->WriteAttr("LastHash", B_STRING_TYPE, 0,
|
||||
newHash->String(), newHash->CountChars());
|
||||
|
||||
if ( *(newHash) == BString(oldHash) )
|
||||
if (*(newHash) == BString(oldHash))
|
||||
updated = false;
|
||||
|
||||
fetched = true;
|
||||
return GetCachePath();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// return whether or not the feed's given URI/path is remote.
|
||||
bool
|
||||
Feed::IsRemote ( )
|
||||
Feed::IsRemote ()
|
||||
{
|
||||
return isRemotePath( inputPath );
|
||||
return isRemotePath(inputPath);
|
||||
}
|
||||
|
||||
|
||||
// return whether or not the feed seems to have been updated
|
||||
bool
|
||||
Feed::IsUpdated ( )
|
||||
Feed::IsUpdated ()
|
||||
{
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
// return whether or not feed is RSS
|
||||
bool
|
||||
Feed::IsRss ( )
|
||||
Feed::IsRss ()
|
||||
{
|
||||
EnsureCached();
|
||||
tinyxml2::XMLDocument xml;
|
||||
xml.LoadFile( GetCachePath().String() );
|
||||
xml.LoadFile(GetCachePath().String());
|
||||
|
||||
if ( xml.FirstChildElement("rss") )
|
||||
if (xml.FirstChildElement("rss"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// return whether or not feed is Atom
|
||||
bool
|
||||
Feed::IsAtom ( )
|
||||
Feed::IsAtom ()
|
||||
{
|
||||
tinyxml2::XMLDocument xml;
|
||||
xml.LoadFile( GetCachePath().String() );
|
||||
xml.LoadFile(GetCachePath().String());
|
||||
|
||||
if ( xml.FirstChildElement("feed") )
|
||||
if (xml.FirstChildElement("feed"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ensure the feed XML is available at the cache path.
|
||||
// if necessary, download it.
|
||||
void
|
||||
Feed::EnsureCached ( )
|
||||
Feed::EnsureCached ()
|
||||
{
|
||||
if ( IsRemote() && fetched == false )
|
||||
if (IsRemote() && fetched == false)
|
||||
FetchRemoteFeed();
|
||||
}
|
||||
|
||||
|
||||
// Return the 'cachePath' (location of XML file locally)
|
||||
BString
|
||||
Feed::GetCachePath ( )
|
||||
Feed::GetCachePath ()
|
||||
{
|
||||
if ( cachePath == NULL )
|
||||
SetCachePath( inputPath );
|
||||
if (cachePath == NULL)
|
||||
SetCachePath(inputPath);
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
Feed::SetCachePath ( BString givenPath )
|
||||
Feed::SetCachePath (BString givenPath)
|
||||
{
|
||||
BUrl givenUrl = BUrl( givenPath );
|
||||
BUrl givenUrl = BUrl(givenPath);
|
||||
BString protocol = givenUrl.Protocol().String();
|
||||
|
||||
if ( protocol == NULL && givenUrl.UrlString() != NULL ) {
|
||||
if (protocol == NULL && givenUrl.UrlString() != NULL) {
|
||||
cachePath = givenPath;
|
||||
return givenPath;
|
||||
}
|
||||
|
||||
BString splitName = givenUrl.Host( );
|
||||
splitName.Append( givenUrl.Path() );
|
||||
BString splitName = givenUrl.Host();
|
||||
splitName.Append(givenUrl.Path());
|
||||
splitName.ReplaceAll("/", "_");
|
||||
|
||||
BString filename = ((App*)be_app)->cfg->cacheDir;
|
||||
|
@ -160,85 +170,149 @@ Feed::SetCachePath ( BString givenPath )
|
|||
return filename;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// count the amount of siblings to an element of given type name
|
||||
int
|
||||
Feed::xmlCountSiblings ( tinyxml2::XMLElement* xsibling, const char* sibling_name )
|
||||
Feed::xmlCountSiblings (tinyxml2::XMLElement* xsibling, const char* sibling_name)
|
||||
{
|
||||
int count = 0;
|
||||
while ( xsibling ) {
|
||||
while (xsibling) {
|
||||
count++;
|
||||
xsibling = xsibling->NextSiblingElement(sibling_name);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// add the given entry to the feed, if appropriate
|
||||
bool
|
||||
Feed::AddEntry ( Entry* newEntry )
|
||||
Feed::AddEntry (Entry* newEntry)
|
||||
{
|
||||
Config* cfg = ((App*)be_app)->cfg;
|
||||
if ( !withinDateRange( cfg->minDate, newEntry->date, cfg->maxDate ) ||
|
||||
!withinDateRange( minDate, newEntry->date, maxDate ) )
|
||||
if (!withinDateRange(cfg->minDate, newEntry->date, cfg->maxDate) ||
|
||||
!withinDateRange(minDate, newEntry->date, maxDate))
|
||||
return false;
|
||||
|
||||
if ( cfg->verbose == true )
|
||||
printf( "\t%s\n", newEntry->title.String() );
|
||||
entries.AddItem( newEntry );
|
||||
if (cfg->verbose == true)
|
||||
printf("\t%s\n", newEntry->title.String());
|
||||
entries.AddItem(newEntry);
|
||||
return true;
|
||||
}
|
||||
BList Feed::GetEntries ( ) { return entries; }
|
||||
|
||||
bool Feed::SetTitle ( const char* titleStr ) {
|
||||
if ( titleStr != NULL ) title = BString( titleStr );
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Feed::SetTitle ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetTitle( elem->GetText() );
|
||||
else return false;
|
||||
}
|
||||
BString Feed::GetTitle ( ) { return title; }
|
||||
|
||||
bool Feed::SetDesc ( const char* descStr ) {
|
||||
if ( descStr != NULL ) description = BString( descStr );
|
||||
BList
|
||||
Feed::GetEntries()
|
||||
{
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Feed::SetTitle(const char* titleStr)
|
||||
{
|
||||
if (titleStr != NULL)
|
||||
title = BString(titleStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Feed::SetDesc ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetDesc( elem->GetText() );
|
||||
|
||||
|
||||
bool
|
||||
Feed::SetTitle(tinyxml2::XMLElement* elem)
|
||||
{
|
||||
if (elem != NULL)
|
||||
return SetTitle(elem->GetText());
|
||||
else return false;
|
||||
}
|
||||
BString Feed::GetDesc ( ) { return description; }
|
||||
|
||||
|
||||
BString
|
||||
Feed::GetTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Feed::SetDesc(const char* descStr)
|
||||
{
|
||||
if (descStr != NULL)
|
||||
description = BString(descStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Feed::SetDesc(tinyxml2::XMLElement* elem)
|
||||
{
|
||||
if (elem != NULL)
|
||||
return SetDesc(elem->GetText());
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
Feed::GetDesc()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
// set a feed's «home URL»
|
||||
bool Feed::SetHomeUrl ( const char* homepageStr ) {
|
||||
if ( homepageStr != NULL ) homeUrl = BString( homepageStr );
|
||||
bool
|
||||
Feed::SetHomeUrl(const char* homepageStr)
|
||||
{
|
||||
if (homepageStr != NULL)
|
||||
homeUrl = BString(homepageStr);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
bool Feed::SetHomeUrl ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetHomeUrl( elem->GetText() );
|
||||
|
||||
|
||||
bool
|
||||
Feed::SetHomeUrl(tinyxml2::XMLElement* elem)
|
||||
{
|
||||
if (elem != NULL)
|
||||
return SetHomeUrl(elem->GetText());
|
||||
else return false;
|
||||
}
|
||||
BString Feed::GetHomeUrl ( ) { return homeUrl; }
|
||||
|
||||
|
||||
BString
|
||||
Feed::GetHomeUrl()
|
||||
{
|
||||
return homeUrl;
|
||||
}
|
||||
|
||||
|
||||
// set the update time for a feed
|
||||
bool Feed::SetDate ( const char* dateCStr ) {
|
||||
if ( dateCStr == NULL )
|
||||
bool
|
||||
Feed::SetDate(const char* dateCStr)
|
||||
{
|
||||
if (dateCStr == NULL)
|
||||
return false;
|
||||
BDateTime newDate = feedDateToBDate( dateCStr );
|
||||
if ( newDate == NULL )
|
||||
BDateTime newDate = feedDateToBDate(dateCStr);
|
||||
if (newDate == NULL)
|
||||
return false;
|
||||
date = newDate;
|
||||
return true;
|
||||
}
|
||||
bool Feed::SetDate ( tinyxml2::XMLElement* elem ) {
|
||||
if ( elem != NULL ) return SetDate( elem->GetText() );
|
||||
|
||||
|
||||
bool
|
||||
Feed::SetDate(tinyxml2::XMLElement* elem)
|
||||
{
|
||||
if (elem != NULL)
|
||||
return SetDate(elem->GetText());
|
||||
else return false;
|
||||
}
|
||||
BDateTime Feed::GetDate ( ) { return date; }
|
||||
|
||||
|
||||
BDateTime
|
||||
Feed::GetDate()
|
||||
{
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
|
|
72
src/Feed.h
72
src/Feed.h
|
@ -1,47 +1,56 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef FEED_H
|
||||
#define FEED_H
|
||||
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <DateTime.h>
|
||||
#include <String.h>
|
||||
#include <List.h>
|
||||
#include <Url.h>
|
||||
|
||||
#include "Entry.h"
|
||||
|
||||
|
||||
class BDateTime;
|
||||
class BString;
|
||||
class BList;
|
||||
class BUrl;
|
||||
|
||||
|
||||
class Feed {
|
||||
public:
|
||||
Feed ( BString );
|
||||
Feed ( );
|
||||
Feed(BString);
|
||||
Feed();
|
||||
|
||||
virtual void Parse ( );
|
||||
virtual void Parse();
|
||||
|
||||
bool IsRemote ( );
|
||||
bool IsUpdated ( );
|
||||
bool IsRss ( );
|
||||
bool IsAtom ( );
|
||||
bool IsRemote();
|
||||
bool IsUpdated();
|
||||
bool IsRss();
|
||||
bool IsAtom();
|
||||
|
||||
bool AddEntry ( Entry* );
|
||||
BList GetEntries ( );
|
||||
bool SetTitle ( const char* );
|
||||
bool SetTitle ( tinyxml2::XMLElement* );
|
||||
BString GetTitle ( );
|
||||
bool SetDesc ( const char* );
|
||||
bool SetDesc ( tinyxml2::XMLElement* );
|
||||
BString GetDesc ( );
|
||||
bool SetHomeUrl ( const char* );
|
||||
bool SetHomeUrl ( tinyxml2::XMLElement* );
|
||||
BString GetHomeUrl ( );
|
||||
bool SetDate ( const char* );
|
||||
bool SetDate ( tinyxml2::XMLElement* );
|
||||
BDateTime GetDate ( );
|
||||
bool AddEntry(Entry*);
|
||||
BList GetEntries();
|
||||
bool SetTitle(const char*);
|
||||
bool SetTitle(tinyxml2::XMLElement*);
|
||||
BString GetTitle();
|
||||
bool SetDesc(const char*);
|
||||
bool SetDesc(tinyxml2::XMLElement*);
|
||||
BString GetDesc();
|
||||
bool SetHomeUrl(const char*);
|
||||
bool SetHomeUrl(tinyxml2::XMLElement*);
|
||||
BString GetHomeUrl();
|
||||
bool SetDate(const char*);
|
||||
bool SetDate(tinyxml2::XMLElement*);
|
||||
BDateTime GetDate();
|
||||
|
||||
BString SetCachePath ( BString );
|
||||
BString GetCachePath ( );
|
||||
BString SetCachePath(BString);
|
||||
BString GetCachePath();
|
||||
|
||||
protected:
|
||||
void EnsureCached ( );
|
||||
BString FetchRemoteFeed ( );
|
||||
int xmlCountSiblings ( tinyxml2::XMLElement*, const char* );
|
||||
void EnsureCached();
|
||||
BString FetchRemoteFeed();
|
||||
int xmlCountSiblings(tinyxml2::XMLElement*, const char*);
|
||||
|
||||
BString title;
|
||||
BString description;
|
||||
|
@ -57,7 +66,8 @@ protected:
|
|||
BList entries;
|
||||
bool fetched;
|
||||
bool updated;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,25 +1,35 @@
|
|||
#include <StorageKit.h>
|
||||
#include <String.h>
|
||||
#include <getopt.h>
|
||||
#include "AtomFeed.h"
|
||||
#include "RssFeed.h"
|
||||
#include "Feed.h"
|
||||
#include "Entry.h"
|
||||
#include "Mimetypes.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "App.h"
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "Invocation.h"
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "App.h"
|
||||
#include "AtomFeed.h"
|
||||
#include "Config.h"
|
||||
#include "Entry.h"
|
||||
#include "Feed.h"
|
||||
#include "Mimetypes.h"
|
||||
#include "RssFeed.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
int
|
||||
usage ( )
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "%s", usageMsg.String());
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
invocation ( int argc, char** argv )
|
||||
invocation(int argc, char** argv)
|
||||
{
|
||||
Config* cfg = ((App*)be_app)->cfg;
|
||||
BDateTime maxDate;
|
||||
|
@ -44,21 +54,21 @@ invocation ( int argc, char** argv )
|
|||
|
||||
switch (c) {
|
||||
case -1:
|
||||
freeargInvocation( argc, argv, optind );
|
||||
freeargInvocation(argc, argv, optind);
|
||||
return 0;
|
||||
case 'h':
|
||||
return usage();
|
||||
case 'c':
|
||||
cfg->configDir = BString( optarg );
|
||||
cfg->configDir = BString(optarg);
|
||||
break;
|
||||
case 'C':
|
||||
cfg->cacheDir = BString( optarg );
|
||||
cfg->cacheDir = BString(optarg);
|
||||
break;
|
||||
case 's':
|
||||
cfg->will_save = true;
|
||||
case 't':
|
||||
minDate = dateRfc3339ToBDate( optarg );
|
||||
if ( minDate != NULL )
|
||||
minDate = dateRfc3339ToBDate(optarg);
|
||||
if (minDate != NULL)
|
||||
cfg->minDate = minDate;
|
||||
else {
|
||||
fprintf(stderr, "Invalid date format for `-%c'.\n", optopt);
|
||||
|
@ -66,8 +76,8 @@ invocation ( int argc, char** argv )
|
|||
}
|
||||
break;
|
||||
case 'T':
|
||||
maxDate = dateRfc3339ToBDate( optarg );
|
||||
if ( maxDate != NULL )
|
||||
maxDate = dateRfc3339ToBDate(optarg);
|
||||
if (maxDate != NULL)
|
||||
cfg->maxDate = maxDate;
|
||||
else {
|
||||
fprintf(stderr, "Invalid date format for `-%c'.\n", optopt);
|
||||
|
@ -75,7 +85,7 @@ invocation ( int argc, char** argv )
|
|||
}
|
||||
break;
|
||||
case 'O':
|
||||
cfg->outDir = BString( optarg );
|
||||
cfg->outDir = BString(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
cfg->updateFeeds = true;
|
||||
|
@ -87,62 +97,62 @@ invocation ( int argc, char** argv )
|
|||
cfg->daemon = false;
|
||||
break;
|
||||
case '?':
|
||||
if ( optopt == 'O' || optopt == 'm' )
|
||||
fprintf( stderr, "Option `-%c` requires an argument.\n",
|
||||
optopt );
|
||||
if (optopt == 'O' || optopt == 'm')
|
||||
fprintf(stderr, "Option `-%c` requires an argument.\n",
|
||||
optopt);
|
||||
else
|
||||
fprintf( stderr, "Unknown option `-%c`.\n", optopt );
|
||||
fprintf(stderr, "Unknown option `-%c`.\n", optopt);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
void
|
||||
freeargInvocation ( int argc, char** argv, int optind )
|
||||
freeargInvocation(int argc, char** argv, int optind)
|
||||
{
|
||||
Config* cfg = ((App*)be_app)->cfg;
|
||||
if ( optind < argc ) {
|
||||
if (optind < argc) {
|
||||
int freeargc = argc - optind;
|
||||
cfg->targetFeeds = BList( freeargc );
|
||||
cfg->targetFeeds = BList(freeargc);
|
||||
|
||||
for ( int i = 0; i < freeargc; i++ ) {
|
||||
BString* newFeed = new BString( argv[optind + i] );
|
||||
cfg->targetFeeds.AddItem( newFeed );
|
||||
for (int i = 0; i < freeargc; i++) {
|
||||
BString* newFeed = new BString(argv[optind + i]);
|
||||
cfg->targetFeeds.AddItem(newFeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
processEntry ( void* entry )
|
||||
processEntry(void* entry)
|
||||
{
|
||||
Entry* entryPtr = (Entry*)entry;
|
||||
entryPtr->Filetize( false );
|
||||
Entry* entryPtr = (Entry*)entry;
|
||||
entryPtr->Filetize(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
processFeed ( void* feedArg )
|
||||
processFeed(void* feedArg)
|
||||
{
|
||||
BString* feedStr = (BString*)feedArg;
|
||||
Feed* testFeed = new Feed( *(feedStr) );
|
||||
Feed* testFeed = new Feed(*(feedStr));
|
||||
BList entries;
|
||||
|
||||
if ( testFeed->IsUpdated() == false && ((App*)be_app)->cfg->updateFeeds == true )
|
||||
if (testFeed->IsUpdated() == false
|
||||
&& ((App*)be_app)->cfg->updateFeeds == true)
|
||||
return false;
|
||||
|
||||
if ( testFeed->IsAtom() ) {
|
||||
AtomFeed* feed = (AtomFeed*)malloc( sizeof(AtomFeed) );
|
||||
feed = new AtomFeed( testFeed );
|
||||
if (testFeed->IsAtom()) {
|
||||
AtomFeed* feed = (AtomFeed*)malloc(sizeof(AtomFeed));
|
||||
feed = new AtomFeed(testFeed);
|
||||
feed->Parse();
|
||||
entries = feed->GetEntries();
|
||||
}
|
||||
if ( testFeed->IsRss() ) {
|
||||
RssFeed* feed = (RssFeed*)malloc( sizeof(RssFeed) );
|
||||
feed = new RssFeed( testFeed );
|
||||
if (testFeed->IsRss()) {
|
||||
RssFeed* feed = (RssFeed*)malloc(sizeof(RssFeed));
|
||||
feed = new RssFeed(testFeed);
|
||||
feed->Parse();
|
||||
entries = feed->GetEntries();
|
||||
}
|
||||
|
@ -150,3 +160,5 @@ processFeed ( void* feedArg )
|
|||
entries.DoForEach(&processEntry);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef INVOCATION_H
|
||||
#define INVOCATION_H
|
||||
|
||||
#include <StorageKit.h>
|
||||
|
||||
int usage ( );
|
||||
int invocation ( int, char** );
|
||||
|
@ -9,6 +12,6 @@ void freeargInvocation ( int, char**, int );
|
|||
bool processItem ( void* );
|
||||
bool processFeed ( void* );
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,47 +1,54 @@
|
|||
// borrowed significantly (addAttribute) from mailserver. thanks! <3
|
||||
#include <iostream>
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "Mimetypes.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <DateTime.h>
|
||||
#include <Message.h>
|
||||
#include <MimeType.h>
|
||||
#include "Mimetypes.h"
|
||||
|
||||
|
||||
// install the Feed Entry mimetype, if need be
|
||||
bool
|
||||
feedMimeType ( )
|
||||
feedMimeType()
|
||||
{
|
||||
BMessage info;
|
||||
BMimeType mime( "text/x-feed-entry" );
|
||||
if ( mime.IsInstalled() ) return true;
|
||||
BMimeType mime("text/x-feed-entry");
|
||||
if (mime.IsInstalled())
|
||||
return true;
|
||||
|
||||
std::cout << "NOT INSTALLED";
|
||||
mime.GetAttrInfo( &info );
|
||||
mime.GetAttrInfo(&info);
|
||||
|
||||
mime.SetShortDescription( "Feed Entry" );
|
||||
mime.SetLongDescription( "Atom/RSS Feed Entry" );
|
||||
mime.SetShortDescription("Feed Entry");
|
||||
mime.SetLongDescription("Atom/RSS Feed Entry");
|
||||
|
||||
addAttribute( info, "FEED:name", "Name" );
|
||||
addAttribute( info, "FEED:description", "Description" );
|
||||
addAttribute( info, "META:url", "URL" );
|
||||
addAttribute( info, "FEED:source", "Source" );
|
||||
addAttribute( info, "FEED:when", "When", B_TIME_TYPE, 150 );
|
||||
addAttribute(info, "FEED:name", "Name");
|
||||
addAttribute(info, "FEED:description", "Description");
|
||||
addAttribute(info, "META:url", "URL");
|
||||
addAttribute(info, "FEED:source", "Source");
|
||||
addAttribute(info, "FEED:when", "When", B_TIME_TYPE, 150);
|
||||
|
||||
return mime.SetAttrInfo( &info );
|
||||
return mime.SetAttrInfo(&info);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
// add the given attribute to a BMessage for use as attr info
|
||||
// borrowed from mailserver (thanks!)
|
||||
static void
|
||||
addAttribute
|
||||
( BMessage& msg, const char* name, const char* publicName, int32 type, int32 width )
|
||||
addAttribute(BMessage& msg, const char* name, const char* publicName,
|
||||
int32 type, int32 width)
|
||||
{
|
||||
msg.AddString( "attr:name", name );
|
||||
msg.AddString( "attr:public_name", publicName );
|
||||
msg.AddInt32( "attr:type", type );
|
||||
msg.AddInt32( "attr:width", width );
|
||||
msg.AddInt32( "attr:alignment", B_ALIGN_LEFT );
|
||||
msg.AddBool( "attr:extra", false );
|
||||
msg.AddBool( "attr:viewable", true );
|
||||
msg.AddBool( "attr:editable", true );
|
||||
msg.AddString("attr:name", name);
|
||||
msg.AddString("attr:public_name", publicName);
|
||||
msg.AddInt32("attr:type", type);
|
||||
msg.AddInt32("attr:width", width);
|
||||
msg.AddInt32("attr:alignment", B_ALIGN_LEFT);
|
||||
msg.AddBool("attr:extra", false);
|
||||
msg.AddBool("attr:viewable", true);
|
||||
msg.AddBool("attr:editable", true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef MIME_H
|
||||
#define MIME_H
|
||||
|
||||
#include <Message.h>
|
||||
#include <String.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <TypeConstants.h>
|
||||
|
||||
bool feedMimeType ( );
|
||||
|
||||
static void addAttribute
|
||||
( BMessage&, const char*, const char*, int32 type = B_STRING_TYPE, int32 width = 200);
|
||||
class BMessage;
|
||||
|
||||
|
||||
bool feedMimeType();
|
||||
|
||||
static void addAttribute(BMessage&, const char*, const char*,
|
||||
int32 type = B_STRING_TYPE, int32 width = 200);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,63 +1,78 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <UrlProtocolListener.h>
|
||||
#include <Url.h>
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "ProtocolListener.h"
|
||||
|
||||
ProtocolListener::ProtocolListener ( bool traceLogging )
|
||||
#include <Url.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
ProtocolListener::ProtocolListener(bool traceLogging)
|
||||
:
|
||||
fDownloadIO(NULL),
|
||||
fTraceLogging(traceLogging)
|
||||
{ }
|
||||
{}
|
||||
|
||||
|
||||
ProtocolListener::~ProtocolListener()
|
||||
{}
|
||||
|
||||
ProtocolListener::~ProtocolListener ( )
|
||||
{ }
|
||||
|
||||
void
|
||||
ProtocolListener::DataReceived ( BUrlRequest* caller, const char* data, off_t position, ssize_t size )
|
||||
ProtocolListener::DataReceived(BUrlRequest* caller, const char* data,
|
||||
off_t position, ssize_t size)
|
||||
{
|
||||
if ( fDownloadIO != NULL )
|
||||
fDownloadIO->Write( data, size );
|
||||
if ( fSha1 != NULL )
|
||||
fSha1->process_bytes( data, size );
|
||||
if (fDownloadIO != NULL)
|
||||
fDownloadIO->Write(data, size);
|
||||
if (fSha1 != NULL)
|
||||
fSha1->process_bytes(data, size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ProtocolListener::SetDownloadIO ( BDataIO* downloadIO )
|
||||
ProtocolListener::SetDownloadIO(BDataIO* downloadIO)
|
||||
{
|
||||
fDownloadIO = downloadIO;
|
||||
}
|
||||
|
||||
|
||||
BDataIO*
|
||||
ProtocolListener::GetDownloadIO ( )
|
||||
ProtocolListener::GetDownloadIO()
|
||||
{
|
||||
return fDownloadIO;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ProtocolListener::SetSha1 ( boost::uuids::detail::sha1* sha1 )
|
||||
ProtocolListener::SetSha1(boost::uuids::detail::sha1* sha1)
|
||||
{
|
||||
fSha1 = sha1;
|
||||
}
|
||||
|
||||
|
||||
boost::uuids::detail::sha1*
|
||||
ProtocolListener::GetSha1 ( )
|
||||
ProtocolListener::GetSha1()
|
||||
{
|
||||
return fSha1;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
ProtocolListener::GetHash ( )
|
||||
ProtocolListener::GetHash()
|
||||
{
|
||||
unsigned int hashInt[5];
|
||||
fSha1->get_digest( hashInt );
|
||||
fSha1->get_digest(hashInt);
|
||||
|
||||
std::ostringstream hashStr;
|
||||
for(std::size_t i=0; i<sizeof(hashInt)/sizeof(hashInt[0]); ++i) {
|
||||
hashStr << std::hex <<hashInt[i];
|
||||
}
|
||||
|
||||
return BString( hashStr.str().c_str() );
|
||||
return BString(hashStr.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,29 +1,36 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef PROTOCOL_LISTENER_H
|
||||
#define PROTOCOL_LISTENER_H
|
||||
|
||||
#include <UrlProtocolListener.h>
|
||||
#include <Url.h>
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
|
||||
#include <UrlProtocolListener.h>
|
||||
|
||||
|
||||
class ProtocolListener : public BUrlProtocolListener
|
||||
{
|
||||
public:
|
||||
ProtocolListener ( bool );
|
||||
|
||||
ProtocolListener(bool);
|
||||
virtual ~ProtocolListener();
|
||||
|
||||
virtual void DataReceived(BUrlRequest*, const char*, off_t, ssize_t);
|
||||
|
||||
void SetDownloadIO ( BDataIO* );
|
||||
BDataIO* GetDownloadIO ( );
|
||||
void SetDownloadIO(BDataIO*);
|
||||
BDataIO* GetDownloadIO();
|
||||
|
||||
void SetSha1 ( boost::uuids::detail::sha1* );
|
||||
boost::uuids::detail::sha1* GetSha1 ( );
|
||||
BString GetHash ( );
|
||||
void SetSha1(boost::uuids::detail::sha1*);
|
||||
boost::uuids::detail::sha1* GetSha1();
|
||||
BString GetHash();
|
||||
|
||||
private:
|
||||
BDataIO* fDownloadIO;
|
||||
BDataIO* fDownloadIO;
|
||||
boost::uuids::detail::sha1* fSha1;
|
||||
bool fTraceLogging;
|
||||
bool fTraceLogging;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
#include <tinyxml2.h>
|
||||
#include "Entry.h"
|
||||
#include "App.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "RssFeed.h"
|
||||
|
||||
RssFeed::RssFeed ( )
|
||||
#include "App.h"
|
||||
#include "Config.h"
|
||||
#include "Entry.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
RssFeed::RssFeed()
|
||||
{
|
||||
title = BString("Untitled Feed");
|
||||
description = BString("");
|
||||
|
@ -14,78 +20,81 @@ RssFeed::RssFeed ( )
|
|||
outputDir = ((App*)be_app)->cfg->outDir;
|
||||
}
|
||||
|
||||
RssFeed::RssFeed ( Feed* feed ) : RssFeed::RssFeed()
|
||||
{ SetCachePath( feed->GetCachePath() ); }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
RssFeed::RssFeed(Feed* feed) : RssFeed::RssFeed()
|
||||
{ SetCachePath(feed->GetCachePath()); }
|
||||
|
||||
|
||||
void
|
||||
RssFeed::Parse ( )
|
||||
RssFeed::Parse()
|
||||
{
|
||||
tinyxml2::XMLDocument xml;
|
||||
tinyxml2::XMLDocument xml;
|
||||
entries = BList();
|
||||
|
||||
Feed::Parse();
|
||||
|
||||
xml.LoadFile( GetCachePath().String() );
|
||||
xml.LoadFile(GetCachePath().String());
|
||||
tinyxml2::XMLElement* xchan = xml.FirstChildElement("rss")->FirstChildElement("channel");
|
||||
|
||||
RootParse( xchan );
|
||||
ParseEntries( xchan );
|
||||
RootParse(xchan);
|
||||
ParseEntries(xchan);
|
||||
|
||||
time_t tt_lastDate = lastDate.Time_t();
|
||||
BFile* feedFile = new BFile( GetCachePath().String(), B_READ_ONLY );
|
||||
feedFile->WriteAttr( "LastDate", B_TIME_TYPE, 0, &tt_lastDate, sizeof(time_t) );
|
||||
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_ONLY);
|
||||
feedFile->WriteAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate, sizeof(time_t));
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
void
|
||||
RssFeed::RootParse ( tinyxml2::XMLElement* xchan )
|
||||
RssFeed::RootParse(tinyxml2::XMLElement* xchan)
|
||||
{
|
||||
SetTitle ( xchan->FirstChildElement("title") );
|
||||
SetDesc ( xchan->FirstChildElement("description") );
|
||||
SetHomeUrl ( xchan->FirstChildElement("link") );
|
||||
SetDate ( xchan->FirstChildElement("lastBuildDate") );
|
||||
SetTitle(xchan->FirstChildElement("title"));
|
||||
SetDesc(xchan->FirstChildElement("description"));
|
||||
SetHomeUrl(xchan->FirstChildElement("link"));
|
||||
SetDate(xchan->FirstChildElement("lastBuildDate"));
|
||||
|
||||
if ( ((App*)be_app)->cfg->verbose )
|
||||
if (((App*)be_app)->cfg->verbose)
|
||||
printf("Channel '%s' at '%s':\n", title.String(), homeUrl.String());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RssFeed::EntryParse ( tinyxml2::XMLElement* xitem )
|
||||
RssFeed::EntryParse(tinyxml2::XMLElement* xitem)
|
||||
{
|
||||
Entry* newEntry = (Entry*)malloc( sizeof(Entry) );
|
||||
newEntry = new Entry( outputDir );
|
||||
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
|
||||
newEntry = new Entry(outputDir);
|
||||
|
||||
newEntry->SetTitle ( xitem->FirstChildElement("title") );
|
||||
newEntry->SetDesc ( xitem->FirstChildElement("description") );
|
||||
newEntry->SetDate ( xitem->FirstChildElement("pubDate") );
|
||||
newEntry->SetPostUrl ( xitem->FirstChildElement("link") );
|
||||
newEntry->SetContent ( xitem->FirstChildElement("content:encoded") );
|
||||
newEntry->SetFeedTitle( title );
|
||||
newEntry->SetTitle(xitem->FirstChildElement("title"));
|
||||
newEntry->SetDesc(xitem->FirstChildElement("description"));
|
||||
newEntry->SetDate(xitem->FirstChildElement("pubDate"));
|
||||
newEntry->SetPostUrl(xitem->FirstChildElement("link"));
|
||||
newEntry->SetContent(xitem->FirstChildElement("content:encoded"));
|
||||
newEntry->SetFeedTitle(title);
|
||||
|
||||
if ( lastDate == NULL || lastDate < newEntry->date )
|
||||
if (lastDate == NULL || lastDate < newEntry->date)
|
||||
lastDate = newEntry->date;
|
||||
|
||||
AddEntry( newEntry );
|
||||
AddEntry(newEntry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RssFeed::ParseEntries ( tinyxml2::XMLElement* xchan )
|
||||
RssFeed::ParseEntries(tinyxml2::XMLElement* xchan)
|
||||
{
|
||||
tinyxml2::XMLElement* xitem;
|
||||
|
||||
xitem = xchan->FirstChildElement("item");
|
||||
|
||||
int entryCount = xmlCountSiblings( xitem, "item" );
|
||||
int entryCount = xmlCountSiblings(xitem, "item");
|
||||
entries = BList(entryCount);
|
||||
|
||||
if ( ((App*)be_app)->cfg->verbose )
|
||||
if (((App*)be_app)->cfg->verbose)
|
||||
printf("\t-%i entries-\n", entryCount);
|
||||
|
||||
while ( xitem ) {
|
||||
EntryParse( xitem );
|
||||
while (xitem) {
|
||||
EntryParse(xitem);
|
||||
xitem = xitem->NextSiblingElement("item");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef RSS_FEED_H
|
||||
#define RSS_FEED_H
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <DateTime.h>
|
||||
#include <String.h>
|
||||
#include <List.h>
|
||||
#include <Url.h>
|
||||
|
||||
#include "Feed.h"
|
||||
|
||||
|
||||
class RssFeed: public Feed {
|
||||
public:
|
||||
RssFeed ( );
|
||||
RssFeed ( Feed* );
|
||||
RssFeed();
|
||||
RssFeed(Feed*);
|
||||
|
||||
void Parse ( );
|
||||
void RootParse ( tinyxml2::XMLElement* );
|
||||
void EntryParse ( tinyxml2::XMLElement* );
|
||||
void ParseEntries ( tinyxml2::XMLElement* );
|
||||
void Parse();
|
||||
void RootParse(tinyxml2::XMLElement*);
|
||||
void EntryParse(tinyxml2::XMLElement*);
|
||||
void ParseEntries(tinyxml2::XMLElement*);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
114
src/Util.cpp
114
src/Util.cpp
|
@ -1,117 +1,125 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <locale>
|
||||
#include <iomanip>
|
||||
#include <DateTime.h>
|
||||
#include <UrlProtocolRoster.h>
|
||||
#include <Url.h>
|
||||
#include <UrlRequest.h>
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#include "ProtocolListener.h"
|
||||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#include <Url.h>
|
||||
#include <UrlProtocolRoster.h>
|
||||
#include <UrlRequest.h>
|
||||
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "ProtocolListener.h"
|
||||
|
||||
|
||||
BDateTime
|
||||
feedDateToBDate ( const char* dateCStr )
|
||||
feedDateToBDate(const char* dateCStr)
|
||||
{
|
||||
BDateTime date = dateRfc822ToBDate( dateCStr );
|
||||
if ( date == NULL ) date = dateRfc3339ToBDate( dateCStr );
|
||||
BDateTime date = dateRfc822ToBDate(dateCStr);
|
||||
if (date == NULL)
|
||||
date = dateRfc3339ToBDate(dateCStr);
|
||||
return date;
|
||||
}
|
||||
|
||||
BDateTime
|
||||
dateRfc3339ToBDate ( const char* dateCStr )
|
||||
{
|
||||
return stringDateToBDate( dateCStr, "%Y-%m-%dT%H:%M:%S" );
|
||||
}
|
||||
|
||||
BDateTime
|
||||
dateRfc822ToBDate ( const char* dateCStr )
|
||||
dateRfc3339ToBDate(const char* dateCStr)
|
||||
{
|
||||
return stringDateToBDate( dateCStr, "%a, %d %b %Y %H:%M:%S" );
|
||||
return stringDateToBDate(dateCStr, "%Y-%m-%dT%H:%M:%S");
|
||||
}
|
||||
|
||||
|
||||
BDateTime
|
||||
stringDateToBDate ( const char* dateCStr, const char* templateCStr )
|
||||
dateRfc822ToBDate(const char* dateCStr)
|
||||
{
|
||||
std::istringstream dateStream( dateCStr );
|
||||
return stringDateToBDate(dateCStr, "%a, %d %b %Y %H:%M:%S");
|
||||
}
|
||||
|
||||
|
||||
BDateTime
|
||||
stringDateToBDate(const char* dateCStr, const char* templateCStr)
|
||||
{
|
||||
std::istringstream dateStream(dateCStr);
|
||||
std::tm time = {};
|
||||
|
||||
if ( dateStream >> std::get_time( &time, templateCStr ) ) {
|
||||
BTime newTime = BTime( time.tm_hour, time.tm_min, time.tm_sec, 0 );
|
||||
BDate newDate = BDate( time.tm_year + 1900, time.tm_mon + 1, time.tm_mday );
|
||||
return BDateTime( newDate, newTime );
|
||||
if (dateStream >> std::get_time(&time, templateCStr)) {
|
||||
BTime newTime = BTime(time.tm_hour, time.tm_min, time.tm_sec, 0);
|
||||
BDate newDate = BDate(time.tm_year + 1900, time.tm_mon + 1,
|
||||
time.tm_mday);
|
||||
return BDateTime(newDate, newTime);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BString
|
||||
dateTo3339String ( BDateTime dt )
|
||||
dateTo3339String(BDateTime dt)
|
||||
{
|
||||
char buffer[18];
|
||||
sprintf( buffer, "%i-%02i-%02iT%02i:%02i:%02i",
|
||||
dt.Date().Year(), dt.Date().Month(), dt.Date().Day(),
|
||||
dt.Time().Hour(), dt.Time().Minute(), dt.Time().Second() );
|
||||
sprintf(buffer, "%i-%02i-%02iT%02i:%02i:%02i",
|
||||
dt.Date().Year(), dt.Date().Month(), dt.Date().Day(),
|
||||
dt.Time().Hour(), dt.Time().Minute(), dt.Time().Second());
|
||||
|
||||
return BString( buffer );
|
||||
return BString(buffer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
withinDateRange ( BDateTime minDate, BDateTime nowDate, BDateTime maxDate )
|
||||
withinDateRange(BDateTime minDate, BDateTime nowDate, BDateTime maxDate)
|
||||
{
|
||||
if ( minDate != NULL && nowDate != NULL && maxDate != NULL )
|
||||
return ( minDate < nowDate && nowDate < maxDate );
|
||||
if ( minDate != NULL && nowDate != NULL )
|
||||
return ( minDate < nowDate );
|
||||
if ( maxDate != NULL && nowDate != NULL )
|
||||
return ( nowDate < maxDate );
|
||||
if (minDate != NULL && nowDate != NULL && maxDate != NULL)
|
||||
return (minDate < nowDate && nowDate < maxDate);
|
||||
if (minDate != NULL && nowDate != NULL)
|
||||
return (minDate < nowDate);
|
||||
if (maxDate != NULL && nowDate != NULL)
|
||||
return (nowDate < maxDate);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// return whether or not the given path is remote
|
||||
bool
|
||||
isRemotePath ( BString path ) {
|
||||
BUrl givenUrl = BUrl( path );
|
||||
isRemotePath(BString path) {
|
||||
BUrl givenUrl = BUrl(path);
|
||||
BString protocol = givenUrl.Protocol().String();
|
||||
|
||||
if ( protocol == NULL || protocol == BString("file") || givenUrl.UrlString() == NULL )
|
||||
if (protocol == NULL || protocol == BString("file")
|
||||
|| givenUrl.UrlString() == NULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int32
|
||||
webFetch ( BUrl url, BDataIO* reply )
|
||||
webFetch(BUrl url, BDataIO* reply)
|
||||
{
|
||||
BString* ignored = new BString();
|
||||
return webFetch( url, reply, ignored );
|
||||
return webFetch(url, reply, ignored);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
webFetch ( BUrl url, BDataIO* reply, BString* hash )
|
||||
webFetch(BUrl url, BDataIO* reply, BString* hash)
|
||||
{
|
||||
ProtocolListener listener(true);
|
||||
boost::uuids::detail::sha1 sha1;
|
||||
|
||||
BUrlRequest* request = BUrlProtocolRoster::MakeRequest( url, &listener );
|
||||
BUrlRequest* request = BUrlProtocolRoster::MakeRequest(url, &listener);
|
||||
|
||||
listener.SetDownloadIO( reply );
|
||||
listener.SetSha1( &sha1 );
|
||||
listener.SetDownloadIO(reply);
|
||||
listener.SetSha1(&sha1);
|
||||
|
||||
thread_id thread = request->Run();
|
||||
wait_for_thread( thread, NULL );
|
||||
wait_for_thread(thread, NULL);
|
||||
|
||||
*(hash) = listener.GetHash();
|
||||
|
||||
return request->Status();
|
||||
return 200;
|
||||
}
|
||||
|
||||
|
||||
|
|
29
src/Util.h
29
src/Util.h
|
@ -1,22 +1,31 @@
|
|||
/*
|
||||
* Copyright 2020, Jaidyn Levesque <jadedctrl@teknik.io>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include <DateTime.h>
|
||||
#include <Url.h>
|
||||
|
||||
#include "ProtocolListener.h"
|
||||
|
||||
BDateTime feedDateToBDate ( const char* );
|
||||
BDateTime dateRfc3339ToBDate ( const char* );
|
||||
BDateTime dateRfc822ToBDate ( const char* );
|
||||
BDateTime stringDateToBDate ( const char*, const char* );
|
||||
class BUrl;
|
||||
|
||||
BString dateTo3339String ( BDateTime );
|
||||
|
||||
bool withinDateRange ( BDateTime, BDateTime, BDateTime );
|
||||
BDateTime feedDateToBDate(const char*);
|
||||
BDateTime dateRfc3339ToBDate(const char*);
|
||||
BDateTime dateRfc822ToBDate(const char*);
|
||||
BDateTime stringDateToBDate(const char*, const char*);
|
||||
|
||||
bool isRemotePath ( BString );
|
||||
BString dateTo3339String(BDateTime);
|
||||
|
||||
bool withinDateRange(BDateTime, BDateTime, BDateTime);
|
||||
|
||||
bool isRemotePath(BString);
|
||||
|
||||
int32 webFetch(BUrl, BDataIO*, BString*);
|
||||
int32 webFetch(BUrl, BDataIO*);
|
||||
|
||||
int32 webFetch ( BUrl, BDataIO*, BString* );
|
||||
int32 webFetch ( BUrl, BDataIO* );
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Ŝarĝante…
Reference in New Issue