mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Documentation tweaks and CS fixes
This commit is contained in:
parent
6c34bf3c9c
commit
22cdc8916d
11 changed files with 55 additions and 48 deletions
26
README.md
26
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
The Arsse is a news aggregator server which implements multiple synchronization protocols, including [version 1.2][NCNv1] of [NextCloud News](https://github.com/nextcloud/news)' protocol and the [Tiny Tiny RSS][TTRSS] protocol ([details](#proto)). Unlike most other aggregator servers, The Arsse does not include a Web front-end (though one is planned as a separate project), and it relies on existing protocols to maximize compatibility with existing clients.
|
The Arsse is a news aggregator server which implements multiple synchronization protocols, including [version 1.2][NCNv1] of [NextCloud News](https://github.com/nextcloud/news)' protocol and the [Tiny Tiny RSS][TTRSS] protocol ([details](#proto)). Unlike most other aggregator servers, The Arsse does not include a Web front-end (though one is planned as a separate project), and it relies on existing protocols to maximize compatibility with existing clients.
|
||||||
|
|
||||||
At present the software should be considered in an "alpha" state: though its core subsystems are covered by unit tests and should be free of major bugs, not everything has been rigorously tested. Additionally, though the NextCloud News protocol is fully supported, many features one would expect from other similar software have yet to be implemented. Areas of future work include:
|
At present the software should be considered in an "alpha" state: though its core subsystems are covered by unit tests and should be free of major bugs, not everything has been rigorously tested. Additionally, many features one would expect from other similar software have yet to be implemented. Areas of future work include:
|
||||||
|
|
||||||
- Support for more database engines (PostgreSQL, MySQL, MariaDB)
|
- Support for more database engines (PostgreSQL, MySQL, MariaDB)
|
||||||
- Providing more sync protocols (Google Reader, Fever, others)
|
- Providing more sync protocols (Google Reader, Fever, others)
|
||||||
|
@ -14,7 +14,7 @@ At present the software should be considered in an "alpha" state: though its cor
|
||||||
The Arsse has the following requirements:
|
The Arsse has the following requirements:
|
||||||
|
|
||||||
- A Linux server utilizing systemd and Nginx (tested on Ubuntu 16.04)
|
- A Linux server utilizing systemd and Nginx (tested on Ubuntu 16.04)
|
||||||
- PHP 7.0.7 or newer with the following extensions:
|
- PHP 7.0.7 or later with the following extensions:
|
||||||
- [intl](http://php.net/manual/en/book.intl.php), [json](http://php.net/manual/en/book.json.php), [hash](http://php.net/manual/en/book.hash.php), and [pcre](http://php.net/manual/en/book.pcre.php)
|
- [intl](http://php.net/manual/en/book.intl.php), [json](http://php.net/manual/en/book.json.php), [hash](http://php.net/manual/en/book.hash.php), and [pcre](http://php.net/manual/en/book.pcre.php)
|
||||||
- [dom](http://php.net/manual/en/book.dom.php), [simplexml](http://php.net/manual/en/book.simplexml.php), and [iconv](http://php.net/manual/en/book.iconv.php) (for picoFeed)
|
- [dom](http://php.net/manual/en/book.dom.php), [simplexml](http://php.net/manual/en/book.simplexml.php), and [iconv](http://php.net/manual/en/book.iconv.php) (for picoFeed)
|
||||||
- [sqlite3](http://php.net/manual/en/book.sqlite3.php)
|
- [sqlite3](http://php.net/manual/en/book.sqlite3.php)
|
||||||
|
@ -62,7 +62,7 @@ php ./arsse.php conf save-defaults "./config.defaults.php"
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The Arsse is made available under the permissive MIT license. See the `LICENSE` file included with the distribution or source code for exact legal text. Dependencies included in the distribution may be governed by other licenses.
|
The Arsse is made available under the permissive MIT license. See the `LICENSE` and `AUTHORS` files included with the distribution or source code for exact legal text and copyright holders. Dependencies included in the distribution may be governed by other licenses.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
@ -76,11 +76,11 @@ Please refer to `CONTRIBUTING.md` for guidelines on contributing code to The Ars
|
||||||
|
|
||||||
The Arsse does not guarantee it will handle type casting of input in the same way as reference implementations for its supported protocols. As a general rule, clients should endeavour to send only correct input.
|
The Arsse does not guarantee it will handle type casting of input in the same way as reference implementations for its supported protocols. As a general rule, clients should endeavour to send only correct input.
|
||||||
|
|
||||||
The Arsse _does_, however, guarantee output to be of the same type. If it is not, this is [a bug][newIssue] and should be reported.
|
The Arsse does, however, guarantee _output_ to be of the same type. If it is not, this is [a bug][newIssue] and should be reported.
|
||||||
|
|
||||||
#### Content sanitization
|
#### Content sanitization
|
||||||
|
|
||||||
The Arsse makes use of the [picoFeed](https://github.com/miniflux/picoFeed/) newsfeed parsing library to sanitize article content. The exact sanitization rules may differ from those of reference implementations for protocols The Arsse supports.
|
The Arsse makes use of the [picoFeed](https://github.com/miniflux/picoFeed/) newsfeed parsing library to sanitize article content. The exact sanitization parameters may differ from those of reference implementations for protocols The Arsse supports.
|
||||||
|
|
||||||
### <a name="proto-ncnv1"></a> NextCloud News v1.2
|
### <a name="proto-ncnv1"></a> NextCloud News v1.2
|
||||||
|
|
||||||
|
@ -97,18 +97,18 @@ As a general rule, The Arsse should yield the same output as the reference imple
|
||||||
- When marking articles as starred the feed ID is ignored, as they are not needed to establish uniqueness
|
- When marking articles as starred the feed ID is ignored, as they are not needed to establish uniqueness
|
||||||
- The feed updater ignores the `userId` parameter: feeds in The Arsse are deduplicated, and have no owner
|
- The feed updater ignores the `userId` parameter: feeds in The Arsse are deduplicated, and have no owner
|
||||||
- The `/feeds/all` route lists only feeds which should be checked for updates, and it also returns all `userId` attributes as empty strings: feeds in The Arsse are deduplicated, and have no owner
|
- The `/feeds/all` route lists only feeds which should be checked for updates, and it also returns all `userId` attributes as empty strings: feeds in The Arsse are deduplicated, and have no owner
|
||||||
- The updater console commands mentioned in the protocol specification are not implemented
|
- The updater console commands mentioned in the protocol specification are not implemented, as The Arsse does not implement the required NextCloud subsystems
|
||||||
- The `lastLoginTimestamp` attribute of the user metadata is always the current time: The Arsse's implementation of the protocol is fully stateless
|
- The `lastLoginTimestamp` attribute of the user metadata is always the current time: The Arsse's implementation of the protocol is fully stateless
|
||||||
|
|
||||||
#### Ambiguities
|
#### Ambiguities
|
||||||
|
|
||||||
- [The protocol][NCNv1] does not specify an output character encoding, but the reference server uses UTF-8; The Arsse also uses UTF-8
|
- NCN does not specify an output character encoding, but the reference server uses UTF-8; The Arsse also uses UTF-8
|
||||||
- The protocol specifies that GET parameters are treated "the same" as request body parameters; it does not specify what to do in cases where they conflict. The Arsse chooses to give GET parameters precedence
|
- NCN specifies that GET parameters are treated "the same" as request body parameters; it does not specify what to do in cases where they conflict. The Arsse chooses to give GET parameters precedence
|
||||||
- The protocol does not define validity of folder and names other than to say that the empty string is invalid. The Arsse further considers any string composed only of whitesapce to be invalid
|
- NCN does not define validity of folder and names other than to say that the empty string is invalid. The Arsse further considers any string composed only of whitesapce to be invalid
|
||||||
- The protocol does not specify a return code for bulk-marking operations without a `newestItemId` provided; The Arsse returns `422`
|
- NCN does not specify a return code for bulk-marking operations without a `newestItemId` provided; The Arsse returns `422`
|
||||||
- The protocol does not specify what should be done when creating a feed in a folder which does not exist; the Arsse adds the feed to the root folder
|
- NCN does not specify what should be done when creating a feed in a folder which does not exist; the Arsse adds the feed to the root folder
|
||||||
- The protocol does not specify what should be done when moving a feed to a folder which does not exist; The Arsse return `422`
|
- NCN does not specify what should be done when moving a feed to a folder which does not exist; The Arsse return `422`
|
||||||
- The protocol does not specify what should be done when renaming a feed to an invalid title, nor what constitutes an invalid title; The Arsse uses the same rules as it does for folders, and returns `422` in cases of rejection
|
- NCN does not specify what should be done when renaming a feed to an invalid title, nor what constitutes an invalid title; The Arsse uses the same rules as it does for folders, and returns `422` in cases of rejection
|
||||||
|
|
||||||
### <a name="proto-ttrss"></a> Tiny Tiny RSS
|
### <a name="proto-ttrss"></a> Tiny Tiny RSS
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,9 @@ class ResultAggregate extends AbstractResult {
|
||||||
// actual public methods
|
// actual public methods
|
||||||
|
|
||||||
public function changes() {
|
public function changes() {
|
||||||
return array_reduce($this->data, function($sum, $value) {return $sum + $value->changes();}, 0);
|
return array_reduce($this->data, function ($sum, $value) {
|
||||||
|
return $sum + $value->changes();
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function lastId() {
|
public function lastId() {
|
||||||
|
|
|
@ -333,7 +333,9 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
'id' => "FEED:".self::FEED_ALL,
|
'id' => "FEED:".self::FEED_ALL,
|
||||||
'bare_id' => self::FEED_ALL,
|
'bare_id' => self::FEED_ALL,
|
||||||
'icon' => "images/folder.png",
|
'icon' => "images/folder.png",
|
||||||
'unread' => array_reduce($subs, function($sum, $value) {return $sum + $value['unread'];}, 0), // the sum of all feeds' unread is the total unread
|
'unread' => array_reduce($subs, function ($sum, $value) {
|
||||||
|
return $sum + $value['unread'];
|
||||||
|
}, 0), // the sum of all feeds' unread is the total unread
|
||||||
], $tSpecial),
|
], $tSpecial),
|
||||||
array_merge([ // Fresh articles
|
array_merge([ // Fresh articles
|
||||||
'name' => Arsse::$lang->msg("API.TTRSS.Feed.Fresh"),
|
'name' => Arsse::$lang->msg("API.TTRSS.Feed.Fresh"),
|
||||||
|
|
|
@ -10,8 +10,6 @@ use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\REST\Response;
|
use JKingWeb\Arsse\REST\Response;
|
||||||
|
|
||||||
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
|
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +23,7 @@ class Icon extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$url = Arsse::$db->subscriptionFavicon((int) $match[1]);
|
$url = Arsse::$db->subscriptionFavicon((int) $match[1]);
|
||||||
if ($url) {
|
if ($url) {
|
||||||
// strip out anything after literal line-end characters; this is to mitigate a potential header (e.g. cookie) injection from the URL
|
// strip out anything after literal line-end characters; this is to mitigate a potential header (e.g. cookie) injection from the URL
|
||||||
if (($pos = strpos($url, "\r")) !== FALSE || ($pos = strpos($url, "\n")) !== FALSE) {
|
if (($pos = strpos($url, "\r")) !== false || ($pos = strpos($url, "\n")) !== false) {
|
||||||
$url = substr($url, 0, $pos);
|
$url = substr($url, 0, $pos);
|
||||||
}
|
}
|
||||||
return new Response(301, "", "", ["Location: $url"]);
|
return new Response(301, "", "", ["Location: $url"]);
|
||||||
|
|
|
@ -6,7 +6,6 @@ use JKingWeb\Arsse\Test\Result;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Db\ResultAggregate<extended> */
|
/** @covers \JKingWeb\Arsse\Db\ResultAggregate<extended> */
|
||||||
class TestResultAggregate extends Test\AbstractTest {
|
class TestResultAggregate extends Test\AbstractTest {
|
||||||
|
|
||||||
public function testGetChangeCountAndLastInsertId() {
|
public function testGetChangeCountAndLastInsertId() {
|
||||||
$in = [
|
$in = [
|
||||||
new Result([], 3, 4),
|
new Result([], 3, 4),
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
/** @covers \JKingWeb\Arsse\Db\ResultEmpty<extended> */
|
/** @covers \JKingWeb\Arsse\Db\ResultEmpty<extended> */
|
||||||
class TestResultEmpty extends Test\AbstractTest {
|
class TestResultEmpty extends Test\AbstractTest {
|
||||||
|
|
||||||
public function testGetChangeCountAndLastInsertId() {
|
public function testGetChangeCountAndLastInsertId() {
|
||||||
$r = new Db\ResultEmpty;
|
$r = new Db\ResultEmpty;
|
||||||
$this->assertEquals(0, $r->changes());
|
$this->assertEquals(0, $r->changes());
|
||||||
|
|
|
@ -1184,11 +1184,15 @@ LONG_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function filterFolders(int $id = null): array {
|
protected function filterFolders(int $id = null): array {
|
||||||
return array_filter($this->folders, function($value) use ($id) {return $value['parent']==$id;});
|
return array_filter($this->folders, function ($value) use ($id) {
|
||||||
|
return $value['parent']==$id;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function filterSubs(int $folder = null): array {
|
protected function filterSubs(int $folder = null): array {
|
||||||
return array_filter($this->subscriptions, function($value) use ($folder) {return $value['folder']==$folder;});
|
return array_filter($this->subscriptions, function ($value) use ($folder) {
|
||||||
|
return $value['folder']==$folder;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function reduceFolders(int $id = null) : int {
|
protected function reduceFolders(int $id = null) : int {
|
||||||
|
@ -1196,7 +1200,11 @@ LONG_STRING;
|
||||||
foreach ($this->filterFolders($id) as $f) {
|
foreach ($this->filterFolders($id) as $f) {
|
||||||
$out += $this->reduceFolders($f['id']);
|
$out += $this->reduceFolders($f['id']);
|
||||||
}
|
}
|
||||||
$out += array_reduce(array_filter($this->subscriptions, function($value) use ($id) {return $value['folder']==$id;}), function($sum, $value) {return $sum + $value['unread'];}, 0);
|
$out += array_reduce(array_filter($this->subscriptions, function ($value) use ($id) {
|
||||||
|
return $value['folder']==$id;
|
||||||
|
}), function ($sum, $value) {
|
||||||
|
return $sum + $value['unread'];
|
||||||
|
}, 0);
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,6 @@ trait SeriesSubscription {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2));
|
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user, 2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testListSubscriptionsInAMissingFolder() {
|
public function testListSubscriptionsInAMissingFolder() {
|
||||||
|
|
Loading…
Reference in a new issue