Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
floviolleau committed Oct 11, 2024
2 parents 7c23fb6 + af26d84 commit f3825ca
Show file tree
Hide file tree
Showing 57 changed files with 928 additions and 622 deletions.
2 changes: 0 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ phpcs.xml export-ignore
phpcompatibility.xml export-ignore
tests/ export-ignore
cache/.gitkeep export-ignore
bridges/DemoBridge.php export-ignore
bridges/FeedExpanderExampleBridge.php export-ignore

## Composer
#
Expand Down
7 changes: 4 additions & 3 deletions actions/ConnectivityAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ class ConnectivityAction implements ActionInterface
{
private BridgeFactory $bridgeFactory;

public function __construct()
{
$this->bridgeFactory = new BridgeFactory();
public function __construct(
BridgeFactory $bridgeFactory
) {
$this->bridgeFactory = $bridgeFactory;
}

public function __invoke(Request $request): Response
Expand Down
16 changes: 11 additions & 5 deletions actions/DetectAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

class DetectAction implements ActionInterface
{
private BridgeFactory $bridgeFactory;

public function __construct(
BridgeFactory $bridgeFactory
) {
$this->bridgeFactory = $bridgeFactory;
}

public function __invoke(Request $request): Response
{
$url = $request->get('url');
Expand All @@ -14,14 +22,12 @@ public function __invoke(Request $request): Response
return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'You must specify a format']));
}

$bridgeFactory = new BridgeFactory();

foreach ($bridgeFactory->getBridgeClassNames() as $bridgeClassName) {
if (!$bridgeFactory->isEnabled($bridgeClassName)) {
foreach ($this->bridgeFactory->getBridgeClassNames() as $bridgeClassName) {
if (!$this->bridgeFactory->isEnabled($bridgeClassName)) {
continue;
}

$bridge = $bridgeFactory->create($bridgeClassName);
$bridge = $this->bridgeFactory->create($bridgeClassName);

$bridgeParams = $bridge->detectParameters($url);

Expand Down
73 changes: 23 additions & 50 deletions actions/DisplayAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ class DisplayAction implements ActionInterface
{
private CacheInterface $cache;
private Logger $logger;

public function __construct()
{
$this->cache = RssBridge::getCache();
$this->logger = RssBridge::getLogger();
private BridgeFactory $bridgeFactory;

public function __construct(
CacheInterface $cache,
Logger $logger,
BridgeFactory $bridgeFactory
) {
$this->cache = $cache;
$this->logger = $logger;
$this->bridgeFactory = $bridgeFactory;
}

public function __invoke(Request $request): Response
Expand All @@ -17,38 +22,18 @@ public function __invoke(Request $request): Response
$format = $request->get('format');
$noproxy = $request->get('_noproxy');

$cacheKey = 'http_' . json_encode($request->toArray());
/** @var Response $cachedResponse */
$cachedResponse = $this->cache->get($cacheKey);
if ($cachedResponse) {
$ifModifiedSince = $request->server('HTTP_IF_MODIFIED_SINCE');
$lastModified = $cachedResponse->getHeader('last-modified');
if ($ifModifiedSince && $lastModified) {
$lastModified = new \DateTimeImmutable($lastModified);
$lastModifiedTimestamp = $lastModified->getTimestamp();
$modifiedSince = strtotime($ifModifiedSince);
// TODO: \DateTimeImmutable can be compared directly
if ($lastModifiedTimestamp <= $modifiedSince) {
$modificationTimeGMT = gmdate('D, d M Y H:i:s ', $lastModifiedTimestamp);
return new Response('', 304, ['last-modified' => $modificationTimeGMT . 'GMT']);
}
}
return $cachedResponse->withHeader('rss-bridge', 'This is a cached response');
}

if (!$bridgeName) {
return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'Missing bridge parameter']), 400);
}
$bridgeFactory = new BridgeFactory();
$bridgeClassName = $bridgeFactory->createBridgeClassName($bridgeName);
$bridgeClassName = $this->bridgeFactory->createBridgeClassName($bridgeName);
if (!$bridgeClassName) {
return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'Bridge not found']), 404);
}

if (!$format) {
return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'You must specify a format']), 400);
}
if (!$bridgeFactory->isEnabled($bridgeClassName)) {
if (!$this->bridgeFactory->isEnabled($bridgeClassName)) {
return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'This bridge is not whitelisted']), 400);
}

Expand All @@ -62,7 +47,9 @@ public function __invoke(Request $request): Response
define('NOPROXY', true);
}

$bridge = $bridgeFactory->create($bridgeClassName);
$cacheKey = 'http_' . json_encode($request->toArray());

$bridge = $this->bridgeFactory->create($bridgeClassName);

$response = $this->createResponse($request, $bridge, $format);

Expand All @@ -76,19 +63,6 @@ public function __invoke(Request $request): Response
$this->cache->set($cacheKey, $response, $ttl);
}

if (in_array($response->getCode(), [403, 429, 503])) {
// Cache these responses for about ~20 mins on average
$this->cache->set($cacheKey, $response, 60 * 15 + rand(1, 60 * 10));
}

if ($response->getCode() === 500) {
$this->cache->set($cacheKey, $response, 60 * 15);
}

if (rand(1, 100) === 2) {
$this->cache->prune();
}

return $response;
}

Expand Down Expand Up @@ -121,17 +95,16 @@ private function createResponse(Request $request, BridgeAbstract $bridge, string
return new Response(render(__DIR__ . '/../templates/exception.html.php', ['e' => $e]), 429);
}
if ($e instanceof HttpException) {
// Reproduce (and log) these responses regardless of error output and report limit
if ($e->getCode() === 429) {
$this->logger->info(sprintf('Exception in DisplayAction(%s): %s', $bridge->getShortName(), create_sane_exception_message($e)));
return new Response(render(__DIR__ . '/../templates/exception.html.php', ['e' => $e]), 429);
}
if ($e->getCode() === 503) {
$this->logger->info(sprintf('Exception in DisplayAction(%s): %s', $bridge->getShortName(), create_sane_exception_message($e)));
return new Response(render(__DIR__ . '/../templates/exception.html.php', ['e' => $e]), 503);
if (in_array($e->getCode(), [429, 503])) {
// Log with debug, immediately reproduce and return
$this->logger->debug(sprintf('Exception in DisplayAction(%s): %s', $bridge->getShortName(), create_sane_exception_message($e)));
return new Response(render(__DIR__ . '/../templates/exception.html.php', ['e' => $e]), $e->getCode());
}
// Some other status code which we let fail normally (but don't log it)
} else {
// Log error if it's not an HttpException
$this->logger->error(sprintf('Exception in DisplayAction(%s)', $bridge->getShortName()), ['e' => $e]);
}
$this->logger->error(sprintf('Exception in DisplayAction(%s)', $bridge->getShortName()), ['e' => $e]);
$errorOutput = Configuration::getConfig('error', 'output');
$reportLimit = Configuration::getConfig('error', 'report_limit');
$errorCount = 1;
Expand Down
16 changes: 11 additions & 5 deletions actions/FindfeedAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
*/
class FindfeedAction implements ActionInterface
{
private BridgeFactory $bridgeFactory;

public function __construct(
BridgeFactory $bridgeFactory
) {
$this->bridgeFactory = $bridgeFactory;
}

public function __invoke(Request $request): Response
{
$url = $request->get('url');
Expand All @@ -19,15 +27,13 @@ public function __invoke(Request $request): Response
return new Response('You must specify a format', 400);
}

$bridgeFactory = new BridgeFactory();

$results = [];
foreach ($bridgeFactory->getBridgeClassNames() as $bridgeClassName) {
if (!$bridgeFactory->isEnabled($bridgeClassName)) {
foreach ($this->bridgeFactory->getBridgeClassNames() as $bridgeClassName) {
if (!$this->bridgeFactory->isEnabled($bridgeClassName)) {
continue;
}

$bridge = $bridgeFactory->create($bridgeClassName);
$bridge = $this->bridgeFactory->create($bridgeClassName);

$bridgeParams = $bridge->detectParameters($url);

Expand Down
17 changes: 12 additions & 5 deletions actions/FrontpageAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@

final class FrontpageAction implements ActionInterface
{
private BridgeFactory $bridgeFactory;

public function __construct(
BridgeFactory $bridgeFactory
) {
$this->bridgeFactory = $bridgeFactory;
}

public function __invoke(Request $request): Response
{
$token = $request->attribute('token');

$messages = [];
$activeBridges = 0;

$bridgeFactory = new BridgeFactory();
$bridgeClassNames = $bridgeFactory->getBridgeClassNames();
$bridgeClassNames = $this->bridgeFactory->getBridgeClassNames();

foreach ($bridgeFactory->getMissingEnabledBridges() as $missingEnabledBridge) {
foreach ($this->bridgeFactory->getMissingEnabledBridges() as $missingEnabledBridge) {
$messages[] = [
'body' => sprintf('Warning : Bridge "%s" not found', $missingEnabledBridge),
'level' => 'warning'
Expand All @@ -21,8 +28,8 @@ public function __invoke(Request $request): Response

$body = '';
foreach ($bridgeClassNames as $bridgeClassName) {
if ($bridgeFactory->isEnabled($bridgeClassName)) {
$body .= BridgeCard::render($bridgeClassName, $token);
if ($this->bridgeFactory->isEnabled($bridgeClassName)) {
$body .= BridgeCard::render($this->bridgeFactory, $bridgeClassName, $token);
$activeBridges++;
}
}
Expand Down
16 changes: 11 additions & 5 deletions actions/ListAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

class ListAction implements ActionInterface
{
private BridgeFactory $bridgeFactory;

public function __construct(
BridgeFactory $bridgeFactory
) {
$this->bridgeFactory = $bridgeFactory;
}

public function __invoke(Request $request): Response
{
$list = new \stdClass();
$list->bridges = [];
$list->total = 0;

$bridgeFactory = new BridgeFactory();

foreach ($bridgeFactory->getBridgeClassNames() as $bridgeClassName) {
$bridge = $bridgeFactory->create($bridgeClassName);
foreach ($this->bridgeFactory->getBridgeClassNames() as $bridgeClassName) {
$bridge = $this->bridgeFactory->create($bridgeClassName);

$list->bridges[$bridgeClassName] = [
'status' => $bridgeFactory->isEnabled($bridgeClassName) ? 'active' : 'inactive',
'status' => $this->bridgeFactory->isEnabled($bridgeClassName) ? 'active' : 'inactive',
'uri' => $bridge->getURI(),
'donationUri' => $bridge->getDonationURI(),
'name' => $bridge->getName(),
Expand Down
19 changes: 4 additions & 15 deletions bin/cache-clear
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,11 @@
*/

require __DIR__ . '/../lib/bootstrap.php';
require __DIR__ . '/../lib/config.php';

$config = [];
if (file_exists(__DIR__ . '/../config.ini.php')) {
$config = parse_ini_file(__DIR__ . '/../config.ini.php', true, INI_SCANNER_TYPED);
if (!$config) {
http_response_code(500);
exit("Error parsing config.ini.php\n");
}
}
Configuration::loadConfiguration($config, getenv());
$container = require __DIR__ . '/../lib/dependencies.php';

$logger = new SimpleLogger('rssbridge');

$logger->addHandler(new StreamHandler('php://stderr', Logger::INFO));

$cacheFactory = new CacheFactory($logger);
$cache = $cacheFactory->create();
/** @var CacheInterface $cache */
$cache = $container['cache'];

$cache->clear();
25 changes: 11 additions & 14 deletions bin/cache-prune
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,19 @@
*/

require __DIR__ . '/../lib/bootstrap.php';
require __DIR__ . '/../lib/config.php';

$config = [];
if (file_exists(__DIR__ . '/../config.ini.php')) {
$config = parse_ini_file(__DIR__ . '/../config.ini.php', true, INI_SCANNER_TYPED);
if (!$config) {
http_response_code(500);
exit("Error parsing config.ini.php\n");
}
}
Configuration::loadConfiguration($config, getenv());

$logger = new SimpleLogger('rssbridge');
$container = require __DIR__ . '/../lib/dependencies.php';

$logger->addHandler(new StreamHandler('php://stderr', Logger::INFO));
if (
Configuration::getConfig('cache', 'type') === 'file'
&& !Configuration::getConfig('FileCache', 'enable_purge')
) {
// Override enable_purge for this particular execution
Configuration::setConfig('FileCache', 'enable_purge', true);
}

$cacheFactory = new CacheFactory($logger);
$cache = $cacheFactory->create();
/** @var CacheInterface $cache */
$cache = $container['cache'];

$cache->prune();
20 changes: 20 additions & 0 deletions bin/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env php
<?php

/**
* Add log records to all three levels (for testing purposes)
*/

require __DIR__ . '/../lib/bootstrap.php';
require __DIR__ . '/../lib/config.php';

$container = require __DIR__ . '/../lib/dependencies.php';

/** @var Logger $logger */
$logger = $container['logger'];

$logger->debug('This is a test debug message');

$logger->info('This is a test info message');

$logger->error('This is a test error message');
6 changes: 3 additions & 3 deletions bridges/ABCNewsBridge.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ public function collectData()
{
$url = sprintf('https://www.abc.net.au/news/%s', $this->getInput('topic'));
$dom = getSimpleHTMLDOM($url);
$dom = $dom->find('div[data-component="CardList"]', 0);
$dom = $dom->find('div[data-component="PaginationList"]', 0);
if (!$dom) {
throw new \Exception(sprintf('Unable to find css selector on `%s`', $url));
}
$dom = defaultLinkTo($dom, $this->getURI());
foreach ($dom->find('div[data-component="GenericCard"]') as $article) {
foreach ($dom->find('article[data-component="DetailCard"]') as $article) {
$a = $article->find('a', 0);
$this->items[] = [
'title' => $a->plaintext,
'uri' => $a->href,
'content' => $article->find('[data-component="CardDescription"]', 0)->plaintext,
'content' => $article->find('p', 0)->plaintext,
'timestamp' => strtotime($article->find('time', 0)->datetime),
];
}
Expand Down
Loading

0 comments on commit f3825ca

Please sign in to comment.