mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2024-11-24 02:16:08 +03:00
chore: add tools for manually administrating the configured cache (#3867)
This commit is contained in:
parent
3ce94409ab
commit
0bf5dbbc0b
10 changed files with 95 additions and 45 deletions
36
README.md
36
README.md
|
@ -251,7 +251,7 @@ Browse http://localhost:3000/
|
||||||
[![Deploy to Cloudron](https://cloudron.io/img/button.svg)](https://www.cloudron.io/store/com.rssbridgeapp.cloudronapp.html)
|
[![Deploy to Cloudron](https://cloudron.io/img/button.svg)](https://www.cloudron.io/store/com.rssbridgeapp.cloudronapp.html)
|
||||||
[![Run on PikaPods](https://www.pikapods.com/static/run-button.svg)](https://www.pikapods.com/pods?run=rssbridge)
|
[![Run on PikaPods](https://www.pikapods.com/static/run-button.svg)](https://www.pikapods.com/pods?run=rssbridge)
|
||||||
|
|
||||||
The Heroku quick deploy currently does not work. It might possibly work if you fork this repo and
|
The Heroku quick deploy currently does not work. It might work if you fork this repo and
|
||||||
modify the `repository` in `scalingo.json`. See https://github.com/RSS-Bridge/rss-bridge/issues/2688
|
modify the `repository` in `scalingo.json`. See https://github.com/RSS-Bridge/rss-bridge/issues/2688
|
||||||
|
|
||||||
Learn more in
|
Learn more in
|
||||||
|
@ -259,11 +259,29 @@ Learn more in
|
||||||
|
|
||||||
## How-to
|
## How-to
|
||||||
|
|
||||||
|
### How to remove all cache items
|
||||||
|
|
||||||
|
As current user:
|
||||||
|
|
||||||
|
bin/cache-clear
|
||||||
|
|
||||||
|
As user rss-bridge:
|
||||||
|
|
||||||
|
sudo -u rss-bridge bin/cache-clear
|
||||||
|
|
||||||
|
As root:
|
||||||
|
|
||||||
|
sudo bin/cache-clear
|
||||||
|
|
||||||
|
### How to remove all expired cache items
|
||||||
|
|
||||||
|
bin/cache-clear
|
||||||
|
|
||||||
### How to fix "PHP Fatal error: Uncaught Exception: The FileCache path is not writable"
|
### How to fix "PHP Fatal error: Uncaught Exception: The FileCache path is not writable"
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Give rssbridge ownership
|
# Give rss-bridge ownership
|
||||||
chown rssbridge:rssbridge -R /var/www/rss-bridge/cache
|
chown rss-bridge:rss-bridge -R /var/www/rss-bridge/cache
|
||||||
|
|
||||||
# Or, give www-data ownership
|
# Or, give www-data ownership
|
||||||
chown www-data:www-data -R /var/www/rss-bridge/cache
|
chown www-data:www-data -R /var/www/rss-bridge/cache
|
||||||
|
@ -275,6 +293,16 @@ chmod 777 -R /var/www/rss-bridge/cache
|
||||||
rm -rf /var/www/rss-bridge/cache/ && mkdir /var/www/rss-bridge/cache/
|
rm -rf /var/www/rss-bridge/cache/ && mkdir /var/www/rss-bridge/cache/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### How to fix "attempt to write a readonly database"
|
||||||
|
|
||||||
|
The sqlite files (db, wal and shm) are not writeable.
|
||||||
|
|
||||||
|
chown -v rss-bridge:rss-bridge cache/*
|
||||||
|
|
||||||
|
### How to fix "Unable to prepare statement: 1, no such table: storage"
|
||||||
|
|
||||||
|
rm cache/*
|
||||||
|
|
||||||
### How to create a new bridge from scratch
|
### How to create a new bridge from scratch
|
||||||
|
|
||||||
Create the new bridge in e.g. `bridges/BearBlogBridge.php`:
|
Create the new bridge in e.g. `bridges/BearBlogBridge.php`:
|
||||||
|
@ -389,6 +417,8 @@ These commands require that you have installed the dev dependencies in `composer
|
||||||
./vendor/bin/phpunit
|
./vendor/bin/phpunit
|
||||||
./vendor/bin/phpcs --standard=phpcs.xml --warning-severity=0 --extensions=php -p ./
|
./vendor/bin/phpcs --standard=phpcs.xml --warning-severity=0 --extensions=php -p ./
|
||||||
|
|
||||||
|
https://github.com/squizlabs/PHP_CodeSniffer/wiki
|
||||||
|
|
||||||
### How to spawn a minimal development environment
|
### How to spawn a minimal development environment
|
||||||
|
|
||||||
php -S 127.0.0.1:9001
|
php -S 127.0.0.1:9001
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Good resource on API return values (Ex: illustType):
|
||||||
|
* https://hackage.haskell.org/package/pixiv-0.1.0/docs/Web-Pixiv-Types.html
|
||||||
|
*/
|
||||||
class PixivBridge extends BridgeAbstract
|
class PixivBridge extends BridgeAbstract
|
||||||
{
|
{
|
||||||
// Good resource on API return values (Ex: illustType):
|
|
||||||
// https://hackage.haskell.org/package/pixiv-0.1.0/docs/Web-Pixiv-Types.html
|
|
||||||
const NAME = 'Pixiv Bridge';
|
const NAME = 'Pixiv Bridge';
|
||||||
const URI = 'https://www.pixiv.net/';
|
const URI = 'https://www.pixiv.net/';
|
||||||
const DESCRIPTION = 'Returns the tag search from pixiv.net';
|
const DESCRIPTION = 'Returns the tag search from pixiv.net';
|
||||||
|
@ -19,7 +21,6 @@ class PixivBridge extends BridgeAbstract
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
const PARAMETERS = [
|
const PARAMETERS = [
|
||||||
'global' => [
|
'global' => [
|
||||||
'posts' => [
|
'posts' => [
|
||||||
|
@ -251,14 +252,13 @@ class PixivBridge extends BridgeAbstract
|
||||||
$img_url = preg_replace('/https:\/\/i\.pximg\.net/', $proxy_url, $result['url']);
|
$img_url = preg_replace('/https:\/\/i\.pximg\.net/', $proxy_url, $result['url']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//else cache and use image.
|
$img_url = $result['url'];
|
||||||
$img_url = $this->cacheImage(
|
// Temporarily disabling caching of the image
|
||||||
$result['url'],
|
//$img_url = $this->cacheImage($result['url'], $result['id'], array_key_exists('illustType', $result));
|
||||||
$result['id'],
|
|
||||||
array_key_exists('illustType', $result)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
$item['content'] = "<img src='" . $img_url . "' />";
|
|
||||||
|
// Currently, this might result in broken image due to their strict referrer check
|
||||||
|
$item['content'] = sprintf('<a href="%s"><img src="%s"/></a>', $img_url, $img_url);
|
||||||
|
|
||||||
// Additional content items
|
// Additional content items
|
||||||
if (array_key_exists('pageCount', $result)) {
|
if (array_key_exists('pageCount', $result)) {
|
||||||
|
@ -318,7 +318,7 @@ class PixivBridge extends BridgeAbstract
|
||||||
if (
|
if (
|
||||||
!(strlen($proxy) > 0 && preg_match('/https?:\/\/.*/', $proxy))
|
!(strlen($proxy) > 0 && preg_match('/https?:\/\/.*/', $proxy))
|
||||||
) {
|
) {
|
||||||
return returnServerError('Invalid proxy_url value set. The proxy must include the HTTP/S at the beginning of the url.');
|
returnServerError('Invalid proxy_url value set. The proxy must include the HTTP/S at the beginning of the url.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,8 +326,7 @@ class PixivBridge extends BridgeAbstract
|
||||||
if ($cookie) {
|
if ($cookie) {
|
||||||
$isAuth = $this->loadCacheValue('is_authenticated');
|
$isAuth = $this->loadCacheValue('is_authenticated');
|
||||||
if (!$isAuth) {
|
if (!$isAuth) {
|
||||||
$res = $this->getData('https://www.pixiv.net/ajax/webpush', true, true)
|
$res = $this->getData('https://www.pixiv.net/ajax/webpush', true, true);
|
||||||
or returnServerError('Invalid PHPSESSID cookie provided. Please check the 🍪 and try again.');
|
|
||||||
if ($res['error'] === false) {
|
if ($res['error'] === false) {
|
||||||
$this->saveCacheValue('is_authenticated', true);
|
$this->saveCacheValue('is_authenticated', true);
|
||||||
}
|
}
|
||||||
|
@ -374,11 +373,11 @@ class PixivBridge extends BridgeAbstract
|
||||||
if ($cache) {
|
if ($cache) {
|
||||||
$data = $this->loadCacheValue($url);
|
$data = $this->loadCacheValue($url);
|
||||||
if (!$data) {
|
if (!$data) {
|
||||||
$data = getContents($url, $httpHeaders, $curlOptions, true) or returnServerError("Could not load $url");
|
$data = getContents($url, $httpHeaders, $curlOptions, true);
|
||||||
$this->saveCacheValue($url, $data);
|
$this->saveCacheValue($url, $data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$data = getContents($url, $httpHeaders, $curlOptions, true) or returnServerError("Could not load $url");
|
$data = getContents($url, $httpHeaders, $curlOptions, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->checkCookie($data['headers']);
|
$this->checkCookie($data['headers']);
|
||||||
|
|
|
@ -2,9 +2,14 @@ PixivBridge
|
||||||
===============
|
===============
|
||||||
|
|
||||||
# Image proxy
|
# Image proxy
|
||||||
As Pixiv requires images to be loaded with the `Referer "https://www.pixiv.net/"` header set, caching or image proxy is required to use this bridge.
|
|
||||||
|
|
||||||
To turn off image caching, set the `proxy_url` value in this bridge's configuration section of `config.ini.php` to the url of the proxy. The bridge will then use the proxy in this format (essentially replacing `https://i.pximg.net` with the proxy):
|
As Pixiv requires images to be loaded with the `Referer "https://www.pixiv.net/"` header set,
|
||||||
|
caching or image proxy is required to use this bridge.
|
||||||
|
|
||||||
|
To turn off image caching, set the `proxy_url` value in this bridge's configuration section of `config.ini.php`
|
||||||
|
to the url of the proxy.
|
||||||
|
|
||||||
|
The bridge will then use the proxy in this format (essentially replacing `https://i.pximg.net` with the proxy):
|
||||||
|
|
||||||
Before: `https://i.pximg.net/img-original/img/0000/00/00/00/00/00/12345678_p0.png`
|
Before: `https://i.pximg.net/img-original/img/0000/00/00/00/00/00/12345678_p0.png`
|
||||||
|
|
||||||
|
@ -15,9 +20,11 @@ proxy_url = "https://proxy.example.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
Authentication is required to view and search R-18+ and non-public images. To enable this, set the following in this bridge's configuration in `config.ini.php`.
|
|
||||||
|
|
||||||
```
|
Authentication is required to view and search R-18+ and non-public images.
|
||||||
|
To enable this, set the following in this bridge's configuration in `config.ini.php`.
|
||||||
|
|
||||||
|
```ini
|
||||||
; from cookie "PHPSESSID". Recommend to get in incognito browser.
|
; from cookie "PHPSESSID". Recommend to get in incognito browser.
|
||||||
cookie = "00000000_hashedsessionidhere"
|
cookie = "00000000_hashedsessionidhere"
|
||||||
```
|
```
|
25
index.php
25
index.php
|
@ -1,33 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
if (version_compare(\PHP_VERSION, '7.4.0') === -1) {
|
|
||||||
exit('RSS-Bridge requires minimum PHP version 7.4.0!');
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once __DIR__ . '/lib/bootstrap.php';
|
require_once __DIR__ . '/lib/bootstrap.php';
|
||||||
|
|
||||||
$errors = Configuration::checkInstallation();
|
|
||||||
if ($errors) {
|
|
||||||
print '<pre>' . implode("\n", $errors) . '</pre>';
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$customConfig = [];
|
|
||||||
if (file_exists(__DIR__ . '/config.ini.php')) {
|
|
||||||
$customConfig = parse_ini_file(__DIR__ . '/config.ini.php', true, INI_SCANNER_TYPED);
|
|
||||||
}
|
|
||||||
Configuration::loadConfiguration($customConfig, getenv());
|
|
||||||
|
|
||||||
// Consider: ini_set('error_reporting', E_ALL & ~E_DEPRECATED);
|
// Consider: ini_set('error_reporting', E_ALL & ~E_DEPRECATED);
|
||||||
date_default_timezone_set(Configuration::getConfig('system', 'timezone'));
|
date_default_timezone_set(Configuration::getConfig('system', 'timezone'));
|
||||||
|
|
||||||
$rssBridge = new RssBridge();
|
|
||||||
|
|
||||||
set_exception_handler(function (\Throwable $e) {
|
set_exception_handler(function (\Throwable $e) {
|
||||||
http_response_code(500);
|
|
||||||
print render(__DIR__ . '/templates/exception.html.php', ['e' => $e]);
|
|
||||||
RssBridge::getLogger()->error('Uncaught Exception', ['e' => $e]);
|
RssBridge::getLogger()->error('Uncaught Exception', ['e' => $e]);
|
||||||
exit(1);
|
http_response_code(500);
|
||||||
|
exit(render(__DIR__ . '/templates/exception.html.php', ['e' => $e]));
|
||||||
});
|
});
|
||||||
|
|
||||||
set_error_handler(function ($code, $message, $file, $line) {
|
set_error_handler(function ($code, $message, $file, $line) {
|
||||||
|
@ -63,4 +44,6 @@ register_shutdown_function(function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$rssBridge = new RssBridge();
|
||||||
|
|
||||||
$rssBridge->main($argv ?? []);
|
$rssBridge->main($argv ?? []);
|
||||||
|
|
|
@ -37,6 +37,7 @@ class CacheFactory
|
||||||
if ($index === false) {
|
if ($index === false) {
|
||||||
throw new \InvalidArgumentException(sprintf('Invalid cache name: "%s"', $name));
|
throw new \InvalidArgumentException(sprintf('Invalid cache name: "%s"', $name));
|
||||||
}
|
}
|
||||||
|
|
||||||
$className = $cacheNames[$index] . 'Cache';
|
$className = $cacheNames[$index] . 'Cache';
|
||||||
if (!preg_match('/^[A-Z][a-zA-Z0-9-]*$/', $className)) {
|
if (!preg_match('/^[A-Z][a-zA-Z0-9-]*$/', $className)) {
|
||||||
throw new \InvalidArgumentException(sprintf('Invalid cache classname: "%s"', $className));
|
throw new \InvalidArgumentException(sprintf('Invalid cache classname: "%s"', $className));
|
||||||
|
|
|
@ -59,7 +59,7 @@ final class Configuration
|
||||||
}
|
}
|
||||||
$config = parse_ini_file(__DIR__ . '/../config.default.ini.php', true, INI_SCANNER_TYPED);
|
$config = parse_ini_file(__DIR__ . '/../config.default.ini.php', true, INI_SCANNER_TYPED);
|
||||||
if (!$config) {
|
if (!$config) {
|
||||||
throw new \Exception('Error parsing config');
|
throw new \Exception('Error parsing ini config');
|
||||||
}
|
}
|
||||||
foreach ($config as $header => $section) {
|
foreach ($config as $header => $section) {
|
||||||
foreach ($section as $key => $value) {
|
foreach ($section as $key => $value) {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
if (version_compare(\PHP_VERSION, '7.4.0') === -1) {
|
||||||
|
exit('RSS-Bridge requires minimum PHP version 7.4.0!');
|
||||||
|
}
|
||||||
|
|
||||||
// Path to the formats library
|
// Path to the formats library
|
||||||
const PATH_LIB_FORMATS = __DIR__ . '/../formats/';
|
const PATH_LIB_FORMATS = __DIR__ . '/../formats/';
|
||||||
|
|
||||||
|
@ -46,3 +50,14 @@ spl_autoload_register(function ($className) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$errors = Configuration::checkInstallation();
|
||||||
|
if ($errors) {
|
||||||
|
exit('<pre>' . implode("\n", $errors) . '</pre>');
|
||||||
|
}
|
||||||
|
|
||||||
|
$customConfig = [];
|
||||||
|
if (file_exists(__DIR__ . '/../config.ini.php')) {
|
||||||
|
$customConfig = parse_ini_file(__DIR__ . '/../config.ini.php', true, INI_SCANNER_TYPED);
|
||||||
|
}
|
||||||
|
Configuration::loadConfiguration($customConfig, getenv());
|
||||||
|
|
|
@ -149,6 +149,7 @@ final class StreamHandler
|
||||||
);
|
);
|
||||||
error_log($text);
|
error_log($text);
|
||||||
if ($record['level'] < Logger::ERROR && Debug::isEnabled()) {
|
if ($record['level'] < Logger::ERROR && Debug::isEnabled()) {
|
||||||
|
// The record level is INFO or WARNING here
|
||||||
// Not a good idea to print here because http headers might not have been sent
|
// Not a good idea to print here because http headers might not have been sent
|
||||||
print sprintf("<pre>%s</pre>\n", e($text));
|
print sprintf("<pre>%s</pre>\n", e($text));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ruleset name="RSS-Bridge Ruleset">
|
<ruleset name="RSS-Bridge Ruleset">
|
||||||
<description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/</description>
|
<description>
|
||||||
|
Originally created with the PHP Coding Standard Generator.
|
||||||
|
But later manually tweaked.
|
||||||
|
http://edorian.github.com/php-coding-standard-generator/
|
||||||
|
</description>
|
||||||
|
|
||||||
<exclude-pattern>./static</exclude-pattern>
|
<exclude-pattern>./static</exclude-pattern>
|
||||||
<exclude-pattern>./vendor</exclude-pattern>
|
<exclude-pattern>./vendor</exclude-pattern>
|
||||||
<exclude-pattern>./templates</exclude-pattern>
|
<exclude-pattern>./templates</exclude-pattern>
|
||||||
|
@ -11,6 +16,7 @@
|
||||||
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
|
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
|
||||||
<exclude name="PSR1.Classes.ClassDeclaration.MultipleClasses"/>
|
<exclude name="PSR1.Classes.ClassDeclaration.MultipleClasses"/>
|
||||||
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
|
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
|
||||||
|
<exclude name="PSR2.Files.EndFileNewline"/>
|
||||||
<exclude name="PSR12.Properties.ConstantVisibility.NotFound"/>
|
<exclude name="PSR12.Properties.ConstantVisibility.NotFound"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,14 @@
|
||||||
</p>
|
</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($e->getCode() === 403): ?>
|
||||||
|
<h2>403 Forbidden</h2>
|
||||||
|
<p>
|
||||||
|
The HTTP 403 Forbidden response status code indicates that the
|
||||||
|
server understands the request but refuses to authorize it.
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($e->getCode() === 404): ?>
|
<?php if ($e->getCode() === 404): ?>
|
||||||
<h2>404 Page Not Found</h2>
|
<h2>404 Page Not Found</h2>
|
||||||
<p>
|
<p>
|
||||||
|
|
Loading…
Reference in a new issue