mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Started integration of PicoFeed
• Integrated PicoFeed into Database->subscriptionAdd • Added exception handling for feeds • Added static method for formatting SQL dates into Db/Common
This commit is contained in:
parent
e6feb8de8d
commit
e5d825d360
5 changed files with 110 additions and 20 deletions
|
@ -39,6 +39,17 @@ abstract class AbstractException extends \Exception {
|
|||
"User/Exception.authMissing" => 10411,
|
||||
"User/Exception.authFailed" => 10412,
|
||||
"User/Exception.notAuthorized" => 10421,
|
||||
"Feed/Exception.invalidCertificate" => 10501,
|
||||
"Feed/Exception.invalidUrl" => 10502,
|
||||
"Feed/Exception.maxRedirect" => 10503,
|
||||
"Feed/Exception.maxSize" => 10504,
|
||||
"Feed/Exception.timeout" => 10505,
|
||||
"Feed/Exception.forbidden" => 10506,
|
||||
"Feed/Exception.unauthorized" => 10507,
|
||||
"Feed/Exception.malformed" => 10511,
|
||||
"Feed/Exception.xmlEntity" => 10512,
|
||||
"Feed/Exception.subscriptionNotFound" => 10521,
|
||||
"Feed/Exception.unsupportedFeedFormat" => 10522
|
||||
];
|
||||
|
||||
public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) {
|
||||
|
|
|
@ -3,6 +3,9 @@ declare(strict_types=1);
|
|||
namespace JKingWeb\NewsSync;
|
||||
|
||||
class Database {
|
||||
use PicoFeed\Reader\Reader;
|
||||
use PicoFeed\PicoFeedException;
|
||||
|
||||
const SCHEMA_VERSION = 1;
|
||||
const FORMAT_TS = "Y-m-d h:i:s";
|
||||
const FORMAT_DATE = "Y-m-d";
|
||||
|
@ -10,6 +13,7 @@ class Database {
|
|||
|
||||
protected $data;
|
||||
public $db;
|
||||
private $driver;
|
||||
|
||||
protected function cleanName(string $name): string {
|
||||
return (string) preg_filter("[^0-9a-zA-Z_\.]", "", $name);
|
||||
|
@ -17,8 +21,8 @@ class Database {
|
|||
|
||||
public function __construct(RuntimeData $data) {
|
||||
$this->data = $data;
|
||||
$driver = $data->conf->dbDriver;
|
||||
$this->db = $driver::create($data, INSTALL);
|
||||
$this->driver = $data->conf->dbDriver;
|
||||
$this->db = $this->driver::create($data, INSTALL);
|
||||
$ver = $this->db->schemaVersion();
|
||||
if(!INSTALL && $ver < self::SCHEMA_VERSION) {
|
||||
$this->db->update(self::SCHEMA_VERSION);
|
||||
|
@ -251,15 +255,55 @@ class Database {
|
|||
}
|
||||
|
||||
public function subscriptionAdd(string $user, string $url, string $fetchUser = "", string $fetchPassword = ""): int {
|
||||
if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
if(!$this->userExists($user)) throw new User\Exception("doesNotExist", ["user" => $user, "action" => __FUNCTION__]);
|
||||
// If the user isn't authorized to perform this action then throw an exception.
|
||||
if (!$this->data->user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// If the user doesn't exist throw an exception.
|
||||
if (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["user" => $user, "action" => __FUNCTION__]);
|
||||
}
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
// If the feed doesn't already exist in the database then add it to the database after determining its validity with picoFeed
|
||||
$qFeed = $this->db->prepare("SELECT id from newssync_feeds where url is ? and username is ? and password is ?", "str", "str", "str");
|
||||
$feed = $qFeed->run($url, $fetchUser, $fetchPassword)->getSingle();
|
||||
if ($feed === null) {
|
||||
$this->db->prepare("INSERT INTO newssync_feeds(url,username,password) values(?,?,?)", "str", "str", "str")->run($url, $fetchUser, $fetchPassword);
|
||||
try {
|
||||
$reader = new Reader;
|
||||
$resource = $reader->download($url);
|
||||
|
||||
$parser = $reader->getParser(
|
||||
$resource->getUrl(),
|
||||
$resource->getContent(),
|
||||
$resource->getEncoding()
|
||||
);
|
||||
|
||||
$feed = $parser->execute();
|
||||
} catch (PicoFeedException $e) {
|
||||
// If there's any error while trying to download or parse the feed then return an exception
|
||||
throw new Feed\Exception($url, $e);
|
||||
}
|
||||
|
||||
$this->db->prepare("INSERT INTO newssync_feeds(url,title,favicon,source,updated,modified,etag,username,password) values(?,?,?)", "str", "str", "str", "str", "str", "str", "str", "str", "str")->run(
|
||||
$url,
|
||||
$feed->title,
|
||||
// Grab the favicon for the feed. Returns an empty string if it cannot find one
|
||||
(new PicoFeed\Reader\Favicon)->find($url),
|
||||
$feed->siteUrl,
|
||||
// Convert the date formats to ISO 8601 before inserting
|
||||
$driver::formatDate($feed->date),
|
||||
$driver::formatDate($resource->getLastModified()),
|
||||
$resource->getEtag(),
|
||||
$fetchUser,
|
||||
$fetchPassword
|
||||
);
|
||||
|
||||
$feed = $qFeed->run($url, $fetchUser, $fetchPassword)->getSingle();
|
||||
}
|
||||
|
||||
// Add the feed to a user's subscriptions.
|
||||
$this->db->prepare("INSERT INTO newssync_subscriptions(owner,feed) values(?,?)", "str", "int")->run($user,$feed);
|
||||
$sub = $this->db->prepare("SELECT id from newssync_subscriptions where owner is ? and feed is ?", "str", "int")->run($user, $feed)->getSingle();
|
||||
$this->db->commit();
|
||||
|
|
|
@ -70,4 +70,13 @@ Trait Common {
|
|||
return $this->prepareArray($query, $paramType);
|
||||
}
|
||||
|
||||
public static function formatDate(string $date): string {
|
||||
// Force UTC.
|
||||
$timezone = date_default_timezone_get();
|
||||
date_default_timezone_set('UTC');
|
||||
// ISO 8601 with space in the middle instead of T.
|
||||
$date = date('Y-m-d h:i:sP', strtotime($date));
|
||||
date_default_timezone_set($timezone);
|
||||
return $date;
|
||||
}
|
||||
}
|
14
lib/Feed/Exception.php
Normal file
14
lib/Feed/Exception.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync\Feed;
|
||||
|
||||
class Exception extends \JKingWeb\NewsSync\AbstractException {
|
||||
public function __construct($url, \Throwable $e) {
|
||||
$className = get_class($e);
|
||||
// Convert the exception thrown by PicoFeed to the one to be thrown here.
|
||||
$msgID = preg_replace('/^PicoFeed\\\(?:Client|Parser|Reader)\\\([A-Za-z]+)Exception$/', '$1', $className);
|
||||
// If the message ID doesn't change then it's unknown.
|
||||
$msgID = ($msgID !== $className) ? lcfirst($msgID) : '';
|
||||
parent::__construct($msgID, ['url' => $url], $e);
|
||||
}
|
||||
}
|
|
@ -51,4 +51,16 @@ return [
|
|||
'Exception.JKingWeb/NewsSync/User/Exception.authMissing' => 'Please log in to proceed',
|
||||
'Exception.JKingWeb/NewsSync/User/Exception.authFailed' => 'Authentication failed',
|
||||
'Exception.JKingWeb/NewsSync/User/ExceptionAuthz.notAuthorized' => 'Authenticated user is not authorized to perform the action "{action}" on behalf of {user}',
|
||||
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.invalidCertificate' => 'Could not download feed "{url}" because its server is serving an invalid SSL certificate',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.invalidURL' => 'Feed URL "{url}" is invalid',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.maxRedirect' => 'Could not download feed "{url}" because its server reached its maximum number of HTTP redirections',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.maxSize' => 'Could not download feed "{url}" because its size exceeds the maximum allowed on its server',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.timeout' => 'Could not download feed "{url}" because its server timed out',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.forbidden' => 'Could not download feed "{url}" because you do not have permission to access it',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.unauthorized' => 'Could not download feed "{url}" because you provided insufficient or invalid credentials',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.malformed' => 'Could not parse feed "{url}" because it is malformed',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.xxe' => 'Refused to parse feed "{url}" because it contains an XXE attack',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.subscriptionNotFound' => 'Unable to find a feed at location "{url}"',
|
||||
'Exception.JKingWeb/NewsSync/Feed/Exception.unsupportedFormat' => 'Feed "{url}" is of an unsupported format'
|
||||
];
|
Loading…
Reference in a new issue