Compare commits
554 Commits
374 changed files with 21509 additions and 13010 deletions
@ -0,0 +1,78 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2017 J. King, Dustin Wilson et al. |
||||
|
* See LICENSE and AUTHORS files for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace JKingWeb\Arsse; |
||||
|
|
||||
|
const BASE = __DIR__.DIRECTORY_SEPARATOR; |
||||
|
|
||||
|
$paths = [ |
||||
|
__FILE__, |
||||
|
BASE."arsse.php", |
||||
|
BASE."RoboFile.php", |
||||
|
BASE."lib", |
||||
|
BASE."tests/cases", |
||||
|
BASE."tests/lib", |
||||
|
BASE."tests/bootstrap.php", |
||||
|
BASE."tests/server.php", |
||||
|
]; |
||||
|
$rules = [ |
||||
|
// house rules where PSR series is silent |
||||
|
'align_multiline_comment' => ['comment_type' => "phpdocs_only"], |
||||
|
'array_syntax' => ['syntax' => "short"], |
||||
|
'binary_operator_spaces' => [ |
||||
|
'default' => "single_space", |
||||
|
'operators' => ['=>' => "align_single_space"], |
||||
|
], |
||||
|
'cast_spaces' => ['space' => "single"], |
||||
|
'concat_space' => ['spacing' => "none"], |
||||
|
'list_syntax' => ['syntax' => "short"], |
||||
|
'magic_constant_casing' => true, |
||||
|
'magic_method_casing' => true, |
||||
|
'modernize_types_casting' => true, |
||||
|
'native_function_casing' => true, |
||||
|
'native_function_type_declaration_casing' => true, |
||||
|
'no_binary_string' => true, |
||||
|
'no_blank_lines_after_phpdoc' => true, |
||||
|
'no_empty_comment' => true, |
||||
|
'no_empty_phpdoc' => true, |
||||
|
'no_empty_statement' => true, |
||||
|
'no_extra_blank_lines' => true, // this could probably use more configuration |
||||
|
'no_mixed_echo_print' => ['use' => "echo"], |
||||
|
'no_short_bool_cast' => true, |
||||
|
'no_trailing_comma_in_singleline_array' => true, |
||||
|
'no_unneeded_control_parentheses' => true, |
||||
|
'no_unneeded_curly_braces' => true, |
||||
|
'no_unused_imports' => true, |
||||
|
'no_whitespace_before_comma_in_array' => true, |
||||
|
'normalize_index_brace' => true, |
||||
|
'object_operator_without_whitespace' => true, |
||||
|
'pow_to_exponentiation' => true, |
||||
|
'set_type_to_cast' => true, |
||||
|
'standardize_not_equals' => true, |
||||
|
'trailing_comma_in_multiline' => ['elements' => ["arrays"]], |
||||
|
'unary_operator_spaces' => true, |
||||
|
'yoda_style' => false, |
||||
|
// PSR standard to apply |
||||
|
'@PSR12' => true, |
||||
|
// house exceptions to PSR rules |
||||
|
'curly_braces_position' => [ |
||||
|
'functions_opening_brace' => "same_line", |
||||
|
'classes_opening_brace' => "same_line", |
||||
|
], |
||||
|
'function_declaration' => ['closure_function_spacing' => "none"], |
||||
|
'new_with_braces' => false, // no option to specify absence of braces |
||||
|
]; |
||||
|
|
||||
|
$finder = \PhpCsFixer\Finder::create(); |
||||
|
foreach ($paths as $path) { |
||||
|
if (is_file($path)) { |
||||
|
$finder = $finder->append([$path]); |
||||
|
} else { |
||||
|
$finder = $finder->in($path); |
||||
|
} |
||||
|
} |
||||
|
return (new \PhpCsFixer\Config)->setRiskyAllowed(true)->setRules($rules)->setFinder($finder); |
@ -1,31 +0,0 @@ |
|||||
<?php |
|
||||
/** @license MIT |
|
||||
* Copyright 2017 J. King, Dustin Wilson et al. |
|
||||
* See LICENSE and AUTHORS files for details */ |
|
||||
|
|
||||
namespace JKingWeb\Arsse; |
|
||||
|
|
||||
const BASE = __DIR__.DIRECTORY_SEPARATOR; |
|
||||
|
|
||||
$paths = [ |
|
||||
__FILE__, |
|
||||
BASE."arsse.php", |
|
||||
BASE."RoboFile.php", |
|
||||
BASE."lib", |
|
||||
BASE."tests", |
|
||||
]; |
|
||||
$rules = [ |
|
||||
'@PSR2' => true, |
|
||||
'braces' => ['position_after_functions_and_oop_constructs' => "same"], |
|
||||
'function_declaration' => ['closure_function_spacing' => "none"], |
|
||||
]; |
|
||||
|
|
||||
$finder = \PhpCsFixer\Finder::create(); |
|
||||
foreach ($paths as $path) { |
|
||||
if (is_file($path)) { |
|
||||
$finder = $finder->append([$path]); |
|
||||
} else { |
|
||||
$finder = $finder->in($path); |
|
||||
} |
|
||||
} |
|
||||
return \PhpCsFixer\Config::create()->setRules($rules)->setFinder($finder); |
|
File diff suppressed because it is too large
@ -1,23 +0,0 @@ |
|||||
# N.B. the unix:/var/run/php/php7.2-fpm.sock path used repeatedly below will |
|
||||
# vary from system to system and will be probably need to be changed |
|
||||
|
|
||||
<VirtualHost *:80> |
|
||||
ServerName localhost |
|
||||
# adjust according to your installation path |
|
||||
DocumentRoot /usr/share/arsse/www |
|
||||
|
|
||||
# adjust according to your installation path |
|
||||
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/arsse/arsse.php" |
|
||||
ProxyPreserveHost On |
|
||||
|
|
||||
# NextCloud News v1.2, Tiny Tiny RSS API, TT-RSS newsfeed icons |
|
||||
<LocationMatch "(/index\.php/apps/news/api/?.+|/tt-rss/(api|feed-icons))"> |
|
||||
ProxyPass "unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/usr/share/arsse" |
|
||||
</LocationMatch> |
|
||||
|
|
||||
# NextCloud News API detection, Fever API |
|
||||
<LocationMatch "(/index\.php/apps/news/api/?$|/fever)"> |
|
||||
# these locations should not be behind HTTP authentication |
|
||||
ProxyPass "unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/usr/share/arsse" |
|
||||
</LocationMatch> |
|
||||
</VirtualHost> |
|
@ -0,0 +1,5 @@ |
|||||
|
ProxyPreserveHost On |
||||
|
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/arsse/arsse.php" |
||||
|
ProxyFCGISetEnvIf "-n req('Authorization')" HTTP_AUTHORIZATION "%{req:Authorization}" |
||||
|
|
||||
|
ProxyPass "unix:/var/run/php/arsse.sock|fcgi://localhost/usr/share/arsse/" |
@ -0,0 +1,34 @@ |
|||||
|
# Nextcloud News protocol |
||||
|
<Location "/index.php/apps/news/api"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
||||
|
|
||||
|
# Tiny Tiny RSS protocol |
||||
|
<Location "/tt-rss/api"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
||||
|
|
||||
|
# Tiny Tiny RSS feed icons |
||||
|
<Location "/tt-rss/feed-icons"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
||||
|
|
||||
|
# Fever protocol |
||||
|
<Location "/fever"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
||||
|
|
||||
|
# Miniflux protocol |
||||
|
<Location "/v1"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
||||
|
|
||||
|
# Miniflux version number |
||||
|
<Location "/version"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
||||
|
|
||||
|
# Miniflux "health check" |
||||
|
<Location "/healthcheck"> |
||||
|
Include "/etc/arsse/apache/arsse-fcgi.conf" |
||||
|
</Location> |
@ -0,0 +1,6 @@ |
|||||
|
DocumentRoot "/usr/share/arsse/www" |
||||
|
<Directory "/usr/share/arsse/www"> |
||||
|
Require all granted |
||||
|
</Directory> |
||||
|
|
||||
|
Include "/etc/arsse/apache/arsse-loc.conf" |
@ -0,0 +1,9 @@ |
|||||
|
<VirtualHost *:443> |
||||
|
ServerName "news.example.com" |
||||
|
SSLEngine On |
||||
|
|
||||
|
SSLCertificateFile "/etc/letsencrypt/live/news.example.com/fullchain.pem" |
||||
|
SSLCertificateKeyFile "/etc/letsencrypt/live/news.example.com/privkey.pem" |
||||
|
|
||||
|
Include "/etc/arsse/apache/arsse.conf" |
||||
|
</VirtualHost> |
@ -0,0 +1,64 @@ |
|||||
|
# Maintainer: J. King <jking@jkingweb.ca> |
||||
|
pkgname="arsse" |
||||
|
pkgver=0.10.4 |
||||
|
pkgrel=1 |
||||
|
epoch= |
||||
|
pkgdesc="Multi-protocol RSS/Atom newsfeed synchronization server" |
||||
|
arch=("any") |
||||
|
url="https://thearsse.com/" |
||||
|
license=("MIT") |
||||
|
conflicts=("arsse-git") |
||||
|
depends=() |
||||
|
makedepends=() |
||||
|
checkdepends=() |
||||
|
optdepends=("nginx: HTTP server" |
||||
|
"apache>=2.4: HTTP server" |
||||
|
"percona-server: Alternate database" |
||||
|
"postgresql>=10: Alternate database" |
||||
|
"php-pgsql-interpreter>=7.3: PostgreSQL database support") |
||||
|
backup=("etc/webapps/arsse/config.php" |
||||
|
"etc/webapps/arsse/systemd-environment" |
||||
|
"etc/php/php-fpm.d/arsse.conf" |
||||
|
"etc/php-legacy/php-fpm.d/arsse.conf" |
||||
|
"etc/webapps/arsse/nginx/example.conf" |
||||
|
"etc/webapps/arsse/nginx/arsse.conf" |
||||
|
"etc/webapps/arsse/nginx/arsse-loc.conf" |
||||
|
"etc/webapps/arsse/nginx/arsse-fcgi.conf" |
||||
|
"etc/webapps/arsse/apache/example.conf" |
||||
|
"etc/webapps/arsse/apache/arsse.conf" |
||||
|
"etc/webapps/arsse/apache/arsse-fcgi.conf" |
||||
|
"etc/webapps/arsse/apache/arsse-loc.conf") |
||||
|
source=("arsse-0.10.4.tar.gz") |
||||
|
md5sums=("SKIP") |
||||
|
|
||||
|
package() { |
||||
|
# define runtime dependencies |
||||
|
depends=("php-interpreter>=7.3" "php-sqlite-interpreter>=7.3" "php-fpm-interpreter>=7.3") |
||||
|
# create most directories necessary for the final package |
||||
|
cd "$pkgdir" |
||||
|
mkdir -p "usr/share/webapps/arsse" "usr/share/doc/arsse" "usr/share/licenses/arsse" "usr/lib/systemd/system" "usr/lib/sysusers.d" "usr/lib/tmpfiles.d" "etc/php/php-fpm.d" "etc/php-legacy/php-fpm.d" "etc/webapps/arsse" |
||||
|
# copy requisite files |
||||
|
cd "$srcdir/arsse" |
||||
|
cp -r lib locale sql vendor www CHANGELOG UPGRADING README.md arsse.php "$pkgdir/usr/share/webapps/arsse" |
||||
|
cp -r manual/* "$pkgdir/usr/share/doc/arsse" |
||||
|
cp LICENSE AUTHORS "$pkgdir/usr/share/licenses/arsse" |
||||
|
cp dist/sysuser.conf "$pkgdir/usr/lib/sysusers.d/arsse.conf" |
||||
|
cp dist/tmpfiles.conf "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" |
||||
|
cp dist/php-fpm.conf "$pkgdir/etc/php/php-fpm.d/arsse.conf" |
||||
|
cp -r dist/man "$pkgdir/usr/share" |
||||
|
cp -r dist/nginx dist/apache config.defaults.php "$pkgdir/etc/webapps/arsse" |
||||
|
# copy files requiring special permissions |
||||
|
install -Dm640 dist/config.php "$pkgdir/etc/webapps/arsse" |
||||
|
# patch generic configuration files to use Arch-specific paths and identifiers |
||||
|
sed -i -se 's/\/\(etc\|usr\/share\)\/arsse\//\/\1\/webapps\/arsse\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" |
||||
|
sed -i -se 's/\/var\/run\/php\//\/run\/php-fpm\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/etc/php/php-fpm.d/arsse.conf" |
||||
|
sed -i -se 's/www-data/http/g' "$pkgdir/etc/php/php-fpm.d/arsse.conf" |
||||
|
# make a duplicate PHP-FPM pool for php-legacy |
||||
|
sed -se 's/php-fpm/php-fpm-legacy/' "$pkgdir/etc/php/php-fpm.d/arsse.conf" > "$pkgdir/etc/php-legacy/php-fpm.d/arsse.conf" |
||||
|
# copy Arch-specific versions of files |
||||
|
install -Dm755 dist/arch/arsse "$pkgdir/usr/bin/arsse" |
||||
|
cp dist/arch/nginx-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/nginx/arsse-fcgi.conf" |
||||
|
cp dist/arch/apache-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/apache/arsse-fcgi.conf" |
||||
|
cp dist/arch/*.service "$pkgdir/usr/lib/systemd/system" |
||||
|
cp dist/arch/systemd-environment "$pkgdir/etc/webapps/arsse/systemd-environment" |
||||
|
} |
@ -0,0 +1,79 @@ |
|||||
|
# Maintainer: J. King <jking@jkingweb.ca> |
||||
|
pkgname="arsse-git" |
||||
|
pkgver=0.10.4 |
||||
|
pkgrel=1 |
||||
|
epoch= |
||||
|
pkgdesc="Multi-protocol RSS/Atom newsfeed synchronization server, bugfix-testing version" |
||||
|
arch=("any") |
||||
|
url="https://thearsse.com/" |
||||
|
license=("MIT") |
||||
|
provides=("arsse") |
||||
|
conflicts=("arsse") |
||||
|
depends=("php-interpreter>=7.3" "php-intl-interpreter>=7.3" "php-sqlite-interpreter>=7.3") |
||||
|
makedepends=("composer") |
||||
|
checkdepends=() |
||||
|
optdepends=("nginx: HTTP server" |
||||
|
"apache>=2.4: HTTP server" |
||||
|
"percona-server: Alternate database" |
||||
|
"postgresql>=10: Alternate database" |
||||
|
"php-pgsql-interpreter>=7.3: PostgreSQL database support") |
||||
|
backup=("etc/webapps/arsse/config.php" |
||||
|
"etc/webapps/arsse/systemd-environment" |
||||
|
"etc/php/php-fpm.d/arsse.conf" |
||||
|
"etc/php-legacy/php-fpm.d/arsse.conf" |
||||
|
"etc/webapps/arsse/nginx/example.conf" |
||||
|
"etc/webapps/arsse/nginx/arsse.conf" |
||||
|
"etc/webapps/arsse/nginx/arsse-loc.conf" |
||||
|
"etc/webapps/arsse/nginx/arsse-fcgi.conf" |
||||
|
"etc/webapps/arsse/apache/example.conf" |
||||
|
"etc/webapps/arsse/apache/arsse.conf" |
||||
|
"etc/webapps/arsse/apache/arsse-fcgi.conf" |
||||
|
"etc/webapps/arsse/apache/arsse-loc.conf") |
||||
|
source=("git+https://code.mensbeam.com/MensBeam/arsse/") |
||||
|
md5sums=("SKIP") |
||||
|
|
||||
|
pkgver() { |
||||
|
cd "arsse" |
||||
|
git describe --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g' |
||||
|
} |
||||
|
|
||||
|
build() { |
||||
|
cd "$srcdir/arsse" |
||||
|
composer install |
||||
|
./robo manual |
||||
|
composer install --no-dev -o --no-scripts |
||||
|
php arsse.php conf save-defaults config.defaults.php |
||||
|
rm -r vendor/bin |
||||
|
} |
||||
|
|
||||
|
package() { |
||||
|
# define runtime dependencies |
||||
|
depends=("php-interpreter>=7.3" "php-sqlite-interpreter>=7.3" "php-fpm-interpreter>=7.3") |
||||
|
# create most directories necessary for the final package |
||||
|
cd "$pkgdir" |
||||
|
mkdir -p "usr/share/webapps/arsse" "usr/share/doc/arsse" "usr/share/licenses/arsse" "usr/lib/systemd/system" "usr/lib/sysusers.d" "usr/lib/tmpfiles.d" "etc/php/php-fpm.d" "etc/php-legacy/php-fpm.d" "etc/webapps/arsse" |
||||
|
# copy requisite files |
||||
|
cd "$srcdir/arsse" |
||||
|
cp -r lib locale sql vendor www CHANGELOG UPGRADING README.md arsse.php "$pkgdir/usr/share/webapps/arsse" |
||||
|
cp -r manual/* "$pkgdir/usr/share/doc/arsse" |
||||
|
cp LICENSE AUTHORS "$pkgdir/usr/share/licenses/arsse" |
||||
|
cp dist/sysuser.conf "$pkgdir/usr/lib/sysusers.d/arsse.conf" |
||||
|
cp dist/tmpfiles.conf "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" |
||||
|
cp dist/php-fpm.conf "$pkgdir/etc/php/php-fpm.d/arsse.conf" |
||||
|
cp -r dist/man "$pkgdir/usr/share" |
||||
|
cp -r dist/nginx dist/apache config.defaults.php "$pkgdir/etc/webapps/arsse" |
||||
|
# copy files requiring special permissions |
||||
|
install -Dm640 dist/config.php "$pkgdir/etc/webapps/arsse" |
||||
|
# patch generic configuration files to use Arch-specific paths and identifiers |
||||
|
sed -i -se 's/\/\(etc\|usr\/share\)\/arsse\//\/\1\/webapps\/arsse\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/usr/lib/tmpfiles.d/arsse.conf" |
||||
|
sed -i -se 's/\/var\/run\/php\//\/run\/php-fpm\//g' "$pkgdir/etc/webapps/arsse/nginx/"* "$pkgdir/etc/webapps/arsse/apache/"* "$pkgdir/etc/php/php-fpm.d/arsse.conf" |
||||
|
sed -i -se 's/www-data/http/g' "$pkgdir/etc/php/php-fpm.d/arsse.conf" |
||||
|
# make a duplicate PHP-FPM pool for php-legacy |
||||
|
sed -se 's/php-fpm/php-fpm-legacy/' "$pkgdir/etc/php/php-fpm.d/arsse.conf" > "$pkgdir/etc/php-legacy/php-fpm.d/arsse.conf" |
||||
|
# copy Arch-specific versions of files |
||||
|
install -Dm755 dist/arch/arsse "$pkgdir/usr/bin/arsse" |
||||
|
cp dist/arch/nginx-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/nginx/arsse-fcgi.conf" |
||||
|
cp dist/arch/apache-arsse-fcgi.conf "$pkgdir/etc/webapps/arsse/apache/arsse-fcgi.conf" |
||||
|
cp dist/arch/*.service "$pkgdir/usr/lib/systemd/system" |
||||
|
cp dist/arch/systemd-environment "$pkgdir/etc/webapps/arsse/systemd-environment" |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
ProxyPreserveHost On |
||||
|
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/webapps/arsse/arsse.php" |
||||
|
ProxyFCGISetEnvIf "-n req('Authorization')" HTTP_AUTHORIZATION "%{req:Authorization}" |
||||
|
|
||||
|
# Modify the below line to begin with "unix:/run/php-fpm-legacy/" if using the php-legacy package |
||||
|
ProxyPass "unix:/run/php-fpm/arsse.sock|fcgi://localhost/usr/share/webapps/arsse/" |
@ -0,0 +1,28 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
|
||||
|
readonly default_php="/usr/bin/php" |
||||
|
php="" |
||||
|
|
||||
|
check_sudo() { |
||||
|
if ! command -v sudo > /dev/null; then |
||||
|
printf "The sudo command is not available.\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# allow overriding the php executable |
||||
|
if [ -n "${ARSSE_PHP}" ] && command -v "${ARSSE_PHP}" > /dev/null; then |
||||
|
php="${ARSSE_PHP}" |
||||
|
else |
||||
|
php="${default_php}" |
||||
|
fi |
||||
|
|
||||
|
if [ "$(whoami)" = "arsse" ]; then |
||||
|
"$php" /usr/share/webapps/arsse/arsse "$@" |
||||
|
elif [ "${UID}" -eq 0 ]; then |
||||
|
runuser -u "arsse" -- "$php" /usr/share/webapps/arsse/arsse "$@" |
||||
|
else |
||||
|
check_sudo |
||||
|
sudo -u "arsse" "$php" /usr/share/webapps/arsse/arsse "$@" |
||||
|
fi |
||||
|
|
@ -0,0 +1,37 @@ |
|||||
|
[Unit] |
||||
|
Description=The Arsse newsfeed fetching service |
||||
|
Documentation=https://thearsse.com/manual/ |
||||
|
PartOf=arsse.service |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
|
|
||||
|
[Service] |
||||
|
User=arsse |
||||
|
Group=arsse |
||||
|
Type=simple |
||||
|
WorkingDirectory=/usr/share/webapps/arsse |
||||
|
EnvironmentFile=/etc/webapps/arsse/systemd-environment |
||||
|
ExecStart=/usr/bin/arsse daemon |
||||
|
|
||||
|
ProtectProc=invisible |
||||
|
NoNewPrivileges=true |
||||
|
ProtectSystem=full |
||||
|
ProtectHome=true |
||||
|
StateDirectory=arsse |
||||
|
ConfigurationDirectory=arsse |
||||
|
PrivateTmp=true |
||||
|
PrivateDevices=true |
||||
|
RestrictSUIDSGID=true |
||||
|
StandardOutput=journal |
||||
|
StandardError=journal |
||||
|
SyslogIdentifier=arsse |
||||
|
Restart=on-failure |
||||
|
RestartPreventStatus= |
||||
|
|
||||
|
# These directives can be used for extra security, but are disabled for now for compatibility |
||||
|
|
||||
|
#ReadOnlyPaths=/ |
||||
|
#ReadWriePaths=/var/lib/arsse |
||||
|
#NoExecPaths=/ |
||||
|
#ExecPaths=/usr/bin/php |
@ -0,0 +1,13 @@ |
|||||
|
[Unit] |
||||
|
Description=The Arsse newsfeed management service |
||||
|
Documentation=https://thearsse.com/manual/ |
||||
|
Requires=arsse-fetch.service |
||||
|
Wants=php-fpm.service php-legacy-fpm.service |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
|
|
||||
|
[Service] |
||||
|
Type=oneshot |
||||
|
RemainAfterExit=true |
||||
|
ExecStart=/usr/bin/true |
@ -0,0 +1,16 @@ |
|||||
|
fastcgi_pass_header Authorization; # required if the Arsse is to perform its own HTTP authentication |
||||
|
fastcgi_pass_request_body on; |
||||
|
fastcgi_pass_request_headers on; |
||||
|
fastcgi_intercept_errors off; |
||||
|
fastcgi_buffering off; |
||||
|
fastcgi_param REQUEST_METHOD $request_method; |
||||
|
fastcgi_param CONTENT_TYPE $content_type; |
||||
|
fastcgi_param CONTENT_LENGTH $content_length; |
||||
|
fastcgi_param REQUEST_URI $uri; |
||||
|
fastcgi_param QUERY_STRING $query_string; |
||||
|
fastcgi_param HTTPS $https if_not_empty; |
||||
|
fastcgi_param REMOTE_USER $remote_user; |
||||
|
fastcgi_param SCRIPT_FILENAME /usr/share/webapps/arsse/arsse.php; |
||||
|
|
||||
|
# Modify the below line to begin with "/run/php-fpm-legacy/" if using the php-legacy package |
||||
|
fastcgi_pass unix:/run/php-fpm/arsse.sock; |
@ -0,0 +1 @@ |
|||||
|
ARSSE_PHP=/usr/bin/php |
@ -0,0 +1,10 @@ |
|||||
|
#! /usr/bin/env php |
||||
|
<?php |
||||
|
if (posix_geteuid() == 0) { |
||||
|
$info = posix_getpwnam("arsse"); |
||||
|
if ($info) { |
||||
|
posix_setgid($info['gid']); |
||||
|
posix_setuid($info['uid']); |
||||
|
} |
||||
|
} |
||||
|
require "/usr/share/arsse/arsse.php"; |
@ -1,15 +0,0 @@ |
|||||
[Unit] |
|
||||
Description=The Arsse feed fetching service |
|
||||
After=network.target mysql.service postgresql.service |
|
||||
|
|
||||
[Service] |
|
||||
User=www-data |
|
||||
Group=www-data |
|
||||
WorkingDirectory=/usr/share/arsse |
|
||||
Type=simple |
|
||||
StandardOutput=null |
|
||||
StandardError=syslog |
|
||||
ExecStart=/usr/bin/env php /usr/share/arsse/arsse.php daemon |
|
||||
|
|
||||
[Install] |
|
||||
WantedBy=multi-user.target |
|
@ -0,0 +1,8 @@ |
|||||
|
<?php |
||||
|
|
||||
|
# Please refer to config.defaults.php or the manual at /usr/share/doc/arsse/ |
||||
|
# for possible configuration parameters |
||||
|
|
||||
|
return [ |
||||
|
'dbSQLite3File' => "/var/lib/arsse/arsse.db", |
||||
|
]; |
@ -0,0 +1,16 @@ |
|||||
|
#!/bin/sh |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
. /usr/share/debconf/confmodule |
||||
|
|
||||
|
# Set up dbconfig-common |
||||
|
if test -f /usr/share/dbconfig-common/dpkg/config; then |
||||
|
. /usr/share/dbconfig-common/dpkg/config |
||||
|
dbc_dbtypes="sqlite3, pgsql, mysql" |
||||
|
dbc_authmethod_user="password" |
||||
|
dbc_go arsse "$@" |
||||
|
fi |
||||
|
|
||||
|
# Prompt for dbconfig-common configuration |
||||
|
db_go || true |
@ -0,0 +1 @@ |
|||||
|
var/lib/arsse |
@ -0,0 +1,18 @@ |
|||||
|
lib usr/share/arsse/ |
||||
|
locale usr/share/arsse/ |
||||
|
sql usr/share/arsse/ |
||||
|
vendor usr/share/arsse/ |
||||
|
www usr/share/arsse/ |
||||
|
CHANGELOG usr/share/arsse/ |
||||
|
UPGRADING usr/share/arsse/ |
||||
|
README.md usr/share/arsse/ |
||||
|
arsse.php usr/share/arsse/ |
||||
|
|
||||
|
config.defaults.php etc/arsse/ |
||||
|
manual usr/share/doc/arsse/ |
||||
|
dist/man/* usr/share/man/ |
||||
|
dist/debian/config.php etc/arsse/ |
||||
|
dist/debian/dbconfig-common.php usr/share/arsse/ |
||||
|
debian/bin/arsse usr/bin/ |
||||
|
debian/nginx etc/arsse/ |
||||
|
debian/apache etc/arsse/ |
@ -0,0 +1 @@ |
|||||
|
etc/arsse/config.php usr/share/arsse/config.php |
@ -0,0 +1,29 @@ |
|||||
|
#!/bin/sh |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
. /usr/share/debconf/confmodule |
||||
|
|
||||
|
if [ "$1" = "configure" ]; then |
||||
|
# Set permissions on configuration file |
||||
|
dpkg-statoverride --list "/etc/arsse/config.php" >/dev/null || dpkg-statoverride --update --add root www-data 640 "/etc/arsse/config.php" |
||||
|
# Set up dbconfig-common |
||||
|
if test -f /usr/share/dbconfig-common/dpkg/postinst; then |
||||
|
. /usr/share/dbconfig-common/dpkg/postinst |
||||
|
dbc_generate_include_owner="root:www-data" |
||||
|
dbc_generate_include_perms="0640" |
||||
|
dbc_generate_include="php:/var/lib/arsse/dbconfig.inc" |
||||
|
dbc_pgsql_createdb_encoding="UTF8' lc_collate='C" |
||||
|
dbc_mysql_createdb_encoding="UTF8" |
||||
|
dbc_dbfile_owner="root:www-data" |
||||
|
dbc_dbfile_perms="0660" |
||||
|
dbc_go arsse "$@" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
# dh_installdeb will replace this with shell code automatically |
||||
|
# generated by other debhelper scripts. |
||||
|
|
||||
|
#DEBHELPER# |
||||
|
|
||||
|
exit 0 |
@ -0,0 +1,20 @@ |
|||||
|
#!/bin/sh |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
if test -f /usr/share/debconf/confmodule; then |
||||
|
. /usr/share/debconf/confmodule |
||||
|
fi |
||||
|
|
||||
|
# Set up dbconfig-common |
||||
|
if test -f /usr/share/dbconfig-common/dpkg/postrm; then |
||||
|
. /usr/share/dbconfig-common/dpkg/postrm |
||||
|
dbc_go arsse "$@" |
||||
|
fi |
||||
|
|
||||
|
# dh_installdeb will replace this with shell code automatically |
||||
|
# generated by other debhelper scripts. |
||||
|
|
||||
|
#DEBHELPER# |
||||
|
|
||||
|
exit 0 |
@ -0,0 +1,16 @@ |
|||||
|
#!/bin/sh |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
. /usr/share/debconf/confmodule |
||||
|
|
||||
|
# Set up dbconfig-common |
||||
|
. /usr/share/dbconfig-common/dpkg/prerm |
||||
|
dbc_go arsse "$@" |
||||
|
|
||||
|
# dh_installdeb will replace this with shell code automatically |
||||
|
# generated by other debhelper scripts. |
||||
|
|
||||
|
#DEBHELPER# |
||||
|
|
||||
|
exit 0 |
@ -0,0 +1 @@ |
|||||
|
10 |
@ -0,0 +1,15 @@ |
|||||
|
<?php |
||||
|
/*** |
||||
|
Please refer to config.defaults.php or the manual at /usr/share/doc/arsse/ |
||||
|
for possible configuration parameters. |
||||
|
|
||||
|
The last line includes database auto-configuration information which |
||||
|
Debian may have created during installation; any database-related |
||||
|
configuration defined in this file will override anything defined in the |
||||
|
included file. |
||||
|
***/ |
||||
|
|
||||
|
return [ |
||||
|
'dbAutoUpdate' => true, |
||||
|
] |
||||
|
+ (@include "/usr/share/arsse/dbconfig-common.php"); |
@ -0,0 +1,32 @@ |
|||||
|
Source: arsse |
||||
|
Maintainer: J. King <jking@jkingweb.ca> |
||||
|
Section: contrib/net |
||||
|
Priority: optional |
||||
|
Standards-Version: 4.5.1 |
||||
|
Homepage: https://thearsse.com/ |
||||
|
Vcs-Browser: https://code.mensbeam.com/MensBeam/arsse/ |
||||
|
Vcs-Git: https://code.mensbeam.com/MensBeam/arsse/ |
||||
|
Build-Depends: debhelper |
||||
|
|
||||
|
Package: arsse |
||||
|
Architecture: all |
||||
|
Section: contrib/net |
||||
|
Priority: optional |
||||
|
Homepage: https://thearsse.com/ |
||||
|
Description: Multi-protocol RSS/Atom newsfeed synchronization server |
||||
|
The Arsse bridges the gap between multiple existing newsfeed aggregator |
||||
|
client protocols such as Tiny Tiny RSS, Nextcloud News and Miniflux, |
||||
|
allowing you to use compatible clients for many protocols with a single |
||||
|
server. |
||||
|
Depends: ${misc:Depends}, |
||||
|
dbconfig-sqlite3 | dbconfig-pgsql | dbconfig-mysql | dbconfig-no-thanks, |
||||
|
php (>= 7.3.0), |
||||
|
php-cli, |
||||
|
php-intl, |
||||
|
php-json, |
||||
|
php-xml, |
||||
|
php-sqlite3 | php-pgsql | php-mysql |
||||
|
Recommends: nginx | apache2, |
||||
|
php-fpm, |
||||
|
php-curl, |
||||
|
ca-certificates |
@ -0,0 +1,34 @@ |
|||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ |
||||
|
Upstream-Name: arsse |
||||
|
Upstream-Contact: J. King <jking@jkingweb.ca> |
||||
|
Source: https://code.mensbeam.com/MensBeam/arsse/ |
||||
|
License: Expat |
||||
|
|
||||
|
Files: * |
||||
|
Copyright: 2017 J. King <jking@jkingweb.ca> |
||||
|
2017 Dustin Wilson <dustin@dustinwilson.com> |
||||
|
License: Expat |
||||
|
|
||||
|
License: Expat |
||||
|
Copyright (c) 2017 J. King, Dustin Wilson |
||||
|
. |
||||
|
Permission is hereby granted, free of charge, to any person |
||||
|
obtaining a copy of this software and associated documentation |
||||
|
files (the "Software"), to deal in the Software without |
||||
|
restriction, including without limitation the rights to use, |
||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
copies of the Software, and to permit persons to whom the |
||||
|
Software is furnished to do so, subject to the following |
||||
|
conditions: |
||||
|
. |
||||
|
The above copyright notice and this permission notice shall be |
||||
|
included in all copies or substantial portions of the Software. |
||||
|
. |
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||||
|
OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,44 @@ |
|||||
|
<?php |
||||
|
|
||||
|
# This script transforms Debian's dbconfig-common PHP-format include files |
||||
|
# into a form usable by The Arsse. This is necessary because The Arsse |
||||
|
# supports defining configuration parameters for all supported database types |
||||
|
# at once, using separate keys for the different types |
||||
|
|
||||
|
$dbconfpath = "/var/lib/arsse/dbconfig.inc"; // path defined in postinst script |
||||
|
|
||||
|
if (file_exists($dbconfpath)) { |
||||
|
require_once "/var/lib/arsse/dbconfig.inc"; |
||||
|
$dbtype = $dbtype ?? ""; |
||||
|
// the returned configuration depends on the $dbtype |
||||
|
if ($dbtype === "sqlite3") { |
||||
|
$conf = ['dbDriver' => "sqlite3"]; |
||||
|
if (strlen((string) $basepath) && strlen((string) $dbname)) { |
||||
|
$conf['dbSQLite3File'] = "$basepath/$dbname"; |
||||
|
} |
||||
|
} elseif ($dbtype === "pgsql") { |
||||
|
$conf = [ |
||||
|
'dbDriver' => "postgresql", |
||||
|
'dbPostgreSQLHost' => $dbserver ?? "", |
||||
|
'dbPostgreSQLUser' => $dbuser ?? "arsse", |
||||
|
'dbPostgreSQLPass' => $dbpass ?? "", |
||||
|
'dbPostgreSQLPort' => (int) $dbport ?: 5432, |
||||
|
'dbPostgreSQLDb' => $dbname ?? "arsse", |
||||
|
]; |
||||
|
} elseif ($dbtype === "mysql") { |
||||
|
$conf = [ |
||||
|
'dbDriver' => "mysql", |
||||
|
'dbMySQLHost' => $dbserver ?? "", |
||||
|
'dbMySQLUser' => $dbuser ?? "arsse", |
||||
|
'dbMySQLPass' => $dbpass ?? "", |
||||
|
'dbMySQLPort' => (int) $dbport ?: 3306, |
||||
|
'dbMySQLDb' => $dbname ?? "arsse", |
||||
|
]; |
||||
|
} else { |
||||
|
throw new \Exception("Debian dbconfig-common configuration file $dbconfpath is invalid"); |
||||
|
} |
||||
|
return $conf; |
||||
|
} else { |
||||
|
// if no configuration file exists simply return an empty array |
||||
|
return []; |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
# We make reference to "Tiny Tiny RSS" |
||||
|
spelling-error-in-description Tiny Tiny (duplicate word) Tiny |
||||
|
# The manual for DrUUID (a dependency) includes a harmless "up" link |
||||
|
privacy-breach-generic usr/share/arsse/vendor/jkingweb/druuid/documentation/manual.html [<link rel="up" href="http://jkingweb.ca/code/">] (http://jkingweb.ca/code/) |
||||
|
# We only ask dbconfig-common questions, which don't seem to require templates |
||||
|
no-debconf-templates |
@ -0,0 +1,40 @@ |
|||||
|
#! /bin/bash -e |
||||
|
|
||||
|
### |
||||
|
# This script is fed to pbuilder to build Debian packages. The base tarball |
||||
|
# should be created with a command similar to the following: |
||||
|
# |
||||
|
# sudo pbuilder create --basetgz pbuilder-arsse.tgz --mirror http://ftp.ca.debian.org/debian/ --extrapackages "debhelper devscripts lintian" |
||||
|
# |
||||
|
# Thereafter pbuilder can be used to build packages with this command: |
||||
|
# |
||||
|
# sudo pbuilder execute --basetgz pbuilder-arsse.tgz --bindmounts `basedir "/path/to/release/tarball"` -- pbuilder.sh "/path/to/release/tarball" |
||||
|
# |
||||
|
# This somewhat roundabout procedure is used because the pbuilder debuild |
||||
|
# command does not seem to work in Arch Linux, nor does pdebuild. Doing |
||||
|
# as much as possible within the chroot itself works around these problems. |
||||
|
### |
||||
|
|
||||
|
# create a temporary directory |
||||
|
tmp=`mktemp -d` |
||||
|
|
||||
|
# define various variables |
||||
|
here=`dirname "$1"` |
||||
|
tarball=`basename "$1"` |
||||
|
version=`echo "$tarball" | grep -oP '\d+(?:\.\d+)*' | head -1` |
||||
|
out="$here/debian" |
||||
|
in="$tmp/arsse-$version" |
||||
|
|
||||
|
# create necessary directories |
||||
|
mkdir -p "$in" "$out" |
||||
|
# extract the release tarball |
||||
|
tar -C "$in" -xf "$1" --strip-components=1 |
||||
|
# repackage the release tarball into a Debian "orig" tarball |
||||
|
tar -C "$tmp" -czf "$tmp/arsse_$version.orig.tar.gz" "arsse-$version" |
||||
|
# copy the "dist/debian" directory down the tree where Debian expects it |
||||
|
cp -r "$in/dist/debian" "$in/debian" |
||||
|
# build the package |
||||
|
cd "$in" |
||||
|
debuild -us -uc |
||||
|
# move the resultant files to their final destination |
||||
|
find "$tmp" -maxdepth 1 -type f -exec mv '{}' "$out" \; |
@ -0,0 +1,26 @@ |
|||||
|
#!/usr/bin/make -f |
||||
|
|
||||
|
DH_VERBOSE = 1 |
||||
|
|
||||
|
%: |
||||
|
dh $@ |
||||
|
|
||||
|
execute_before_dh_install: |
||||
|
# Adapt the systemd service for Debian: this involves using only the "arsse-fetch" unit (renamed to "arsse"), removing the "PartOf" directive, and changing the user and group to "www-data" |
||||
|
cp dist/systemd/arsse-fetch.service debian/arsse.service |
||||
|
sed -i -se 's/^PartOf=.*//' debian/arsse.service |
||||
|
sed -i -se 's/^\(User\|Group\)=.*/\1=www-data/' debian/arsse.service |
||||
|
# Adapt the init script for Debian: this involves changing the user and group to "www-data" |
||||
|
cp dist/init.sh debian/arsse.init |
||||
|
sed -i -se 's/^\([ \t]*chown\) arsse:arsse /\1 www-data:www-data /' debian/arsse.init |
||||
|
# Change the user and group references in tmpfiles |
||||
|
cp dist/tmpfiles.conf debian/arsse.tmpfiles |
||||
|
sed -i -se 's/ arsse / www-data /' debian/arsse.tmpfiles |
||||
|
sed -i -se 's/ arsse / www-data /' debian/arsse.tmpfiles |
||||
|
# Change the user reference in the executable file |
||||
|
mkdir -p debian/bin |
||||
|
cp dist/arsse debian/bin/arsse |
||||
|
sed -i -se 's/posix_getpwnam("arsse"/posix_getpwnam("www-data"/' debian/bin/arsse |
||||
|
# Change PHP-FPM socket paths |
||||
|
cp -r dist/apache dist/nginx debian |
||||
|
sed -i -se 's/arsse\.sock/php-fpm.sock/' debian/apache/arsse.conf debian/nginx/arsse.conf |
@ -0,0 +1 @@ |
|||||
|
3.0 (quilt) |
@ -0,0 +1,2 @@ |
|||||
|
# Development environment is slightly out of date |
||||
|
newer-standards-version |
@ -0,0 +1,78 @@ |
|||||
|
#!/bin/sh |
||||
|
|
||||
|
### BEGIN INIT INFO |
||||
|
# Provides: arsse |
||||
|
# Required-Start: $local_fs $network |
||||
|
# Required-Stop: $local_fs postgresql mysql |
||||
|
# Should-Start: postgresql mysql |
||||
|
# Should-Stop: postgresql mysql |
||||
|
# Default-Start: 2 3 4 5 |
||||
|
# Default-Stop: 0 1 6 |
||||
|
# Short-Description: The Advanced RSS Environment |
||||
|
# Description: The Arsse is a multi-protocol Web newsfeed synchronization service |
||||
|
### END INIT INFO |
||||
|
|
||||
|
# This script is designed for Debian; some adaptation will be required for other systems |
||||
|
|
||||
|
PATH=/usr/sbin/:/usr/bin:/sbin:/bin |
||||
|
NAME=arsse |
||||
|
DESC="newsfeed synchronization server" |
||||
|
PIDFILE=/run/arsse.pid |
||||
|
DAEMON=/usr/bin/$NAME |
||||
|
|
||||
|
. /lib/init/vars.sh |
||||
|
. /lib/lsb/init-functions |
||||
|
|
||||
|
arsse_start() { |
||||
|
touch "$PIDFILE" |
||||
|
chown arsse:arsse "$PIDFILE" |
||||
|
$DAEMON daemon --fork="$PIDFILE" || return 2 |
||||
|
} |
||||
|
|
||||
|
arsse_stop() { |
||||
|
killproc -p "$PIDFILE" "$DAEMON" |
||||
|
} |
||||
|
|
||||
|
arsse_reload() { |
||||
|
killproc -p "$PIDFILE" "$DAEMON" HUP |
||||
|
} |
||||
|
|
||||
|
case "$1" in |
||||
|
start) |
||||
|
log_daemon_msg "Starting $DESC" "$NAME" |
||||
|
if pidofproc -p $PIDFILE "$DAEMON" > /dev/null 2>&1 ; then |
||||
|
return 1 |
||||
|
fi |
||||
|
arsse_start |
||||
|
;; |
||||
|
stop) |
||||
|
log_daemon_msg "Stopping $DESC" "$NAME" |
||||
|
arsse_stop |
||||
|
;; |
||||
|
restart) |
||||
|
log_daemon_msg "Restarting $DESC" "$NAME" |
||||
|
if pidofproc -p $PIDFILE "$DAEMON" > /dev/null 2>&1 ; then |
||||
|
arsse_stop |
||||
|
fi |
||||
|
arsse_start |
||||
|
;; |
||||
|
try-restart) |
||||
|
if pidofproc -p $PIDFILE "$DAEMON" > /dev/null 2>&1 ; then |
||||
|
log_daemon_msg "Restarting $DESC" "$NAME" |
||||
|
arsse_stop |
||||
|
arsse_start |
||||
|
fi |
||||
|
;; |
||||
|
reload|force-reload) |
||||
|
log_daemon_msg "Reloading $DESC" "$NAME" |
||||
|
arsse_reload |
||||
|
;; |
||||
|
status) |
||||
|
status_of_proc -p $PIDFILE $DAEMON $NAME |
||||
|
exit $? |
||||
|
;; |
||||
|
*) |
||||
|
echo "Usage: $0 {start|stop|restart|try-restart|reload|status}" >&2 |
||||
|
exit 3 |
||||
|
;; |
||||
|
esac |
@ -0,0 +1,342 @@ |
|||||
|
.Dd October 27, 2023 |
||||
|
.Dt ARSSE 1 |
||||
|
.Os "The Arsse" 0.10.4 |
||||
|
. |
||||
|
. |
||||
|
.Sh NAME |
||||
|
.Nm arsse |
||||
|
.Nd manage an instance of The Advanced RSS Environment (The Arsse) |
||||
|
. |
||||
|
. |
||||
|
.Sh SYNOPSIS |
||||
|
.Nm "arsse user" |
||||
|
.Op Nm list |
||||
|
.Nm "arsse user add" |
||||
|
.Ar username |
||||
|
.Op Ar password |
||||
|
.Op Fl Fl admin |
||||
|
.Nm "arsse user remove" |
||||
|
.Ar username |
||||
|
.Nm "arsse user show" |
||||
|
.Ar username |
||||
|
.Nm "arsse user set" |
||||
|
.Ar username |
||||
|
.Ar property |
||||
|
.Ar value |
||||
|
.Nm "arsse user unset" |
||||
|
.Ar username |
||||
|
.Ar property |
||||
|
.Nm "arsse user set\-pass" |
||||
|
.Ar username |
||||
|
.Op Ar password |
||||
|
.Op Fl Fl fever |
||||
|
.Nm "arsse user unset\-pass" |
||||
|
.Ar username |
||||
|
.Op Fl Fl fever |
||||
|
.Nm "arsse user auth" |
||||
|
.Ar username |
||||
|
.Op Ar password |
||||
|
.Op Fl Fl fever |
||||
|
.Nm "arsse token list" |
||||
|
.Ar username |
||||
|
.Nm "arsse token create" |
||||
|
.Ar username |
||||
|
.Op Ar label |
||||
|
.Nm "arsse token revoke" |
||||
|
.Ar username |
||||
|
.Op Ar token |
||||
|
.Nm "arsse import" |
||||
|
.Ar username |
||||
|
.Op Ar file |
||||
|
.Op Fl f | Fl Fl flat |
||||
|
.Op Fl r | Fl Fl replace |
||||
|
.Nm "arsse export" |
||||
|
.Ar username |
||||
|
.Op Ar file |
||||
|
.Op Fl f | Fl Fl flat |
||||
|
.Nm "arsse daemon" |
||||
|
.Op Fl Fl fork Ns = Ns Ar pidfile |
||||
|
.Nm "arsse feed refresh\-all" |
||||
|
.Nm "arsse feed refresh" |
||||
|
.Ar n |
||||
|
.Nm "arsse conf save\-defaults" |
||||
|
.Nm "arsse" |
||||
|
.Fl Fl version | Fl h | Fl Fl help |
||||
|
. |
||||
|
. |
||||
|
.Sh DESCRIPTION |
||||
|
.Nm |
||||
|
allows a sufficiently privileged user to perform various administrative operations related to The Arsse, including: |
||||
|
.Pp |
||||
|
.Bl -bullet -compact |
||||
|
.It |
||||
|
Adding and removing users and managing their metadata |
||||
|
.It |
||||
|
Managing passwords and authentication tokens |
||||
|
.It |
||||
|
Importing and exporting OPML newsfeed-lists |
||||
|
.El |
||||
|
.Pp |
||||
|
These are documented in the next section |
||||
|
.Sx COMMANDS Ns No . |
||||
|
Further, seldom-used commands are documented in the subsequent section |
||||
|
.Sx ADDITIONAL COMMANDS Ns No . |
||||
|
. |
||||
|
. |
||||
|
.Sh COMMANDS |
||||
|
. |
||||
|
.Ss Managing users and metadata |
||||
|
.Bl -tag |
||||
|
.It Nm "user" Op Nm list |
||||
|
Displays a simple list of user names with one entry per line |
||||
|
.It Nm "user add" Ar username Oo Ar password Oc Oo Fl Fl admin Oc |
||||
|
Adds a new user to the database with the specified username and password. |
||||
|
If |
||||
|
.Ar password |
||||
|
is omitted a random password will be generated and printed. |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl admin |
||||
|
flag may be used to mark the user as an administrator. |
||||
|
This has no meaning within the context of The Arsse as a whole, |
||||
|
but it is used control access to certain features in the Miniflux and Nextcloud News protocols. |
||||
|
.It Nm "user remove" Ar username |
||||
|
Immediately removes a user from the database. |
||||
|
All associated data (folders, subscriptions, etc.) are also removed. |
||||
|
.It Nm "user show" Ar username |
||||
|
Displays a table of metadata properties and their assigned values for |
||||
|
.Ar username Ns No . |
||||
|
These properties are primarily used by the Miniflux protocol. |
||||
|
Consult the section |
||||
|
.Sx USER METADATA |
||||
|
for details. |
||||
|
.It Nm "user set" Ar username Ar property Ar value |
||||
|
Sets a metadata property for a user. |
||||
|
These properties are primarily used by the Miniflux protocol. |
||||
|
Consult the section |
||||
|
.Sx USER METADATA |
||||
|
for details. |
||||
|
.It Nm "user unset" Ar username Ar property |
||||
|
Clears a metadata property for a user. |
||||
|
The property is thereafter set to its default value, which is protocol-dependent. |
||||
|
.El |
||||
|
. |
||||
|
.Ss Managing passwords and authentication tokens |
||||
|
.Bl -tag |
||||
|
.It Nm "user set\-pass" Ar username Oo Ar password Oc Oo Fl Fl fever Oc |
||||
|
Changes a user's password to the specified value. |
||||
|
If no password is specified, a random password will be generated and printed. |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl fever |
||||
|
option sets a user's Fever protocol password instead of their general password. |
||||
|
As the Fever protocol requires that passwords be stored insecurely, |
||||
|
users do not have Fever passwords by default, and logging in to the Fever protocol is disabled until a suitable password is set. |
||||
|
It is highly recommended that a user's Fever password be different from their general password. |
||||
|
.It Nm "user unset\-pass" Ar username Oo Fl Fl fever Oc |
||||
|
Unsets a user's password, effectively disabling their account. |
||||
|
As with password setting, the |
||||
|
.Fl Fl fever |
||||
|
option may be used to operate on a user's Fever password instead of their general password. |
||||
|
.It Nm "user auth" Ar username Ar password Oo Fl Fl fever Oc |
||||
|
Tests logging a user in. |
||||
|
This only checks that the user's password is correctly recognized; |
||||
|
it has no side effects. |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl fever |
||||
|
option may be used to test the user's Fever protocol password, if any. |
||||
|
.It Nm "token list" Ar username |
||||
|
Displays a user's authentication tokens in a simple tabular format. |
||||
|
These tokens act as an alternative means of authentication for the Miniflux protocol and may be required by some clients. |
||||
|
They do not expire. |
||||
|
.It Nm "token create" Ar username Oo Ar label Oc |
||||
|
Creates a new random login token and prints it. |
||||
|
These tokens act as an alternative means of authentication for the Miniflux protocol and may be required by some clients. |
||||
|
An optional |
||||
|
.Ar label |
||||
|
may be specified to give the token a meaningful name. |
||||
|
.It Nm "token revoke" Ar username Oo Ar token Oc |
||||
|
Deletes the specified |
||||
|
.Ar token |
||||
|
from the database. |
||||
|
The token itself must be supplied, not its label. |
||||
|
If it is omitted all tokens for |
||||
|
.Ar username |
||||
|
are revoked. |
||||
|
.El |
||||
|
. |
||||
|
.Ss Importing and exporting data |
||||
|
.Bl -tag |
||||
|
.It Nm "import" Ar username Oo Ar file Oc Oo Fl r | Fl Fl replace Oc Oo Fl f | Fl Fl flat Oc |
||||
|
Imports the newsfeeds, folders, and tags found in the OPML formatted |
||||
|
.Ar file |
||||
|
into the account of the specified user. |
||||
|
If no file is specified, data is instead read from standard input. |
||||
|
Import operations are atomic: |
||||
|
if any of the newsfeeds listed in the input cannot be retrieved, the entire import operation will fail. |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl replace |
||||
|
(or |
||||
|
.Fl r Ns |
||||
|
) option interprets the OPML file as the list of |
||||
|
.Em all |
||||
|
desired newsfeeds, folders and tags, performing any deletion or moving of existing entries which do not appear in the flle. |
||||
|
If this option is not specified, the file is assumed to list desired |
||||
|
.Em additions only Ns No . |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl flat |
||||
|
(or |
||||
|
.Fl f Ns |
||||
|
) option can be used to ignore any folder structures in the file, importing any newsfeeds directly into the root folder. |
||||
|
Combining this with the |
||||
|
.Fl Fl replace |
||||
|
option is possible. |
||||
|
.It Nm "export" Ar username Oo Ar file Oc Oo Fl f | Fl Fl flat Oc |
||||
|
Exports a user's newsfeeds, folders, and tags to the OPML file specified by |
||||
|
.Ar file Ns |
||||
|
, or standard output if no file is specified. |
||||
|
Note that due to a limitation of the OPML format, any commas present in tag names will not be retained in the export. |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl flat |
||||
|
(or |
||||
|
.Fl f Ns |
||||
|
) option can be used to omit folders from the export. |
||||
|
Some OPML implementations may not support folders, or arbitrary nesting; |
||||
|
this option may be used when planning to import into such software. |
||||
|
.El |
||||
|
. |
||||
|
. |
||||
|
.Sh ADDITIONAL COMMANDS |
||||
|
.Bl -tag |
||||
|
.It Nm "daemon" Oo Fl Fl fork Ns = Ns Ar pidfile Oc |
||||
|
Starts the newsfeed fetching service. |
||||
|
Normally this command is only invoked by systemd. |
||||
|
.Pp |
||||
|
The |
||||
|
.Fl Fl fork |
||||
|
option executes an "old-style" fork-then-terminate daemon rather than a "new-style" non-terminating daemon. |
||||
|
This option should only be employed if using a System V-style init daemon on POSIX systems; |
||||
|
normally systemd is used. When using this option the daemon will write its process identifier to |
||||
|
.Ar pidfile |
||||
|
after forking. |
||||
|
.It Nm "feed refresh\-all" |
||||
|
Performs a one-time fetch of all stale feeds. |
||||
|
This command can be used as the basis of a |
||||
|
.Nm cron |
||||
|
job to keep newsfeeds up-to-date. |
||||
|
.It Nm "feed refresh" Ar n |
||||
|
Performs a one-time fetch of the feed (not subscription) identified by integer |
||||
|
.Ar n Ns No . |
||||
|
This is used internally by the fetching service and should not normally be needed. |
||||
|
.It Nm "conf save\-defaults" Oo Ar file Oc |
||||
|
Prints default configuration parameters to standard output, or to |
||||
|
.Ar file |
||||
|
if specified. |
||||
|
Each parameter is annotated with a short description of its purpose and usage. |
||||
|
.El |
||||
|
. |
||||
|
. |
||||
|
.Sh USER METADATA |
||||
|
User metadata are primarily used by the Miniflux protocol, |
||||
|
and most properties have identical or similar names to those used by Miniflux. |
||||
|
Properties may also affect other protocols, or conversely may have no effect even when using the Miniflux protocol; |
||||
|
this is noted below when appropriate. |
||||
|
.Pp |
||||
|
Booleans accept any of the values |
||||
|
.Ar true Ns No / Ns Ar false Ns No , |
||||
|
.Ar 1 Ns No / Ns Ar 0 Ns No , |
||||
|
.Ar yes Ns No / Ns Ar no Ns No , |
||||
|
or |
||||
|
.Ar on Ns No / Ns Ar off Ns No . |
||||
|
.Pp |
||||
|
The following metadata properties exist for each user: |
||||
|
.Pp |
||||
|
.Bl -tag |
||||
|
.It Cm num No (integer) |
||||
|
The numeric identifier of the user. |
||||
|
This is assigned at user creation and is read-only. |
||||
|
.It Cm admin No (boolean) |
||||
|
Boolean. Whether the user is an administrator. |
||||
|
Administrators may manage other users via the Miniflux protocol, |
||||
|
and also may trigger feed updates manually via the Nextcloud News protocol. |
||||
|
.It Cm lang No (string) |
||||
|
The preferred language of the user as a BCP 47 language tag, for example "en-ca". |
||||
|
Note that since The Arsse currently only includes English text it is not used by The Arsse itself, |
||||
|
but clients may use this metadatum in protocols which expose it. |
||||
|
.It Cm tz No (string) |
||||
|
The time zone of the user as a Time Zone Database identifier, for example "America/Los_Angeles". |
||||
|
.It Cm root_folder_name No (string) |
||||
|
The name of the root folder, in protocols which allow it to be renamed. |
||||
|
.It Cm sort_asc No (boolean) |
||||
|
Whether the user prefers ascending sort order for articles. |
||||
|
Descending order is usually the default, |
||||
|
but explicitly setting this property false will also make a preference for descending order explicit. |
||||
|
.It Cm theme No (string) |
||||
|
The user's preferred user-interface theme. |
||||
|
This is not used by The Arsse itself, but clients may use this metadatum in protocols which expose it. |
||||
|
.It Cm page_size No (integer) |
||||
|
The user's preferred page size when listing articles. |
||||
|
This is not used by The Arsse itself, but clients may use this metadatum in protocols which expose it. |
||||
|
.It Cm shortcuts No (boolean) |
||||
|
Whether to enable keyboard shortcuts. |
||||
|
This is not used by The Arsse itself, but clients may use this metadatum in protocols which expose it. |
||||
|
.It Cm gestures No (boolean) |
||||
|
Whether to enable touch gestures. |
||||
|
This is not used by The Arsse itself, but clients may use this metadatum in protocols which expose it. |
||||
|
.It Cm reading_time No (boolean) |
||||
|
Whether to calculate and display the estimated reading time for articles. |
||||
|
Currently The Arsse does not calculate reading time, so changing this will likely have no effect. |
||||
|
.It Cm stylesheet No (string) |
||||
|
A user stylesheet in CSS format. |
||||
|
This is not used by The Arsse itself, but clients may use this metadatum in protocols which expose it. |
||||
|
.El |
||||
|
. |
||||
|
. |
||||
|
.Sh EXAMPLES |
||||
|
.Bl -tag |
||||
|
.It Add an administrator to the database with an explicit password: |
||||
|
.Bd -literal |
||||
|
$ arsse user add \-\-admin alice "Curiouser and curiouser!" |
||||
|
.Ed |
||||
|
.It Add a regular user to the database with a random password: |
||||
|
.Bd -literal |
||||
|
$ arsse user add "Bob the Builder" |
||||
|
bLS!$_UUZ!iN2i_!^IC6 |
||||
|
.Ed |
||||
|
.It Make Bob the Builder an administrator: |
||||
|
.Bd -literal |
||||
|
$ arsse user set "Bob the Builder" admin true |
||||
|
.Ed |
||||
|
.It Disable Alice's account by clearing her password: |
||||
|
.Bd -literal |
||||
|
$ arsse user unset\-pass alice |
||||
|
.Ed |
||||
|
.It Move all of Foobar's newsfeeds to the root folder: |
||||
|
.Bd -literal |
||||
|
$ arsse export foobar \-f | arsse import \-r foobar |
||||
|
.Ed |
||||
|
.It Fail to log in as Alice: |
||||
|
.Bd -literal |
||||
|
$ arsse user auth alice "Oh, dear!" |
||||
|
Authentication failed |
||||
|
$ echo $? |
||||
|
1 |
||||
|
.Ed |
||||
|
.El |
||||
|
. |
||||
|
. |
||||
|
.Sh REPORTING BUGS |
||||
|
Any bugs found in The Arsse may be reported on the Web via the |
||||
|
.Lk https://code.mensbeam.com/MensBeam/arsse "MensBeam code repository" |
||||
|
or may be directed to the principal authors by e-mail: |
||||
|
.Pp |
||||
|
.Bl -bullet -compact |
||||
|
.It |
||||
|
.Lk https://jkingweb.ca/ "J. King" |
||||
|
.It |
||||
|
.Lk https://dustinwilson.com/ "Dustin Wilson" |
||||
|
.El |
@ -1,57 +0,0 @@ |
|||||
server { |
|
||||
server_name example.com; |
|
||||
listen 80; # adding HTTPS configuration is highly recommended |
|
||||
root /usr/share/arsse/www; # adjust according to your installation path |
|
||||
|
|
||||
location / { |
|
||||
try_files $uri $uri/ =404; |
|
||||
} |
|
||||
|
|
||||
location @arsse { |
|
||||
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; # adjust according to your system configuration |
|
||||
fastcgi_pass_header Authorization; # required if the Arsse is to perform its own HTTP authentication |
|
||||
fastcgi_pass_request_body on; |
|
||||
fastcgi_pass_request_headers on; |
|
||||
fastcgi_intercept_errors off; |
|
||||
fastcgi_buffering off; |
|
||||
fastcgi_param SCRIPT_FILENAME /usr/share/arsse/arsse.php; # adjust according to your installation path |
|
||||
fastcgi_param REQUEST_METHOD $request_method; |
|
||||
fastcgi_param CONTENT_TYPE $content_type; |
|
||||
fastcgi_param CONTENT_LENGTH $content_length; |
|
||||
fastcgi_param REQUEST_URI $uri; |
|
||||
fastcgi_param HTTPS $https if_not_empty; |
|
||||
fastcgi_param REMOTE_USER $remote_user; |
|
||||
} |
|
||||
|
|
||||
# NextCloud News protocol |
|
||||
location /index.php/apps/news/api { |
|
||||
try_files $uri @arsse; |
|
||||
|
|
||||
location ~ ^/index\.php/apps/news/api/?$ { |
|
||||
# this path should not be behind HTTP authentication |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
# Tiny Tiny RSS protocol |
|
||||
location /tt-rss/api { |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
|
|
||||
# Tiny Tiny RSS feed icons |
|
||||
location /tt-rss/feed-icons/ { |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
|
|
||||
# Tiny Tiny RSS special-feed icons; these are static files |
|
||||
location /tt-rss/images/ { |
|
||||
# this path should not be behind HTTP authentication |
|
||||
try_files $uri =404; |
|
||||
} |
|
||||
|
|
||||
# Fever protocol |
|
||||
location /fever/ { |
|
||||
# this path should not be behind HTTP authentication |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,15 @@ |
|||||
|
fastcgi_pass_header Authorization; # required if the Arsse is to perform its own HTTP authentication |
||||
|
fastcgi_pass_request_body on; |
||||
|
fastcgi_pass_request_headers on; |
||||
|
fastcgi_intercept_errors off; |
||||
|
fastcgi_buffering off; |
||||
|
fastcgi_param REQUEST_METHOD $request_method; |
||||
|
fastcgi_param CONTENT_TYPE $content_type; |
||||
|
fastcgi_param CONTENT_LENGTH $content_length; |
||||
|
fastcgi_param REQUEST_URI $uri; |
||||
|
fastcgi_param QUERY_STRING $query_string; |
||||
|
fastcgi_param HTTPS $https if_not_empty; |
||||
|
fastcgi_param REMOTE_USER $remote_user; |
||||
|
|
||||
|
fastcgi_pass unix:/var/run/php/arsse.sock; |
||||
|
fastcgi_param SCRIPT_FILENAME /usr/share/arsse/arsse.php; |
@ -0,0 +1,49 @@ |
|||||
|
# Any provided static files |
||||
|
location / { |
||||
|
try_files $uri $uri/ =404; |
||||
|
} |
||||
|
|
||||
|
# Nextcloud News protocol |
||||
|
location /index.php/apps/news/api { |
||||
|
try_files $uri @arsse; |
||||
|
|
||||
|
location ~ ^/index\.php/apps/news/api/?$ { |
||||
|
try_files $uri @arsse_public; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
# Tiny Tiny RSS protocol |
||||
|
location /tt-rss/api { |
||||
|
try_files $uri @arsse; |
||||
|
} |
||||
|
|
||||
|
# Tiny Tiny RSS feed icons |
||||
|
location /tt-rss/feed-icons/ { |
||||
|
try_files $uri @arsse; |
||||
|
} |
||||
|
|
||||
|
# Tiny Tiny RSS special-feed icons; these are static files |
||||
|
location /tt-rss/images/ { |
||||
|
try_files $uri =404; |
||||
|
} |
||||
|
|
||||
|
# Fever protocol |
||||
|
location /fever/ { |
||||
|
try_files $uri @arsse; |
||||
|
} |
||||
|
|
||||
|
# Miniflux protocol |
||||
|
location /v1/ { |
||||
|
# If put behind HTTP authentication token login will not be possible |
||||
|
try_files $uri @arsse; |
||||
|
} |
||||
|
|
||||
|
# Miniflux version number |
||||
|
location /version { |
||||
|
try_files $uri @arsse_public; |
||||
|
} |
||||
|
|
||||
|
# Miniflux "health check" |
||||
|
location /healthcheck { |
||||
|
try_files $uri @arsse_public; |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
root /usr/share/arsse/www; |
||||
|
|
||||
|
location @arsse { |
||||
|
# HTTP authentication may be enabled for this location, though this may impact some features |
||||
|
include /etc/arsse/nginx/arsse-fcgi.conf; |
||||
|
} |
||||
|
|
||||
|
location @arsse_public { |
||||
|
# HTTP authentication should not be enabled for this location |
||||
|
include /etc/arsse/nginx/arsse-fcgi.conf; |
||||
|
} |
||||
|
|
||||
|
include /etc/arsse/nginx/arsse-loc.conf; |
@ -0,0 +1,13 @@ |
|||||
|
server { |
||||
|
server_name news.example.com; |
||||
|
listen 80; |
||||
|
listen [::]:80; |
||||
|
listen 443 ssl http2; |
||||
|
listen [::]:443 ssl http2; |
||||
|
|
||||
|
ssl_certificate /etc/letsencrypt/live/news.example.com/fullchain.pem; |
||||
|
ssl_certificate_key /etc/letsencrypt/live/news.example.com/privkey.pem; |
||||
|
ssl_trusted_certificate /etc/letsencrypt/live/news.example.com/chain.pem; |
||||
|
|
||||
|
include /etc/arsse/nginx/arsse.conf; |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
[arsse] |
||||
|
user = arsse |
||||
|
group = arsse |
||||
|
listen = /var/run/php/arsse.sock |
||||
|
listen.owner = arsse |
||||
|
listen.group = www-data |
||||
|
pm = dynamic |
||||
|
pm.max_children = 5 |
||||
|
pm.start_servers = 2 |
||||
|
pm.min_spare_servers = 1 |
||||
|
pm.max_spare_servers = 3 |
@ -0,0 +1,36 @@ |
|||||
|
[Unit] |
||||
|
Description=The Arsse newsfeed fetching service |
||||
|
Documentation=https://thearsse.com/manual/ |
||||
|
PartOf=arsse.service |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
|
|
||||
|
[Service] |
||||
|
User=arsse |
||||
|
Group=arsse |
||||
|
Type=simple |
||||
|
WorkingDirectory=/usr/share/arsse |
||||
|
ExecStart=/usr/bin/arsse daemon |
||||
|
|
||||
|
ProtectProc=invisible |
||||
|
NoNewPrivileges=true |
||||
|
ProtectSystem=full |
||||
|
ProtectHome=true |
||||
|
StateDirectory=arsse |
||||
|
ConfigurationDirectory=arsse |
||||
|
PrivateTmp=true |
||||
|
PrivateDevices=true |
||||
|
RestrictSUIDSGID=true |
||||
|
StandardOutput=journal |
||||
|
StandardError=journal |
||||
|
SyslogIdentifier=arsse |
||||
|
Restart=on-failure |
||||
|
RestartPreventStatus= |
||||
|
|
||||
|
# These directives can be used for extra security, but are disabled for now for compatibility |
||||
|
|
||||
|
#ReadOnlyPaths=/ |
||||
|
#ReadWriePaths=/var/lib/arsse |
||||
|
#NoExecPaths=/ |
||||
|
#ExecPaths=/usr/bin/php |
@ -0,0 +1,14 @@ |
|||||
|
[Unit] |
||||
|
Description=The Arsse newsfeed management service |
||||
|
Documentation=https://thearsse.com/manual/ |
||||
|
Requires=arsse-fetch.service |
||||
|
BindsTo=php-fpm.service |
||||
|
After=php-fpm.service |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
|
|
||||
|
[Service] |
||||
|
Type=oneshot |
||||
|
RemainAfterExit=true |
||||
|
ExecStart=/usr/bin/true |
@ -0,0 +1 @@ |
|||||
|
u arsse - "The Arsse" /var/lib/arsse - |
@ -0,0 +1,5 @@ |
|||||
|
z /usr/bin/arsse 0755 root arsse - - |
||||
|
z /etc/arsse/config.php 0640 root arsse - - |
||||
|
L /usr/share/arsse/config.php - root arsse - /etc/arsse/config.php |
||||
|
d /var/lib/arsse 0750 arsse arsse - - |
||||
|
L /usr/share/arsse/arsse - root arsse - /usr/share/arsse/arsse.php |
@ -1,15 +0,0 @@ |
|||||
The Arsse has the following requirements: |
|
||||
|
|
||||
- A Linux server running Nginx or Apache 2.4 (tested on Ubuntu 16.04 and 18.04) |
|
||||
- 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 [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) |
|
||||
- One of: |
|
||||
- [sqlite3](http://php.net/manual/en/book.sqlite3.php) or [pdo_sqlite](http://php.net/manual/en/ref.pdo-sqlite.php) for SQLite databases |
|
||||
- [pgsql](http://php.net/manual/en/book.pgsql.php) or [pdo_pgsql](http://php.net/manual/en/ref.pdo-pgsql.php) for PostgreSQL 10 or later databases |
|
||||
- [mysqli](http://php.net/manual/en/book.mysqli.php) or [pdo_mysql](http://php.net/manual/en/ref.pdo-mysql.php) for MySQL/Percona 8.0.11 or later databases |
|
||||
- Privileges either to create and run systemd services, or to run cron jobs |
|
||||
|
|
||||
Instructions for how to satisfy the PHP extension requirements for Debian systems are included in the next section. |
|
||||
|
|
||||
It is also be possible to run The Arsse on other operating systems (including Windows) and with other Web servers, but the configuration required to do so is not documented in this manual. |
|
@ -1,41 +0,0 @@ |
|||||
[TOC] |
|
||||
|
|
||||
# Downloading The Arse |
|
||||
|
|
||||
The latest version of The Arsse can be downloaded [from our releases page](https://code.mensbeam.com/MensBeam/arsse/releases). The attachments named _arsse-x.x.x.tar.gz_ should be used rather than those marked "Source Code". |
|
||||
|
|
||||
Installation from source code is also possible, but the release packages are recommended. |
|
||||
|
|
||||
# Installation |
|
||||
|
|
||||
In order for The Arsse to function correctly, [its requirements](Requirements) must first be satisfied. The process of installing the required PHP extensions differs from one system to the next, but on Debian the following series of commands should do: |
|
||||
|
|
||||
```sh |
|
||||
# Install PHP; this assumes the FastCGI process manager will be used |
|
||||
sudo apt install php-cli php-fpm |
|
||||
# Install the needed PHP extensions; php-curl is optional |
|
||||
sudo apt install php-intl php-json php-xml php-curl |
|
||||
# Install any one of the required database extensions |
|
||||
sudo apt install php-sqlite3 php-pgsql php-mysql |
|
||||
``` |
|
||||
|
|
||||
Then, it's a simple matter of unpacking the archive someplace (`/usr/share/arsse` is the recommended location on Debian systems, but it can be anywhere) and setting permissions: |
|
||||
|
|
||||
```sh |
|
||||
# Unpack the archive |
|
||||
sudo tar -xzf arsse-x.x.x.tar.gz -C "/usr/share" |
|
||||
# Make the user running the Web server the owner of the files |
|
||||
sudo chown -R www-data:www-data "/usr/share/arsse" |
|
||||
# Ensure the owner can create files such as the SQLite database |
|
||||
sudo chmod o+rwX "/usr/share/arsse" |
|
||||
``` |
|
||||
|
|
||||
# Next steps |
|
||||
|
|
||||
If using a database other than SQLite, you will likely want to [set it up](Database_Setup) before doing anything else. |
|
||||
|
|
||||
In order for the various synchronization protocols to work, a Web server [must be configured](Web_Server_Configuration), and in order for The Arsse to serve users, those users [must be created](/en/Using_The_Arsse/Managing_Users). |
|
||||
|
|
||||
You may also want to review the `config.defaults.php` file included in the download package and create [a configuration file](Configuration), though The Arsse can function even without using a configuration file. |
|
||||
|
|
||||
Finally, The Arsse's [newsfeed refreshing service](/en/Using_The_Arsse/Keeping_Newsfeeds_Up_to_Date) needs to be installed in order for news to actually be fetched from the Internet. |
|
@ -0,0 +1,71 @@ |
|||||
|
[TOC] |
||||
|
|
||||
|
# Downloading The Arsse |
||||
|
|
||||
|
Since version 0.9.2 The Arsse is available from the [Arch User Repository](https://aur.archlinux.org/) as packages `arsse` and `arsse-git`. The latter should normally only be used to test bug fixes. |
||||
|
|
||||
|
Generic release tarballs may also be downloaded [from our Web site](https://thearsse.com), and the `PKGBUILD` file (found under `arsse/dist/arch/`) can then be extracted alongside the tarball and used to build the `arsse` package. Installing directly from the generic release tarball without producing an Arch package is not recommended as the package-building process performs various adjustments to handle Arch peculiarities. |
||||
|
|
||||
|
# Installation |
||||
|
|
||||
|
For illustrative purposes, this document assumes the `yay` [AUR helper](https://wiki.archlinux.org/title/AUR_helpers) will be used to download, build, and install The Arsse. This section summarises the steps necessary to configure and use The Arsse after installtion: |
||||
|
|
||||
|
```sh |
||||
|
# Install the package |
||||
|
sudo yay -S arsse |
||||
|
# Enable the necessary PHP extensions; curl is optional but recommended; pdo_sqlite may be used instead of sqlite3, but this is not recommended |
||||
|
sudo sed -i -e 's/^;\(extension=\(curl\|iconv\|intl\|sqlite3\)\)$/\1/' /etc/php/php.ini |
||||
|
# Enable and start the necessary systemd units |
||||
|
sudo systemctl enable php-fpm arsse |
||||
|
sudo systemctl restart php-fpm arsse |
||||
|
``` |
||||
|
|
||||
|
Note that the above is the most concise process, not necessarily the recommended one. In particular [it is recommended](https://wiki.archlinux.org/title/PHP#Extensions) to use `/etc/php/conf.d/` to enable PHP extensions rather than editing `php.ini` as done above. |
||||
|
|
||||
|
# Web server configuration |
||||
|
|
||||
|
Sample configuration for both Nginx and Apache HTTP Server can be found in `/etc/webapps/arsse/nginx/` and `/etc/webapps/arsse/apache/`, respectively. The `example.conf` files are basic virtual host examples; the other files they include should normally be usable without modification, but may be modified if desired. |
||||
|
|
||||
|
If using Apache HTTP Server the `mod_proxy` and `mod_proxy_fcgi` modules must be enabled. This can be achieved by adding the following lines to your virtual host or global configuration: |
||||
|
|
||||
|
```apache |
||||
|
LoadModule proxy_module modules/mod_proxy.so |
||||
|
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so |
||||
|
``` |
||||
|
|
||||
|
No additional set-up is required for Nginx. |
||||
|
|
||||
|
# Using an alternative PHP interpreter |
||||
|
|
||||
|
The above instructions assume you will be using the `php` package as your PHP interpreter. If you wish to use `php-legacy` (which is always one feature version behind, for compatibility) a few configuration tweaks are required. The follwoing commands are a short summary: |
||||
|
|
||||
|
```sh |
||||
|
# Enable the necessary PHP extensions; curl is optional but recommended; pdo_sqlite may be used instead of sqlite3, but this is not recommended |
||||
|
sudo sed -i -e 's/^;\(extension=\(curl\|iconv\|intl\|sqlite3\)\)$/\1/' /etc/php-legacy/php.ini |
||||
|
# Modify the system service's environment |
||||
|
sudo sed -i -e 's/^ARSSE_PHP=.*/ARSSE_PHP=\/usr\/bin\/php-legacy/' /etc/webapps/arsse/systemd-environment |
||||
|
# Modify the PAM environment for the administrative CLI |
||||
|
echo "export ARSSE_PHP=/usr/bin/php-legacy" | sudo tee -a /etc/profile.d/arsse >/dev/null |
||||
|
# Modify the Nginx and Apache HTTPD configurations |
||||
|
sudo sed -i -se 's/\/run\/php-fpm\//\/run\/php-fpm-legacy\//' /etc/webapps/arsse/apache/arsse-fcgi.conf /etc/webapps/arsse/nginx/arsse-fcgi.conf |
||||
|
``` |
||||
|
|
||||
|
The above procedure can also be applied to use another PHP version from AUR if so desired. |
||||
|
|
||||
|
# Next steps |
||||
|
|
||||
|
If using a database other than SQLite, you will likely want to [set it up](/en/Getting_Started/Database_Setup) before doing anything else. |
||||
|
|
||||
|
In order for The Arsse to serve users, those users [must be created](/en/Using_The_Arsse/Managing_Users). |
||||
|
|
||||
|
You may also want to review the `config.defaults.php` file included in `/etc/webapps/arsse/` or consult [the documentation for the configuration file](/en/Getting_Started/Configuration), though The Arsse should function with the default configuration. |
||||
|
|
||||
|
# Upgrading |
||||
|
|
||||
|
Upgrading The Arsse is done like any other package. By default The Arsse will perform any required database schema upgrades when the new version is executed, so the service does need to be restarted: |
||||
|
|
||||
|
```sh |
||||
|
sudo systemctl restart arsse |
||||
|
``` |
||||
|
|
||||
|
Occasionally changes to Web server configuration have been required, such as when new protocols become supported; these changes are always explicit in the `UPGRADING` file. |
@ -0,0 +1,72 @@ |
|||||
|
[TOC] |
||||
|
|
||||
|
# Downloading The Arsse |
||||
|
|
||||
|
Since version 0.10.0 pre-built Debian packages for The Arsse are available from the [OpenSUSE Build Service](https://build.opensuse.org/) (OBS) under [the author's personal project repository](https://build.opensuse.org/package/show/home:JKingWeb/arsse). This is the preferred method for instaling the software and is the means documented below. |
||||
|
|
||||
|
Generic release tarballs may also be downloaded [from our Web site](https://thearsse.com), and a Debian package built manually. Installing directly from the generic release tarball without producing a Debian package is not recommended as the Debian packages make the set-up process on Debian systems significantly simpler. |
||||
|
|
||||
|
# Adding the repository |
||||
|
|
||||
|
In order to install The Arsse, the OBS repository must first be configured along with its signing key: |
||||
|
|
||||
|
```sh |
||||
|
# Add the key |
||||
|
wget -q -O - "https://download.opensuse.org/repositories/home:/JKingWeb/Debian_Unstable/Release.key" | gpg --dearmor | sudo tee "/usr/share/keyrings/arsse-obs-keyring.gpg" >/dev/null |
||||
|
# Add the repository |
||||
|
echo "deb [signed-by=/usr/share/keyrings/arsse-obs-keyring.gpg] https://download.opensuse.org/repositories/home:/JKingWeb/Debian_Unstable/ ./" | sudo tee "/etc/apt/sources.list.d/arsse-obs.list" >/dev/null |
||||
|
# Update APT's database |
||||
|
sudo apt update -qq |
||||
|
``` |
||||
|
|
||||
|
Please note that the "Unstable" qualifier in the repository URL is a reference to Debian's "sid" release and is not a reflection on The Arsse's stability. The repository should be suitable for any Debian version or derivative which includes a sufficiently recent version of PHP. |
||||
|
|
||||
|
# Installation |
||||
|
|
||||
|
Once the OBS repository is configured, installing The Arsse is achieved with a single command: |
||||
|
|
||||
|
```sh |
||||
|
sudo apt install arsse |
||||
|
``` |
||||
|
|
||||
|
After installation is complete The Arsse will be started automatically. |
||||
|
|
||||
|
During the installation process you will be prompted whether to allow `dbconfig-common` to configure The Arsse's database automatically. The default `sqlite3` (SQLite) option is a good choice, but `pgsql` (PostgreSQL) and `mysql` (MySQL) are possible alternatives. If you wish to [use a database other than SQLite](/en/Getting_Started/Database_Setup/index), you should install it before installing The Arsse: |
||||
|
|
||||
|
```sh |
||||
|
# Install PostgreSQL |
||||
|
sudo apt install postgresql php-pgsql |
||||
|
# Install MySQL |
||||
|
sudo apt install mysql-server php-mysql |
||||
|
# Install SQLite explicitly |
||||
|
sudo apt install php-sqlite3 |
||||
|
``` |
||||
|
|
||||
|
If you wish to change the database backend after having installed The Arsse, running `dpkg-reconfigure` after installing the database server can be used to achieve this: |
||||
|
|
||||
|
```sh |
||||
|
sudo dpkg-reconfigure arsse |
||||
|
``` |
||||
|
|
||||
|
# Web server configuration |
||||
|
|
||||
|
Sample configuration for both Nginx and Apache HTTP Server can be found in `/etc/arsse/nginx/` and `/etc/arsse/apache/`, respectively. The `example.conf` files are basic virtual host examples; the other files they include should normally be usable without modification, but may be modified if needed or desired. In particularly users of systems older than Debian 11 (Bullseye) or Ubuntu 20.04 (Focal Fossa) or derivatives will need to change the PHP-FPM socket path in Nginx or Apache's `arsse.conf`. |
||||
|
|
||||
|
In order to use Apache HTTP Server the FastCGI proxy module must be enabled and the server restarted: |
||||
|
|
||||
|
```sh |
||||
|
sudo a2enmod proxy proxy_fcgi |
||||
|
sudo systemctl restart apache2 |
||||
|
``` |
||||
|
|
||||
|
No additional set-up is required for Nginx. |
||||
|
|
||||
|
# Next steps |
||||
|
|
||||
|
In order for The Arsse to serve users, those users [must be created](/en/Using_The_Arsse/Managing_Users). |
||||
|
|
||||
|
You may also want to review the `config.defaults.php` file included in the download package and create [a configuration file](/en/Getting_Started/Configuration), though The Arsse can function even without using a configuration file. |
||||
|
|
||||
|
# Upgrading |
||||
|
|
||||
|
Upgrading The Arsse is done like any other package. Occasionally changes to Web server configuration have been required, such as when new protocols become supported; these changes are always explicit in the `UPGRADING` file. |
@ -0,0 +1,53 @@ |
|||||
|
# Downloading The Arsse |
||||
|
|
||||
|
The Arsse should run on any operating system for which PHP and a Web server are available, but only the combination of Linux, Systemd, Nginx, and PHP-FPM has been extensively tested. |
||||
|
|
||||
|
Below are very generic instructions and suggestions for installing The Arsse on systems for which pre-built packages are not available. |
||||
|
|
||||
|
# Requirements |
||||
|
|
||||
|
The Arsse has the following requirements: |
||||
|
|
||||
|
- A Web server such as: |
||||
|
- [Nginx](https://nginx.org) |
||||
|
- [Apache HTTP server](https://httpd.apache.org) 2.4 or later |
||||
|
- PHP 7.3.0 or later with the following extensions: |
||||
|
- [intl](https://php.net/manual/en/book.intl.php), [json](https://php.net/manual/en/book.json.php), [hash](https://php.net/manual/en/book.hash.php), [filter](https://php.net/manual/en/book.filter.php), and [dom](https://php.net/manual/en/book.dom.php) |
||||
|
- [simplexml](https://php.net/manual/en/book.simplexml.php), and [iconv](https://php.net/manual/en/book.iconv.php) |
||||
|
- One of: |
||||
|
- [sqlite3](https://php.net/manual/en/book.sqlite3.php) or [pdo_sqlite](https://php.net/manual/en/ref.pdo-sqlite.php) for SQLite databases |
||||
|
- [pgsql](https://php.net/manual/en/book.pgsql.php) or [pdo_pgsql](https://php.net/manual/en/ref.pdo-pgsql.php) for PostgreSQL 10 or later databases |
||||
|
- [mysqli](https://php.net/manual/en/book.mysqli.php) or [pdo_mysql](https://php.net/manual/en/ref.pdo-mysql.php) for MySQL/Percona 8.0.11 or later databases |
||||
|
- [curl](https://php.net/manual/en/book.curl.php) (optional) |
||||
|
- [posix](https://php.net/manual/en/book.posix.php) and [pcntl](https://php.net/manual/en/book.pcntl.php) (both optional) |
||||
|
- An interface between PHP and the Web server, such as [PHP-FPM](https://php.net/manual/en/install.fpm.php) |
||||
|
- Privileges either to create and run system services, or to run cron jobs |
||||
|
|
||||
|
# Installation |
||||
|
|
||||
|
1. Download [the latest release](https://thearsse.com/releases/current) and extract it somewhere, such as `/usr/share/arsse/` |
||||
|
2. [Set up your database](/en/Getting_Started/Database_Setup) |
||||
|
3. Create [a configuration file](/en/Getting_Started/Configuration) if needed |
||||
|
4. Consult the files under `dist/nginx` and `dist/apache` for sample Web server configuration |
||||
|
5. Consult `dist/arsse` for a sample executable script which drops privileges on POSIX systems |
||||
|
6. Start the newsfeed fetching service: |
||||
|
- Sample Systemd service files are available under `dist/systemd` |
||||
|
- A sample System V init script is available in `dist/init.sh` |
||||
|
- A persistent process can be started by running `php arsse.php daemon` |
||||
|
- It is also possible [to use cron](/en/Using_The_Arsse/Other_Topics.html#page_Refreshing_newsfeeds_with_a_cron_job) or a similar task-scheduling tool |
||||
|
7. [Create users](/en/Using_The_Arsse/Managing_Users) to grant them access |
||||
|
|
||||
|
# Upgrading |
||||
|
|
||||
|
Upgrading The Arsse is usually simple: |
||||
|
|
||||
|
1. Download the latest release |
||||
|
2. Check the `UPGRADING` file for any special notes |
||||
|
3. Stop the newsfeed refreshing service if it is running |
||||
|
4. Back up your configurationm and database |
||||
|
5. Extract the new version on top of the old one |
||||
|
6. Restart the newsfeed refreshing service |
||||
|
|
||||
|
By default The Arsse will perform any required database schema upgrades when the new version is executed. |
||||
|
|
||||
|
Occasionally changes to Web server configuration have been required, when new protocols become supported; such changes are always explicit in the `UPGRADING` file |
@ -0,0 +1,16 @@ |
|||||
|
# Installing from a package manager |
||||
|
|
||||
|
We currently provide a few pre-built installation packages for the following operating systems: |
||||
|
|
||||
|
- [Arch Linux and derivatives](On_Arch_Linux) |
||||
|
- [Debian and derivatives](On_Debian_and_Derivatives) |
||||
|
|
||||
|
These packages significantly simplify installation, though a bit of manual effort may still be required. Updating The Arsse using these packages should require no manual intervention. |
||||
|
|
||||
|
# Installing manually |
||||
|
|
||||
|
For other systems The Arsse must currently be installed manually. As each operating system is different, we can only provide very general instructions: |
||||
|
|
||||
|
- [Installing on other systems](On_Other_Systems) |
||||
|
|
||||
|
We hope to support more operating systems in the future. |
@ -1,106 +0,0 @@ |
|||||
[TOC] |
|
||||
|
|
||||
# Preface |
|
||||
|
|
||||
As a PHP application, The Arsse requires the aid of a Web server in order to communicate with clients. How to install and configure a Web server in general is outside the scope of this document, but this section provides examples and advice for Web server configuration specific to The Arsse. Any server capable of interfacing with PHP should work, though we have only tested Nginx and Apache 2.4. |
|
||||
|
|
||||
Samples included here only cover the bare minimum for configuring a virtual host. In particular, configuration for HTTPS (which is highly recommended) is omitted for the sake of clarity |
|
||||
|
|
||||
# Configuration for Nginx |
|
||||
|
|
||||
```nginx |
|
||||
server { |
|
||||
server_name example.com; |
|
||||
listen 80; # adding HTTPS configuration is highly recommended |
|
||||
root /usr/share/arsse/www; # adjust according to your installation path |
|
||||
|
|
||||
location / { |
|
||||
try_files $uri $uri/ =404; |
|
||||
} |
|
||||
|
|
||||
location @arsse { |
|
||||
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; # adjust according to your system configuration |
|
||||
fastcgi_pass_header Authorization; # required if the Arsse is to perform its own HTTP authentication |
|
||||
fastcgi_pass_request_body on; |
|
||||
fastcgi_pass_request_headers on; |
|
||||
fastcgi_intercept_errors off; |
|
||||
fastcgi_buffering off; |
|
||||
fastcgi_param SCRIPT_FILENAME /usr/share/arsse/arsse.php; # adjust according to your installation path |
|
||||
fastcgi_param REQUEST_METHOD $request_method; |
|
||||
fastcgi_param CONTENT_TYPE $content_type; |
|
||||
fastcgi_param CONTENT_LENGTH $content_length; |
|
||||
fastcgi_param REQUEST_URI $uri; |
|
||||
fastcgi_param HTTPS $https if_not_empty; |
|
||||
fastcgi_param REMOTE_USER $remote_user; |
|
||||
} |
|
||||
|
|
||||
# NextCloud News protocol |
|
||||
location /index.php/apps/news/api { |
|
||||
try_files $uri @arsse; |
|
||||
|
|
||||
location ~ ^/index\.php/apps/news/api/?$ { |
|
||||
# this path should not be behind HTTP authentication |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
# Tiny Tiny RSS protocol |
|
||||
location /tt-rss/api { |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
|
|
||||
# Tiny Tiny RSS feed icons |
|
||||
location /tt-rss/feed-icons/ { |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
|
|
||||
# Tiny Tiny RSS special-feed icons; these are static files |
|
||||
location /tt-rss/images/ { |
|
||||
# this path should not be behind HTTP authentication |
|
||||
try_files $uri =404; |
|
||||
} |
|
||||
|
|
||||
# Fever protocol |
|
||||
location /fever/ { |
|
||||
# this path should not be behind HTTP authentication |
|
||||
try_files $uri @arsse; |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
# Configuration for Apache2 |
|
||||
|
|
||||
There are many ways for Apache to interface with PHP, but the recommended way today is to use `mod_proxy` and `mod_proxy_fcgi` to communicate with PHP-FPM. If necessary you can enable these modules on Debian systems using the following commands: |
|
||||
|
|
||||
```sh |
|
||||
sudo a2enmod proxy proxy_fcgi |
|
||||
sudo systemctl restart apache2 |
|
||||
``` |
|
||||
|
|
||||
Afterward the follow virtual host configuration should work, after modifying path as appropriate: |
|
||||
|
|
||||
```apache |
|
||||
# N.B. the unix:/var/run/php/php7.2-fpm.sock path used repeatedly below will |
|
||||
# vary from system to system and will be probably need to be changed |
|
||||
|
|
||||
<VirtualHost *:80> |
|
||||
ServerName localhost |
|
||||
# adjust according to your installation path |
|
||||
DocumentRoot /usr/share/arsse/www |
|
||||
|
|
||||
# adjust according to your installation path |
|
||||
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/usr/share/arsse/arsse.php" |
|
||||
ProxyPreserveHost On |
|
||||
|
|
||||
# NextCloud News v1.2, Tiny Tiny RSS API, TT-RSS newsfeed icons |
|
||||
<LocationMatch "(/index\.php/apps/news/api/?.+|/tt-rss/(api|feed-icons))"> |
|
||||
ProxyPass "unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/usr/share/arsse" |
|
||||
</LocationMatch> |
|
||||
|
|
||||
# NextCloud News API detection, Fever API |
|
||||
<LocationMatch "(/index\.php/apps/news/api/?$|/fever)"> |
|
||||
# these locations should not be behind HTTP authentication |
|
||||
ProxyPass "unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/usr/share/arsse" |
|
||||
</LocationMatch> |
|
||||
</VirtualHost> |
|
||||
``` |
|
@ -1,3 +0,0 @@ |
|||||
Presently installing and setting up The Arsse is a manual process. We hope to have pre-configured installation packages available for various operating systems eventually, but for now the pages in this section should help get you up and running. |
|
||||
|
|
||||
Though The Arsse itself makes no assumptions about the operating system which hosts it, we use and have the most experience with Debian; the instructions contained here therefore are for Debian systems will will probably either not work with other systems or not be consistent with their conventions. Nevertheless, they should still serve as a useful guide. |
|
@ -1,49 +0,0 @@ |
|||||
[TOC] |
|
||||
|
|
||||
# Preface |
|
||||
|
|
||||
In normal operation The Arsse is expected to regularly check whether newsfeeds might have new articles, then fetch them and process them to present new or updated articles to clients. This can be achieved either by having The Arsse operate a persistent background process (termed a [daemon](https://en.wikipedia.org/wiki/Daemon_(computing)) or service), or by using an external scheduler to periodically perform single checks. Normally a daemon is preferred. |
|
||||
|
|
||||
There are many ways to administer daemons, and many schedulers can be used. This section outlines a few, but many other arrangements are possible. |
|
||||
|
|
||||
# As a daemon via systemd |
|
||||
|
|
||||
The Arsse includes a sample systemd service unit file which can be used to quickly get a daemon running with the following procedure: |
|
||||
|
|
||||
```sh |
|
||||
# Copy the service unit |
|
||||
sudo cp "/usr/share/arsse/dist/arsse.service" "/etc/systemd/system" |
|
||||
# Modify the unit file if needed |
|
||||
sudoedit "/etc/systemd/system/arsse.service" |
|
||||
# Enable and start the service |
|
||||
sudo systemctl enable --now arsse |
|
||||
``` |
|
||||
|
|
||||
The Arsse's feed updater can then be manipulated as with any other service. Consult [the `systemctl` manual](https://www.freedesktop.org/software/systemd/man/systemctl.html) for details. |
|
||||
|
|
||||
# As a cron job |
|
||||
|
|
||||
Keeping newsfeeds updated with [cron](https://en.wikipedia.org/wiki/Cron) is not difficult. Simply run the following command: |
|
||||
|
|
||||
|
|
||||
```sh |
|
||||
sudo crontab -u www-data -e |
|
||||
``` |
|
||||
|
|
||||
And add a line such as this one: |
|
||||
|
|
||||
``` |
|
||||
*/2 * * * * /usr/bin/env php /usr/share/arsse/arsse.php refresh-all |
|
||||
``` |
|
||||
|
|
||||
Thereafter The Arsse's will be scheduled to check newsfeeds every two minutes. Consult the manual pages for the `crontab` [format](http://man7.org/linux/man-pages/man5/crontab.5.html) and [command](http://man7.org/linux/man-pages/man1/crontab.1.html) for details. |
|
||||
|
|
||||
# Appendix: how often newsfeeds are fetched |
|
||||
|
|
||||
Though by default The Arsse will wake up every two minutes, newsfeeds are not actually downloaded so frequently. Instead, each newsfeed is assigned a time at which it should next be fetched, and once that time is reached a [conditional request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests) is made. The interval between requests for a particular newsfeed can vary from 15 minutes to 24 hours based on multiple factors such as: |
|
||||
|
|
||||
- The length of time since the newsfeed last changed |
|
||||
- The interval between publishing of articles in the newsfeed |
|
||||
- Whether the last fetch or last several fetches resulted in error |
|
||||
|
|
||||
As a general rule, newsfeeds which change frequently are checked frequently, and those which change seldom are fetched at most daily. |
|
@ -0,0 +1,34 @@ |
|||||
|
[TOC] |
||||
|
|
||||
|
# Preface |
||||
|
|
||||
|
This section describes in brief some CLI commands. Please read [the general notes on the command line interface](index) before continuing. |
||||
|
|
||||
|
# Refreshing newsfeeds with a cron job |
||||
|
|
||||
|
Normally The Arsse has a systemd service which checks newsfeeds for updates and processes them into its database for the user. If for whatever reason this is not practical a [cron](https://en.wikipedia.org/wiki/Cron) job may be used instead. |
||||
|
|
||||
|
Keeping newsfeeds updated with cron is not difficult. Simply run the following command: |
||||
|
|
||||
|
|
||||
|
```sh |
||||
|
sudo crontab -u arsse -e |
||||
|
``` |
||||
|
|
||||
|
And add a line such as this one: |
||||
|
|
||||
|
``` |
||||
|
*/2 * * * * /usr/bin/arsse refresh-all |
||||
|
``` |
||||
|
|
||||
|
Thereafter The Arsse's will be scheduled to check newsfeeds every two minutes. Consult the manual pages for the `crontab` [format](http://man7.org/linux/man-pages/man5/crontab.5.html) and [command](http://man7.org/linux/man-pages/man1/crontab.1.html) for details. |
||||
|
|
||||
|
# How often newsfeeds are fetched |
||||
|
|
||||
|
Though by default The Arsse will wake up every two minutes, newsfeeds are not actually downloaded so frequently. Instead, each newsfeed is assigned a time at which it should next be fetched, and once that time is reached a [conditional request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests) is made. The interval between requests for a particular newsfeed can vary from 15 minutes to 24 hours based on multiple factors such as: |
||||
|
|
||||
|
- The length of time since the newsfeed last changed |
||||
|
- The interval between publishing of articles in the newsfeed |
||||
|
- Whether the last fetch or last several fetches resulted in error |
||||
|
|
||||
|
As a general rule, newsfeeds which change frequently are checked frequently, and those which change seldom are fetched at most daily. |
@ -1,12 +0,0 @@ |
|||||
Upgrading The Arsse is usually simple: |
|
||||
|
|
||||
1. Download the latest release |
|
||||
2. Check the `UPGRADING` file for any special notes |
|
||||
3. Stop the newsfeed refreshing service if it is running |
|
||||
4. Extract the new version on top of the old one |
|
||||
5. Ensure permissions are still correct |
|
||||
6. Restart the newsfeed refreshing service |
|
||||
|
|
||||
By default The Arsse will perform any required database schema upgrades when the new version is executed, and release packages contain all newly required library dependencies. |
|
||||
|
|
||||
Occasionally changes to Web server configuration have been required, when new protocols become supported; such changes are always explicit in the `UPGRADING` file |
|
@ -0,0 +1,59 @@ |
|||||
|
[TOC] |
||||
|
|
||||
|
# About |
||||
|
|
||||
|
<dl> |
||||
|
<dt>Supported since</dt> |
||||
|
<dd>0.9.0</dd> |
||||
|
<dt>Base URL</dt> |
||||
|
<dd>/</dd> |
||||
|
<dt>API endpoint</dt> |
||||
|
<dd>/v1/</dd> |
||||
|
<dt>Specifications</dt> |
||||
|
<dd><a href="https://miniflux.app/docs/api.html">API Reference</a>, <a href="https://miniflux.app/docs/rules.html#filtering-rules">Filtering Rules</a></dd> |
||||
|
</dl> |
||||
|
|
||||
|
The Miniflux protocol is a fairly well-designed protocol supporting a wide variety of operations on newsfeeds, folders (termed "categories"), and articles; it also allows for user administration, and native OPML importing and exporting. Architecturally it is similar to the Nextcloud News protocol, but has more capabilities. |
||||
|
|
||||
|
Miniflux version 2.0.28 is emulated, though not all features are implemented |
||||
|
|
||||
|
# Missing features |
||||
|
|
||||
|
- JSON Feed format is not suported |
||||
|
- Various feed-related features are not supported; attempting to use them has no effect |
||||
|
- Rewrite rules and scraper rules |
||||
|
- Custom User-Agent strings |
||||
|
- The `disabled`, `ignore_http_cache`, and `fetch_via_proxy` flags |
||||
|
- Changing the URL, username, or password of a feed |
||||
|
- Manually refreshing feeds |
||||
|
- Titles and types are not available during feed discovery and are filled with generic data |
||||
|
- Reading time is not calculated and will always be zero |
||||
|
- Only the first enclosure of an article is retained |
||||
|
- Comment URLs of articles are not exposed |
||||
|
|
||||
|
# Differences |
||||
|
|
||||
|
- Various error codes and messages differ due to significant implementation differences |
||||
|
- The "All" category is treated specially (see below for details) |
||||
|
- Feed and category titles consisting only of whitespace are rejected along with the empty string |
||||
|
- Filtering rules may not function identically (see below for details) |
||||
|
- The `checked_at` field of feeds indicates when the feed was last updated rather than when it was last checked |
||||
|
- Creating a feed with the `scrape` property set to `true` might not return scraped content for the initial synchronization |
||||
|
- Search strings will match partial words |
||||
|
- OPML import either succeeds or fails atomically: if one feed fails, no feeds are imported |
||||
|
|
||||
|
# Behaviour of filtering (block and keep) rules |
||||
|
|
||||
|
The Miniflux documentation gives only a brief example of a pattern for its filtering rules; the allowed syntax is described in full [in Google's documentation for RE2](https://github.com/google/re2/wiki/Syntax). Being a PHP application, The Arsse instead accepts [PCRE syntax](http://www.pcre.org/original/doc/html/pcresyntax.html) (or since PHP 7.3 [PCRE2 syntax](https://www.pcre.org/current/doc/html/pcre2syntax.html)), specifically in UTF-8 mode. Delimiters should not be included, and slashes should not be escaped; anchors may be used if desired. For example `^(?i)RE/MAX$` is a valid pattern. |
||||
|
|
||||
|
For convenience the patterns are tested after collapsing whitespace. Unlike Miniflux, The Arsse tests the patterns against an article's author-supplied categories if they do not match its title. Also unlike Miniflux, when filter rules are modified they are re-evaluated against all applicable articles immediately. |
||||
|
|
||||
|
# Special handling of the "All" category |
||||
|
|
||||
|
Nextcloud News' root folder and Tiny Tiny RSS' "Uncategorized" catgory are mapped to Miniflux's initial "All" category. This Miniflux category can be renamed, but it cannot be deleted. Attempting to do so will delete the child feeds it contains, but not the category itself. |
||||
|
|
||||
|
Because the root folder does not existing in the database as a separate entity, it will always sort first when ordering by `category_id` or `category_title`. |
||||
|
|
||||
|
# Interaction with nested categories |
||||
|
|
||||
|
Tiny Tiny RSS is unique in allowing newsfeeds to be grouped into categories nested to arbitrary depth. When newsfeeds are placed into nested categories, they simply appear in the top-level category when accessed via the Miniflux protocol. This does not affect OPML exports, where full nesting is preserved. |
File diff suppressed because one or more lines are too long
@ -0,0 +1,28 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2017 J. King, Dustin Wilson et al. |
||||
|
* See LICENSE and AUTHORS files for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace JKingWeb\Arsse\Context; |
||||
|
|
||||
|
abstract class AbstractContext { |
||||
|
protected $props = []; |
||||
|
protected $parent = null; |
||||
|
|
||||
|
protected function act(string $prop, int $set, $value) { |
||||
|
if ($set) { |
||||
|
if (is_null($value)) { |
||||
|
unset($this->props[$prop]); |
||||
|
$this->$prop = (new \ReflectionClass($this))->getDefaultProperties()[$prop]; |
||||
|
} else { |
||||
|
$this->props[$prop] = true; |
||||
|
$this->$prop = $value; |
||||
|
} |
||||
|
return $this->parent ?? $this; |
||||
|
} else { |
||||
|
return isset($this->props[$prop]); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2017 J. King, Dustin Wilson et al. |
||||
|
* See LICENSE and AUTHORS files for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace JKingWeb\Arsse\Context; |
||||
|
|
||||
|
trait BooleanMembers { |
||||
|
public $unread = null; |
||||
|
public $starred = null; |
||||
|
public $hidden = null; |
||||
|
public $labelled = null; |
||||
|
public $annotated = null; |
||||
|
|
||||
|
public function unread(bool $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function starred(bool $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function hidden(bool $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function labelled(bool $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function annotated(bool $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
} |
@ -0,0 +1,262 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2017 J. King, Dustin Wilson et al. |
||||
|
* See LICENSE and AUTHORS files for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace JKingWeb\Arsse\Context; |
||||
|
|
||||
|
use JKingWeb\Arsse\Misc\ValueInfo; |
||||
|
use JKingWeb\Arsse\Misc\Date; |
||||
|
|
||||
|
trait ExclusionMembers { |
||||
|
public $folder = null; |
||||
|
public $folders = []; |
||||
|
public $folderShallow = null; |
||||
|
public $foldersShallow = []; |
||||
|
public $tag = null; |
||||
|
public $tags = []; |
||||
|
public $tagName = null; |
||||
|
public $tagNames = []; |
||||
|
public $subscription = null; |
||||
|
public $subscriptions = []; |
||||
|
public $edition = null; |
||||
|
public $editions = []; |
||||
|
public $article = null; |
||||
|
public $articles = []; |
||||
|
public $label = null; |
||||
|
public $labels = []; |
||||
|
public $labelName = null; |
||||
|
public $labelNames = []; |
||||
|
public $annotationTerms = []; |
||||
|
public $searchTerms = []; |
||||
|
public $titleTerms = []; |
||||
|
public $authorTerms = []; |
||||
|
public $articleRange = [null, null]; |
||||
|
public $editionRange = [null, null]; |
||||
|
public $modifiedRange = [null, null]; |
||||
|
public $modifiedRanges = []; |
||||
|
public $markedRange = [null, null]; |
||||
|
public $markedRanges = []; |
||||
|
|
||||
|
protected function cleanIdArray(array $spec, bool $allowZero = false): array { |
||||
|
$spec = array_values($spec); |
||||
|
for ($a = 0; $a < sizeof($spec); $a++) { |
||||
|
if (ValueInfo::id($spec[$a], $allowZero)) { |
||||
|
$spec[$a] = (int) $spec[$a]; |
||||
|
} else { |
||||
|
$spec[$a] = null; |
||||
|
} |
||||
|
} |
||||
|
return array_values(array_unique(array_filter($spec, function($v) { |
||||
|
return !is_null($v); |
||||
|
}))); |
||||
|
} |
||||
|
|
||||
|
protected function cleanStringArray(array $spec): array { |
||||
|
$spec = array_values($spec); |
||||
|
$stop = sizeof($spec); |
||||
|
for ($a = 0; $a < $stop; $a++) { |
||||
|
if (strlen($str = ValueInfo::normalize($spec[$a], ValueInfo::T_STRING | ValueInfo::M_DROP) ?? "")) { |
||||
|
$spec[$a] = $str; |
||||
|
} else { |
||||
|
unset($spec[$a]); |
||||
|
} |
||||
|
} |
||||
|
return array_values(array_unique($spec)); |
||||
|
} |
||||
|
|
||||
|
protected function cleanDateRangeArray(array $spec): array { |
||||
|
$spec = array_values($spec); |
||||
|
$stop = sizeof($spec); |
||||
|
for ($a = 0; $a < $stop; $a++) { |
||||
|
if (!is_array($spec[$a]) || sizeof($spec[$a]) !== 2) { |
||||
|
unset($spec[$a]); |
||||
|
} else { |
||||
|
$spec[$a] = ValueInfo::normalize($spec[$a], ValueInfo::T_DATE | ValueInfo::M_ARRAY | ValueInfo::M_DROP); |
||||
|
if ($spec[$a] === [null, null]) { |
||||
|
unset($spec[$a]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return array_values(array_unique($spec, \SORT_REGULAR)); |
||||
|
} |
||||
|
|
||||
|
public function folder(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function folders(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec, true); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function folderShallow(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function foldersShallow(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec, true); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function tag(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function tags(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function tagName(string $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function tagNames(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanStringArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function subscription(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function subscriptions(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function edition(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function article(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function editions(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function articles(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function label(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function labels(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanIdArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function labelName(string $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function labelNames(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanStringArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function annotationTerms(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanStringArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function searchTerms(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanStringArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function titleTerms(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanStringArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function authorTerms(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanStringArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function articleRange(?int $start = null, ?int $end = null) { |
||||
|
if ($start === null && $end === null) { |
||||
|
$spec = null; |
||||
|
} else { |
||||
|
$spec = [$start, $end]; |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function editionRange(?int $start = null, ?int $end = null) { |
||||
|
if ($start === null && $end === null) { |
||||
|
$spec = null; |
||||
|
} else { |
||||
|
$spec = [$start, $end]; |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function modifiedRange($start = null, $end = null) { |
||||
|
if ($start === null && $end === null) { |
||||
|
$spec = null; |
||||
|
} else { |
||||
|
$spec = [Date::normalize($start), Date::normalize($end)]; |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function modifiedRanges(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanDateRangeArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function markedRange($start = null, $end = null) { |
||||
|
if ($start === null && $end === null) { |
||||
|
$spec = null; |
||||
|
} else { |
||||
|
$spec = [Date::normalize($start), Date::normalize($end)]; |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function markedRanges(array $spec = null) { |
||||
|
if (isset($spec)) { |
||||
|
$spec = $this->cleanDateRangeArray($spec); |
||||
|
} |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2017 J. King, Dustin Wilson et al. |
||||
|
* See LICENSE and AUTHORS files for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace JKingWeb\Arsse\Context; |
||||
|
|
||||
|
abstract class RootContext extends AbstractContext { |
||||
|
public $limit = 0; |
||||
|
public $offset = 0; |
||||
|
|
||||
|
public function limit(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
|
||||
|
public function offset(int $spec = null) { |
||||
|
return $this->act(__FUNCTION__, func_num_args(), $spec); |
||||
|
} |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
<?php |
||||
|
/** @license MIT |
||||
|
* Copyright 2017 J. King, Dustin Wilson et al. |
||||
|
* See LICENSE and AUTHORS files for details */ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace JKingWeb\Arsse\Context; |
||||
|
|
||||
|
class UnionContext extends RootContext implements \ArrayAccess, \Countable, \IteratorAggregate { |
||||
|
protected $contexts = []; |
||||
|
|
||||
|
#[\ReturnTypeWillChange] |
||||
|
public function offsetExists($offset) { |
||||
|
return isset($this->contexts[$offset]); |
||||
|
} |
||||
|
|
||||
|
#[\ReturnTypeWillChange] |
||||
|
public function offsetGet($offset) { |
||||
|
return $this->contexts[$offset] ?? null; |
||||
|
} |
||||
|
|
||||
|
#[\ReturnTypeWillChange] |
||||
|
public function offsetSet($offset, $value) { |
||||
|
assert($value instanceof RootContext, new \Exception("Union contexts may only contain other non-exclusion contexts")); |
||||
|
if (isset($offset)) { |
||||
|
$this->contexts[$offset] = $value; |
||||
|
} else { |
||||
|
$this->contexts[] = $value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#[\ReturnTypeWillChange] |
||||
|
public function offsetUnset($offset) { |
||||
|
unset($this->contexts[$offset]); |
||||
|
} |
||||
|
|
||||
|
public function count(): int { |
||||
|
return count($this->contexts); |
||||
|
} |
||||
|
|
||||
|
public function getIterator(): \Traversable { |
||||
|
foreach ($this->contexts as $k => $c) { |
||||
|
yield $k => $c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function __construct(RootContext ...$context) { |
||||
|
$this->contexts = $context; |
||||
|
} |
||||
|
} |
File diff suppressed because it is too large
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue