Reformat codebase v4 (#2872)

Reformat code base to PSR12

Co-authored-by: rssbridge <noreply@github.com>
This commit is contained in:
Dag 2022-07-01 15:10:30 +02:00 committed by GitHub
parent 66568e3a39
commit 4f75591060
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
398 changed files with 58607 additions and 56442 deletions

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* This file is part of RSS-Bridge, a PHP project capable of generating RSS and * This file is part of RSS-Bridge, a PHP project capable of generating RSS and
* Atom feeds for websites that don't have one. * Atom feeds for websites that don't have one.
@ -25,13 +26,13 @@ class ConnectivityAction implements ActionInterface
{ {
public $userData = []; public $userData = [];
public function execute() { public function execute()
{
if(!Debug::isEnabled()) { if (!Debug::isEnabled()) {
returnError('This action is only available in debug mode!', 400); returnError('This action is only available in debug mode!', 400);
} }
if(!isset($this->userData['bridge'])) { if (!isset($this->userData['bridge'])) {
$this->returnEntryPage(); $this->returnEntryPage();
return; return;
} }
@ -39,7 +40,6 @@ class ConnectivityAction implements ActionInterface
$bridgeName = $this->userData['bridge']; $bridgeName = $this->userData['bridge'];
$this->reportBridgeConnectivity($bridgeName); $this->reportBridgeConnectivity($bridgeName);
} }
/** /**
@ -55,52 +55,52 @@ class ConnectivityAction implements ActionInterface
* @param string $bridgeName Name of the bridge to generate the report for * @param string $bridgeName Name of the bridge to generate the report for
* @return void * @return void
*/ */
private function reportBridgeConnectivity($bridgeName) { private function reportBridgeConnectivity($bridgeName)
{
$bridgeFac = new \BridgeFactory(); $bridgeFac = new \BridgeFactory();
if(!$bridgeFac->isWhitelisted($bridgeName)) { if (!$bridgeFac->isWhitelisted($bridgeName)) {
header('Content-Type: text/html'); header('Content-Type: text/html');
returnServerError('Bridge is not whitelisted!'); returnServerError('Bridge is not whitelisted!');
} }
header('Content-Type: text/json'); header('Content-Type: text/json');
$retVal = array( $retVal = [
'bridge' => $bridgeName, 'bridge' => $bridgeName,
'successful' => false, 'successful' => false,
'http_code' => 200, 'http_code' => 200,
); ];
$bridge = $bridgeFac->create($bridgeName); $bridge = $bridgeFac->create($bridgeName);
if($bridge === false) { if ($bridge === false) {
echo json_encode($retVal); echo json_encode($retVal);
return; return;
} }
$curl_opts = array( $curl_opts = [
CURLOPT_CONNECTTIMEOUT => 5 CURLOPT_CONNECTTIMEOUT => 5
); ];
try { try {
$reply = getContents($bridge::URI, array(), $curl_opts, true); $reply = getContents($bridge::URI, [], $curl_opts, true);
if($reply['code'] === 200) { if ($reply['code'] === 200) {
$retVal['successful'] = true; $retVal['successful'] = true;
if (strpos(implode('', $reply['status_lines']), '301 Moved Permanently')) { if (strpos(implode('', $reply['status_lines']), '301 Moved Permanently')) {
$retVal['http_code'] = 301; $retVal['http_code'] = 301;
} }
} }
} catch(Exception $e) { } catch (Exception $e) {
$retVal['successful'] = false; $retVal['successful'] = false;
} }
echo json_encode($retVal); echo json_encode($retVal);
} }
private function returnEntryPage() { private function returnEntryPage()
{
echo <<<EOD echo <<<EOD
<!DOCTYPE html> <!DOCTYPE html>

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* This file is part of RSS-Bridge, a PHP project capable of generating RSS and * This file is part of RSS-Bridge, a PHP project capable of generating RSS and
* Atom feeds for websites that don't have one. * Atom feeds for websites that don't have one.
@ -15,7 +16,8 @@ class DetectAction implements ActionInterface
{ {
public $userData = []; public $userData = [];
public function execute() { public function execute()
{
$targetURL = $this->userData['url'] $targetURL = $this->userData['url']
or returnClientError('You must specify a url!'); or returnClientError('You must specify a url!');
@ -24,21 +26,20 @@ class DetectAction implements ActionInterface
$bridgeFac = new \BridgeFactory(); $bridgeFac = new \BridgeFactory();
foreach($bridgeFac->getBridgeNames() as $bridgeName) { foreach ($bridgeFac->getBridgeNames() as $bridgeName) {
if (!$bridgeFac->isWhitelisted($bridgeName)) {
if(!$bridgeFac->isWhitelisted($bridgeName)) {
continue; continue;
} }
$bridge = $bridgeFac->create($bridgeName); $bridge = $bridgeFac->create($bridgeName);
if($bridge === false) { if ($bridge === false) {
continue; continue;
} }
$bridgeParams = $bridge->detectParameters($targetURL); $bridgeParams = $bridge->detectParameters($targetURL);
if(is_null($bridgeParams)) { if (is_null($bridgeParams)) {
continue; continue;
} }
@ -47,7 +48,6 @@ class DetectAction implements ActionInterface
header('Location: ?action=display&' . http_build_query($bridgeParams), true, 301); header('Location: ?action=display&' . http_build_query($bridgeParams), true, 301);
die(); die();
} }
returnClientError('No bridge found for given URL: ' . $targetURL); returnClientError('No bridge found for given URL: ' . $targetURL);

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* This file is part of RSS-Bridge, a PHP project capable of generating RSS and * This file is part of RSS-Bridge, a PHP project capable of generating RSS and
* Atom feeds for websites that don't have one. * Atom feeds for websites that don't have one.
@ -15,7 +16,8 @@ class DisplayAction implements ActionInterface
{ {
public $userData = []; public $userData = [];
private function getReturnCode($error) { private function getReturnCode($error)
{
$returnCode = $error->getCode(); $returnCode = $error->getCode();
if ($returnCode === 301 || $returnCode === 302) { if ($returnCode === 301 || $returnCode === 302) {
# Don't pass redirect codes to the exterior # Don't pass redirect codes to the exterior
@ -24,7 +26,8 @@ class DisplayAction implements ActionInterface
return $returnCode; return $returnCode;
} }
public function execute() { public function execute()
{
$bridge = array_key_exists('bridge', $this->userData) ? $this->userData['bridge'] : null; $bridge = array_key_exists('bridge', $this->userData) ? $this->userData['bridge'] : null;
$format = $this->userData['format'] $format = $this->userData['format']
@ -33,7 +36,7 @@ class DisplayAction implements ActionInterface
$bridgeFac = new \BridgeFactory(); $bridgeFac = new \BridgeFactory();
// whitelist control // whitelist control
if(!$bridgeFac->isWhitelisted($bridge)) { if (!$bridgeFac->isWhitelisted($bridge)) {
throw new \Exception('This bridge is not whitelisted', 401); throw new \Exception('This bridge is not whitelisted', 401);
die; die;
} }
@ -45,15 +48,14 @@ class DisplayAction implements ActionInterface
$noproxy = array_key_exists('_noproxy', $this->userData) $noproxy = array_key_exists('_noproxy', $this->userData)
&& filter_var($this->userData['_noproxy'], FILTER_VALIDATE_BOOLEAN); && filter_var($this->userData['_noproxy'], FILTER_VALIDATE_BOOLEAN);
if(defined('PROXY_URL') && PROXY_BYBRIDGE && $noproxy) { if (defined('PROXY_URL') && PROXY_BYBRIDGE && $noproxy) {
define('NOPROXY', true); define('NOPROXY', true);
} }
// Cache timeout // Cache timeout
$cache_timeout = -1; $cache_timeout = -1;
if(array_key_exists('_cache_timeout', $this->userData)) { if (array_key_exists('_cache_timeout', $this->userData)) {
if (!CUSTOM_CACHE_TIMEOUT) {
if(!CUSTOM_CACHE_TIMEOUT) {
unset($this->userData['_cache_timeout']); unset($this->userData['_cache_timeout']);
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) . '?' . http_build_query($this->userData); $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) . '?' . http_build_query($this->userData);
header('Location: ' . $uri, true, 301); header('Location: ' . $uri, true, 301);
@ -61,7 +63,6 @@ class DisplayAction implements ActionInterface
} }
$cache_timeout = filter_var($this->userData['_cache_timeout'], FILTER_VALIDATE_INT); $cache_timeout = filter_var($this->userData['_cache_timeout'], FILTER_VALIDATE_INT);
} else { } else {
$cache_timeout = $bridge->getCacheTimeout(); $cache_timeout = $bridge->getCacheTimeout();
} }
@ -70,27 +71,31 @@ class DisplayAction implements ActionInterface
$bridge_params = array_diff_key( $bridge_params = array_diff_key(
$this->userData, $this->userData,
array_fill_keys( array_fill_keys(
array( [
'action', 'action',
'bridge', 'bridge',
'format', 'format',
'_noproxy', '_noproxy',
'_cache_timeout', '_cache_timeout',
'_error_time' '_error_time'
), '') ],
''
)
); );
// Remove parameters that don't concern caches // Remove parameters that don't concern caches
$cache_params = array_diff_key( $cache_params = array_diff_key(
$this->userData, $this->userData,
array_fill_keys( array_fill_keys(
array( [
'action', 'action',
'format', 'format',
'_noproxy', '_noproxy',
'_cache_timeout', '_cache_timeout',
'_error_time' '_error_time'
), '') ],
''
)
); );
// Initialize cache // Initialize cache
@ -101,20 +106,21 @@ class DisplayAction implements ActionInterface
$cache->purgeCache(86400); // 24 hours $cache->purgeCache(86400); // 24 hours
$cache->setKey($cache_params); $cache->setKey($cache_params);
$items = array(); $items = [];
$infos = array(); $infos = [];
$mtime = $cache->getTime(); $mtime = $cache->getTime();
if($mtime !== false if (
$mtime !== false
&& (time() - $cache_timeout < $mtime) && (time() - $cache_timeout < $mtime)
&& !Debug::isEnabled()) { // Load cached data && !Debug::isEnabled()
) { // Load cached data
// Send "Not Modified" response if client supports it // Send "Not Modified" response if client supports it
// Implementation based on https://stackoverflow.com/a/10847262 // Implementation based on https://stackoverflow.com/a/10847262
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$stime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); $stime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if($mtime <= $stime) { // Cached data is older or same if ($mtime <= $stime) { // Cached data is older or same
header('Last-Modified: ' . gmdate('D, d M Y H:i:s ', $mtime) . 'GMT', true, 304); header('Last-Modified: ' . gmdate('D, d M Y H:i:s ', $mtime) . 'GMT', true, 304);
die(); die();
} }
@ -122,16 +128,14 @@ class DisplayAction implements ActionInterface
$cached = $cache->loadData(); $cached = $cache->loadData();
if(isset($cached['items']) && isset($cached['extraInfos'])) { if (isset($cached['items']) && isset($cached['extraInfos'])) {
foreach($cached['items'] as $item) { foreach ($cached['items'] as $item) {
$items[] = new \FeedItem($item); $items[] = new \FeedItem($item);
} }
$infos = $cached['extraInfos']; $infos = $cached['extraInfos'];
} }
} else { // Collect new data } else { // Collect new data
try { try {
$bridge->setDatas($bridge_params); $bridge->setDatas($bridge_params);
$bridge->collectData(); $bridge->collectData();
@ -140,27 +144,27 @@ class DisplayAction implements ActionInterface
// Transform "legacy" items to FeedItems if necessary. // Transform "legacy" items to FeedItems if necessary.
// Remove this code when support for "legacy" items ends! // Remove this code when support for "legacy" items ends!
if(isset($items[0]) && is_array($items[0])) { if (isset($items[0]) && is_array($items[0])) {
$feedItems = array(); $feedItems = [];
foreach($items as $item) { foreach ($items as $item) {
$feedItems[] = new \FeedItem($item); $feedItems[] = new \FeedItem($item);
} }
$items = $feedItems; $items = $feedItems;
} }
$infos = array( $infos = [
'name' => $bridge->getName(), 'name' => $bridge->getName(),
'uri' => $bridge->getURI(), 'uri' => $bridge->getURI(),
'donationUri' => $bridge->getDonationURI(), 'donationUri' => $bridge->getDonationURI(),
'icon' => $bridge->getIcon() 'icon' => $bridge->getIcon()
); ];
} catch(\Throwable $e) { } catch (\Throwable $e) {
error_log($e); error_log($e);
if(logBridgeError($bridge::NAME, $e->getCode()) >= Configuration::getConfig('error', 'report_limit')) { if (logBridgeError($bridge::NAME, $e->getCode()) >= Configuration::getConfig('error', 'report_limit')) {
if(Configuration::getConfig('error', 'output') === 'feed') { if (Configuration::getConfig('error', 'output') === 'feed') {
$item = new \FeedItem(); $item = new \FeedItem();
// Create "new" error message every 24 hours // Create "new" error message every 24 hours
@ -183,7 +187,7 @@ class DisplayAction implements ActionInterface
$item->setContent(buildBridgeException($e, $bridge)); $item->setContent(buildBridgeException($e, $bridge));
$items[] = $item; $items[] = $item;
} elseif(Configuration::getConfig('error', 'output') === 'http') { } elseif (Configuration::getConfig('error', 'output') === 'http') {
header('Content-Type: text/html', true, $this->getReturnCode($e)); header('Content-Type: text/html', true, $this->getReturnCode($e));
die(buildTransformException($e, $bridge)); die(buildTransformException($e, $bridge));
} }
@ -191,11 +195,12 @@ class DisplayAction implements ActionInterface
} }
// Store data in cache // Store data in cache
$cache->saveData(array( $cache->saveData([
'items' => array_map(function($i){ return $i->toArray(); }, $items), 'items' => array_map(function ($i) {
return $i->toArray();
}, $items),
'extraInfos' => $infos 'extraInfos' => $infos
)); ]);
} }
// Data transformation // Data transformation
@ -212,7 +217,7 @@ class DisplayAction implements ActionInterface
header('Content-Type: ' . $format->getMimeType() . '; charset=' . $format->getCharset()); header('Content-Type: ' . $format->getMimeType() . '; charset=' . $format->getCharset());
echo $format->stringify(); echo $format->stringify();
} catch(\Throwable $e) { } catch (\Throwable $e) {
error_log($e); error_log($e);
header('Content-Type: text/html', true, $e->getCode()); header('Content-Type: text/html', true, $e->getCode());
die(buildTransformException($e, $bridge)); die(buildTransformException($e, $bridge));

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* This file is part of RSS-Bridge, a PHP project capable of generating RSS and * This file is part of RSS-Bridge, a PHP project capable of generating RSS and
* Atom feeds for websites that don't have one. * Atom feeds for websites that don't have one.
@ -13,30 +14,28 @@
class ListAction implements ActionInterface class ListAction implements ActionInterface
{ {
public function execute() { public function execute()
{
$list = new StdClass(); $list = new StdClass();
$list->bridges = array(); $list->bridges = [];
$list->total = 0; $list->total = 0;
$bridgeFac = new \BridgeFactory(); $bridgeFac = new \BridgeFactory();
foreach($bridgeFac->getBridgeNames() as $bridgeName) { foreach ($bridgeFac->getBridgeNames() as $bridgeName) {
$bridge = $bridgeFac->create($bridgeName); $bridge = $bridgeFac->create($bridgeName);
if($bridge === false) { // Broken bridge, show as inactive if ($bridge === false) { // Broken bridge, show as inactive
$list->bridges[$bridgeName] = [
$list->bridges[$bridgeName] = array(
'status' => 'inactive' 'status' => 'inactive'
); ];
continue; continue;
} }
$status = $bridgeFac->isWhitelisted($bridgeName) ? 'active' : 'inactive'; $status = $bridgeFac->isWhitelisted($bridgeName) ? 'active' : 'inactive';
$list->bridges[$bridgeName] = array( $list->bridges[$bridgeName] = [
'status' => $status, 'status' => $status,
'uri' => $bridge->getURI(), 'uri' => $bridge->getURI(),
'donationUri' => $bridge->getDonationURI(), 'donationUri' => $bridge->getDonationURI(),
@ -45,8 +44,7 @@ class ListAction implements ActionInterface
'parameters' => $bridge->getParameters(), 'parameters' => $bridge->getParameters(),
'maintainer' => $bridge->getMaintainer(), 'maintainer' => $bridge->getMaintainer(),
'description' => $bridge->getDescription() 'description' => $bridge->getDescription()
); ];
} }
$list->total = count($list->bridges); $list->total = count($list->bridges);

View file

@ -1,17 +1,19 @@
<?php <?php
class ABCNewsBridge extends BridgeAbstract {
class ABCNewsBridge extends BridgeAbstract
{
const NAME = 'ABC News Bridge'; const NAME = 'ABC News Bridge';
const URI = 'https://www.abc.net.au'; const URI = 'https://www.abc.net.au';
const DESCRIPTION = 'Topics of the Australian Broadcasting Corporation'; const DESCRIPTION = 'Topics of the Australian Broadcasting Corporation';
const MAINTAINER = 'yue-dongchen'; const MAINTAINER = 'yue-dongchen';
const PARAMETERS = array( const PARAMETERS = [
array( [
'topic' => array( 'topic' => [
'type' => 'list', 'type' => 'list',
'name' => 'Region', 'name' => 'Region',
'title' => 'Choose state', 'title' => 'Choose state',
'values' => array( 'values' => [
'ACT' => 'act', 'ACT' => 'act',
'NSW' => 'nsw', 'NSW' => 'nsw',
'NT' => 'nt', 'NT' => 'nt',
@ -20,18 +22,19 @@ class ABCNewsBridge extends BridgeAbstract {
'TAS' => 'tas', 'TAS' => 'tas',
'VIC' => 'vic', 'VIC' => 'vic',
'WA' => 'wa' 'WA' => 'wa'
), ],
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$url = 'https://www.abc.net.au/news/' . $this->getInput('topic'); $url = 'https://www.abc.net.au/news/' . $this->getInput('topic');
$html = getSimpleHTMLDOM($url)->find('.YAJzu._2FvRw.ZWhbj._3BZxh', 0); $html = getSimpleHTMLDOM($url)->find('.YAJzu._2FvRw.ZWhbj._3BZxh', 0);
$html = defaultLinkTo($html, $this->getURI()); $html = defaultLinkTo($html, $this->getURI());
foreach($html->find('._2H7Su') as $article) { foreach ($html->find('._2H7Su') as $article) {
$item = array(); $item = [];
$title = $article->find('._3T9Id.fmhNa.nsZdE._2c2Zy._1tOey._3EOTW', 0); $title = $article->find('._3T9Id.fmhNa.nsZdE._2c2Zy._1tOey._3EOTW', 0);
$item['title'] = $title->plaintext; $item['title'] = $title->plaintext;

View file

@ -1,49 +1,53 @@
<?php <?php
class AO3Bridge extends BridgeAbstract { class AO3Bridge extends BridgeAbstract
{
const NAME = 'AO3'; const NAME = 'AO3';
const URI = 'https://archiveofourown.org/'; const URI = 'https://archiveofourown.org/';
const CACHE_TIMEOUT = 1800; const CACHE_TIMEOUT = 1800;
const DESCRIPTION = 'Returns works or chapters from Archive of Our Own'; const DESCRIPTION = 'Returns works or chapters from Archive of Our Own';
const MAINTAINER = 'Obsidienne'; const MAINTAINER = 'Obsidienne';
const PARAMETERS = array( const PARAMETERS = [
'List' => array( 'List' => [
'url' => array( 'url' => [
'name' => 'url', 'name' => 'url',
'required' => true, 'required' => true,
// Example: F/F tag, complete works only // Example: F/F tag, complete works only
'exampleValue' => 'https://archiveofourown.org/works?work_search[complete]=T&tag_id=F*s*F', 'exampleValue' => 'https://archiveofourown.org/works?work_search[complete]=T&tag_id=F*s*F',
), ],
), ],
'Bookmarks' => array( 'Bookmarks' => [
'user' => array( 'user' => [
'name' => 'user', 'name' => 'user',
'required' => true, 'required' => true,
// Example: Nyaaru's bookmarks // Example: Nyaaru's bookmarks
'exampleValue' => 'Nyaaru', 'exampleValue' => 'Nyaaru',
), ],
), ],
'Work' => array( 'Work' => [
'id' => array( 'id' => [
'name' => 'id', 'name' => 'id',
'required' => true, 'required' => true,
// Example: latest chapters from A Better Past by LysSerris // Example: latest chapters from A Better Past by LysSerris
'exampleValue' => '18181853', 'exampleValue' => '18181853',
), ],
) ]
); ];
// Feed for lists of works (e.g. recent works, search results, filtered tags, // Feed for lists of works (e.g. recent works, search results, filtered tags,
// bookmarks, series, collections). // bookmarks, series, collections).
private function collectList($url) { private function collectList($url)
{
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
$html = defaultLinkTo($html, self::URI); $html = defaultLinkTo($html, self::URI);
foreach($html->find('.index.group > li') as $element) { foreach ($html->find('.index.group > li') as $element) {
$item = array(); $item = [];
$title = $element->find('div h4 a', 0); $title = $element->find('div h4 a', 0);
if (!isset($title)) continue; // discard deleted works if (!isset($title)) {
continue; // discard deleted works
}
$item['title'] = $title->plaintext; $item['title'] = $title->plaintext;
$item['content'] = $element; $item['content'] = $element;
$item['uri'] = $title->href; $item['uri'] = $title->href;
@ -61,15 +65,16 @@ class AO3Bridge extends BridgeAbstract {
} }
// Feed for recent chapters of a specific work. // Feed for recent chapters of a specific work.
private function collectWork($id) { private function collectWork($id)
{
$url = self::URI . "/works/$id/navigate"; $url = self::URI . "/works/$id/navigate";
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
$html = defaultLinkTo($html, self::URI); $html = defaultLinkTo($html, self::URI);
$this->title = $html->find('h2 a', 0)->plaintext; $this->title = $html->find('h2 a', 0)->plaintext;
foreach($html->find('ol.index.group > li') as $element) { foreach ($html->find('ol.index.group > li') as $element) {
$item = array(); $item = [];
$item['title'] = $element->find('a', 0)->plaintext; $item['title'] = $element->find('a', 0)->plaintext;
$item['content'] = $element; $item['content'] = $element;
@ -88,8 +93,9 @@ class AO3Bridge extends BridgeAbstract {
$this->items = array_reverse($this->items); $this->items = array_reverse($this->items);
} }
public function collectData() { public function collectData()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Bookmarks': case 'Bookmarks':
$user = $this->getInput('user'); $user = $this->getInput('user');
$this->title = $user; $this->title = $user;
@ -97,22 +103,28 @@ class AO3Bridge extends BridgeAbstract {
. '/users/' . $user . '/users/' . $user
. '/bookmarks?bookmark_search[sort_column]=bookmarkable_date'; . '/bookmarks?bookmark_search[sort_column]=bookmarkable_date';
return $this->collectList($url); return $this->collectList($url);
case 'List': return $this->collectList( case 'List':
return $this->collectList(
$this->getInput('url') $this->getInput('url')
); );
case 'Work': return $this->collectWork( case 'Work':
return $this->collectWork(
$this->getInput('id') $this->getInput('id')
); );
} }
} }
public function getName() { public function getName()
{
$name = parent::getName() . " $this->queriedContext"; $name = parent::getName() . " $this->queriedContext";
if (isset($this->title)) $name .= " - $this->title"; if (isset($this->title)) {
$name .= " - $this->title";
}
return $name; return $name;
} }
public function getIcon() { public function getIcon()
{
return self::URI . '/favicon.ico'; return self::URI . '/favicon.ico';
} }
} }

View file

@ -1,5 +1,7 @@
<?php <?php
class ARDMediathekBridge extends BridgeAbstract {
class ARDMediathekBridge extends BridgeAbstract
{
const NAME = 'ARD-Mediathek Bridge'; const NAME = 'ARD-Mediathek Bridge';
const URI = 'https://www.ardmediathek.de'; const URI = 'https://www.ardmediathek.de';
const DESCRIPTION = 'Feed of any series in the ARD-Mediathek, specified by its path'; const DESCRIPTION = 'Feed of any series in the ARD-Mediathek, specified by its path';
@ -39,18 +41,19 @@ class ARDMediathekBridge extends BridgeAbstract {
*/ */
const IMAGEWIDTHPLACEHOLDER = '{width}'; const IMAGEWIDTHPLACEHOLDER = '{width}';
const PARAMETERS = array( const PARAMETERS = [
array( [
'path' => array( 'path' => [
'name' => 'Show Link or ID', 'name' => 'Show Link or ID',
'required' => true, 'required' => true,
'title' => 'Link to the show page or just its alphanumeric suffix', 'title' => 'Link to the show page or just its alphanumeric suffix',
'defaultValue' => 'https://www.ardmediathek.de/sendung/45-min/Y3JpZDovL25kci5kZS8xMzkx/' 'defaultValue' => 'https://www.ardmediathek.de/sendung/45-min/Y3JpZDovL25kci5kZS8xMzkx/'
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$oldTz = date_default_timezone_get(); $oldTz = date_default_timezone_get();
date_default_timezone_set('Europe/Berlin'); date_default_timezone_set('Europe/Berlin');
@ -69,20 +72,20 @@ class ARDMediathekBridge extends BridgeAbstract {
} }
} }
$url = SELF::APIENDPOINT . $showID . '/?pageSize=' . SELF::PAGESIZE; $url = self::APIENDPOINT . $showID . '/?pageSize=' . self::PAGESIZE;
$rawJSON = getContents($url); $rawJSON = getContents($url);
$processedJSON = json_decode($rawJSON); $processedJSON = json_decode($rawJSON);
foreach($processedJSON->teasers as $video) { foreach ($processedJSON->teasers as $video) {
$item = array(); $item = [];
// there is also ->links->self->id, ->links->self->urlId, ->links->target->id, ->links->target->urlId // there is also ->links->self->id, ->links->self->urlId, ->links->target->id, ->links->target->urlId
$item['uri'] = SELF::VIDEOLINKPREFIX . $video->id . '/'; $item['uri'] = self::VIDEOLINKPREFIX . $video->id . '/';
// there is also ->mediumTitle and ->shortTitle // there is also ->mediumTitle and ->shortTitle
$item['title'] = $video->longTitle; $item['title'] = $video->longTitle;
// in the test, aspect16x9 was the only child of images, not sure whether that is always true // in the test, aspect16x9 was the only child of images, not sure whether that is always true
$item['enclosures'] = array( $item['enclosures'] = [
str_replace(SELF::IMAGEWIDTHPLACEHOLDER, SELF::IMAGEWIDTH, $video->images->aspect16x9->src) str_replace(self::IMAGEWIDTHPLACEHOLDER, self::IMAGEWIDTH, $video->images->aspect16x9->src)
); ];
$item['content'] = '<img src="' . $item['enclosures'][0] . '" /><p>'; $item['content'] = '<img src="' . $item['enclosures'][0] . '" /><p>';
$item['timestamp'] = $video->broadcastedOn; $item['timestamp'] = $video->broadcastedOn;
$item['uid'] = $video->id; $item['uid'] = $video->id;

View file

@ -1,21 +1,23 @@
<?php <?php
class ASRockNewsBridge extends BridgeAbstract {
class ASRockNewsBridge extends BridgeAbstract
{
const NAME = 'ASRock News Bridge'; const NAME = 'ASRock News Bridge';
const URI = 'https://www.asrock.com'; const URI = 'https://www.asrock.com';
const DESCRIPTION = 'Returns latest news articles'; const DESCRIPTION = 'Returns latest news articles';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array(); const PARAMETERS = [];
const CACHE_TIMEOUT = 3600; // 1 hour const CACHE_TIMEOUT = 3600; // 1 hour
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM(self::URI . '/news/index.asp'); $html = getSimpleHTMLDOM(self::URI . '/news/index.asp');
$html = defaultLinkTo($html, self::URI . '/news/'); $html = defaultLinkTo($html, self::URI . '/news/');
foreach($html->find('div.inner > a') as $index => $a) { foreach ($html->find('div.inner > a') as $index => $a) {
$item = array(); $item = [];
$articlePath = $a->href; $articlePath = $a->href;
@ -41,7 +43,8 @@ class ASRockNewsBridge extends BridgeAbstract {
} }
} }
private function extractDate($text) { private function extractDate($text)
{
$dateRegex = '/^([0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2})/'; $dateRegex = '/^([0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2})/';
$text = trim($text); $text = trim($text);

View file

@ -1,6 +1,7 @@
<?php <?php
class AcrimedBridge extends FeedExpander {
class AcrimedBridge extends FeedExpander
{
const MAINTAINER = 'qwertygc'; const MAINTAINER = 'qwertygc';
const NAME = 'Acrimed Bridge'; const NAME = 'Acrimed Bridge';
const URI = 'https://www.acrimed.org/'; const URI = 'https://www.acrimed.org/';
@ -17,14 +18,16 @@ class AcrimedBridge extends FeedExpander {
] ]
]; ];
public function collectData(){ public function collectData()
{
$this->collectExpandableDatas( $this->collectExpandableDatas(
static::URI . 'spip.php?page=backend', static::URI . 'spip.php?page=backend',
$this->getInput('limit') $this->getInput('limit')
); );
} }
protected function parseItem($newsItem){ protected function parseItem($newsItem)
{
$item = parent::parseItem($newsItem); $item = parent::parseItem($newsItem);
$articlePage = getSimpleHTMLDOM($newsItem->link); $articlePage = getSimpleHTMLDOM($newsItem->link);

View file

@ -1,16 +1,17 @@
<?php <?php
class AirBreizhBridge extends BridgeAbstract {
class AirBreizhBridge extends BridgeAbstract
{
const MAINTAINER = 'fanch317'; const MAINTAINER = 'fanch317';
const NAME = 'Air Breizh'; const NAME = 'Air Breizh';
const URI = 'https://www.airbreizh.asso.fr/'; const URI = 'https://www.airbreizh.asso.fr/';
const DESCRIPTION = 'Returns newests publications on Air Breizh'; const DESCRIPTION = 'Returns newests publications on Air Breizh';
const PARAMETERS = array( const PARAMETERS = [
'Publications' => array( 'Publications' => [
'theme' => array( 'theme' => [
'name' => 'Thematique', 'name' => 'Thematique',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Tout' => '', 'Tout' => '',
'Rapport d\'activite' => 'rapport-dactivite', 'Rapport d\'activite' => 'rapport-dactivite',
'Etude' => 'etudes', 'Etude' => 'etudes',
@ -18,22 +19,24 @@ class AirBreizhBridge extends BridgeAbstract {
'Autres documents' => 'autres-documents', 'Autres documents' => 'autres-documents',
'Plan Régional de Surveillance de la qualité de lair' => 'prsqa', 'Plan Régional de Surveillance de la qualité de lair' => 'prsqa',
'Transport' => 'transport' 'Transport' => 'transport'
) ]
) ]
) ]
); ];
public function getIcon() { public function getIcon()
{
return 'https://www.airbreizh.asso.fr/voy_content/uploads/2017/11/favicon.png'; return 'https://www.airbreizh.asso.fr/voy_content/uploads/2017/11/favicon.png';
} }
public function collectData(){ public function collectData()
{
$html = ''; $html = '';
$html = getSimpleHTMLDOM(static::URI . 'publications/?fwp_publications_thematiques=' . $this->getInput('theme')) $html = getSimpleHTMLDOM(static::URI . 'publications/?fwp_publications_thematiques=' . $this->getInput('theme'))
or returnClientError('No results for this query.'); or returnClientError('No results for this query.');
foreach ($html->find('article') as $article) { foreach ($html->find('article') as $article) {
$item = array(); $item = [];
// Title // Title
$item['title'] = $article->find('h2', 0)->plaintext; $item['title'] = $article->find('h2', 0)->plaintext;
// Author // Author

View file

@ -1,24 +1,25 @@
<?php <?php
class AlbionOnlineBridge extends BridgeAbstract {
class AlbionOnlineBridge extends BridgeAbstract
{
const NAME = 'Albion Online Changelog'; const NAME = 'Albion Online Changelog';
const MAINTAINER = 'otakuf'; const MAINTAINER = 'otakuf';
const URI = 'https://albiononline.com'; const URI = 'https://albiononline.com';
const DESCRIPTION = 'Returns the changes made to the Albion Online'; const DESCRIPTION = 'Returns the changes made to the Albion Online';
const CACHE_TIMEOUT = 3600; // 60min const CACHE_TIMEOUT = 3600; // 60min
const PARAMETERS = array( array( const PARAMETERS = [ [
'postcount' => array( 'postcount' => [
'name' => 'Limit', 'name' => 'Limit',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'title' => 'Maximum number of items to return', 'title' => 'Maximum number of items to return',
'defaultValue' => 5, 'defaultValue' => 5,
), ],
'language' => array( 'language' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'English' => 'en', 'English' => 'en',
'Deutsch' => 'de', 'Deutsch' => 'de',
'Polski' => 'pl', 'Polski' => 'pl',
@ -26,19 +27,20 @@ class AlbionOnlineBridge extends BridgeAbstract {
'Русский' => 'ru', 'Русский' => 'ru',
'Português' => 'pt', 'Português' => 'pt',
'Español' => 'es', 'Español' => 'es',
), ],
'title' => 'Language of changelog posts', 'title' => 'Language of changelog posts',
'defaultValue' => 'en', 'defaultValue' => 'en',
), ],
'full' => array( 'full' => [
'name' => 'Full changelog', 'name' => 'Full changelog',
'type' => 'checkbox', 'type' => 'checkbox',
'required' => false, 'required' => false,
'title' => 'Enable to receive the full changelog post for each item' 'title' => 'Enable to receive the full changelog post for each item'
), ],
)); ]];
public function collectData() { public function collectData()
{
$api = 'https://albiononline.com/'; $api = 'https://albiononline.com/';
// Example: https://albiononline.com/en/changelog/1/5 // Example: https://albiononline.com/en/changelog/1/5
$url = $api . $this->getInput('language') . '/changelog/1/' . $this->getInput('postcount'); $url = $api . $this->getInput('language') . '/changelog/1/' . $this->getInput('postcount');
@ -46,14 +48,14 @@ class AlbionOnlineBridge extends BridgeAbstract {
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
foreach ($html->find('li') as $data) { foreach ($html->find('li') as $data) {
$item = array(); $item = [];
$item['uri'] = self::URI . $data->find('a', 0)->getAttribute('href'); $item['uri'] = self::URI . $data->find('a', 0)->getAttribute('href');
$item['title'] = trim(explode('|', $data->find('span', 0)->plaintext)[0]); $item['title'] = trim(explode('|', $data->find('span', 0)->plaintext)[0]);
// Time below work only with en lang. Need to think about solution. May be separate request like getFullChangelog, but to english list for all language // Time below work only with en lang. Need to think about solution. May be separate request like getFullChangelog, but to english list for all language
//print_r( date_parse_from_format( 'M j, Y' , 'Sep 9, 2020') ); //print_r( date_parse_from_format( 'M j, Y' , 'Sep 9, 2020') );
//$item['timestamp'] = $this->extractDate($a->plaintext); //$item['timestamp'] = $this->extractDate($a->plaintext);
$item['author'] = 'albiononline.com'; $item['author'] = 'albiononline.com';
if($this->getInput('full')) { if ($this->getInput('full')) {
$item['content'] = $this->getFullChangelog($item['uri']); $item['content'] = $this->getFullChangelog($item['uri']);
} else { } else {
//$item['content'] = trim(preg_replace('/\s+/', ' ', $data->find('span', 0)->plaintext)); //$item['content'] = trim(preg_replace('/\s+/', ' ', $data->find('span', 0)->plaintext));
@ -65,7 +67,8 @@ class AlbionOnlineBridge extends BridgeAbstract {
} }
} }
private function getFullChangelog($url) { private function getFullChangelog($url)
{
$html = getSimpleHTMLDOMCached($url); $html = getSimpleHTMLDOMCached($url);
$html = defaultLinkTo($html, self::URI); $html = defaultLinkTo($html, self::URI);
return $html->find('div.small-12.columns', 1)->innertext; return $html->find('div.small-12.columns', 1)->innertext;

View file

@ -1,46 +1,48 @@
<?php <?php
class AlfaBankByBridge extends BridgeAbstract {
class AlfaBankByBridge extends BridgeAbstract
{
const MAINTAINER = 'lassana'; const MAINTAINER = 'lassana';
const NAME = 'AlfaBank.by Новости'; const NAME = 'AlfaBank.by Новости';
const URI = 'https://www.alfabank.by'; const URI = 'https://www.alfabank.by';
const DESCRIPTION = 'Уведомления Alfa-Now — новости от Альфа-Банка'; const DESCRIPTION = 'Уведомления Alfa-Now — новости от Альфа-Банка';
const CACHE_TIMEOUT = 3600; // 1 hour const CACHE_TIMEOUT = 3600; // 1 hour
const PARAMETERS = array( const PARAMETERS = [
'News' => array( 'News' => [
'business' => array( 'business' => [
'name' => 'Альфа Бизнес', 'name' => 'Альфа Бизнес',
'type' => 'list', 'type' => 'list',
'title' => 'В зависимости от выбора, возращает уведомления для" . 'title' => 'В зависимости от выбора, возращает уведомления для" .
" клиентов физ. лиц либо для клиентов-юридических лиц и ИП', " клиентов физ. лиц либо для клиентов-юридических лиц и ИП',
'values' => array( 'values' => [
'Новости' => 'news', 'Новости' => 'news',
'Новости бизнеса' => 'newsBusiness' 'Новости бизнеса' => 'newsBusiness'
), ],
'defaultValue' => 'news' 'defaultValue' => 'news'
), ],
'fullContent' => array( 'fullContent' => [
'name' => 'Включать содержимое', 'name' => 'Включать содержимое',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Если выбрано, содержимое уведомлений вставляется в поток (работает медленно)' 'title' => 'Если выбрано, содержимое уведомлений вставляется в поток (работает медленно)'
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$business = $this->getInput('business') == 'newsBusiness'; $business = $this->getInput('business') == 'newsBusiness';
$fullContent = $this->getInput('fullContent') == 'on'; $fullContent = $this->getInput('fullContent') == 'on';
$mainPageUrl = self::URI . '/about/articles/uvedomleniya/'; $mainPageUrl = self::URI . '/about/articles/uvedomleniya/';
if($business) { if ($business) {
$mainPageUrl .= '?business=true'; $mainPageUrl .= '?business=true';
} }
$html = getSimpleHTMLDOM($mainPageUrl); $html = getSimpleHTMLDOM($mainPageUrl);
$limit = 0; $limit = 0;
foreach($html->find('a.notifications__item') as $element) { foreach ($html->find('a.notifications__item') as $element) {
if($limit < 10) { if ($limit < 10) {
$item = array(); $item = [];
$item['uid'] = 'urn:sha1:' . hash('sha1', $element->getAttribute('data-notification-id')); $item['uid'] = 'urn:sha1:' . hash('sha1', $element->getAttribute('data-notification-id'));
$item['title'] = $element->find('div.item-title', 0)->innertext; $item['title'] = $element->find('div.item-title', 0)->innertext;
$item['timestamp'] = DateTime::createFromFormat( $item['timestamp'] = DateTime::createFromFormat(
@ -49,14 +51,14 @@ class AlfaBankByBridge extends BridgeAbstract {
)->getTimestamp(); )->getTimestamp();
$itemUrl = self::URI . $element->href; $itemUrl = self::URI . $element->href;
if($business) { if ($business) {
$itemUrl = str_replace('?business=true', '', $itemUrl); $itemUrl = str_replace('?business=true', '', $itemUrl);
} }
$item['uri'] = $itemUrl; $item['uri'] = $itemUrl;
if($fullContent) { if ($fullContent) {
$itemHtml = getSimpleHTMLDOM($itemUrl); $itemHtml = getSimpleHTMLDOM($itemUrl);
if($itemHtml) { if ($itemHtml) {
$item['content'] = $itemHtml->find('div.now-p__content-text', 0)->innertext; $item['content'] = $itemHtml->find('div.now-p__content-text', 0)->innertext;
} }
} }
@ -67,17 +69,19 @@ class AlfaBankByBridge extends BridgeAbstract {
} }
} }
public function getIcon() { public function getIcon()
{
return static::URI . '/local/images/favicon.ico'; return static::URI . '/local/images/favicon.ico';
} }
private function ruMonthsToEn($date) { private function ruMonthsToEn($date)
$ruMonths = array( {
$ruMonths = [
'Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня', 'Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня',
'Июля', 'Августа', 'Сентября', 'Октября', 'Ноября', 'Декабря' ); 'Июля', 'Августа', 'Сентября', 'Октября', 'Ноября', 'Декабря' ];
$enMonths = array( $enMonths = [
'January', 'February', 'March', 'April', 'May', 'June', 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December' ); 'July', 'August', 'September', 'October', 'November', 'December' ];
return str_replace($ruMonths, $enMonths, $date); return str_replace($ruMonths, $enMonths, $date);
} }
} }

View file

@ -1,17 +1,18 @@
<?php <?php
class AllocineFRBridge extends BridgeAbstract {
class AllocineFRBridge extends BridgeAbstract
{
const MAINTAINER = 'superbaillot.net'; const MAINTAINER = 'superbaillot.net';
const NAME = 'Allo Cine Bridge'; const NAME = 'Allo Cine Bridge';
const CACHE_TIMEOUT = 25200; // 7h const CACHE_TIMEOUT = 25200; // 7h
const URI = 'https://www.allocine.fr'; const URI = 'https://www.allocine.fr';
const DESCRIPTION = 'Bridge for allocine.fr'; const DESCRIPTION = 'Bridge for allocine.fr';
const PARAMETERS = array( array( const PARAMETERS = [ [
'category' => array( 'category' => [
'name' => 'Emission', 'name' => 'Emission',
'type' => 'list', 'type' => 'list',
'title' => 'Sélectionner l\'emission', 'title' => 'Sélectionner l\'emission',
'values' => array( 'values' => [
'Faux Raccord' => 'faux-raccord', 'Faux Raccord' => 'faux-raccord',
'Fanzone' => 'fanzone', 'Fanzone' => 'fanzone',
'Game In Ciné' => 'game-in-cine', 'Game In Ciné' => 'game-in-cine',
@ -27,14 +28,14 @@ class AllocineFRBridge extends BridgeAbstract {
'Complètement...' => 'completement', 'Complètement...' => 'completement',
'#Fun Facts' => 'fun-facts', '#Fun Facts' => 'fun-facts',
'Origin Story' => 'origin-story', 'Origin Story' => 'origin-story',
) ]
) ]
)); ]];
public function getURI(){ public function getURI()
if(!is_null($this->getInput('category'))) { {
if (!is_null($this->getInput('category'))) {
$categories = array( $categories = [
'faux-raccord' => '/video/programme-12284/', 'faux-raccord' => '/video/programme-12284/',
'fanzone' => '/video/programme-12298/', 'fanzone' => '/video/programme-12298/',
'game-in-cine' => '/video/programme-12288/', 'game-in-cine' => '/video/programme-12288/',
@ -50,10 +51,10 @@ class AllocineFRBridge extends BridgeAbstract {
'completement' => '/video/programme-23859/', 'completement' => '/video/programme-23859/',
'fun-facts' => '/video/programme-23040/', 'fun-facts' => '/video/programme-23040/',
'origin-story' => '/video/programme-25667/' 'origin-story' => '/video/programme-25667/'
); ];
$category = $this->getInput('category'); $category = $this->getInput('category');
if(array_key_exists($category, $categories)) { if (array_key_exists($category, $categories)) {
return static::URI . $this->getLastSeasonURI($categories[$category]); return static::URI . $this->getLastSeasonURI($categories[$category]);
} else { } else {
returnClientError('Emission inconnue'); returnClientError('Emission inconnue');
@ -71,8 +72,9 @@ class AllocineFRBridge extends BridgeAbstract {
return $URI; return $URI;
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('category'))) { {
if (!is_null($this->getInput('category'))) {
return self::NAME . ' : ' return self::NAME . ' : '
. array_search( . array_search(
$this->getInput('category'), $this->getInput('category'),
@ -83,16 +85,16 @@ class AllocineFRBridge extends BridgeAbstract {
return parent::getName(); return parent::getName();
} }
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
$category = array_search( $category = array_search(
$this->getInput('category'), $this->getInput('category'),
self::PARAMETERS[$this->queriedContext]['category']['values'] self::PARAMETERS[$this->queriedContext]['category']['values']
); );
foreach($html->find('div[class=gd-col-left]', 0)->find('div[class*=video-card]') as $element) { foreach ($html->find('div[class=gd-col-left]', 0)->find('div[class*=video-card]') as $element) {
$item = array(); $item = [];
$title = $element->find('a[class*=meta-title-link]', 0); $title = $element->find('a[class*=meta-title-link]', 0);
$content = trim(defaultLinkTo($element->outertext, static::URI)); $content = trim(defaultLinkTo($element->outertext, static::URI));

View file

@ -1,35 +1,35 @@
<?php <?php
class AmazonBridge extends BridgeAbstract { class AmazonBridge extends BridgeAbstract
{
const MAINTAINER = 'Alexis CHEMEL'; const MAINTAINER = 'Alexis CHEMEL';
const NAME = 'Amazon'; const NAME = 'Amazon';
const URI = 'https://www.amazon.com/'; const URI = 'https://www.amazon.com/';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'Returns products from Amazon search'; const DESCRIPTION = 'Returns products from Amazon search';
const PARAMETERS = array(array( const PARAMETERS = [[
'q' => array( 'q' => [
'name' => 'Keyword', 'name' => 'Keyword',
'required' => true, 'required' => true,
'exampleValue' => 'watch', 'exampleValue' => 'watch',
), ],
'sort' => array( 'sort' => [
'name' => 'Sort by', 'name' => 'Sort by',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Relevance' => 'relevanceblender', 'Relevance' => 'relevanceblender',
'Price: Low to High' => 'price-asc-rank', 'Price: Low to High' => 'price-asc-rank',
'Price: High to Low' => 'price-desc-rank', 'Price: High to Low' => 'price-desc-rank',
'Average Customer Review' => 'review-rank', 'Average Customer Review' => 'review-rank',
'Newest Arrivals' => 'date-desc-rank', 'Newest Arrivals' => 'date-desc-rank',
), ],
'defaultValue' => 'relevanceblender', 'defaultValue' => 'relevanceblender',
), ],
'tld' => array( 'tld' => [
'name' => 'Country', 'name' => 'Country',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Australia' => 'com.au', 'Australia' => 'com.au',
'Brazil' => 'com.br', 'Brazil' => 'com.br',
'Canada' => 'ca', 'Canada' => 'ca',
@ -46,13 +46,13 @@ class AmazonBridge extends BridgeAbstract {
'Turkey' => 'com.tr', 'Turkey' => 'com.tr',
'United Kingdom' => 'co.uk', 'United Kingdom' => 'co.uk',
'United States' => 'com', 'United States' => 'com',
), ],
'defaultValue' => 'com', 'defaultValue' => 'com',
), ],
)); ]];
public function collectData() {
public function collectData()
{
$baseUrl = sprintf('https://www.amazon.%s', $this->getInput('tld')); $baseUrl = sprintf('https://www.amazon.%s', $this->getInput('tld'));
$url = sprintf( $url = sprintf(
@ -66,7 +66,7 @@ class AmazonBridge extends BridgeAbstract {
$elements = $dom->find('div.s-result-item'); $elements = $dom->find('div.s-result-item');
foreach($elements as $element) { foreach ($elements as $element) {
$item = []; $item = [];
$title = $element->find('h2', 0); $title = $element->find('h2', 0);
@ -93,8 +93,9 @@ class AmazonBridge extends BridgeAbstract {
} }
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('tld')) && !is_null($this->getInput('q'))) { {
if (!is_null($this->getInput('tld')) && !is_null($this->getInput('q'))) {
return 'Amazon.' . $this->getInput('tld') . ': ' . $this->getInput('q'); return 'Amazon.' . $this->getInput('tld') . ': ' . $this->getInput('q');
} }

View file

@ -1,25 +1,26 @@
<?php <?php
class AmazonPriceTrackerBridge extends BridgeAbstract { class AmazonPriceTrackerBridge extends BridgeAbstract
{
const MAINTAINER = 'captn3m0, sal0max'; const MAINTAINER = 'captn3m0, sal0max';
const NAME = 'Amazon Price Tracker'; const NAME = 'Amazon Price Tracker';
const URI = 'https://www.amazon.com/'; const URI = 'https://www.amazon.com/';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'Tracks price for a single product on Amazon'; const DESCRIPTION = 'Tracks price for a single product on Amazon';
const PARAMETERS = array( const PARAMETERS = [
array( [
'asin' => array( 'asin' => [
'name' => 'ASIN', 'name' => 'ASIN',
'required' => true, 'required' => true,
'exampleValue' => 'B071GB1VMQ', 'exampleValue' => 'B071GB1VMQ',
// https://stackoverflow.com/a/12827734 // https://stackoverflow.com/a/12827734
'pattern' => 'B[\dA-Z]{9}|\d{9}(X|\d)', 'pattern' => 'B[\dA-Z]{9}|\d{9}(X|\d)',
), ],
'tld' => array( 'tld' => [
'name' => 'Country', 'name' => 'Country',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Australia' => 'com.au', 'Australia' => 'com.au',
'Brazil' => 'com.br', 'Brazil' => 'com.br',
'Canada' => 'ca', 'Canada' => 'ca',
@ -36,19 +37,19 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
'Turkey' => 'com.tr', 'Turkey' => 'com.tr',
'United Kingdom' => 'co.uk', 'United Kingdom' => 'co.uk',
'United States' => 'com', 'United States' => 'com',
), ],
'defaultValue' => 'com', 'defaultValue' => 'com',
), ],
)); ]];
const PRICE_SELECTORS = array( const PRICE_SELECTORS = [
'#priceblock_ourprice', '#priceblock_ourprice',
'.priceBlockBuyingPriceString', '.priceBlockBuyingPriceString',
'#newBuyBoxPrice', '#newBuyBoxPrice',
'#tp_price_block_total_price_ww', '#tp_price_block_total_price_ww',
'span.offer-price', 'span.offer-price',
'.a-color-price', '.a-color-price',
); ];
const WHITESPACE = " \t\n\r\0\x0B\xC2\xA0"; const WHITESPACE = " \t\n\r\0\x0B\xC2\xA0";
@ -57,14 +58,16 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
/** /**
* Generates domain name given a amazon TLD * Generates domain name given a amazon TLD
*/ */
private function getDomainName() { private function getDomainName()
{
return 'https://www.amazon.' . $this->getInput('tld'); return 'https://www.amazon.' . $this->getInput('tld');
} }
/** /**
* Generates URI for a Amazon product page * Generates URI for a Amazon product page
*/ */
public function getURI() { public function getURI()
{
if (!is_null($this->getInput('asin'))) { if (!is_null($this->getInput('asin'))) {
return $this->getDomainName() . '/dp/' . $this->getInput('asin'); return $this->getDomainName() . '/dp/' . $this->getInput('asin');
} }
@ -75,7 +78,8 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
* Scrapes the product title from the html page * Scrapes the product title from the html page
* returns the default title if scraping fails * returns the default title if scraping fails
*/ */
private function getTitle($html) { private function getTitle($html)
{
$titleTag = $html->find('#productTitle', 0); $titleTag = $html->find('#productTitle', 0);
if (!$titleTag) { if (!$titleTag) {
@ -88,7 +92,8 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
/** /**
* Title used by the feed if none could be found * Title used by the feed if none could be found
*/ */
private function getDefaultTitle() { private function getDefaultTitle()
{
return 'Amazon.' . $this->getInput('tld') . ': ' . $this->getInput('asin'); return 'Amazon.' . $this->getInput('tld') . ': ' . $this->getInput('asin');
} }
@ -96,7 +101,8 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
* Returns name for the feed * Returns name for the feed
* Uses title (already scraped) if it has one * Uses title (already scraped) if it has one
*/ */
public function getName() { public function getName()
{
if (isset($this->title)) { if (isset($this->title)) {
return $this->title; return $this->title;
} else { } else {
@ -104,7 +110,8 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
} }
} }
private function parseDynamicImage($attribute) { private function parseDynamicImage($attribute)
{
$json = json_decode(html_entity_decode($attribute), true); $json = json_decode(html_entity_decode($attribute), true);
if ($json and count($json) > 0) { if ($json and count($json) > 0) {
@ -115,7 +122,8 @@ class AmazonPriceTrackerBridge extends BridgeAbstract {
/** /**
* Returns a generated image tag for the product * Returns a generated image tag for the product
*/ */
private function getImage($html) { private function getImage($html)
{
$imageSrc = $html->find('#main-image-container img', 0); $imageSrc = $html->find('#main-image-container img', 0);
if ($imageSrc) { if ($imageSrc) {
@ -134,49 +142,53 @@ EOT;
* Return \simple_html_dom object * Return \simple_html_dom object
* for the entire html of the product page * for the entire html of the product page
*/ */
private function getHtml() { private function getHtml()
{
$uri = $this->getURI(); $uri = $this->getURI();
return getSimpleHTMLDOM($uri) ?: returnServerError('Could not request Amazon.'); return getSimpleHTMLDOM($uri) ?: returnServerError('Could not request Amazon.');
} }
private function scrapePriceFromMetrics($html) { private function scrapePriceFromMetrics($html)
{
$asinData = $html->find('#cerberus-data-metrics', 0); $asinData = $html->find('#cerberus-data-metrics', 0);
// <div id="cerberus-data-metrics" style="display: none;" // <div id="cerberus-data-metrics" style="display: none;"
// data-asin="B00WTHJ5SU" data-asin-price="14.99" data-asin-shipping="0" // data-asin="B00WTHJ5SU" data-asin-price="14.99" data-asin-shipping="0"
// data-asin-currency-code="USD" data-substitute-count="-1" ... /> // data-asin-currency-code="USD" data-substitute-count="-1" ... />
if ($asinData) { if ($asinData) {
return array( return [
'price' => $asinData->getAttribute('data-asin-price'), 'price' => $asinData->getAttribute('data-asin-price'),
'currency' => $asinData->getAttribute('data-asin-currency-code'), 'currency' => $asinData->getAttribute('data-asin-currency-code'),
'shipping' => $asinData->getAttribute('data-asin-shipping') 'shipping' => $asinData->getAttribute('data-asin-shipping')
); ];
} }
return false; return false;
} }
private function scrapePriceTwister($html) { private function scrapePriceTwister($html)
{
$str = $html->find('.twister-plus-buying-options-price-data', 0); $str = $html->find('.twister-plus-buying-options-price-data', 0);
$data = json_decode($str->innertext, true); $data = json_decode($str->innertext, true);
if(count($data) === 1) { if (count($data) === 1) {
$data = $data[0]; $data = $data[0];
return array( return [
'displayPrice' => $data['displayPrice'], 'displayPrice' => $data['displayPrice'],
'currency' => $data['currency'], 'currency' => $data['currency'],
'shipping' => '0', 'shipping' => '0',
); ];
} }
return false; return false;
} }
private function scrapePriceGeneric($html) { private function scrapePriceGeneric($html)
{
$priceDiv = null; $priceDiv = null;
foreach(self::PRICE_SELECTORS as $sel) { foreach (self::PRICE_SELECTORS as $sel) {
$priceDiv = $html->find($sel, 0); $priceDiv = $html->find($sel, 0);
if ($priceDiv) { if ($priceDiv) {
break; break;
@ -194,17 +206,18 @@ EOT;
$currency = str_replace($price, '', $priceString); $currency = str_replace($price, '', $priceString);
if ($price != null && $currency != null) { if ($price != null && $currency != null) {
return array( return [
'price' => $price, 'price' => $price,
'currency' => $currency, 'currency' => $currency,
'shipping' => '0' 'shipping' => '0'
); ];
} }
return false; return false;
} }
private function renderContent($image, $data) { private function renderContent($image, $data)
{
$price = $data['displayPrice']; $price = $data['displayPrice'];
if (!$price) { if (!$price) {
$price = "{$data['price']} {$data['currency']}"; $price = "{$data['price']} {$data['currency']}";
@ -223,20 +236,21 @@ EOT;
* Scrape method for Amazon product page * Scrape method for Amazon product page
* @return [type] [description] * @return [type] [description]
*/ */
public function collectData() { public function collectData()
{
$html = $this->getHtml(); $html = $this->getHtml();
$this->title = $this->getTitle($html); $this->title = $this->getTitle($html);
$imageTag = $this->getImage($html); $imageTag = $this->getImage($html);
$data = $this->scrapePriceGeneric($html); $data = $this->scrapePriceGeneric($html);
$item = array( $item = [
'title' => $this->title, 'title' => $this->title,
'uri' => $this->getURI(), 'uri' => $this->getURI(),
'content' => $this->renderContent($imageTag, $data), 'content' => $this->renderContent($imageTag, $data),
// This is to ensure that feed readers notice the price change // This is to ensure that feed readers notice the price change
'uid' => md5($data['price']) 'uid' => md5($data['price'])
); ];
$this->items[] = $item; $this->items[] = $item;
} }

View file

@ -1,18 +1,19 @@
<?php <?php
class AnidexBridge extends BridgeAbstract {
class AnidexBridge extends BridgeAbstract
{
const MAINTAINER = 'ORelio'; const MAINTAINER = 'ORelio';
const NAME = 'Anidex'; const NAME = 'Anidex';
const URI = 'http://anidex.info/'; // anidex.info has ddos-guard so we need to use anidex.moe const URI = 'http://anidex.info/'; // anidex.info has ddos-guard so we need to use anidex.moe
const ALTERNATE_URI = 'https://anidex.moe/'; // anidex.moe returns 301 unless Host is set to anidex.info const ALTERNATE_URI = 'https://anidex.moe/'; // anidex.moe returns 301 unless Host is set to anidex.info
const ALTERNATE_HOST = 'anidex.info'; // Correct host for requesting anidex.moe without 301 redirect const ALTERNATE_HOST = 'anidex.info'; // Correct host for requesting anidex.moe without 301 redirect
const DESCRIPTION = 'Returns the newest torrents, with optional search criteria.'; const DESCRIPTION = 'Returns the newest torrents, with optional search criteria.';
const PARAMETERS = array( const PARAMETERS = [
array( [
'id' => array( 'id' => [
'name' => 'Category', 'name' => 'Category',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'All categories' => '0', 'All categories' => '0',
'Anime' => '1,2,3', 'Anime' => '1,2,3',
'Anime - Sub' => '1', 'Anime - Sub' => '1',
@ -34,12 +35,12 @@ class AnidexBridge extends BridgeAbstract {
'Pictures' => '14', 'Pictures' => '14',
'Adult Video' => '15', 'Adult Video' => '15',
'Other' => '16' 'Other' => '16'
) ]
), ],
'lang_id' => array( 'lang_id' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'All languages' => '0', 'All languages' => '0',
'English' => '1', 'English' => '1',
'Japanese' => '2', 'Japanese' => '2',
@ -72,52 +73,52 @@ class AnidexBridge extends BridgeAbstract {
'Spanish (LATAM)' => '29', 'Spanish (LATAM)' => '29',
'Persian' => '30', 'Persian' => '30',
'Malaysian' => '31' 'Malaysian' => '31'
) ]
), ],
'group_id' => array( 'group_id' => [
'name' => 'Group ID', 'name' => 'Group ID',
'type' => 'number' 'type' => 'number'
), ],
'r' => array( 'r' => [
'name' => 'Hide Remakes', 'name' => 'Hide Remakes',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'b' => array( 'b' => [
'name' => 'Only Batches', 'name' => 'Only Batches',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'a' => array( 'a' => [
'name' => 'Only Authorized', 'name' => 'Only Authorized',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'q' => array( 'q' => [
'name' => 'Keyword', 'name' => 'Keyword',
'description' => 'Keyword(s)', 'description' => 'Keyword(s)',
'type' => 'text' 'type' => 'text'
), ],
'h' => array( 'h' => [
'name' => 'Adult content', 'name' => 'Adult content',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'No filter' => '0', 'No filter' => '0',
'Hide +18' => '1', 'Hide +18' => '1',
'Only +18' => '2' 'Only +18' => '2'
) ]
) ]
) ]
); ];
public function collectData() {
public function collectData()
{
// Build Search URL from user-provided parameters // Build Search URL from user-provided parameters
$search_url = self::ALTERNATE_URI . '?s=upload_timestamp&o=desc'; $search_url = self::ALTERNATE_URI . '?s=upload_timestamp&o=desc';
foreach (array('id', 'lang_id', 'group_id') as $param_name) { foreach (['id', 'lang_id', 'group_id'] as $param_name) {
$param = $this->getInput($param_name); $param = $this->getInput($param_name);
if (!empty($param) && intval($param) != 0 && ctype_digit(str_replace(',', '', $param))) { if (!empty($param) && intval($param) != 0 && ctype_digit(str_replace(',', '', $param))) {
$search_url .= '&' . $param_name . '=' . $param; $search_url .= '&' . $param_name . '=' . $param;
} }
} }
foreach (array('r', 'b', 'a') as $param_name) { foreach (['r', 'b', 'a'] as $param_name) {
$param = $this->getInput($param_name); $param = $this->getInput($param_name);
if (!empty($param) && boolval($param)) { if (!empty($param) && boolval($param)) {
$search_url .= '&' . $param_name . '=1'; $search_url .= '&' . $param_name . '=1';
@ -127,14 +128,14 @@ class AnidexBridge extends BridgeAbstract {
if (!empty($query)) { if (!empty($query)) {
$search_url .= '&q=' . urlencode($query); $search_url .= '&q=' . urlencode($query);
} }
$opt = array(); $opt = [];
$h = $this->getInput('h'); $h = $this->getInput('h');
if (!empty($h) && intval($h) != 0 && ctype_digit($h)) { if (!empty($h) && intval($h) != 0 && ctype_digit($h)) {
$opt[CURLOPT_COOKIE] = 'anidex_h_toggle=' . $h; $opt[CURLOPT_COOKIE] = 'anidex_h_toggle=' . $h;
} }
// We need to use a different Host HTTP header to reach the correct page on ALTERNATE_URI // We need to use a different Host HTTP header to reach the correct page on ALTERNATE_URI
$headers = array('Host: ' . self::ALTERNATE_HOST); $headers = ['Host: ' . self::ALTERNATE_HOST];
// The HTTPS certificate presented by anidex.moe is for anidex.info. We need to ignore this. // The HTTPS certificate presented by anidex.moe is for anidex.info. We need to ignore this.
// As a consequence, the bridge is intentionally marked as insecure by setting self::URI to http:// // As a consequence, the bridge is intentionally marked as insecure by setting self::URI to http://
@ -144,18 +145,20 @@ class AnidexBridge extends BridgeAbstract {
// Retrieve torrent listing from search results, which does not contain torrent description // Retrieve torrent listing from search results, which does not contain torrent description
$html = getSimpleHTMLDOM($search_url, $headers, $opt); $html = getSimpleHTMLDOM($search_url, $headers, $opt);
$links = $html->find('a'); $links = $html->find('a');
$results = array(); $results = [];
foreach ($links as $link) foreach ($links as $link) {
if (strpos($link->href, '/torrent/') === 0 && !in_array($link->href, $results)) if (strpos($link->href, '/torrent/') === 0 && !in_array($link->href, $results)) {
$results[] = $link->href; $results[] = $link->href;
if (empty($results) && empty($this->getInput('q'))) }
}
if (empty($results) && empty($this->getInput('q'))) {
returnServerError('No results from Anidex: ' . $search_url); returnServerError('No results from Anidex: ' . $search_url);
}
//Process each item individually //Process each item individually
foreach ($results as $element) { foreach ($results as $element) {
//Limit total amount of requests //Limit total amount of requests
if(count($this->items) >= 20) { if (count($this->items) >= 20) {
break; break;
} }
@ -163,14 +166,12 @@ class AnidexBridge extends BridgeAbstract {
//Ignore entries without valid torrent ID //Ignore entries without valid torrent ID
if ($torrent_id != 0 && ctype_digit($torrent_id)) { if ($torrent_id != 0 && ctype_digit($torrent_id)) {
//Retrieve data for this torrent ID //Retrieve data for this torrent ID
$item_browse_uri = self::URI . 'torrent/' . $torrent_id; $item_browse_uri = self::URI . 'torrent/' . $torrent_id;
$item_fetch_uri = self::ALTERNATE_URI . 'torrent/' . $torrent_id; $item_fetch_uri = self::ALTERNATE_URI . 'torrent/' . $torrent_id;
//Retrieve full description from torrent page (cached for 24 hours: 86400 seconds) //Retrieve full description from torrent page (cached for 24 hours: 86400 seconds)
if ($item_html = getSimpleHTMLDOMCached($item_fetch_uri, 86400, $headers, $opt)) { if ($item_html = getSimpleHTMLDOMCached($item_fetch_uri, 86400, $headers, $opt)) {
//Retrieve data from page contents //Retrieve data from page contents
$item_title = str_replace(' (Torrent) - AniDex ', '', $item_html->find('title', 0)->plaintext); $item_title = str_replace(' (Torrent) - AniDex ', '', $item_html->find('title', 0)->plaintext);
$item_desc = $item_html->find('div.panel-body', 0); $item_desc = $item_html->find('div.panel-body', 0);
@ -200,12 +201,12 @@ class AnidexBridge extends BridgeAbstract {
} }
//Build and add final item //Build and add final item
$item = array(); $item = [];
$item['uri'] = $item_browse_uri; $item['uri'] = $item_browse_uri;
$item['title'] = $item_title; $item['title'] = $item_title;
$item['author'] = $item_author; $item['author'] = $item_author;
$item['timestamp'] = $item_date; $item['timestamp'] = $item_date;
$item['enclosures'] = array($item_image); $item['enclosures'] = [$item_image];
$item['content'] = $item_desc; $item['content'] = $item_desc;
$this->items[] = $item; $this->items[] = $item;
} }

View file

@ -1,28 +1,29 @@
<?php <?php
class AnimeUltimeBridge extends BridgeAbstract {
class AnimeUltimeBridge extends BridgeAbstract
{
const MAINTAINER = 'ORelio'; const MAINTAINER = 'ORelio';
const NAME = 'Anime-Ultime'; const NAME = 'Anime-Ultime';
const URI = 'http://www.anime-ultime.net/'; const URI = 'http://www.anime-ultime.net/';
const CACHE_TIMEOUT = 10800; // 3h const CACHE_TIMEOUT = 10800; // 3h
const DESCRIPTION = 'Returns the newest releases posted on Anime-Ultime.'; const DESCRIPTION = 'Returns the newest releases posted on Anime-Ultime.';
const PARAMETERS = array( array( const PARAMETERS = [ [
'type' => array( 'type' => [
'name' => 'Type', 'name' => 'Type',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Everything' => '', 'Everything' => '',
'Anime' => 'A', 'Anime' => 'A',
'Drama' => 'D', 'Drama' => 'D',
'Tokusatsu' => 'T' 'Tokusatsu' => 'T'
) ]
) ]
)); ]];
private $filter = 'Releases'; private $filter = 'Releases';
public function collectData(){ public function collectData()
{
//Add type filter if provided //Add type filter if provided
$typeFilter = array_search( $typeFilter = array_search(
$this->getInput('type'), $this->getInput('type'),
@ -35,8 +36,7 @@ class AnimeUltimeBridge extends BridgeAbstract {
//Process each HTML page until having 10 releases //Process each HTML page until having 10 releases
$processedOK = 0; $processedOK = 0;
foreach (array($thismonth, $lastmonth) as $requestFilter) { foreach ([$thismonth, $lastmonth] as $requestFilter) {
$url = self::URI . 'history-0-1/' . $requestFilter; $url = self::URI . 'history-0-1/' . $requestFilter;
$html = getContents($url); $html = getContents($url);
// Convert html from iso-8859-1 => utf8 // Convert html from iso-8859-1 => utf8
@ -44,8 +44,7 @@ class AnimeUltimeBridge extends BridgeAbstract {
$html = str_get_html($html); $html = str_get_html($html);
//Relases are sorted by day : process each day individually //Relases are sorted by day : process each day individually
foreach($html->find('div.history', 0)->find('h3') as $daySection) { foreach ($html->find('div.history', 0)->find('h3') as $daySection) {
//Retrieve day and build date information //Retrieve day and build date information
$dateString = $daySection->plaintext; $dateString = $daySection->plaintext;
$day = intval(substr($dateString, strpos($dateString, ' ') + 1, 2)); $day = intval(substr($dateString, strpos($dateString, ' ') + 1, 2));
@ -59,9 +58,8 @@ class AnimeUltimeBridge extends BridgeAbstract {
$release = $daySection->next_sibling()->next_sibling()->first_child(); $release = $daySection->next_sibling()->next_sibling()->first_child();
//Process each release of that day, ignoring first table row: contains table headers //Process each release of that day, ignoring first table row: contains table headers
while(!is_null($release = $release->next_sibling())) { while (!is_null($release = $release->next_sibling())) {
if(count($release->find('td')) > 0) { if (count($release->find('td')) > 0) {
//Retrieve metadata from table columns //Retrieve metadata from table columns
$item_link_element = $release->find('td', 0)->find('a', 0); $item_link_element = $release->find('td', 0)->find('a', 0);
$item_uri = self::URI . $item_link_element->href; $item_uri = self::URI . $item_link_element->href;
@ -85,8 +83,7 @@ class AnimeUltimeBridge extends BridgeAbstract {
$item_fansub = $release->find('td', 2)->plaintext; $item_fansub = $release->find('td', 2)->plaintext;
$item_type = $release->find('td', 4)->plaintext; $item_type = $release->find('td', 4)->plaintext;
if(!empty($item_uri)) { if (!empty($item_uri)) {
// Retrieve description from description page // Retrieve description from description page
$html_item = getContents($item_uri); $html_item = getContents($item_uri);
// Convert html from iso-8859-1 => utf8 // Convert html from iso-8859-1 => utf8
@ -95,7 +92,8 @@ class AnimeUltimeBridge extends BridgeAbstract {
$html_item, $html_item,
strpos($html_item, 'class="principal_contain" align="center">') + 41 strpos($html_item, 'class="principal_contain" align="center">') + 41
); );
$item_description = substr($item_description, $item_description = substr(
$item_description,
0, 0,
strpos($item_description, '<div id="table">') strpos($item_description, '<div id="table">')
); );
@ -106,18 +104,18 @@ class AnimeUltimeBridge extends BridgeAbstract {
$item_description = str_replace("\n", '', $item_description); $item_description = str_replace("\n", '', $item_description);
//Build and add final item //Build and add final item
$item = array(); $item = [];
$item['uri'] = $item_uri; $item['uri'] = $item_uri;
$item['title'] = $item_name . ' ' . $item_type . ' ' . $item_episode; $item['title'] = $item_name . ' ' . $item_type . ' ' . $item_episode;
$item['author'] = $item_fansub; $item['author'] = $item_fansub;
$item['timestamp'] = $item_date; $item['timestamp'] = $item_date;
$item['enclosures'] = array($item_image); $item['enclosures'] = [$item_image];
$item['content'] = $item_description; $item['content'] = $item_description;
$this->items[] = $item; $this->items[] = $item;
$processedOK++; $processedOK++;
//Stop processing once limit is reached //Stop processing once limit is reached
if ($processedOK >= 10) if ($processedOK >= 10) {
return; return;
} }
} }
@ -125,9 +123,11 @@ class AnimeUltimeBridge extends BridgeAbstract {
} }
} }
} }
}
public function getName() { public function getName()
if(!is_null($this->getInput('type'))) { {
if (!is_null($this->getInput('type'))) {
$typeFilter = array_search( $typeFilter = array_search(
$this->getInput('type'), $this->getInput('type'),
self::PARAMETERS[$this->queriedContext]['type']['values'] self::PARAMETERS[$this->queriedContext]['type']['values']

View file

@ -1,23 +1,23 @@
<?php <?php
class AppleAppStoreBridge extends BridgeAbstract { class AppleAppStoreBridge extends BridgeAbstract
{
const MAINTAINER = 'captn3m0'; const MAINTAINER = 'captn3m0';
const NAME = 'Apple App Store'; const NAME = 'Apple App Store';
const URI = 'https://apps.apple.com/'; const URI = 'https://apps.apple.com/';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'Returns version updates for a specific application'; const DESCRIPTION = 'Returns version updates for a specific application';
const PARAMETERS = array(array( const PARAMETERS = [[
'id' => array( 'id' => [
'name' => 'Application ID', 'name' => 'Application ID',
'required' => true, 'required' => true,
'exampleValue' => '310633997' 'exampleValue' => '310633997'
), ],
'p' => array( 'p' => [
'name' => 'Platform', 'name' => 'Platform',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'iPad' => 'ipad', 'iPad' => 'ipad',
'iPhone' => 'iphone', 'iPhone' => 'iphone',
'Mac' => 'mac', 'Mac' => 'mac',
@ -26,36 +26,39 @@ class AppleAppStoreBridge extends BridgeAbstract {
// but not yet tested // but not yet tested
'Web' => 'web', 'Web' => 'web',
'Apple TV' => 'appletv', 'Apple TV' => 'appletv',
), ],
'defaultValue' => 'iphone', 'defaultValue' => 'iphone',
), ],
'country' => array( 'country' => [
'name' => 'Store Country', 'name' => 'Store Country',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'US' => 'US', 'US' => 'US',
'India' => 'IN', 'India' => 'IN',
'Canada' => 'CA', 'Canada' => 'CA',
'Germany' => 'DE', 'Germany' => 'DE',
), ],
'defaultValue' => 'US', 'defaultValue' => 'US',
), ],
)); ]];
const PLATFORM_MAPPING = array( const PLATFORM_MAPPING = [
'iphone' => 'ios', 'iphone' => 'ios',
'ipad' => 'ios', 'ipad' => 'ios',
); ];
private function makeHtmlUrl($id, $country){ private function makeHtmlUrl($id, $country)
{
return 'https://apps.apple.com/' . $country . '/app/id' . $id; return 'https://apps.apple.com/' . $country . '/app/id' . $id;
} }
private function makeJsonUrl($id, $platform, $country){ private function makeJsonUrl($id, $platform, $country)
{
return "https://amp-api.apps.apple.com/v1/catalog/$country/apps/$id?platform=$platform&extend=versionHistory"; return "https://amp-api.apps.apple.com/v1/catalog/$country/apps/$id?platform=$platform&extend=versionHistory";
} }
public function getName(){ public function getName()
{
if (isset($this->name)) { if (isset($this->name)) {
return $this->name . ' - AppStore Updates'; return $this->name . ' - AppStore Updates';
} }
@ -66,7 +69,8 @@ class AppleAppStoreBridge extends BridgeAbstract {
/** /**
* In case of some platforms, the data is present in the initial response * In case of some platforms, the data is present in the initial response
*/ */
private function getDataFromShoebox($id, $platform, $country){ private function getDataFromShoebox($id, $platform, $country)
{
$uri = $this->makeHtmlUrl($id, $country); $uri = $this->makeHtmlUrl($id, $country);
$html = getSimpleHTMLDOMCached($uri, 3600); $html = getSimpleHTMLDOMCached($uri, 3600);
$script = $html->find('script[id="shoebox-ember-data-store"]', 0); $script = $html->find('script[id="shoebox-ember-data-store"]', 0);
@ -75,7 +79,8 @@ class AppleAppStoreBridge extends BridgeAbstract {
return $json['data']; return $json['data'];
} }
private function getJWTToken($id, $platform, $country){ private function getJWTToken($id, $platform, $country)
{
$uri = $this->makeHtmlUrl($id, $country); $uri = $this->makeHtmlUrl($id, $country);
$html = getSimpleHTMLDOMCached($uri, 3600); $html = getSimpleHTMLDOMCached($uri, 3600);
@ -89,13 +94,14 @@ class AppleAppStoreBridge extends BridgeAbstract {
return $json->MEDIA_API->token; return $json->MEDIA_API->token;
} }
private function getAppData($id, $platform, $country, $token){ private function getAppData($id, $platform, $country, $token)
{
$uri = $this->makeJsonUrl($id, $platform, $country); $uri = $this->makeJsonUrl($id, $platform, $country);
$headers = array( $headers = [
"Authorization: Bearer $token", "Authorization: Bearer $token",
'Origin: https://apps.apple.com', 'Origin: https://apps.apple.com',
); ];
$json = json_decode(getContents($uri, $headers), true); $json = json_decode(getContents($uri, $headers), true);
@ -106,8 +112,9 @@ class AppleAppStoreBridge extends BridgeAbstract {
* Parses the version history from the data received * Parses the version history from the data received
* @return array list of versions with details on each element * @return array list of versions with details on each element
*/ */
private function getVersionHistory($data, $platform){ private function getVersionHistory($data, $platform)
switch($platform) { {
switch ($platform) {
case 'mac': case 'mac':
return $data['relationships']['platforms']['data'][0]['attributes']['versionHistory']; return $data['relationships']['platforms']['data'][0]['attributes']['versionHistory'];
default: default:
@ -116,7 +123,8 @@ class AppleAppStoreBridge extends BridgeAbstract {
} }
} }
public function collectData() { public function collectData()
{
$id = $this->getInput('id'); $id = $this->getInput('id');
$country = $this->getInput('country'); $country = $this->getInput('country');
$platform = $this->getInput('p'); $platform = $this->getInput('p');
@ -136,7 +144,7 @@ class AppleAppStoreBridge extends BridgeAbstract {
$author = $data['attributes']['artistName']; $author = $data['attributes']['artistName'];
foreach ($versionHistory as $row) { foreach ($versionHistory as $row) {
$item = array(); $item = [];
$item['content'] = nl2br($row['releaseNotes']); $item['content'] = nl2br($row['releaseNotes']);
$item['title'] = $name . ' - ' . $row['versionDisplay']; $item['title'] = $name . ' - ' . $row['versionDisplay'];

View file

@ -1,25 +1,27 @@
<?php <?php
class AppleMusicBridge extends BridgeAbstract { class AppleMusicBridge extends BridgeAbstract
{
const NAME = 'Apple Music'; const NAME = 'Apple Music';
const URI = 'https://www.apple.com'; const URI = 'https://www.apple.com';
const DESCRIPTION = 'Fetches the latest releases from an artist'; const DESCRIPTION = 'Fetches the latest releases from an artist';
const MAINTAINER = 'bockiii'; const MAINTAINER = 'bockiii';
const PARAMETERS = array(array( const PARAMETERS = [[
'artist' => array( 'artist' => [
'name' => 'Artist ID', 'name' => 'Artist ID',
'exampleValue' => '909253', 'exampleValue' => '909253',
'required' => true, 'required' => true,
), ],
'limit' => array( 'limit' => [
'name' => 'Latest X Releases (max 50)', 'name' => 'Latest X Releases (max 50)',
'defaultValue' => '10', 'defaultValue' => '10',
'required' => true, 'required' => true,
), ],
)); ]];
const CACHE_TIMEOUT = 21600; // 6 hours const CACHE_TIMEOUT = 21600; // 6 hours
public function collectData() { public function collectData()
{
# Limit the amount of releases to 50 # Limit the amount of releases to 50
if ($this->getInput('limit') > 50) { if ($this->getInput('limit') > 50) {
$limit = 50; $limit = 50;
@ -38,7 +40,7 @@ class AppleMusicBridge extends BridgeAbstract {
foreach ($json->results as $obj) { foreach ($json->results as $obj) {
if ($obj->wrapperType === 'collection') { if ($obj->wrapperType === 'collection') {
$this->items[] = array( $this->items[] = [
'title' => $obj->artistName . ' - ' . $obj->collectionName, 'title' => $obj->artistName . ' - ' . $obj->collectionName,
'uri' => $obj->collectionViewUrl, 'uri' => $obj->collectionViewUrl,
'timestamp' => $obj->releaseDate, 'timestamp' => $obj->releaseDate,
@ -48,7 +50,7 @@ class AppleMusicBridge extends BridgeAbstract {
. $obj->artistName . ' - ' . $obj->collectionName . $obj->artistName . ' - ' . $obj->collectionName
. '<br>' . '<br>'
. $obj->copyright, . $obj->copyright,
); ];
} }
} }
} }

View file

@ -1,65 +1,72 @@
<?php <?php
class ArtStationBridge extends BridgeAbstract {
class ArtStationBridge extends BridgeAbstract
{
const NAME = 'ArtStation'; const NAME = 'ArtStation';
const URI = 'https://www.artstation.com'; const URI = 'https://www.artstation.com';
const DESCRIPTION = 'Fetches the latest ten artworks from a search query on ArtStation.'; const DESCRIPTION = 'Fetches the latest ten artworks from a search query on ArtStation.';
const MAINTAINER = 'thefranke'; const MAINTAINER = 'thefranke';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const PARAMETERS = array( const PARAMETERS = [
'Search Query' => array( 'Search Query' => [
'q' => array( 'q' => [
'name' => 'Search term', 'name' => 'Search term',
'required' => true, 'required' => true,
'exampleValue' => 'bird' 'exampleValue' => 'bird'
) ]
) ]
); ];
public function getIcon() { public function getIcon()
{
return 'https://www.artstation.com/assets/favicon-58653022bc38c1905ac7aa1b10bffa6b.ico'; return 'https://www.artstation.com/assets/favicon-58653022bc38c1905ac7aa1b10bffa6b.ico';
} }
public function getName() { public function getName()
{
return self::NAME . ': ' . $this->getInput('q'); return self::NAME . ': ' . $this->getInput('q');
} }
private function fetchSearch($searchQuery) { private function fetchSearch($searchQuery)
{
$data = '{"query":"' . $searchQuery . '","page":1,"per_page":50,"sorting":"date",'; $data = '{"query":"' . $searchQuery . '","page":1,"per_page":50,"sorting":"date",';
$data .= '"pro_first":"1","filters":[],"additional_fields":[]}'; $data .= '"pro_first":"1","filters":[],"additional_fields":[]}';
$header = array( $header = [
'Content-Type: application/json', 'Content-Type: application/json',
'Accept: application/json' 'Accept: application/json'
); ];
$opts = array( $opts = [
CURLOPT_POST => true, CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data, CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true CURLOPT_RETURNTRANSFER => true
); ];
$jsonSearchURL = self::URI . '/api/v2/search/projects.json'; $jsonSearchURL = self::URI . '/api/v2/search/projects.json';
$jsonSearchStr = getContents($jsonSearchURL, $header, $opts); $jsonSearchStr = getContents($jsonSearchURL, $header, $opts);
return json_decode($jsonSearchStr); return json_decode($jsonSearchStr);
} }
private function fetchProject($hashID) { private function fetchProject($hashID)
{
$jsonProjectURL = self::URI . '/projects/' . $hashID . '.json'; $jsonProjectURL = self::URI . '/projects/' . $hashID . '.json';
$jsonProjectStr = getContents($jsonProjectURL); $jsonProjectStr = getContents($jsonProjectURL);
return json_decode($jsonProjectStr); return json_decode($jsonProjectStr);
} }
public function collectData() { public function collectData()
{
$searchTerm = $this->getInput('q'); $searchTerm = $this->getInput('q');
$jsonQuery = $this->fetchSearch($searchTerm); $jsonQuery = $this->fetchSearch($searchTerm);
foreach($jsonQuery->data as $media) { foreach ($jsonQuery->data as $media) {
// get detailed info about media item // get detailed info about media item
$jsonProject = $this->fetchProject($media->hash_id); $jsonProject = $this->fetchProject($media->hash_id);
// create item // create item
$item = array(); $item = [];
$item['title'] = $media->title; $item['title'] = $media->title;
$item['uri'] = $media->url; $item['uri'] = $media->url;
$item['timestamp'] = strtotime($jsonProject->published_at); $item['timestamp'] = strtotime($jsonProject->published_at);
@ -76,17 +83,19 @@ class ArtStationBridge extends BridgeAbstract {
$numAssets = count($jsonProject->assets); $numAssets = count($jsonProject->assets);
if ($numAssets > 1) if ($numAssets > 1) {
$item['content'] .= '<p><a href="' $item['content'] .= '<p><a href="'
. $media->url . $media->url
. '">Project contains ' . '">Project contains '
. ($numAssets - 1) . ($numAssets - 1)
. ' more item(s).</a></p>'; . ' more item(s).</a></p>';
}
$this->items[] = $item; $this->items[] = $item;
if (count($this->items) >= 10) if (count($this->items) >= 10) {
break; break;
} }
} }
}
} }

View file

@ -1,6 +1,7 @@
<?php <?php
class Arte7Bridge extends BridgeAbstract {
class Arte7Bridge extends BridgeAbstract
{
const NAME = 'Arte +7'; const NAME = 'Arte +7';
const URI = 'https://www.arte.tv/'; const URI = 'https://www.arte.tv/';
const MAINTAINER = 'imagoiq'; const MAINTAINER = 'imagoiq';
@ -9,14 +10,14 @@ class Arte7Bridge extends BridgeAbstract {
const API_TOKEN = 'Nzc1Yjc1ZjJkYjk1NWFhN2I2MWEwMmRlMzAzNjI5NmU3NWU3ODg4ODJjOWMxNTMxYzEzZGRjYjg2ZGE4MmIwOA'; const API_TOKEN = 'Nzc1Yjc1ZjJkYjk1NWFhN2I2MWEwMmRlMzAzNjI5NmU3NWU3ODg4ODJjOWMxNTMxYzEzZGRjYjg2ZGE4MmIwOA';
const PARAMETERS = array( const PARAMETERS = [
'global' => [ 'global' => [
'sort_by' => array( 'sort_by' => [
'type' => 'list', 'type' => 'list',
'name' => 'Sort by', 'name' => 'Sort by',
'required' => false, 'required' => false,
'defaultValue' => null, 'defaultValue' => null,
'values' => array( 'values' => [
'Default' => null, 'Default' => null,
'Video rights start date' => 'videoRightsBegin', 'Video rights start date' => 'videoRightsBegin',
'Video rights end date' => 'videoRightsEnd', 'Video rights end date' => 'videoRightsEnd',
@ -27,18 +28,18 @@ class Arte7Bridge extends BridgeAbstract {
'Number of views per period' => 'viewsPeriod', 'Number of views per period' => 'viewsPeriod',
'Available screens' => 'availableScreens', 'Available screens' => 'availableScreens',
'Episode' => 'episode' 'Episode' => 'episode'
), ],
), ],
'sort_direction' => array( 'sort_direction' => [
'type' => 'list', 'type' => 'list',
'name' => 'Sort direction', 'name' => 'Sort direction',
'required' => false, 'required' => false,
'defaultValue' => 'DESC', 'defaultValue' => 'DESC',
'values' => array( 'values' => [
'Ascending' => 'ASC', 'Ascending' => 'ASC',
'Descending' => 'DESC' 'Descending' => 'DESC'
), ],
), ],
'exclude_trailers' => [ 'exclude_trailers' => [
'name' => 'Exclude trailers', 'name' => 'Exclude trailers',
'type' => 'checkbox', 'type' => 'checkbox',
@ -46,23 +47,23 @@ class Arte7Bridge extends BridgeAbstract {
'defaultValue' => false 'defaultValue' => false
], ],
], ],
'Category' => array( 'Category' => [
'lang' => array( 'lang' => [
'type' => 'list', 'type' => 'list',
'name' => 'Language', 'name' => 'Language',
'values' => array( 'values' => [
'Français' => 'fr', 'Français' => 'fr',
'Deutsch' => 'de', 'Deutsch' => 'de',
'English' => 'en', 'English' => 'en',
'Español' => 'es', 'Español' => 'es',
'Polski' => 'pl', 'Polski' => 'pl',
'Italiano' => 'it' 'Italiano' => 'it'
), ],
), ],
'cat' => array( 'cat' => [
'type' => 'list', 'type' => 'list',
'name' => 'Category', 'name' => 'Category',
'values' => array( 'values' => [
'All videos' => null, 'All videos' => null,
'News & society' => 'ACT', 'News & society' => 'ACT',
'Series & fiction' => 'SER', 'Series & fiction' => 'SER',
@ -73,33 +74,34 @@ class Arte7Bridge extends BridgeAbstract {
'History' => 'HIST', 'History' => 'HIST',
'Science' => 'SCI', 'Science' => 'SCI',
'Other' => 'AUT' 'Other' => 'AUT'
) ]
), ],
), ],
'Collection' => array( 'Collection' => [
'lang' => array( 'lang' => [
'type' => 'list', 'type' => 'list',
'name' => 'Language', 'name' => 'Language',
'values' => array( 'values' => [
'Français' => 'fr', 'Français' => 'fr',
'Deutsch' => 'de', 'Deutsch' => 'de',
'English' => 'en', 'English' => 'en',
'Español' => 'es', 'Español' => 'es',
'Polski' => 'pl', 'Polski' => 'pl',
'Italiano' => 'it' 'Italiano' => 'it'
) ]
), ],
'col' => array( 'col' => [
'name' => 'Collection id', 'name' => 'Collection id',
'required' => true, 'required' => true,
'title' => 'ex. RC-014095 pour https://www.arte.tv/de/videos/RC-014095/blow-up/', 'title' => 'ex. RC-014095 pour https://www.arte.tv/de/videos/RC-014095/blow-up/',
'exampleValue' => 'RC-014095' 'exampleValue' => 'RC-014095'
) ]
) ]
); ];
public function collectData(){ public function collectData()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Category': case 'Category':
$category = $this->getInput('cat'); $category = $this->getInput('cat');
$collectionId = null; $collectionId = null;
@ -120,29 +122,30 @@ class Arte7Bridge extends BridgeAbstract {
. ($category != null ? '&category.code=' . $category : '') . ($category != null ? '&category.code=' . $category : '')
. ($collectionId != null ? '&collections.collectionId=' . $collectionId : ''); . ($collectionId != null ? '&collections.collectionId=' . $collectionId : '');
$header = array( $header = [
'Authorization: Bearer ' . self::API_TOKEN 'Authorization: Bearer ' . self::API_TOKEN
); ];
$input = getContents($url, $header); $input = getContents($url, $header);
$input_json = json_decode($input, true); $input_json = json_decode($input, true);
foreach($input_json['videos'] as $element) { foreach ($input_json['videos'] as $element) {
if($this->getInput('exclude_trailers') && $element['platform'] == 'EXTRAIT') { if ($this->getInput('exclude_trailers') && $element['platform'] == 'EXTRAIT') {
continue; continue;
} }
$durationSeconds = $element['durationSeconds']; $durationSeconds = $element['durationSeconds'];
$item = array(); $item = [];
$item['uri'] = $element['url']; $item['uri'] = $element['url'];
$item['id'] = $element['id']; $item['id'] = $element['id'];
$item['timestamp'] = strtotime($element['videoRightsBegin']); $item['timestamp'] = strtotime($element['videoRightsBegin']);
$item['title'] = $element['title']; $item['title'] = $element['title'];
if(!empty($element['subtitle'])) if (!empty($element['subtitle'])) {
$item['title'] = $element['title'] . ' | ' . $element['subtitle']; $item['title'] = $element['title'] . ' | ' . $element['subtitle'];
}
$durationMinutes = round((int)$durationSeconds / 60); $durationMinutes = round((int)$durationSeconds / 60);
$item['content'] = $element['teaserText'] $item['content'] = $element['teaserText']

View file

@ -1,16 +1,18 @@
<?php <?php
class AsahiShimbunAJWBridge extends BridgeAbstract {
class AsahiShimbunAJWBridge extends BridgeAbstract
{
const NAME = 'Asahi Shimbun AJW'; const NAME = 'Asahi Shimbun AJW';
const BASE_URI = 'http://www.asahi.com'; const BASE_URI = 'http://www.asahi.com';
const URI = self::BASE_URI . '/ajw/'; const URI = self::BASE_URI . '/ajw/';
const DESCRIPTION = 'Asahi Shimbun - Asia & Japan Watch'; const DESCRIPTION = 'Asahi Shimbun - Asia & Japan Watch';
const MAINTAINER = 'somini'; const MAINTAINER = 'somini';
const PARAMETERS = array( const PARAMETERS = [
array( [
'section' => array( 'section' => [
'type' => 'list', 'type' => 'list',
'name' => 'Section', 'name' => 'Section',
'values' => array( 'values' => [
'Japan » Social Affairs' => 'japan/social', 'Japan » Social Affairs' => 'japan/social',
'Japan » People' => 'japan/people', 'Japan » People' => 'japan/people',
'Japan » 3/11 Disaster' => 'japan/0311disaster', 'Japan » 3/11 Disaster' => 'japan/0311disaster',
@ -26,25 +28,27 @@ class AsahiShimbunAJWBridge extends BridgeAbstract {
'Asia » World' => 'asia_world/world', 'Asia » World' => 'asia_world/world',
'Opinion » Editorial' => 'opinion/editorial', 'Opinion » Editorial' => 'opinion/editorial',
'Opinion » Vox Populi' => 'opinion/vox', 'Opinion » Vox Populi' => 'opinion/vox',
), ],
'defaultValue' => 'politics', 'defaultValue' => 'politics',
) ]
) ]
); ];
private function getSectionURI($section) { private function getSectionURI($section)
{
return self::getURI() . $section . '/'; return self::getURI() . $section . '/';
} }
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getSectionURI($this->getInput('section'))); $html = getSimpleHTMLDOM($this->getSectionURI($this->getInput('section')));
foreach($html->find('#MainInner li a') as $element) { foreach ($html->find('#MainInner li a') as $element) {
if ($element->parent()->class == 'HeadlineTopImage-S') { if ($element->parent()->class == 'HeadlineTopImage-S') {
Debug::log('Skip Headline, it is repeated below'); Debug::log('Skip Headline, it is repeated below');
continue; continue;
} }
$item = array(); $item = [];
$item['uri'] = self::BASE_URI . $element->href; $item['uri'] = self::BASE_URI . $element->href;
$e_lead = $element->find('span.Lead', 0); $e_lead = $element->find('span.Lead', 0);

View file

@ -1,33 +1,36 @@
<?php <?php
class AskfmBridge extends BridgeAbstract {
class AskfmBridge extends BridgeAbstract
{
const MAINTAINER = 'az5he6ch, logmanoriginal'; const MAINTAINER = 'az5he6ch, logmanoriginal';
const NAME = 'Ask.fm Answers'; const NAME = 'Ask.fm Answers';
const URI = 'https://ask.fm/'; const URI = 'https://ask.fm/';
const CACHE_TIMEOUT = 300; //5 min const CACHE_TIMEOUT = 300; //5 min
const DESCRIPTION = 'Returns answers from an Ask.fm user'; const DESCRIPTION = 'Returns answers from an Ask.fm user';
const PARAMETERS = array( const PARAMETERS = [
'Ask.fm username' => array( 'Ask.fm username' => [
'u' => array( 'u' => [
'name' => 'Username', 'name' => 'Username',
'required' => true, 'required' => true,
'exampleValue' => 'ApprovedAndReal' 'exampleValue' => 'ApprovedAndReal'
) ]
) ]
); ];
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
$html = defaultLinkTo($html, self::URI); $html = defaultLinkTo($html, self::URI);
foreach($html->find('article.streamItem-answer') as $element) { foreach ($html->find('article.streamItem-answer') as $element) {
$item = array(); $item = [];
$item['uri'] = $element->find('a.streamItem_meta', 0)->href; $item['uri'] = $element->find('a.streamItem_meta', 0)->href;
$question = trim($element->find('header.streamItem_header', 0)->innertext); $question = trim($element->find('header.streamItem_header', 0)->innertext);
$item['title'] = trim( $item['title'] = trim(
htmlspecialchars_decode($element->find('header.streamItem_header', 0)->plaintext, htmlspecialchars_decode(
$element->find('header.streamItem_header', 0)->plaintext,
ENT_QUOTES ENT_QUOTES
) )
); );
@ -37,13 +40,13 @@ class AskfmBridge extends BridgeAbstract {
$answer = trim($element->find('div.streamItem_content', 0)->innertext); $answer = trim($element->find('div.streamItem_content', 0)->innertext);
// This probably should be cleaned up, especially for YouTube embeds // This probably should be cleaned up, especially for YouTube embeds
if($visual = $element->find('div.streamItem_visual', 0)) { if ($visual = $element->find('div.streamItem_visual', 0)) {
$visual = $visual->innertext; $visual = $visual->innertext;
} }
// Fix tracking links, also doesn't work // Fix tracking links, also doesn't work
foreach($element->find('a') as $link) { foreach ($element->find('a') as $link) {
if(strpos($link->href, 'l.ask.fm') !== false) { if (strpos($link->href, 'l.ask.fm') !== false) {
$link->href = $link->plaintext; $link->href = $link->plaintext;
} }
} }
@ -56,16 +59,18 @@ class AskfmBridge extends BridgeAbstract {
} }
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('u'))) { {
if (!is_null($this->getInput('u'))) {
return self::NAME . ' : ' . $this->getInput('u'); return self::NAME . ' : ' . $this->getInput('u');
} }
return parent::getName(); return parent::getName();
} }
public function getURI(){ public function getURI()
if(!is_null($this->getInput('u'))) { {
if (!is_null($this->getInput('u'))) {
return self::URI . urlencode($this->getInput('u')); return self::URI . urlencode($this->getInput('u'));
} }

View file

@ -1,15 +1,17 @@
<?php <?php
class AssociatedPressNewsBridge extends BridgeAbstract {
class AssociatedPressNewsBridge extends BridgeAbstract
{
const NAME = 'Associated Press News Bridge'; const NAME = 'Associated Press News Bridge';
const URI = 'https://apnews.com/'; const URI = 'https://apnews.com/';
const DESCRIPTION = 'Returns newest articles by topic'; const DESCRIPTION = 'Returns newest articles by topic';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array( const PARAMETERS = [
'Standard Topics' => array( 'Standard Topics' => [
'topic' => array( 'topic' => [
'name' => 'Topic', 'name' => 'Topic',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'AP Top News' => 'apf-topnews', 'AP Top News' => 'apf-topnews',
'Sports' => 'apf-sports', 'Sports' => 'apf-sports',
'Entertainment' => 'apf-entertainment', 'Entertainment' => 'apf-entertainment',
@ -27,19 +29,19 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
'Photo Galleries' => 'PhotoGalleries', 'Photo Galleries' => 'PhotoGalleries',
'Fact Checks' => 'APFactCheck', 'Fact Checks' => 'APFactCheck',
'Videos' => 'apf-videos', 'Videos' => 'apf-videos',
), ],
'defaultValue' => 'apf-topnews', 'defaultValue' => 'apf-topnews',
), ],
), ],
'Custom Topic' => array( 'Custom Topic' => [
'topic' => array( 'topic' => [
'name' => 'Topic', 'name' => 'Topic',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'europe' 'exampleValue' => 'europe'
), ],
) ]
); ];
const CACHE_TIMEOUT = 900; // 15 mins const CACHE_TIMEOUT = 900; // 15 mins
@ -47,10 +49,11 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
private $tagEndpoint = 'https://afs-prod.appspot.com/api/v2/feed/tag?tags='; private $tagEndpoint = 'https://afs-prod.appspot.com/api/v2/feed/tag?tags=';
private $feedName = ''; private $feedName = '';
public function detectParameters($url) { public function detectParameters($url)
$params = array(); {
$params = [];
if(preg_match($this->detectParamRegex, $url, $matches) > 0) { if (preg_match($this->detectParamRegex, $url, $matches) > 0) {
$params['topic'] = $matches[1]; $params['topic'] = $matches[1];
$params['context'] = 'Custom Topic'; $params['context'] = 'Custom Topic';
return $params; return $params;
@ -59,8 +62,9 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
return null; return null;
} }
public function collectData() { public function collectData()
switch($this->getInput('topic')) { {
switch ($this->getInput('topic')) {
case 'Podcasts': case 'Podcasts':
returnClientError('Podcasts topic feed is not supported'); returnClientError('Podcasts topic feed is not supported');
break; break;
@ -72,7 +76,8 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
} }
} }
public function getURI() { public function getURI()
{
if (!is_null($this->getInput('topic'))) { if (!is_null($this->getInput('topic'))) {
return self::URI . $this->getInput('topic'); return self::URI . $this->getInput('topic');
} }
@ -80,7 +85,8 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
public function getName() { public function getName()
{
if (!empty($this->feedName)) { if (!empty($this->feedName)) {
return $this->feedName . ' - Associated Press'; return $this->feedName . ' - Associated Press';
} }
@ -88,7 +94,8 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
return parent::getName(); return parent::getName();
} }
private function getTagURI() { private function getTagURI()
{
if (!is_null($this->getInput('topic'))) { if (!is_null($this->getInput('topic'))) {
return $this->tagEndpoint . $this->getInput('topic'); return $this->tagEndpoint . $this->getInput('topic');
} }
@ -96,7 +103,8 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
private function collectCardData() { private function collectCardData()
{
$json = getContents($this->getTagURI()) $json = getContents($this->getTagURI())
or returnServerError('Could not request: ' . $this->getTagURI()); or returnServerError('Could not request: ' . $this->getTagURI());
@ -109,7 +117,7 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
$this->feedName = $tagContents['tagObjs'][0]['name']; $this->feedName = $tagContents['tagObjs'][0]['name'];
foreach ($tagContents['cards'] as $card) { foreach ($tagContents['cards'] as $card) {
$item = array(); $item = [];
// skip hub peeks & Notifications // skip hub peeks & Notifications
if ($card['cardType'] == 'Hub Peek' || $card['cardType'] == 'Notification') { if ($card['cardType'] == 'Hub Peek' || $card['cardType'] == 'Notification') {
@ -118,7 +126,7 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
$storyContent = $card['contents'][0]; $storyContent = $card['contents'][0];
switch($storyContent['contentType']) { switch ($storyContent['contentType']) {
case 'web': // Skip link only content case 'web': // Skip link only content
continue 2; continue 2;
@ -178,8 +186,8 @@ class AssociatedPressNewsBridge extends BridgeAbstract {
} }
} }
private function processMediaPlaceholders($html, $id) { private function processMediaPlaceholders($html, $id)
{
if ($html->find('div.media-placeholder', 0)) { if ($html->find('div.media-placeholder', 0)) {
// Fetch page content // Fetch page content
$json = getContents('https://afs-prod.appspot.com/api/v2/content/' . $id); $json = getContents('https://afs-prod.appspot.com/api/v2/content/' . $id);
@ -216,11 +224,10 @@ EOD;
/* /*
Create full coverage links (HubLinks) Create full coverage links (HubLinks)
*/ */
private function processHubLinks($html, $storyContent) { private function processHubLinks($html, $storyContent)
{
if (!empty($storyContent['richEmbeds'])) { if (!empty($storyContent['richEmbeds'])) {
foreach ($storyContent['richEmbeds'] as $embed) { foreach ($storyContent['richEmbeds'] as $embed) {
if ($embed['type'] === 'Hub Link') { if ($embed['type'] === 'Hub Link') {
$url = self::URI . $embed['tag']['id']; $url = self::URI . $embed['tag']['id'];
$div = $html->find('div[id=' . $embed['id'] . ']', 0); $div = $html->find('div[id=' . $embed['id'] . ']', 0);
@ -235,7 +242,8 @@ EOD;
} }
} }
private function processVideo($storyContent) { private function processVideo($storyContent)
{
$video = $storyContent['media'][0]; $video = $storyContent['media'][0];
if ($video['type'] === 'YouTube') { if ($video['type'] === 'YouTube') {
@ -255,8 +263,8 @@ EOD;
} }
// Remove datawrapper.dwcdn.net iframes and related javaScript // Remove datawrapper.dwcdn.net iframes and related javaScript
private function processIframes($html) { private function processIframes($html)
{
foreach ($html->find('iframe') as $index => $iframe) { foreach ($html->find('iframe') as $index => $iframe) {
if (preg_match('/datawrapper\.dwcdn\.net/', $iframe->src)) { if (preg_match('/datawrapper\.dwcdn\.net/', $iframe->src)) {
$iframe->outertext = ''; $iframe->outertext = '';

View file

@ -1,42 +1,47 @@
<?php <?php
class AstrophysicsDataSystemBridge extends BridgeAbstract {
class AstrophysicsDataSystemBridge extends BridgeAbstract
{
const NAME = 'SAO/NASA Astrophysics Data System'; const NAME = 'SAO/NASA Astrophysics Data System';
const DESCRIPTION = 'Returns the latest publications from a query'; const DESCRIPTION = 'Returns the latest publications from a query';
const URI = 'https://ui.adsabs.harvard.edu'; const URI = 'https://ui.adsabs.harvard.edu';
const PARAMETERS = array( const PARAMETERS = [
'Publications' => array( 'Publications' => [
'query' => array( 'query' => [
'name' => 'query', 'name' => 'query',
'title' => 'Same format as the search bar on the website', 'title' => 'Same format as the search bar on the website',
'exampleValue' => 'author:"huchra, john"', 'exampleValue' => 'author:"huchra, john"',
'required' => true 'required' => true
) ]
)); ]];
private $feedTitle; private $feedTitle;
public function getName() { public function getName()
{
if ($this->queriedContext === 'Publications') { if ($this->queriedContext === 'Publications') {
return $this->feedTitle; return $this->feedTitle;
} }
return parent::getName(); return parent::getName();
} }
public function getURI() { public function getURI()
{
if ($this->queriedContext === 'Publications') { if ($this->queriedContext === 'Publications') {
return self::URI . '/search/?q=' . urlencode($this->getInput('query')); return self::URI . '/search/?q=' . urlencode($this->getInput('query'));
} }
return parent::getURI(); return parent::getURI();
} }
public function collectData() { public function collectData()
$headers = array ( {
$headers = [
'Cookie: core=always;' 'Cookie: core=always;'
); ];
$html = str_get_html(defaultLinkTo(getContents($this->getURI(), $headers), self::URI)); $html = str_get_html(defaultLinkTo(getContents($this->getURI(), $headers), self::URI));
$this->feedTitle = html_entity_decode($html->find('title', 0)->plaintext); $this->feedTitle = html_entity_decode($html->find('title', 0)->plaintext);
foreach($html->find('div.row > ul > li') as $pub) { foreach ($html->find('div.row > ul > li') as $pub) {
$item = array(); $item = [];
$item['title'] = $pub->find('h3.s-results-title', 0)->plaintext; $item['title'] = $pub->find('h3.s-results-title', 0)->plaintext;
$item['content'] = $pub->find('div.s-results-links', 0); $item['content'] = $pub->find('div.s-results-links', 0);
$item['uri'] = $pub->find('a.abs-redirect-link', 0)->href; $item['uri'] = $pub->find('a.abs-redirect-link', 0)->href;

View file

@ -1,22 +1,24 @@
<?php <?php
class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
class AtmoNouvelleAquitaineBridge extends BridgeAbstract
{
const NAME = 'Atmo Nouvelle Aquitaine'; const NAME = 'Atmo Nouvelle Aquitaine';
const URI = 'https://www.atmo-nouvelleaquitaine.org'; const URI = 'https://www.atmo-nouvelleaquitaine.org';
const DESCRIPTION = 'Fetches the latest air polution of cities in Nouvelle Aquitaine from Atmo'; const DESCRIPTION = 'Fetches the latest air polution of cities in Nouvelle Aquitaine from Atmo';
const MAINTAINER = 'floviolleau'; const MAINTAINER = 'floviolleau';
const PARAMETERS = array(array( const PARAMETERS = [[
'cities' => array( 'cities' => [
'name' => 'Choisir une ville', 'name' => 'Choisir une ville',
'type' => 'list', 'type' => 'list',
'values' => self::CITIES 'values' => self::CITIES
) ]
)); ]];
const CACHE_TIMEOUT = 7200; const CACHE_TIMEOUT = 7200;
private $dom; private $dom;
private function getClosest($search, $arr) { private function getClosest($search, $arr)
{
$closest = null; $closest = null;
foreach ($arr as $key => $value) { foreach ($arr as $key => $value) {
if ($closest === null || abs((int)$search - $closest) > abs((int)$key - (int)$search)) { if ($closest === null || abs((int)$search - $closest) > abs((int)$key - (int)$search)) {
@ -26,7 +28,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return $arr[$closest]; return $arr[$closest];
} }
public function collectData() { public function collectData()
{
$uri = self::URI . '/monair/commune/' . $this->getInput('cities'); $uri = self::URI . '/monair/commune/' . $this->getInput('cities');
$html = getSimpleHTMLDOM($uri); $html = getSimpleHTMLDOM($uri);
@ -47,7 +50,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
} }
private function getIndex() { private function getIndex()
{
$index = $this->dom->find('.indice', 0)->innertext; $index = $this->dom->find('.indice', 0)->innertext;
if ($index == 'XX') { if ($index == 'XX') {
@ -57,12 +61,14 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return $index; return $index;
} }
private function getMaxIndexText() { private function getMaxIndexText()
{
// will return '/100' // will return '/100'
return $this->dom->find('.pourcent', 0)->innertext; return $this->dom->find('.pourcent', 0)->innertext;
} }
private function getQualityText($index, $indexes) { private function getQualityText($index, $indexes)
{
if ($index == -1) { if ($index == -1) {
if (array_key_exists('no-available', $indexes)) { if (array_key_exists('no-available', $indexes)) {
return $indexes['no-available']; return $indexes['no-available'];
@ -74,9 +80,10 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return $this->getClosest($index, $indexes); return $this->getClosest($index, $indexes);
} }
private function getLegendIndexes() { private function getLegendIndexes()
{
$rawIndexes = $this->dom->find('.prevision-legend .prevision-legend-label'); $rawIndexes = $this->dom->find('.prevision-legend .prevision-legend-label');
$indexes = array(); $indexes = [];
for ($i = 0; $i < count($rawIndexes); $i++) { for ($i = 0; $i < count($rawIndexes); $i++) {
if ($rawIndexes[$i]->hasAttribute('data-color')) { if ($rawIndexes[$i]->hasAttribute('data-color')) {
$indexes[$rawIndexes[$i]->getAttribute('data-color')] = $rawIndexes[$i]->innertext; $indexes[$rawIndexes[$i]->getAttribute('data-color')] = $rawIndexes[$i]->innertext;
@ -86,7 +93,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return $indexes; return $indexes;
} }
private function getTomorrowTrendIndex() { private function getTomorrowTrendIndex()
{
$tomorrowTrendDomNode = $this->dom $tomorrowTrendDomNode = $this->dom
->find('.day-controls.raster-controls .list-raster-controls .raster-control', 2); ->find('.day-controls.raster-controls .list-raster-controls .raster-control', 2);
$tomorrowTrendIndexNode = null; $tomorrowTrendIndexNode = null;
@ -104,7 +112,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return $tomorrowTrendIndex; return $tomorrowTrendIndex;
} }
private function getTomorrowTrendQualityText($trendIndex, $indexes) { private function getTomorrowTrendQualityText($trendIndex, $indexes)
{
if ($trendIndex == -1) { if ($trendIndex == -1) {
if (array_key_exists('no-available', $indexes)) { if (array_key_exists('no-available', $indexes)) {
return $indexes['no-available']; return $indexes['no-available'];
@ -116,7 +125,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return $this->getClosest($trendIndex, $indexes); return $this->getClosest($trendIndex, $indexes);
} }
private function getIndexMessage() { private function getIndexMessage()
{
$index = $this->getIndex(); $index = $this->getIndex();
$maxIndexText = $this->getMaxIndexText(); $maxIndexText = $this->getMaxIndexText();
@ -127,7 +137,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return "L'indice d'aujourd'hui est $index$maxIndexText."; return "L'indice d'aujourd'hui est $index$maxIndexText.";
} }
private function getQualityMessage() { private function getQualityMessage()
{
$index = $index = $this->getIndex(); $index = $index = $this->getIndex();
$indexes = $this->getLegendIndexes(); $indexes = $this->getLegendIndexes();
$quality = $this->getQualityText($index, $indexes); $quality = $this->getQualityText($index, $indexes);
@ -139,7 +150,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return "La qualité de l'air est $quality."; return "La qualité de l'air est $quality.";
} }
private function getTomorrowTrendIndexMessage() { private function getTomorrowTrendIndexMessage()
{
$trendIndex = $this->getTomorrowTrendIndex(); $trendIndex = $this->getTomorrowTrendIndex();
$maxIndexText = $this->getMaxIndexText(); $maxIndexText = $this->getMaxIndexText();
@ -150,7 +162,8 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return "L'indice prévu pour demain est $trendIndex$maxIndexText."; return "L'indice prévu pour demain est $trendIndex$maxIndexText.";
} }
private function getTomorrowTrendQualityMessage() { private function getTomorrowTrendQualityMessage()
{
$trendIndex = $this->getTomorrowTrendIndex(); $trendIndex = $this->getTomorrowTrendIndex();
$indexes = $this->getLegendIndexes(); $indexes = $this->getLegendIndexes();
$trendQuality = $this->getTomorrowTrendQualityText($trendIndex, $indexes); $trendQuality = $this->getTomorrowTrendQualityText($trendIndex, $indexes);
@ -161,7 +174,7 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
return "La qualite de l'air pour demain sera $trendQuality."; return "La qualite de l'air pour demain sera $trendQuality.";
} }
const CITIES = array( const CITIES = [
'Aast (64460)' => '64001', 'Aast (64460)' => '64001',
'Abère (64160)' => '64002', 'Abère (64160)' => '64002',
'Abidos (64150)' => '64003', 'Abidos (64150)' => '64003',
@ -4633,5 +4646,5 @@ class AtmoNouvelleAquitaineBridge extends BridgeAbstract {
'Yvrac (33370)' => '33554', 'Yvrac (33370)' => '33554',
'Yvrac-et-Malleyrand (16110)' => '16425', 'Yvrac-et-Malleyrand (16110)' => '16425',
'Yzosse (40180)' => '40334' 'Yzosse (40180)' => '40334'
); ];
} }

View file

@ -1,20 +1,22 @@
<?php <?php
class AtmoOccitanieBridge extends BridgeAbstract {
class AtmoOccitanieBridge extends BridgeAbstract
{
const NAME = 'Atmo Occitanie'; const NAME = 'Atmo Occitanie';
const URI = 'https://www.atmo-occitanie.org/'; const URI = 'https://www.atmo-occitanie.org/';
const DESCRIPTION = 'Fetches the latest air polution of cities in Occitanie from Atmo'; const DESCRIPTION = 'Fetches the latest air polution of cities in Occitanie from Atmo';
const MAINTAINER = 'floviolleau'; const MAINTAINER = 'floviolleau';
const PARAMETERS = array(array( const PARAMETERS = [[
'city' => array( 'city' => [
'name' => 'Ville', 'name' => 'Ville',
'required' => true, 'required' => true,
'exampleValue' => 'cahors' 'exampleValue' => 'cahors'
) ]
)); ]];
const CACHE_TIMEOUT = 7200; const CACHE_TIMEOUT = 7200;
public function collectData() { public function collectData()
{
$uri = self::URI . $this->getInput('city'); $uri = self::URI . $this->getInput('city');
$html = getSimpleHTMLDOM($uri); $html = getSimpleHTMLDOM($uri);

View file

@ -1,48 +1,49 @@
<?php <?php
class AutoJMBridge extends BridgeAbstract { class AutoJMBridge extends BridgeAbstract
{
const NAME = 'AutoJM'; const NAME = 'AutoJM';
const URI = 'https://www.autojm.fr/'; const URI = 'https://www.autojm.fr/';
const DESCRIPTION = 'Suivre les offres de véhicules proposés par AutoJM en fonction des critères de filtrages'; const DESCRIPTION = 'Suivre les offres de véhicules proposés par AutoJM en fonction des critères de filtrages';
const MAINTAINER = 'sysadminstory'; const MAINTAINER = 'sysadminstory';
const PARAMETERS = array( const PARAMETERS = [
'Afficher les offres de véhicules disponible sur la recheche AutoJM' => array( 'Afficher les offres de véhicules disponible sur la recheche AutoJM' => [
'url' => array( 'url' => [
'name' => 'URL de la page de recherche', 'name' => 'URL de la page de recherche',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'title' => 'URL d\'une recherche avec filtre de véhicules sans le http://www.autojm.fr/', 'title' => 'URL d\'une recherche avec filtre de véhicules sans le http://www.autojm.fr/',
'exampleValue' => 'recherche?brands[]=peugeot&ranges[]=peugeot-nouvelle-308-2021-5p' 'exampleValue' => 'recherche?brands[]=peugeot&ranges[]=peugeot-nouvelle-308-2021-5p'
), ],
) ]
); ];
const CACHE_TIMEOUT = 3600; const CACHE_TIMEOUT = 3600;
public function getIcon() { public function getIcon()
{
return self::URI . 'favicon.ico'; return self::URI . 'favicon.ico';
} }
public function getName() { public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Afficher les offres de véhicules disponible sur la recheche AutoJM': case 'Afficher les offres de véhicules disponible sur la recheche AutoJM':
return 'AutoJM | Recherche de véhicules'; return 'AutoJM | Recherche de véhicules';
break; break;
default: default:
return parent::getName(); return parent::getName();
} }
} }
public function collectData() { public function collectData()
{
// Get the number of result for this search // Get the number of result for this search
$search_url = self::URI . $this->getInput('url') . '&open=energy&onlyFilters=false'; $search_url = self::URI . $this->getInput('url') . '&open=energy&onlyFilters=false';
// Set the header 'X-Requested-With' like the website does it // Set the header 'X-Requested-With' like the website does it
$header = array( $header = [
'X-Requested-With: XMLHttpRequest' 'X-Requested-With: XMLHttpRequest'
); ];
// Get the JSON content of the form // Get the JSON content of the form
$json = getContents($search_url, $header); $json = getContents($search_url, $header);
@ -54,14 +55,13 @@ class AutoJMBridge extends BridgeAbstract {
$total_pages = ceil($nb_results / 15); $total_pages = ceil($nb_results / 15);
// Limit the number of page to analyse to 10 // Limit the number of page to analyse to 10
for($page = 1; $page <= $total_pages && $page <= 10; $page++) { for ($page = 1; $page <= $total_pages && $page <= 10; $page++) {
// Get the result the next page // Get the result the next page
$html = $this->getResults($page); $html = $this->getResults($page);
// Go through every car of the search // Go through every car of the search
$list = $html->find('div[class*=card-car card-car--listing]'); $list = $html->find('div[class*=card-car card-car--listing]');
foreach ($list as $car) { foreach ($list as $car) {
// Get the info about the car offer // Get the info about the car offer
$image = $car->find('div[class=card-car__header__img]', 0)->find('img', 0)->src; $image = $car->find('div[class=card-car__header__img]', 0)->find('img', 0)->src;
// Decode HTML attribute JSON data // Decode HTML attribute JSON data
@ -89,7 +89,7 @@ class AutoJMBridge extends BridgeAbstract {
$transmission = $car->find('span[data-cfg=vehicle__transmission]', 0)->plaintext; $transmission = $car->find('span[data-cfg=vehicle__transmission]', 0)->plaintext;
$loa_html = $car->find('span[data-cfg=vehicle__loa]', 0); $loa_html = $car->find('span[data-cfg=vehicle__loa]', 0);
// Check if any LOA price is displayed // Check if any LOA price is displayed
if($loa_html != null) { if ($loa_html != null) {
$loa_value = $car->find('span[data-cfg=vehicle__loa]', 0)->plaintext; $loa_value = $car->find('span[data-cfg=vehicle__loa]', 0)->plaintext;
$loa = '<li>LOA : à partir de ' . $loa_value . ' / mois </li>'; $loa = '<li>LOA : à partir de ' . $loa_value . ' / mois </li>';
} else { } else {
@ -97,7 +97,7 @@ class AutoJMBridge extends BridgeAbstract {
} }
// Construct the new item // Construct the new item
$item = array(); $item = [];
$item['title'] = $car_model; $item['title'] = $car_model;
$item['content'] = '<p><img style="vertical-align:middle ; padding: 10px" src="' . $image . '" />' $item['content'] = '<p><img style="vertical-align:middle ; padding: 10px" src="' . $image . '" />'
. $car_model . '</p>'; . $car_model . '</p>';

View file

@ -1,5 +1,7 @@
<?php <?php
class AwwwardsBridge extends BridgeAbstract {
class AwwwardsBridge extends BridgeAbstract
{
const NAME = 'Awwwards'; const NAME = 'Awwwards';
const URI = 'https://www.awwwards.com/'; const URI = 'https://www.awwwards.com/';
const DESCRIPTION = 'Fetches the latest ten sites of the day from Awwwards'; const DESCRIPTION = 'Fetches the latest ten sites of the day from Awwwards';
@ -10,31 +12,37 @@ class AwwwardsBridge extends BridgeAbstract {
const SITEURI = 'https://www.awwwards.com/sites/'; const SITEURI = 'https://www.awwwards.com/sites/';
const ASSETSURI = 'https://assets.awwwards.com/awards/media/cache/thumb_417_299/'; const ASSETSURI = 'https://assets.awwwards.com/awards/media/cache/thumb_417_299/';
private $sites = array(); private $sites = [];
public function getIcon() { public function getIcon()
{
return 'https://www.awwwards.com/favicon.ico'; return 'https://www.awwwards.com/favicon.ico';
} }
private function fetchSites() { private function fetchSites()
{
Debug::log('Fetching all sites'); Debug::log('Fetching all sites');
$sites = getSimpleHTMLDOM(self::SITESURI); $sites = getSimpleHTMLDOM(self::SITESURI);
Debug::log('Parsing all JSON data'); Debug::log('Parsing all JSON data');
foreach($sites->find('li[data-model]') as $site) { foreach ($sites->find('li[data-model]') as $site) {
$decode = html_entity_decode($site->attr['data-model'], $decode = html_entity_decode(
ENT_QUOTES, 'utf-8'); $site->attr['data-model'],
ENT_QUOTES,
'utf-8'
);
$decode = json_decode($decode, true); $decode = json_decode($decode, true);
$this->sites[] = $decode; $this->sites[] = $decode;
} }
} }
public function collectData() { public function collectData()
{
$this->fetchSites(); $this->fetchSites();
Debug::log('Building RSS feed'); Debug::log('Building RSS feed');
foreach($this->sites as $site) { foreach ($this->sites as $site) {
$item = array(); $item = [];
$item['title'] = $site['title']; $item['title'] = $site['title'];
$item['timestamp'] = $site['createdAt']; $item['timestamp'] = $site['createdAt'];
$item['categories'] = $site['tags']; $item['categories'] = $site['tags'];
@ -47,8 +55,9 @@ class AwwwardsBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
if(count($this->items) >= 10) if (count($this->items) >= 10) {
break; break;
} }
} }
}
} }

View file

@ -1,30 +1,33 @@
<?php <?php
class BAEBridge extends BridgeAbstract {
class BAEBridge extends BridgeAbstract
{
const MAINTAINER = 'couraudt'; const MAINTAINER = 'couraudt';
const NAME = 'Bourse Aux Equipiers Bridge'; const NAME = 'Bourse Aux Equipiers Bridge';
const URI = 'https://www.bourse-aux-equipiers.com'; const URI = 'https://www.bourse-aux-equipiers.com';
const DESCRIPTION = 'Returns the newest sailing offers.'; const DESCRIPTION = 'Returns the newest sailing offers.';
const PARAMETERS = array( const PARAMETERS = [
array( [
'keyword' => array( 'keyword' => [
'name' => 'Filtrer par mots clés', 'name' => 'Filtrer par mots clés',
'title' => 'Entrez le mot clé à filtrer ici' 'title' => 'Entrez le mot clé à filtrer ici'
), ],
'type' => array( 'type' => [
'name' => 'Type de recherche', 'name' => 'Type de recherche',
'title' => 'Afficher seuleument un certain type d\'annonce', 'title' => 'Afficher seuleument un certain type d\'annonce',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Toutes les annonces' => false, 'Toutes les annonces' => false,
'Les embarquements' => 'boat', 'Les embarquements' => 'boat',
'Les skippers' => 'skipper', 'Les skippers' => 'skipper',
'Les équipiers' => 'crew' 'Les équipiers' => 'crew'
) ]
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$url = $this->getURI(); $url = $this->getURI();
$html = getSimpleHTMLDOM($url) or returnClientError('No results for this query.'); $html = getSimpleHTMLDOM($url) or returnClientError('No results for this query.');
@ -33,10 +36,11 @@ class BAEBridge extends BridgeAbstract {
$detail = $annonce->find('footer a', 0); $detail = $annonce->find('footer a', 0);
$htmlDetail = getSimpleHTMLDOMCached(parent::getURI() . $detail->href); $htmlDetail = getSimpleHTMLDOMCached(parent::getURI() . $detail->href);
if (!$htmlDetail) if (!$htmlDetail) {
continue; continue;
}
$item = array(); $item = [];
$item['title'] = $annonce->find('header h2', 0)->plaintext; $item['title'] = $annonce->find('header h2', 0)->plaintext;
$item['uri'] = parent::getURI() . $detail->href; $item['uri'] = parent::getURI() . $detail->href;
@ -58,13 +62,14 @@ class BAEBridge extends BridgeAbstract {
$item['content'] = defaultLinkTo($content, parent::getURI()); $item['content'] = defaultLinkTo($content, parent::getURI());
$image = $htmlDetail->find('#zoom', 0); $image = $htmlDetail->find('#zoom', 0);
if ($image) { if ($image) {
$item['enclosures'] = array(parent::getURI() . $image->getAttribute('src')); $item['enclosures'] = [parent::getURI() . $image->getAttribute('src')];
} }
$this->items[] = $item; $this->items[] = $item;
} }
} }
public function getURI() { public function getURI()
{
$uri = parent::getURI(); $uri = parent::getURI();
if (!empty($this->getInput('type'))) { if (!empty($this->getInput('type'))) {
if ($this->getInput('type') == 'boat') { if ($this->getInput('type') == 'boat') {
@ -79,8 +84,9 @@ class BAEBridge extends BridgeAbstract {
return $uri; return $uri;
} }
private function removeAccents($string) { private function removeAccents($string)
$chars = array( {
$chars = [
// Decompositions for Latin-1 Supplement // Decompositions for Latin-1 Supplement
'ª' => 'a', 'º' => 'o', 'ª' => 'a', 'º' => 'o',
'À' => 'A', 'Á' => 'A', 'À' => 'A', 'Á' => 'A',
@ -254,7 +260,7 @@ class BAEBridge extends BridgeAbstract {
'Ǚ' => 'U', 'ǚ' => 'u', 'Ǚ' => 'U', 'ǚ' => 'u',
// grave accent // grave accent
'Ǜ' => 'U', 'ǜ' => 'u', 'Ǜ' => 'U', 'ǜ' => 'u',
); ];
$string = strtr($string, $chars); $string = strtr($string, $chars);

View file

@ -1,55 +1,57 @@
<?php <?php
class BadDragonBridge extends BridgeAbstract {
class BadDragonBridge extends BridgeAbstract
{
const NAME = 'Bad Dragon Bridge'; const NAME = 'Bad Dragon Bridge';
const URI = 'https://bad-dragon.com/'; const URI = 'https://bad-dragon.com/';
const CACHE_TIMEOUT = 300; // 5min const CACHE_TIMEOUT = 300; // 5min
const DESCRIPTION = 'Returns sales or new clearance items'; const DESCRIPTION = 'Returns sales or new clearance items';
const MAINTAINER = 'Roliga'; const MAINTAINER = 'Roliga';
const PARAMETERS = array( const PARAMETERS = [
'Sales' => array( 'Sales' => [
), ],
'Clearance' => array( 'Clearance' => [
'ready_made' => array( 'ready_made' => [
'name' => 'Ready Made', 'name' => 'Ready Made',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'flop' => array( 'flop' => [
'name' => 'Flops', 'name' => 'Flops',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'skus' => array( 'skus' => [
'name' => 'Products', 'name' => 'Products',
'exampleValue' => 'chanceflared, crackers', 'exampleValue' => 'chanceflared, crackers',
'title' => 'Comma separated list of product SKUs' 'title' => 'Comma separated list of product SKUs'
), ],
'onesize' => array( 'onesize' => [
'name' => 'One-Size', 'name' => 'One-Size',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'mini' => array( 'mini' => [
'name' => 'Mini', 'name' => 'Mini',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'small' => array( 'small' => [
'name' => 'Small', 'name' => 'Small',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'medium' => array( 'medium' => [
'name' => 'Medium', 'name' => 'Medium',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'large' => array( 'large' => [
'name' => 'Large', 'name' => 'Large',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'extralarge' => array( 'extralarge' => [
'name' => 'Extra Large', 'name' => 'Extra Large',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'category' => array( 'category' => [
'name' => 'Category', 'name' => 'Category',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'All' => 'all', 'All' => 'all',
'Accessories' => 'accessories', 'Accessories' => 'accessories',
'Merchandise' => 'merchandise', 'Merchandise' => 'merchandise',
@ -59,50 +61,50 @@ class BadDragonBridge extends BridgeAbstract {
'Lil\' Squirts' => 'shooter', 'Lil\' Squirts' => 'shooter',
'Lil\' Vibes' => 'vibrator', 'Lil\' Vibes' => 'vibrator',
'Wearables' => 'wearable' 'Wearables' => 'wearable'
), ],
'defaultValue' => 'all', 'defaultValue' => 'all',
), ],
'soft' => array( 'soft' => [
'name' => 'Soft Firmness', 'name' => 'Soft Firmness',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'med_firm' => array( 'med_firm' => [
'name' => 'Medium Firmness', 'name' => 'Medium Firmness',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'firm' => array( 'firm' => [
'name' => 'Firm', 'name' => 'Firm',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'split' => array( 'split' => [
'name' => 'Split Firmness', 'name' => 'Split Firmness',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'maxprice' => array( 'maxprice' => [
'name' => 'Max Price', 'name' => 'Max Price',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'defaultValue' => 300 'defaultValue' => 300
), ],
'minprice' => array( 'minprice' => [
'name' => 'Min Price', 'name' => 'Min Price',
'type' => 'number', 'type' => 'number',
'defaultValue' => 0 'defaultValue' => 0
), ],
'cumtube' => array( 'cumtube' => [
'name' => 'Cumtube', 'name' => 'Cumtube',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'suctionCup' => array( 'suctionCup' => [
'name' => 'Suction Cup', 'name' => 'Suction Cup',
'type' => 'checkbox' 'type' => 'checkbox'
), ],
'noAccessories' => array( 'noAccessories' => [
'name' => 'No Accessories', 'name' => 'No Accessories',
'type' => 'checkbox' 'type' => 'checkbox'
) ]
) ]
); ];
/* /*
* This sets index $strFrom (or $strTo if set) in $outArr to 'on' if * This sets index $strFrom (or $strTo if set) in $outArr to 'on' if
@ -122,32 +124,34 @@ class BadDragonBridge extends BridgeAbstract {
* [flop] => on * [flop] => on
* ) * )
* */ * */
private function setParam($inArr, &$outArr, $param, $strFrom, $strTo = null) { private function setParam($inArr, &$outArr, $param, $strFrom, $strTo = null)
if(isset($inArr[$param]) && in_array($strFrom, $inArr[$param])) { {
if (isset($inArr[$param]) && in_array($strFrom, $inArr[$param])) {
$outArr[($strTo ?: $strFrom)] = 'on'; $outArr[($strTo ?: $strFrom)] = 'on';
} }
} }
public function detectParameters($url) { public function detectParameters($url)
$params = array(); {
$params = [];
// Sale // Sale
$regex = '/^(https?:\/\/)?bad-dragon\.com\/sales/'; $regex = '/^(https?:\/\/)?bad-dragon\.com\/sales/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
return $params; return $params;
} }
// Clearance // Clearance
$regex = '/^(https?:\/\/)?bad-dragon\.com\/shop\/clearance/'; $regex = '/^(https?:\/\/)?bad-dragon\.com\/shop\/clearance/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
parse_str(parse_url($url, PHP_URL_QUERY), $urlParams); parse_str(parse_url($url, PHP_URL_QUERY), $urlParams);
$this->setParam($urlParams, $params, 'type', 'ready_made'); $this->setParam($urlParams, $params, 'type', 'ready_made');
$this->setParam($urlParams, $params, 'type', 'flop'); $this->setParam($urlParams, $params, 'type', 'flop');
if(isset($urlParams['skus'])) { if (isset($urlParams['skus'])) {
$skus = array(); $skus = [];
foreach($urlParams['skus'] as $sku) { foreach ($urlParams['skus'] as $sku) {
is_string($sku) && $skus[] = $sku; is_string($sku) && $skus[] = $sku;
is_array($sku) && $skus[] = $sku[0]; is_array($sku) && $skus[] = $sku[0];
} }
@ -161,9 +165,9 @@ class BadDragonBridge extends BridgeAbstract {
$this->setParam($urlParams, $params, 'sizes', 'large'); $this->setParam($urlParams, $params, 'sizes', 'large');
$this->setParam($urlParams, $params, 'sizes', 'extralarge'); $this->setParam($urlParams, $params, 'sizes', 'extralarge');
if(isset($urlParams['category'])) { if (isset($urlParams['category'])) {
$params['category'] = strtolower($urlParams['category']); $params['category'] = strtolower($urlParams['category']);
} else{ } else {
$params['category'] = 'all'; $params['category'] = 'all';
} }
@ -172,7 +176,7 @@ class BadDragonBridge extends BridgeAbstract {
$this->setParam($urlParams, $params, 'firmnessValues', 'firm'); $this->setParam($urlParams, $params, 'firmnessValues', 'firm');
$this->setParam($urlParams, $params, 'firmnessValues', 'split'); $this->setParam($urlParams, $params, 'firmnessValues', 'split');
if(isset($urlParams['price'])) { if (isset($urlParams['price'])) {
isset($urlParams['price']['max']) isset($urlParams['price']['max'])
&& $params['maxprice'] = $urlParams['price']['max']; && $params['maxprice'] = $urlParams['price']['max'];
isset($urlParams['price']['min']) isset($urlParams['price']['min'])
@ -195,8 +199,9 @@ class BadDragonBridge extends BridgeAbstract {
return null; return null;
} }
public function getName() { public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Sales': case 'Sales':
return 'Bad Dragon Sales'; return 'Bad Dragon Sales';
case 'Clearance': case 'Clearance':
@ -206,8 +211,9 @@ class BadDragonBridge extends BridgeAbstract {
} }
} }
public function getURI() { public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Sales': case 'Sales':
return self::URI . 'sales'; return self::URI . 'sales';
case 'Clearance': case 'Clearance':
@ -217,13 +223,14 @@ class BadDragonBridge extends BridgeAbstract {
} }
} }
public function collectData() { public function collectData()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Sales': case 'Sales':
$sales = json_decode(getContents(self::URI . 'api/sales')); $sales = json_decode(getContents(self::URI . 'api/sales'));
foreach($sales as $sale) { foreach ($sales as $sale) {
$item = array(); $item = [];
$item['title'] = $sale->title; $item['title'] = $sale->title;
$item['timestamp'] = strtotime($sale->startDate); $item['timestamp'] = strtotime($sale->startDate);
@ -231,7 +238,7 @@ class BadDragonBridge extends BridgeAbstract {
$item['uri'] = $this->getURI() . '/' . $sale->slug; $item['uri'] = $this->getURI() . '/' . $sale->slug;
$contentHTML = '<p><img src="' . $sale->image->url . '"></p>'; $contentHTML = '<p><img src="' . $sale->image->url . '"></p>';
if(isset($sale->endDate)) { if (isset($sale->endDate)) {
$contentHTML .= '<p><b>This promotion ends on ' $contentHTML .= '<p><b>This promotion ends on '
. gmdate('M j, Y \a\t g:i A T', strtotime($sale->endDate)) . gmdate('M j, Y \a\t g:i A T', strtotime($sale->endDate))
. '</b></p>'; . '</b></p>';
@ -240,8 +247,8 @@ class BadDragonBridge extends BridgeAbstract {
} }
$ul = false; $ul = false;
$content = json_decode($sale->content); $content = json_decode($sale->content);
foreach($content->blocks as $block) { foreach ($content->blocks as $block) {
switch($block->type) { switch ($block->type) {
case 'header-one': case 'header-one':
$contentHTML .= '<h1>' . $block->text . '</h1>'; $contentHTML .= '<h1>' . $block->text . '</h1>';
break; break;
@ -252,14 +259,14 @@ class BadDragonBridge extends BridgeAbstract {
$contentHTML .= '<h3>' . $block->text . '</h3>'; $contentHTML .= '<h3>' . $block->text . '</h3>';
break; break;
case 'unordered-list-item': case 'unordered-list-item':
if(!$ul) { if (!$ul) {
$contentHTML .= '<ul>'; $contentHTML .= '<ul>';
$ul = true; $ul = true;
} }
$contentHTML .= '<li>' . $block->text . '</li>'; $contentHTML .= '<li>' . $block->text . '</li>';
break; break;
default: default:
if($ul) { if ($ul) {
$contentHTML .= '</ul>'; $contentHTML .= '</ul>';
$ul = false; $ul = false;
} }
@ -278,16 +285,16 @@ class BadDragonBridge extends BridgeAbstract {
$productList = json_decode(getContents(self::URI $productList = json_decode(getContents(self::URI
. 'api/inventory-toy/product-list')); . 'api/inventory-toy/product-list'));
foreach($toyData->toys as $toy) { foreach ($toyData->toys as $toy) {
$item = array(); $item = [];
$item['uri'] = $this->getURI() $item['uri'] = $this->getURI()
. '#' . '#'
. $toy->id; . $toy->id;
$item['timestamp'] = strtotime($toy->created); $item['timestamp'] = strtotime($toy->created);
foreach($productList as $product) { foreach ($productList as $product) {
if($product->sku == $toy->sku) { if ($product->sku == $toy->sku) {
$item['title'] = $product->name; $item['title'] = $product->name;
break; break;
} }
@ -295,7 +302,7 @@ class BadDragonBridge extends BridgeAbstract {
// images // images
$content = '<p>'; $content = '<p>';
foreach($toy->images as $image) { foreach ($toy->images as $image) {
$content .= '<a href="' $content .= '<a href="'
. $image->fullFilename . $image->fullFilename
. '"><img src="' . '"><img src="'
@ -318,44 +325,44 @@ class BadDragonBridge extends BridgeAbstract {
. ($toy->cumtube ? 'Cumtube' : '') . ($toy->cumtube ? 'Cumtube' : '')
. ($toy->suction_cup || $toy->cumtube ? '' : 'None'); . ($toy->suction_cup || $toy->cumtube ? '' : 'None');
// firmness // firmness
$firmnessTexts = array( $firmnessTexts = [
'2' => 'Extra soft', '2' => 'Extra soft',
'3' => 'Soft', '3' => 'Soft',
'5' => 'Medium', '5' => 'Medium',
'8' => 'Firm' '8' => 'Firm'
); ];
$firmnesses = explode('/', $toy->firmness); $firmnesses = explode('/', $toy->firmness);
if(count($firmnesses) === 2) { if (count($firmnesses) === 2) {
$content .= '<br /><b>Firmness:</b> ' $content .= '<br /><b>Firmness:</b> '
. $firmnessTexts[$firmnesses[0]] . $firmnessTexts[$firmnesses[0]]
. ', ' . ', '
. $firmnessTexts[$firmnesses[1]]; . $firmnessTexts[$firmnesses[1]];
} else{ } else {
$content .= '<br /><b>Firmness:</b> ' $content .= '<br /><b>Firmness:</b> '
. $firmnessTexts[$firmnesses[0]]; . $firmnessTexts[$firmnesses[0]];
} }
// flop // flop
if($toy->type === 'flop') { if ($toy->type === 'flop') {
$content .= '<br /><b>Flop reason:</b> ' $content .= '<br /><b>Flop reason:</b> '
. $toy->flop_reason; . $toy->flop_reason;
} }
$content .= '</p>'; $content .= '</p>';
$item['content'] = $content; $item['content'] = $content;
$enclosures = array(); $enclosures = [];
foreach($toy->images as $image) { foreach ($toy->images as $image) {
$enclosures[] = $image->fullFilename; $enclosures[] = $image->fullFilename;
} }
$item['enclosures'] = $enclosures; $item['enclosures'] = $enclosures;
$categories = array(); $categories = [];
$categories[] = $toy->sku; $categories[] = $toy->sku;
$categories[] = $toy->type; $categories[] = $toy->type;
$categories[] = $toy->size; $categories[] = $toy->size;
if($toy->cumtube) { if ($toy->cumtube) {
$categories[] = 'cumtube'; $categories[] = 'cumtube';
} }
if($toy->suction_cup) { if ($toy->suction_cup) {
$categories[] = 'suction_cup'; $categories[] = 'suction_cup';
} }
$item['categories'] = $categories; $item['categories'] = $categories;
@ -366,7 +373,8 @@ class BadDragonBridge extends BridgeAbstract {
} }
} }
private function inputToURL($api = false) { private function inputToURL($api = false)
{
$url = self::URI; $url = self::URI;
$url .= ($api ? 'api/inventory-toys?' : 'shop/clearance?'); $url .= ($api ? 'api/inventory-toys?' : 'shop/clearance?');
@ -381,7 +389,7 @@ class BadDragonBridge extends BridgeAbstract {
$url .= ($this->getInput('flop') ? '&type[]=flop' : ''); $url .= ($this->getInput('flop') ? '&type[]=flop' : '');
// Product names // Product names
foreach(array_filter(explode(',', $this->getInput('skus'))) as $sku) { foreach (array_filter(explode(',', $this->getInput('skus'))) as $sku) {
$url .= '&skus[]=' . urlencode(trim($sku)); $url .= '&skus[]=' . urlencode(trim($sku));
} }
@ -398,18 +406,18 @@ class BadDragonBridge extends BridgeAbstract {
. urlencode($this->getInput('category')) : ''); . urlencode($this->getInput('category')) : '');
// Firmness // Firmness
if($api) { if ($api) {
$url .= ($this->getInput('soft') ? '&firmnessValues[]=3' : ''); $url .= ($this->getInput('soft') ? '&firmnessValues[]=3' : '');
$url .= ($this->getInput('med_firm') ? '&firmnessValues[]=5' : ''); $url .= ($this->getInput('med_firm') ? '&firmnessValues[]=5' : '');
$url .= ($this->getInput('firm') ? '&firmnessValues[]=8' : ''); $url .= ($this->getInput('firm') ? '&firmnessValues[]=8' : '');
if($this->getInput('split')) { if ($this->getInput('split')) {
$url .= '&firmnessValues[]=3/5'; $url .= '&firmnessValues[]=3/5';
$url .= '&firmnessValues[]=3/8'; $url .= '&firmnessValues[]=3/8';
$url .= '&firmnessValues[]=8/3'; $url .= '&firmnessValues[]=8/3';
$url .= '&firmnessValues[]=5/8'; $url .= '&firmnessValues[]=5/8';
$url .= '&firmnessValues[]=8/5'; $url .= '&firmnessValues[]=8/5';
} }
} else{ } else {
$url .= ($this->getInput('soft') ? '&firmnessValues[]=soft' : ''); $url .= ($this->getInput('soft') ? '&firmnessValues[]=soft' : '');
$url .= ($this->getInput('med_firm') ? '&firmnessValues[]=medium' : ''); $url .= ($this->getInput('med_firm') ? '&firmnessValues[]=medium' : '');
$url .= ($this->getInput('firm') ? '&firmnessValues[]=firm' : ''); $url .= ($this->getInput('firm') ? '&firmnessValues[]=firm' : '');

View file

@ -1,107 +1,126 @@
<?php <?php
class BakaUpdatesMangaReleasesBridge extends BridgeAbstract {
class BakaUpdatesMangaReleasesBridge extends BridgeAbstract
{
const NAME = 'Baka Updates Manga Releases'; const NAME = 'Baka Updates Manga Releases';
const URI = 'https://www.mangaupdates.com/'; const URI = 'https://www.mangaupdates.com/';
const DESCRIPTION = 'Get the latest series releases'; const DESCRIPTION = 'Get the latest series releases';
const MAINTAINER = 'fulmeek, KamaleiZestri'; const MAINTAINER = 'fulmeek, KamaleiZestri';
const PARAMETERS = array( const PARAMETERS = [
'By series' => array( 'By series' => [
'series_id' => array( 'series_id' => [
'name' => 'Series ID', 'name' => 'Series ID',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'exampleValue' => '188066' 'exampleValue' => '188066'
) ]
), ],
'By list' => array( 'By list' => [
'list_id' => array( 'list_id' => [
'name' => 'List ID and Type', 'name' => 'List ID and Type',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => '4395&list=read' 'exampleValue' => '4395&list=read'
) ]
) ]
); ];
const LIMIT_COLS = 5; const LIMIT_COLS = 5;
const LIMIT_ITEMS = 10; const LIMIT_ITEMS = 10;
const RELEASES_URL = 'https://www.mangaupdates.com/releases.html'; const RELEASES_URL = 'https://www.mangaupdates.com/releases.html';
private $feedName = ''; private $feedName = '';
public function collectData() { public function collectData()
if($this -> queriedContext == 'By series') {
if ($this -> queriedContext == 'By series') {
$this -> collectDataBySeries(); $this -> collectDataBySeries();
else //queriedContext == 'By list' } else { //queriedContext == 'By list'
$this -> collectDataByList(); $this -> collectDataByList();
} }
}
public function getURI(){ public function getURI()
if($this -> queriedContext == 'By series') { {
if ($this -> queriedContext == 'By series') {
$series_id = $this->getInput('series_id'); $series_id = $this->getInput('series_id');
if (!empty($series_id)) { if (!empty($series_id)) {
return self::URI . 'releases.html?search=' . $series_id . '&stype=series'; return self::URI . 'releases.html?search=' . $series_id . '&stype=series';
} }
} else //queriedContext == 'By list' } else { //queriedContext == 'By list'
return self::RELEASES_URL; return self::RELEASES_URL;
}
return self::URI; return self::URI;
} }
public function getName(){ public function getName()
if(!empty($this->feedName)) { {
if (!empty($this->feedName)) {
return $this->feedName . ' - ' . self::NAME; return $this->feedName . ' - ' . self::NAME;
} }
return parent::getName(); return parent::getName();
} }
private function getSanitizedHash($string) { private function getSanitizedHash($string)
{
return hash('sha1', preg_replace('/[^a-zA-Z0-9\-\.]/', '', ucwords(strtolower($string)))); return hash('sha1', preg_replace('/[^a-zA-Z0-9\-\.]/', '', ucwords(strtolower($string))));
} }
private function filterText($text) { private function filterText($text)
{
return rtrim($text, '* '); return rtrim($text, '* ');
} }
private function filterHTML($text) { private function filterHTML($text)
{
return $this->filterText(html_entity_decode($text)); return $this->filterText(html_entity_decode($text));
} }
private function findID($manga) { private function findID($manga)
{
// sometimes new series are on the release list that have no ID. just drop them. // sometimes new series are on the release list that have no ID. just drop them.
if(@$this -> filterHTML($manga -> find('a', 0) -> href) != null) { if (@$this -> filterHTML($manga -> find('a', 0) -> href) != null) {
preg_match('/id=([0-9]*)/', $this -> filterHTML($manga -> find('a', 0) -> href), $match); preg_match('/id=([0-9]*)/', $this -> filterHTML($manga -> find('a', 0) -> href), $match);
return $match[1]; return $match[1];
} else } else {
return 0; return 0;
} }
}
private function collectDataBySeries() { private function collectDataBySeries()
{
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
// content is an unstructured pile of divs, ugly to parse // content is an unstructured pile of divs, ugly to parse
$cols = $html->find('div#main_content div.row > div.text'); $cols = $html->find('div#main_content div.row > div.text');
if (!$cols) if (!$cols) {
returnServerError('No releases'); returnServerError('No releases');
}
$rows = array_slice( $rows = array_slice(
array_chunk($cols, self::LIMIT_COLS), 0, self::LIMIT_ITEMS array_chunk($cols, self::LIMIT_COLS),
0,
self::LIMIT_ITEMS
); );
if (isset($rows[0][1])) { if (isset($rows[0][1])) {
$this->feedName = $this->filterHTML($rows[0][1]->plaintext); $this->feedName = $this->filterHTML($rows[0][1]->plaintext);
} }
foreach($rows as $cols) { foreach ($rows as $cols) {
if (count($cols) < self::LIMIT_COLS) continue; if (count($cols) < self::LIMIT_COLS) {
continue;
}
$item = array(); $item = [];
$title = array(); $title = [];
$item['content'] = ''; $item['content'] = '';
$objDate = $cols[0]; $objDate = $cols[0];
if ($objDate) if ($objDate) {
$item['timestamp'] = strtotime($objDate->plaintext); $item['timestamp'] = strtotime($objDate->plaintext);
}
$objTitle = $cols[1]; $objTitle = $cols[1];
if ($objTitle) { if ($objTitle) {
@ -110,12 +129,14 @@ class BakaUpdatesMangaReleasesBridge extends BridgeAbstract {
} }
$objVolume = $cols[2]; $objVolume = $cols[2];
if ($objVolume && !empty($objVolume->plaintext)) if ($objVolume && !empty($objVolume->plaintext)) {
$title[] = 'Vol.' . $objVolume->plaintext; $title[] = 'Vol.' . $objVolume->plaintext;
}
$objChapter = $cols[3]; $objChapter = $cols[3];
if ($objChapter && !empty($objChapter->plaintext)) if ($objChapter && !empty($objChapter->plaintext)) {
$title[] = 'Chp.' . $objChapter->plaintext; $title[] = 'Chp.' . $objChapter->plaintext;
}
$objAuthor = $cols[4]; $objAuthor = $cols[4];
if ($objAuthor && !empty($objAuthor->plaintext)) { if ($objAuthor && !empty($objAuthor->plaintext)) {
@ -131,9 +152,10 @@ class BakaUpdatesMangaReleasesBridge extends BridgeAbstract {
} }
} }
private function collectDataByList() { private function collectDataByList()
{
$this -> feedName = 'Releases'; $this -> feedName = 'Releases';
$list = array(); $list = [];
$releasesHTML = getSimpleHTMLDOM(self::RELEASES_URL); $releasesHTML = getSimpleHTMLDOM(self::RELEASES_URL);
@ -142,7 +164,7 @@ class BakaUpdatesMangaReleasesBridge extends BridgeAbstract {
//get ids of the manga that the user follows, //get ids of the manga that the user follows,
$parts = $listHTML -> find('table#ptable tr > td.pl'); $parts = $listHTML -> find('table#ptable tr > td.pl');
foreach($parts as $part) { foreach ($parts as $part) {
$list[] = $this -> findID($part); $list[] = $this -> findID($part);
} }
@ -150,13 +172,15 @@ class BakaUpdatesMangaReleasesBridge extends BridgeAbstract {
$cols = $releasesHTML -> find('div#main_content div.row > div.pbreak'); $cols = $releasesHTML -> find('div#main_content div.row > div.pbreak');
$rows = array_slice(array_chunk($cols, 3), 0); $rows = array_slice(array_chunk($cols, 3), 0);
foreach($rows as $cols) { foreach ($rows as $cols) {
//check if current manga is in user's list. //check if current manga is in user's list.
$id = $this -> findId($cols[0]); $id = $this -> findId($cols[0]);
if(!array_search($id, $list)) continue; if (!array_search($id, $list)) {
continue;
}
$item = array(); $item = [];
$title = array(); $title = [];
$item['content'] = ''; $item['content'] = '';
@ -167,8 +191,9 @@ class BakaUpdatesMangaReleasesBridge extends BridgeAbstract {
} }
$objVolChap = $cols[1]; $objVolChap = $cols[1];
if ($objVolChap && !empty($objVolChap->plaintext)) if ($objVolChap && !empty($objVolChap->plaintext)) {
$title[] = $this -> filterHTML($objVolChap -> innertext); $title[] = $this -> filterHTML($objVolChap -> innertext);
}
$objAuthor = $cols[2]; $objAuthor = $cols[2];
if ($objAuthor && !empty($objAuthor->plaintext)) { if ($objAuthor && !empty($objAuthor->plaintext)) {

View file

@ -1,120 +1,123 @@
<?php <?php
class BandcampBridge extends BridgeAbstract {
class BandcampBridge extends BridgeAbstract
{
const MAINTAINER = 'sebsauvage, Roliga'; const MAINTAINER = 'sebsauvage, Roliga';
const NAME = 'Bandcamp Bridge'; const NAME = 'Bandcamp Bridge';
const URI = 'https://bandcamp.com/'; const URI = 'https://bandcamp.com/';
const CACHE_TIMEOUT = 600; // 10min const CACHE_TIMEOUT = 600; // 10min
const DESCRIPTION = 'New bandcamp releases by tag, band or album'; const DESCRIPTION = 'New bandcamp releases by tag, band or album';
const PARAMETERS = array( const PARAMETERS = [
'By tag' => array( 'By tag' => [
'tag' => array( 'tag' => [
'name' => 'tag', 'name' => 'tag',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'hip-hop-rap' 'exampleValue' => 'hip-hop-rap'
) ]
), ],
'By band' => array( 'By band' => [
'band' => array( 'band' => [
'name' => 'band', 'name' => 'band',
'type' => 'text', 'type' => 'text',
'title' => 'Band name as seen in the band page URL', 'title' => 'Band name as seen in the band page URL',
'required' => true, 'required' => true,
'exampleValue' => 'aesoprock' 'exampleValue' => 'aesoprock'
), ],
'type' => array( 'type' => [
'name' => 'Articles are', 'name' => 'Articles are',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Releases' => 'releases', 'Releases' => 'releases',
'Releases, new one when track list changes' => 'changes', 'Releases, new one when track list changes' => 'changes',
'Individual tracks' => 'tracks' 'Individual tracks' => 'tracks'
), ],
'defaultValue' => 'changes' 'defaultValue' => 'changes'
), ],
'limit' => array( 'limit' => [
'name' => 'limit', 'name' => 'limit',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'title' => 'Number of releases to return', 'title' => 'Number of releases to return',
'defaultValue' => 5 'defaultValue' => 5
) ]
), ],
'By label' => array( 'By label' => [
'label' => array( 'label' => [
'name' => 'label', 'name' => 'label',
'type' => 'text', 'type' => 'text',
'title' => 'label name as seen in the label page URL', 'title' => 'label name as seen in the label page URL',
'required' => true 'required' => true
), ],
'type' => array( 'type' => [
'name' => 'Articles are', 'name' => 'Articles are',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Releases' => 'releases', 'Releases' => 'releases',
'Releases, new one when track list changes' => 'changes', 'Releases, new one when track list changes' => 'changes',
'Individual tracks' => 'tracks' 'Individual tracks' => 'tracks'
), ],
'defaultValue' => 'changes' 'defaultValue' => 'changes'
), ],
'limit' => array( 'limit' => [
'name' => 'limit', 'name' => 'limit',
'type' => 'number', 'type' => 'number',
'title' => 'Number of releases to return', 'title' => 'Number of releases to return',
'defaultValue' => 5 'defaultValue' => 5
) ]
), ],
'By album' => array( 'By album' => [
'band' => array( 'band' => [
'name' => 'band', 'name' => 'band',
'type' => 'text', 'type' => 'text',
'title' => 'Band name as seen in the album page URL', 'title' => 'Band name as seen in the album page URL',
'required' => true, 'required' => true,
'exampleValue' => 'aesoprock' 'exampleValue' => 'aesoprock'
), ],
'album' => array( 'album' => [
'name' => 'album', 'name' => 'album',
'type' => 'text', 'type' => 'text',
'title' => 'Album name as seen in the album page URL', 'title' => 'Album name as seen in the album page URL',
'required' => true, 'required' => true,
'exampleValue' => 'appleseed' 'exampleValue' => 'appleseed'
), ],
'type' => array( 'type' => [
'name' => 'Articles are', 'name' => 'Articles are',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Releases' => 'releases', 'Releases' => 'releases',
'Releases, new one when track list changes' => 'changes', 'Releases, new one when track list changes' => 'changes',
'Individual tracks' => 'tracks' 'Individual tracks' => 'tracks'
), ],
'defaultValue' => 'tracks' 'defaultValue' => 'tracks'
) ]
) ]
); ];
const IMGURI = 'https://f4.bcbits.com/'; const IMGURI = 'https://f4.bcbits.com/';
const IMGSIZE_300PX = 23; const IMGSIZE_300PX = 23;
const IMGSIZE_700PX = 16; const IMGSIZE_700PX = 16;
private $feedName; private $feedName;
public function getIcon() { public function getIcon()
{
return 'https://s4.bcbits.com/img/bc_favicon.ico'; return 'https://s4.bcbits.com/img/bc_favicon.ico';
} }
public function collectData(){ public function collectData()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'By tag': case 'By tag':
$url = self::URI . 'api/hub/1/dig_deeper'; $url = self::URI . 'api/hub/1/dig_deeper';
$data = $this->buildRequestJson(); $data = $this->buildRequestJson();
$header = array( $header = [
'Content-Type: application/json', 'Content-Type: application/json',
'Content-Length: ' . strlen($data) 'Content-Length: ' . strlen($data)
); ];
$opts = array( $opts = [
CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $data CURLOPT_POSTFIELDS => $data
); ];
$content = getContents($url, $header, $opts); $content = getContents($url, $header, $opts);
$json = json_decode($content); $json = json_decode($content);
@ -139,13 +142,13 @@ class BandcampBridge extends BridgeAbstract {
$small_img = $this->getImageUrl($entry->art_id, self::IMGSIZE_300PX); $small_img = $this->getImageUrl($entry->art_id, self::IMGSIZE_300PX);
$img = $this->getImageUrl($entry->art_id, self::IMGSIZE_700PX); $img = $this->getImageUrl($entry->art_id, self::IMGSIZE_700PX);
$item = array( $item = [
'uri' => $url, 'uri' => $url,
'author' => $full_artist, 'author' => $full_artist,
'title' => $full_title 'title' => $full_title
); ];
$item['content'] = "<img src='$small_img' /><br/>$full_title"; $item['content'] = "<img src='$small_img' /><br/>$full_title";
$item['enclosures'] = array($img); $item['enclosures'] = [$img];
$this->items[] = $item; $this->items[] = $item;
} }
break; break;
@ -161,45 +164,47 @@ class BandcampBridge extends BridgeAbstract {
} }
$regex = '/band_id=(\d+)/'; $regex = '/band_id=(\d+)/';
if(preg_match($regex, $html, $matches) == false) if (preg_match($regex, $html, $matches) == false) {
returnServerError('Unable to find band ID on: ' . $this->getURI()); returnServerError('Unable to find band ID on: ' . $this->getURI());
}
$band_id = $matches[1]; $band_id = $matches[1];
$tralbums = array(); $tralbums = [];
switch($this->queriedContext) { switch ($this->queriedContext) {
case 'By band': case 'By band':
case 'By label': case 'By label':
$query_data = array( $query_data = [
'band_id' => $band_id 'band_id' => $band_id
); ];
$band_data = $this->apiGet('mobile/22/band_details', $query_data); $band_data = $this->apiGet('mobile/22/band_details', $query_data);
$num_albums = min(count($band_data->discography), $this->getInput('limit')); $num_albums = min(count($band_data->discography), $this->getInput('limit'));
for($i = 0; $i < $num_albums; $i++) { for ($i = 0; $i < $num_albums; $i++) {
$album_basic_data = $band_data->discography[$i]; $album_basic_data = $band_data->discography[$i];
// 'a' or 't' for albums and individual tracks respectively // 'a' or 't' for albums and individual tracks respectively
$tralbum_type = substr($album_basic_data->item_type, 0, 1); $tralbum_type = substr($album_basic_data->item_type, 0, 1);
$query_data = array( $query_data = [
'band_id' => $band_id, 'band_id' => $band_id,
'tralbum_type' => $tralbum_type, 'tralbum_type' => $tralbum_type,
'tralbum_id' => $album_basic_data->item_id 'tralbum_id' => $album_basic_data->item_id
); ];
$tralbums[] = $this->apiGet('mobile/22/tralbum_details', $query_data); $tralbums[] = $this->apiGet('mobile/22/tralbum_details', $query_data);
} }
break; break;
case 'By album': case 'By album':
$regex = '/album=(\d+)/'; $regex = '/album=(\d+)/';
if(preg_match($regex, $html, $matches) == false) if (preg_match($regex, $html, $matches) == false) {
returnServerError('Unable to find album ID on: ' . $this->getURI()); returnServerError('Unable to find album ID on: ' . $this->getURI());
}
$album_id = $matches[1]; $album_id = $matches[1];
$query_data = array( $query_data = [
'band_id' => $band_id, 'band_id' => $band_id,
'tralbum_type' => 'a', 'tralbum_type' => 'a',
'tralbum_id' => $album_id 'tralbum_id' => $album_id
); ];
$tralbums[] = $this->apiGet('mobile/22/tralbum_details', $query_data); $tralbums[] = $this->apiGet('mobile/22/tralbum_details', $query_data);
break; break;
@ -208,11 +213,11 @@ class BandcampBridge extends BridgeAbstract {
foreach ($tralbums as $tralbum_data) { foreach ($tralbums as $tralbum_data) {
if ($tralbum_data->type === 'a' && $this->getInput('type') === 'tracks') { if ($tralbum_data->type === 'a' && $this->getInput('type') === 'tracks') {
foreach ($tralbum_data->tracks as $track) { foreach ($tralbum_data->tracks as $track) {
$query_data = array( $query_data = [
'band_id' => $band_id, 'band_id' => $band_id,
'tralbum_type' => 't', 'tralbum_type' => 't',
'tralbum_id' => $track->track_id 'tralbum_id' => $track->track_id
); ];
$track_data = $this->apiGet('mobile/22/tralbum_details', $query_data); $track_data = $this->apiGet('mobile/22/tralbum_details', $query_data);
$this->items[] = $this->buildTralbumItem($track_data); $this->items[] = $this->buildTralbumItem($track_data);
@ -225,7 +230,8 @@ class BandcampBridge extends BridgeAbstract {
} }
} }
private function buildTralbumItem($tralbum_data){ private function buildTralbumItem($tralbum_data)
{
$band_data = $tralbum_data->band; $band_data = $tralbum_data->band;
// Format title like: ARTIST - ALBUM/TRACK (OPTIONAL RELEASER) // Format title like: ARTIST - ALBUM/TRACK (OPTIONAL RELEASER)
@ -250,15 +256,15 @@ class BandcampBridge extends BridgeAbstract {
$small_img = $this->getImageUrl($tralbum_data->art_id, self::IMGSIZE_300PX); $small_img = $this->getImageUrl($tralbum_data->art_id, self::IMGSIZE_300PX);
$img = $this->getImageUrl($tralbum_data->art_id, self::IMGSIZE_700PX); $img = $this->getImageUrl($tralbum_data->art_id, self::IMGSIZE_700PX);
$item = array( $item = [
'uri' => $tralbum_data->bandcamp_url, 'uri' => $tralbum_data->bandcamp_url,
'author' => $full_artist, 'author' => $full_artist,
'title' => $full_title, 'title' => $full_title,
'enclosures' => array($img), 'enclosures' => [$img],
'timestamp' => $tralbum_data->release_date 'timestamp' => $tralbum_data->release_date
); ];
$item['categories'] = array(); $item['categories'] = [];
foreach ($tralbum_data->tags as $tag) { foreach ($tralbum_data->tags as $tag) {
$item['categories'][] = $tag->norm_name; $item['categories'][] = $tag->norm_name;
} }
@ -289,29 +295,33 @@ class BandcampBridge extends BridgeAbstract {
return $item; return $item;
} }
private function buildRequestJson(){ private function buildRequestJson()
$requestJson = array( {
$requestJson = [
'tag' => $this->getInput('tag'), 'tag' => $this->getInput('tag'),
'page' => 1, 'page' => 1,
'sort' => 'date' 'sort' => 'date'
); ];
return json_encode($requestJson); return json_encode($requestJson);
} }
private function getImageUrl($id, $size){ private function getImageUrl($id, $size)
{
return self::IMGURI . 'img/a' . $id . '_' . $size . '.jpg'; return self::IMGURI . 'img/a' . $id . '_' . $size . '.jpg';
} }
private function apiGet($endpoint, $query_data) { private function apiGet($endpoint, $query_data)
{
$url = self::URI . 'api/' . $endpoint . '?' . http_build_query($query_data); $url = self::URI . 'api/' . $endpoint . '?' . http_build_query($query_data);
$data = json_decode(getContents($url)); $data = json_decode(getContents($url));
return $data; return $data;
} }
public function getURI(){ public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'By tag': case 'By tag':
if(!is_null($this->getInput('tag'))) { if (!is_null($this->getInput('tag'))) {
return self::URI return self::URI
. 'tag/' . 'tag/'
. urlencode($this->getInput('tag')) . urlencode($this->getInput('tag'))
@ -319,21 +329,21 @@ class BandcampBridge extends BridgeAbstract {
} }
break; break;
case 'By label': case 'By label':
if(!is_null($this->getInput('label'))) { if (!is_null($this->getInput('label'))) {
return 'https://' return 'https://'
. $this->getInput('label') . $this->getInput('label')
. '.bandcamp.com/music'; . '.bandcamp.com/music';
} }
break; break;
case 'By band': case 'By band':
if(!is_null($this->getInput('band'))) { if (!is_null($this->getInput('band'))) {
return 'https://' return 'https://'
. $this->getInput('band') . $this->getInput('band')
. '.bandcamp.com/music'; . '.bandcamp.com/music';
} }
break; break;
case 'By album': case 'By album':
if(!is_null($this->getInput('band')) && !is_null($this->getInput('album'))) { if (!is_null($this->getInput('band')) && !is_null($this->getInput('album'))) {
return 'https://' return 'https://'
. $this->getInput('band') . $this->getInput('band')
. '.bandcamp.com/album/' . '.bandcamp.com/album/'
@ -345,31 +355,32 @@ class BandcampBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
public function getName(){ public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'By tag': case 'By tag':
if(!is_null($this->getInput('tag'))) { if (!is_null($this->getInput('tag'))) {
return $this->getInput('tag') . ' - Bandcamp Tag'; return $this->getInput('tag') . ' - Bandcamp Tag';
} }
break; break;
case 'By band': case 'By band':
if(isset($this->feedName)) { if (isset($this->feedName)) {
return $this->feedName . ' - Bandcamp Band'; return $this->feedName . ' - Bandcamp Band';
} elseif(!is_null($this->getInput('band'))) { } elseif (!is_null($this->getInput('band'))) {
return $this->getInput('band') . ' - Bandcamp Band'; return $this->getInput('band') . ' - Bandcamp Band';
} }
break; break;
case 'By label': case 'By label':
if(isset($this->feedName)) { if (isset($this->feedName)) {
return $this->feedName . ' - Bandcamp Label'; return $this->feedName . ' - Bandcamp Label';
} elseif(!is_null($this->getInput('label'))) { } elseif (!is_null($this->getInput('label'))) {
return $this->getInput('label') . ' - Bandcamp Label'; return $this->getInput('label') . ' - Bandcamp Label';
} }
break; break;
case 'By album': case 'By album':
if(isset($this->feedName)) { if (isset($this->feedName)) {
return $this->feedName . ' - Bandcamp Album'; return $this->feedName . ' - Bandcamp Album';
} elseif(!is_null($this->getInput('album'))) { } elseif (!is_null($this->getInput('album'))) {
return $this->getInput('album') . ' - Bandcamp Album'; return $this->getInput('album') . ' - Bandcamp Album';
} }
break; break;
@ -378,26 +389,27 @@ class BandcampBridge extends BridgeAbstract {
return parent::getName(); return parent::getName();
} }
public function detectParameters($url) { public function detectParameters($url)
$params = array(); {
$params = [];
// By tag // By tag
$regex = '/^(https?:\/\/)?bandcamp\.com\/tag\/([^\/.&?\n]+)/'; $regex = '/^(https?:\/\/)?bandcamp\.com\/tag\/([^\/.&?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
$params['tag'] = urldecode($matches[2]); $params['tag'] = urldecode($matches[2]);
return $params; return $params;
} }
// By band // By band
$regex = '/^(https?:\/\/)?([^\/.&?\n]+?)\.bandcamp\.com/'; $regex = '/^(https?:\/\/)?([^\/.&?\n]+?)\.bandcamp\.com/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
$params['band'] = urldecode($matches[2]); $params['band'] = urldecode($matches[2]);
return $params; return $params;
} }
// By album // By album
$regex = '/^(https?:\/\/)?([^\/.&?\n]+?)\.bandcamp\.com\/album\/([^\/.&?\n]+)/'; $regex = '/^(https?:\/\/)?([^\/.&?\n]+?)\.bandcamp\.com\/album\/([^\/.&?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
$params['band'] = urldecode($matches[2]); $params['band'] = urldecode($matches[2]);
$params['album'] = urldecode($matches[3]); $params['album'] = urldecode($matches[3]);
return $params; return $params;

View file

@ -1,16 +1,18 @@
<?php <?php
class BandcampDailyBridge extends BridgeAbstract {
class BandcampDailyBridge extends BridgeAbstract
{
const NAME = 'Bandcamp Daily Bridge'; const NAME = 'Bandcamp Daily Bridge';
const URI = 'https://daily.bandcamp.com'; const URI = 'https://daily.bandcamp.com';
const DESCRIPTION = 'Returns newest articles'; const DESCRIPTION = 'Returns newest articles';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array( const PARAMETERS = [
'Latest articles' => array(), 'Latest articles' => [],
'Best of' => array( 'Best of' => [
'best-content' => array( 'best-content' => [
'name' => 'content', 'name' => 'content',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Best Ambient' => 'best-ambient', 'Best Ambient' => 'best-ambient',
'Best Beat Tapes' => 'best-beat-tapes', 'Best Beat Tapes' => 'best-beat-tapes',
'Best Dance 12\'s' => 'best-dance-12s', 'Best Dance 12\'s' => 'best-dance-12s',
@ -23,15 +25,15 @@ class BandcampDailyBridge extends BridgeAbstract {
'Best Punk' => 'best-punk', 'Best Punk' => 'best-punk',
'Best Reissues' => 'best-reissues', 'Best Reissues' => 'best-reissues',
'Best Soul' => 'best-soul', 'Best Soul' => 'best-soul',
), ],
'defaultValue' => 'best-ambient', 'defaultValue' => 'best-ambient',
), ],
), ],
'Genres' => array( 'Genres' => [
'genres-content' => array( 'genres-content' => [
'name' => 'content', 'name' => 'content',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Acoustic' => 'genres/acoustic', 'Acoustic' => 'genres/acoustic',
'Alternative' => 'genres/alternative', 'Alternative' => 'genres/alternative',
'Ambient' => 'genres/ambient', 'Ambient' => 'genres/ambient',
@ -57,15 +59,15 @@ class BandcampDailyBridge extends BridgeAbstract {
'Soundtrack' => 'genres/soundtrack', 'Soundtrack' => 'genres/soundtrack',
'Spoken Word' => 'genres/spoken-word', 'Spoken Word' => 'genres/spoken-word',
'World' => 'genres/world', 'World' => 'genres/world',
), ],
'defaultValue' => 'genres/acoustic', 'defaultValue' => 'genres/acoustic',
), ],
), ],
'Franchises' => array( 'Franchises' => [
'franchises-content' => array( 'franchises-content' => [
'name' => 'content', 'name' => 'content',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Lists' => 'lists', 'Lists' => 'lists',
'Features' => 'features', 'Features' => 'features',
'Album of the Day' => 'album-of-the-day', 'Album of the Day' => 'album-of-the-day',
@ -81,15 +83,16 @@ class BandcampDailyBridge extends BridgeAbstract {
'Scene Report' => 'scene-report', 'Scene Report' => 'scene-report',
'Seven Essential Releases' => 'seven-essential-releases', 'Seven Essential Releases' => 'seven-essential-releases',
'The Merch Table' => 'the-merch-table', 'The Merch Table' => 'the-merch-table',
), ],
'defaultValue' => 'lists', 'defaultValue' => 'lists',
), ],
) ]
); ];
const CACHE_TIMEOUT = 3600; // 1 hour const CACHE_TIMEOUT = 3600; // 1 hour
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI()) $html = getSimpleHTMLDOM($this->getURI())
or returnServerError('Could not request: ' . $this->getURI()); or returnServerError('Could not request: ' . $this->getURI());
@ -97,8 +100,8 @@ class BandcampDailyBridge extends BridgeAbstract {
$articles = $html->find('articles-list', 0); $articles = $html->find('articles-list', 0);
foreach($articles->find('div.list-article') as $index => $article) { foreach ($articles->find('div.list-article') as $index => $article) {
$item = array(); $item = [];
$articlePath = $article->find('a.title', 0)->href; $articlePath = $article->find('a.title', 0)->href;
@ -126,8 +129,9 @@ class BandcampDailyBridge extends BridgeAbstract {
} }
} }
public function getURI() { public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Latest articles': case 'Latest articles':
return self::URI . '/latest'; return self::URI . '/latest';
case 'Best of': case 'Best of':
@ -141,8 +145,9 @@ class BandcampDailyBridge extends BridgeAbstract {
} }
} }
public function getName() { public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Latest articles': case 'Latest articles':
return $this->queriedContext . ' - Bandcamp Daily'; return $this->queriedContext . ' - Bandcamp Daily';
case 'Best of': case 'Best of':

View file

@ -1,20 +1,22 @@
<?php <?php
class BastaBridge extends BridgeAbstract {
class BastaBridge extends BridgeAbstract
{
const MAINTAINER = 'qwertygc'; const MAINTAINER = 'qwertygc';
const NAME = 'Bastamag Bridge'; const NAME = 'Bastamag Bridge';
const URI = 'https://www.bastamag.net/'; const URI = 'https://www.bastamag.net/';
const CACHE_TIMEOUT = 7200; // 2h const CACHE_TIMEOUT = 7200; // 2h
const DESCRIPTION = 'Returns the newest articles.'; const DESCRIPTION = 'Returns the newest articles.';
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI . 'spip.php?page=backend'); $html = getSimpleHTMLDOM(self::URI . 'spip.php?page=backend');
$limit = 0; $limit = 0;
foreach($html->find('item') as $element) { foreach ($html->find('item') as $element) {
if($limit < 10) { if ($limit < 10) {
$item = array(); $item = [];
$item['title'] = $element->find('title', 0)->innertext; $item['title'] = $element->find('title', 0)->innertext;
$item['uri'] = $element->find('guid', 0)->plaintext; $item['uri'] = $element->find('guid', 0)->plaintext;
$item['timestamp'] = strtotime($element->find('dc:date', 0)->plaintext); $item['timestamp'] = strtotime($element->find('dc:date', 0)->plaintext);

View file

@ -1,31 +1,34 @@
<?php <?php
class BinanceBridge extends BridgeAbstract {
class BinanceBridge extends BridgeAbstract
{
const NAME = 'Binance Blog'; const NAME = 'Binance Blog';
const URI = 'https://www.binance.com/en/blog'; const URI = 'https://www.binance.com/en/blog';
const DESCRIPTION = 'Subscribe to the Binance blog.'; const DESCRIPTION = 'Subscribe to the Binance blog.';
const MAINTAINER = 'thefranke'; const MAINTAINER = 'thefranke';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
public function getIcon() { public function getIcon()
{
return 'https://bin.bnbstatic.com/static/images/common/favicon.ico'; return 'https://bin.bnbstatic.com/static/images/common/favicon.ico';
} }
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM(self::URI) $html = getSimpleHTMLDOM(self::URI)
or returnServerError('Could not fetch Binance blog data.'); or returnServerError('Could not fetch Binance blog data.');
$appData = $html->find('script[id="__APP_DATA"]'); $appData = $html->find('script[id="__APP_DATA"]');
$appDataJson = json_decode($appData[0]->innertext); $appDataJson = json_decode($appData[0]->innertext);
foreach($appDataJson->pageData->redux->blogList->blogList as $element) { foreach ($appDataJson->pageData->redux->blogList->blogList as $element) {
$date = $element->postTime; $date = $element->postTime;
$abstract = $element->brief; $abstract = $element->brief;
$uri = self::URI . '/' . $element->lang . '/blog/' . $element->idStr; $uri = self::URI . '/' . $element->lang . '/blog/' . $element->idStr;
$title = $element->title; $title = $element->title;
$content = $element->content; $content = $element->content;
$item = array(); $item = [];
$item['title'] = $title; $item['title'] = $title;
$item['uri'] = $uri; $item['uri'] = $uri;
$item['timestamp'] = substr($date, 0, -3); $item['timestamp'] = substr($date, 0, -3);
@ -34,8 +37,9 @@ class BinanceBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
if (count($this->items) >= 10) if (count($this->items) >= 10) {
break; break;
} }
} }
}
} }

View file

@ -1,23 +1,24 @@
<?php <?php
class BlaguesDeMerdeBridge extends BridgeAbstract {
class BlaguesDeMerdeBridge extends BridgeAbstract
{
const MAINTAINER = 'superbaillot.net, logmanoriginal'; const MAINTAINER = 'superbaillot.net, logmanoriginal';
const NAME = 'Blagues De Merde'; const NAME = 'Blagues De Merde';
const URI = 'http://www.blaguesdemerde.fr/'; const URI = 'http://www.blaguesdemerde.fr/';
const CACHE_TIMEOUT = 7200; // 2h const CACHE_TIMEOUT = 7200; // 2h
const DESCRIPTION = 'Blagues De Merde'; const DESCRIPTION = 'Blagues De Merde';
public function getIcon() { public function getIcon()
{
return self::URI . 'assets/img/favicon.ico'; return self::URI . 'assets/img/favicon.ico';
} }
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
foreach($html->find('div.blague') as $element) { foreach ($html->find('div.blague') as $element) {
$item = [];
$item = array();
$item['uri'] = static::URI . '#' . $element->id; $item['uri'] = static::URI . '#' . $element->id;
$item['author'] = $element->find('div[class="blague-footer"] p strong', 0)->plaintext; $item['author'] = $element->find('div[class="blague-footer"] p strong', 0)->plaintext;
@ -38,8 +39,6 @@ class BlaguesDeMerdeBridge extends BridgeAbstract {
$item['timestamp'] = strtotime($matches[1]); $item['timestamp'] = strtotime($matches[1]);
$this->items[] = $item; $this->items[] = $item;
} }
} }
} }

View file

@ -1,16 +1,18 @@
<?php <?php
class BleepingComputerBridge extends FeedExpander {
class BleepingComputerBridge extends FeedExpander
{
const MAINTAINER = 'csisoap'; const MAINTAINER = 'csisoap';
const NAME = 'Bleeping Computer'; const NAME = 'Bleeping Computer';
const URI = 'https://www.bleepingcomputer.com/'; const URI = 'https://www.bleepingcomputer.com/';
const DESCRIPTION = 'Returns the newest articles.'; const DESCRIPTION = 'Returns the newest articles.';
protected function parseItem($item){ protected function parseItem($item)
{
$item = parent::parseItem($item); $item = parent::parseItem($item);
$article_html = getSimpleHTMLDOMCached($item['uri']); $article_html = getSimpleHTMLDOMCached($item['uri']);
if(!$article_html) { if (!$article_html) {
$item['content'] .= '<p><em>Could not request ' . $this->getName() . ': ' . $item['uri'] . '</em></p>'; $item['content'] .= '<p><em>Could not request ' . $this->getName() . ': ' . $item['uri'] . '</em></p>';
return $item; return $item;
} }
@ -22,7 +24,8 @@ class BleepingComputerBridge extends FeedExpander {
return $item; return $item;
} }
public function collectData(){ public function collectData()
{
$feed = static::URI . 'feed/'; $feed = static::URI . 'feed/';
$this->collectExpandableDatas($feed); $this->collectExpandableDatas($feed);
} }

View file

@ -1,17 +1,17 @@
<?php <?php
class BlizzardNewsBridge extends XPathAbstract { class BlizzardNewsBridge extends XPathAbstract
{
const NAME = 'Blizzard News'; const NAME = 'Blizzard News';
const URI = 'https://news.blizzard.com'; const URI = 'https://news.blizzard.com';
const DESCRIPTION = 'Blizzard (game company) newsfeed'; const DESCRIPTION = 'Blizzard (game company) newsfeed';
const MAINTAINER = 'Niehztog'; const MAINTAINER = 'Niehztog';
const PARAMETERS = array( const PARAMETERS = [
'' => array( '' => [
'locale' => array( 'locale' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Deutsch' => 'de-de', 'Deutsch' => 'de-de',
'English (EU)' => 'en-gb', 'English (EU)' => 'en-gb',
'English (US)' => 'en-us', 'English (US)' => 'en-us',
@ -27,12 +27,12 @@ class BlizzardNewsBridge extends XPathAbstract {
'ภาษาไทย' => 'th-th', 'ภาษาไทย' => 'th-th',
'简体中文' => 'zh-cn', '简体中文' => 'zh-cn',
'繁體中文' => 'zh-tw' '繁體中文' => 'zh-tw'
), ],
'defaultValue' => 'en-us', 'defaultValue' => 'en-us',
'title' => 'Select your language' 'title' => 'Select your language'
) ]
) ]
); ];
const CACHE_TIMEOUT = 3600; const CACHE_TIMEOUT = 3600;
const XPATH_EXPRESSION_ITEM = '/html/body/div/div[4]/div[2]/div[2]/div/div/section/ol/li/article'; const XPATH_EXPRESSION_ITEM = '/html/body/div/div[4]/div[2]/div[2]/div/div/section/ol/li/article';
@ -49,10 +49,10 @@ class BlizzardNewsBridge extends XPathAbstract {
* Source Web page URL (should provide either HTML or XML content) * Source Web page URL (should provide either HTML or XML content)
* @return string * @return string
*/ */
protected function getSourceUrl(){ protected function getSourceUrl()
{
$locale = $this->getInput('locale'); $locale = $this->getInput('locale');
if('zh-cn' === $locale) { if ('zh-cn' === $locale) {
return 'https://cn.news.blizzard.com'; return 'https://cn.news.blizzard.com';
} }
return 'https://news.blizzard.com/' . $locale; return 'https://news.blizzard.com/' . $locale;

View file

@ -1,6 +1,7 @@
<?php <?php
class BookMyShowBridge extends BridgeAbstract {
class BookMyShowBridge extends BridgeAbstract
{
const MAINTAINER = 'captn3m0'; const MAINTAINER = 'captn3m0';
const NAME = 'BookMyShow Bridge'; const NAME = 'BookMyShow Bridge';
const URI = 'https://in.bookmyshow.com'; const URI = 'https://in.bookmyshow.com';
@ -1091,7 +1092,8 @@ class BookMyShowBridge extends BridgeAbstract {
// The city information is passed via a cookie // The city information is passed via a cookie
const URL_PREFIX = 'https://in.bookmyshow.com/serv/getData?cmd=QUICKBOOK&type='; const URL_PREFIX = 'https://in.bookmyshow.com/serv/getData?cmd=QUICKBOOK&type=';
public function collectData(){ public function collectData()
{
$city = $this->getInput('city'); $city = $this->getInput('city');
$category = $this->getInput('category'); $category = $this->getInput('category');
@ -1113,18 +1115,20 @@ class BookMyShowBridge extends BridgeAbstract {
} }
} }
usort($this->items, function($a, $b) { usort($this->items, function ($a, $b) {
return $b['timestamp'] - $a['timestamp']; return $b['timestamp'] - $a['timestamp'];
}); });
$this->items = array_slice($this->items, 0, 15); $this->items = array_slice($this->items, 0, 15);
} }
private function makeUrl($category){ private function makeUrl($category)
{
return self::URL_PREFIX . $category; return self::URL_PREFIX . $category;
} }
private function getDatesHtml($dates){ private function getDatesHtml($dates)
{
$tz = new DateTimeZone(self::TIMEZONE); $tz = new DateTimeZone(self::TIMEZONE);
$firstDate = DateTime::createFromFormat('Ymd', $dates[0]['ShowDateCode'], $tz) $firstDate = DateTime::createFromFormat('Ymd', $dates[0]['ShowDateCode'], $tz)
->format('D, d M Y'); ->format('D, d M Y');
@ -1142,7 +1146,8 @@ class BookMyShowBridge extends BridgeAbstract {
* @param array $event * @param array $event
* @see https://gist.github.com/captn3m0/6dbd539ca67579d22d6f90fab710ccd2 Sample JSON data for various events * @see https://gist.github.com/captn3m0/6dbd539ca67579d22d6f90fab710ccd2 Sample JSON data for various events
*/ */
private function generateEventHtml($event, $category){ private function generateEventHtml($event, $category)
{
$html = $this->getDatesHtml($event['arrDates']); $html = $this->getDatesHtml($event['arrDates']);
switch ($category) { switch ($category) {
case self::MOVIES: case self::MOVIES:
@ -1160,7 +1165,8 @@ class BookMyShowBridge extends BridgeAbstract {
* Generates a simple Venue HTML, even for multiple venues * Generates a simple Venue HTML, even for multiple venues
* spread across multiple dates as a description list. * spread across multiple dates as a description list.
*/ */
private function generateVenueHtml($venues){ private function generateVenueHtml($venues)
{
$html = '<h3>Venues</h3><table><thead><tr><th>Venue</th><th>Directions</th></tr></thead><tbody>'; $html = '<h3>Venues</h3><table><thead><tr><th>Venue</th><th>Directions</th></tr></thead><tbody>';
foreach ($venues as $i => $venueData) { foreach ($venues as $i => $venueData) {
@ -1180,7 +1186,8 @@ class BookMyShowBridge extends BridgeAbstract {
* Generates a simple Table with event Data * Generates a simple Table with event Data
* @todo Add support for jsonGenre as a tags row * @todo Add support for jsonGenre as a tags row
*/ */
private function generateEventDetailsTable($event, $headers = self::TABLE_HEADERS){ private function generateEventDetailsTable($event, $headers = self::TABLE_HEADERS)
{
$table = ''; $table = '';
foreach ($headers as $key => $header) { foreach ($headers as $key => $header) {
if ($header == 'Language') { if ($header == 'Language') {
@ -1189,7 +1196,7 @@ class BookMyShowBridge extends BridgeAbstract {
if ($event[$key] == 'Y') { if ($event[$key] == 'Y') {
$value = 'Yes'; $value = 'Yes';
} else if ($event[$key] == 'N') { } elseif ($event[$key] == 'N') {
$value = 'No'; $value = 'No';
} else { } else {
$value = $event[$key]; $value = $event[$key];
@ -1206,7 +1213,8 @@ EOT;
return "<table>$table</table>"; return "<table>$table</table>";
} }
private function generateStandardHtml($event){ private function generateStandardHtml($event)
{
$table = $this->generateEventDetailsTable($event); $table = $this->generateEventDetailsTable($event);
$imgsrc = $event['BannerURL']; $imgsrc = $event['BannerURL'];
@ -1224,7 +1232,8 @@ EOT;
* Converts some movie details from child entries, such as language * Converts some movie details from child entries, such as language
* into a single row item, either as a list, or as a Y/N * into a single row item, either as a list, or as a Y/N
*/ */
private function generateInnerMovieDetails($data){ private function generateInnerMovieDetails($data)
{
// Show list of languages and list of formats // Show list of languages and list of formats
$headers = ['EventLanguage', 'EventDimension']; $headers = ['EventLanguage', 'EventDimension'];
// if any of these has a Y for any of the screenings, mark it as YES // if any of these has a Y for any of the screenings, mark it as YES
@ -1262,7 +1271,7 @@ EOT;
// Put a yes for the boolean entries // Put a yes for the boolean entries
foreach ($booleanHeaders as $header) { foreach ($booleanHeaders as $header) {
if(in_array('Y', $items[$header])) { if (in_array('Y', $items[$header])) {
$html .= self::INNER_MOVIE_HEADERS[$header] . ': Yes<br>'; $html .= self::INNER_MOVIE_HEADERS[$header] . ': Yes<br>';
} }
} }
@ -1270,7 +1279,8 @@ EOT;
return $html; return $html;
} }
private function generateMovieHtml($eventGroup){ private function generateMovieHtml($eventGroup)
{
$data = $eventGroup['ChildEvents'][0]; $data = $eventGroup['ChildEvents'][0];
$table = $this->generateEventDetailsTable($data, self::MOVIE_TABLE_HEADERS); $table = $this->generateEventDetailsTable($data, self::MOVIE_TABLE_HEADERS);
@ -1290,17 +1300,18 @@ EOT;
More Details are available on the <a href="$url">BookMyShow website</a> and a trailer is available More Details are available on the <a href="$url">BookMyShow website</a> and a trailer is available
<a href="${data['EventTrailerURL']}" title="Trailer URL">here</a> <a href="${data['EventTrailerURL']}" title="Trailer URL">here</a>
EOT; EOT;
} }
/** /**
* Generates a canonical movie URL * Generates a canonical movie URL
*/ */
private function generateMovieUrl($eventGroup){ private function generateMovieUrl($eventGroup)
{
return self::URI . '/movies/' . $eventGroup['EventURLTitle'] . '/' . $eventGroup['EventCode']; return self::URI . '/movies/' . $eventGroup['EventURLTitle'] . '/' . $eventGroup['EventCode'];
} }
private function generateMoviesData($eventGroup){ private function generateMoviesData($eventGroup)
{
// Additional data picked up from the first Child Event // Additional data picked up from the first Child Event
$data = $eventGroup['ChildEvents'][0]; $data = $eventGroup['ChildEvents'][0];
$date = new DateTime($data['EventDate']); $date = new DateTime($data['EventDate']);
@ -1323,8 +1334,9 @@ EOT;
]; ];
} }
private function generateEventData($event, $category){ private function generateEventData($event, $category)
if($category == self::MOVIES) { {
if ($category == self::MOVIES) {
return $this->generateMoviesData($event); return $this->generateMoviesData($event);
} }
@ -1334,7 +1346,8 @@ EOT;
/** /**
* Takes an event data as array and returns data for RSS Post * Takes an event data as array and returns data for RSS Post
*/ */
private function generateGenericEventData($event, $category){ private function generateGenericEventData($event, $category)
{
$datetime = $event['Event_dtmCreated']; $datetime = $event['Event_dtmCreated'];
if (empty($datetime)) { if (empty($datetime)) {
return null; return null;
@ -1362,7 +1375,8 @@ EOT;
* Check if this is an online event. We can't rely on * Check if this is an online event. We can't rely on
* EventIsWebView, since that is set to Y for everything * EventIsWebView, since that is set to Y for everything
*/ */
private function isEventOnline($event){ private function isEventOnline($event)
{
if (isset($event['arrVenues']) && count($event['arrVenues']) === 1) { if (isset($event['arrVenues']) && count($event['arrVenues']) === 1) {
if (preg_match('/(Online|Zoom)/i', $event['arrVenues'][0]['VenueName'])) { if (preg_match('/(Online|Zoom)/i', $event['arrVenues'][0]['VenueName'])) {
return true; return true;
@ -1372,7 +1386,8 @@ EOT;
return false; return false;
} }
private function matchesLanguage(){ private function matchesLanguage()
{
if ($this->getInput('language') !== 'all') { if ($this->getInput('language') !== 'all') {
$language = $this->getInput('language'); $language = $this->getInput('language');
return in_array($language, $this->languages); return in_array($language, $this->languages);
@ -1380,7 +1395,8 @@ EOT;
return true; return true;
} }
private function matchesOnline($event){ private function matchesOnline($event)
{
if ($this->getInput('include_online')) { if ($this->getInput('include_online')) {
return true; return true;
} }
@ -1390,17 +1406,19 @@ EOT;
/** /**
* Currently only checks if the language filter matches * Currently only checks if the language filter matches
*/ */
private function matchesFilters($category, $event){ private function matchesFilters($category, $event)
{
return $this->matchesLanguage() and $this->matchesOnline($event); return $this->matchesLanguage() and $this->matchesOnline($event);
} }
/** /**
* Generates the RSS Feed title * Generates the RSS Feed title
*/ */
public function getName(){ public function getName()
{
$city = $this->getInput('city'); $city = $this->getInput('city');
$category = $this->getInput('category'); $category = $this->getInput('category');
if(!is_null($city) and !is_null($category)) { if (!is_null($city) and !is_null($category)) {
$categoryName = self::CATEGORIES[$category]; $categoryName = self::CATEGORIES[$category];
$cityNames = array_flip(self::CITIES); $cityNames = array_flip(self::CITIES);
$cityName = $cityNames[$city]; $cityName = $cityNames[$city];
@ -1420,7 +1438,8 @@ EOT;
* @param string $city City Code * @param string $city City Code
* @return array list of headers * @return array list of headers
*/ */
private function makeHeaders($city){ private function makeHeaders($city)
{
$uniqid = uniqid(); $uniqid = uniqid();
$rgn = urlencode("|Code=$city|"); $rgn = urlencode("|Code=$city|");
return [ return [
@ -1432,7 +1451,8 @@ EOT;
* Generates various URLs as per https://tools.ietf.org/html/rfc5870 * Generates various URLs as per https://tools.ietf.org/html/rfc5870
* and other standards * and other standards
*/ */
private function generateDirectionsHtml($lat, $long, $address = ''){ private function generateDirectionsHtml($lat, $long, $address = '')
{
$address = urlencode($address); $address = urlencode($address);
$links = [ $links = [

View file

@ -1,68 +1,74 @@
<?php <?php
class BooruprojectBridge extends DanbooruBridge { class BooruprojectBridge extends DanbooruBridge
{
const MAINTAINER = 'mitsukarenai'; const MAINTAINER = 'mitsukarenai';
const NAME = 'Booruproject'; const NAME = 'Booruproject';
const URI = 'https://booru.org/'; const URI = 'https://booru.org/';
const DESCRIPTION = 'Returns images from given page of booruproject'; const DESCRIPTION = 'Returns images from given page of booruproject';
const PARAMETERS = array( const PARAMETERS = [
'global' => array( 'global' => [
'p' => array( 'p' => [
'name' => 'page', 'name' => 'page',
'defaultValue' => 0, 'defaultValue' => 0,
'type' => 'number' 'type' => 'number'
), ],
't' => array( 't' => [
'name' => 'tags', 'name' => 'tags',
'required' => true, 'required' => true,
'exampleValue' => 'tagme', 'exampleValue' => 'tagme',
'title' => 'Use "all" to get all posts' 'title' => 'Use "all" to get all posts'
) ]
), ],
'Booru subdomain (subdomain.booru.org)' => array( 'Booru subdomain (subdomain.booru.org)' => [
'i' => array( 'i' => [
'name' => 'Subdomain', 'name' => 'Subdomain',
'required' => true, 'required' => true,
'exampleValue' => 'rm' 'exampleValue' => 'rm'
) ]
) ]
); ];
const PATHTODATA = '.thumb'; const PATHTODATA = '.thumb';
const IDATTRIBUTE = 'id'; const IDATTRIBUTE = 'id';
const TAGATTRIBUTE = 'title'; const TAGATTRIBUTE = 'title';
const PIDBYPAGE = 20; const PIDBYPAGE = 20;
protected function getFullURI(){ protected function getFullURI()
{
return $this->getURI() return $this->getURI()
. 'index.php?page=post&s=list&pid=' . 'index.php?page=post&s=list&pid='
. ($this->getInput('p') ? ($this->getInput('p') - 1) * static::PIDBYPAGE : '') . ($this->getInput('p') ? ($this->getInput('p') - 1) * static::PIDBYPAGE : '')
. '&tags=' . urlencode($this->getInput('t')); . '&tags=' . urlencode($this->getInput('t'));
} }
protected function getTags($element){ protected function getTags($element)
{
$tags = parent::getTags($element); $tags = parent::getTags($element);
$tags = explode(' ', $tags); $tags = explode(' ', $tags);
// Remove statistics from the tags list (identified by colon) // Remove statistics from the tags list (identified by colon)
foreach($tags as $key => $tag) { foreach ($tags as $key => $tag) {
if(strpos($tag, ':') !== false) unset($tags[$key]); if (strpos($tag, ':') !== false) {
unset($tags[$key]);
}
} }
return implode(' ', $tags); return implode(' ', $tags);
} }
public function getURI(){ public function getURI()
if(!is_null($this->getInput('i'))) { {
if (!is_null($this->getInput('i'))) {
return 'https://' . $this->getInput('i') . '.booru.org/'; return 'https://' . $this->getInput('i') . '.booru.org/';
} }
return parent::getURI(); return parent::getURI();
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('i'))) { {
if (!is_null($this->getInput('i'))) {
return static::NAME . ' ' . $this->getInput('i'); return static::NAME . ' ' . $this->getInput('i');
} }

View file

@ -1,14 +1,16 @@
<?php <?php
class BrutBridge extends BridgeAbstract {
class BrutBridge extends BridgeAbstract
{
const NAME = 'Brut Bridge'; const NAME = 'Brut Bridge';
const URI = 'https://www.brut.media'; const URI = 'https://www.brut.media';
const DESCRIPTION = 'Returns 10 newest videos by category and edition'; const DESCRIPTION = 'Returns 10 newest videos by category and edition';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array(array( const PARAMETERS = [[
'category' => array( 'category' => [
'name' => 'Category', 'name' => 'Category',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'News' => 'news', 'News' => 'news',
'International' => 'international', 'International' => 'international',
'Economy' => 'economy', 'Economy' => 'economy',
@ -17,37 +19,37 @@ class BrutBridge extends BridgeAbstract {
'Sports' => 'sport', 'Sports' => 'sport',
'Nature' => 'nature', 'Nature' => 'nature',
'Health' => 'health', 'Health' => 'health',
), ],
'defaultValue' => 'news', 'defaultValue' => 'news',
), ],
'edition' => array( 'edition' => [
'name' => ' Edition', 'name' => ' Edition',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'United States' => 'us', 'United States' => 'us',
'United Kingdom' => 'uk', 'United Kingdom' => 'uk',
'France' => 'fr', 'France' => 'fr',
'Spain' => 'es', 'Spain' => 'es',
'India' => 'in', 'India' => 'in',
'Mexico' => 'mx', 'Mexico' => 'mx',
), ],
'defaultValue' => 'us', 'defaultValue' => 'us',
) ]
) ]
); ];
const CACHE_TIMEOUT = 1800; // 30 mins const CACHE_TIMEOUT = 1800; // 30 mins
private $jsonRegex = '/window\.__PRELOADED_STATE__ = ((?:.*)});/'; private $jsonRegex = '/window\.__PRELOADED_STATE__ = ((?:.*)});/';
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
$results = $html->find('div.results', 0); $results = $html->find('div.results', 0);
foreach($results->find('li.col-6.col-sm-4.col-md-3.col-lg-2.px-2.pb-4') as $li) { foreach ($results->find('li.col-6.col-sm-4.col-md-3.col-lg-2.px-2.pb-4') as $li) {
$item = array(); $item = [];
$videoPath = self::URI . $li->children(0)->href; $videoPath = self::URI . $li->children(0)->href;
$videoPageHtml = getSimpleHTMLDOMCached($videoPath, 3600); $videoPageHtml = getSimpleHTMLDOMCached($videoPath, 3600);
@ -83,8 +85,8 @@ EOD;
} }
} }
public function getURI() { public function getURI()
{
if (!is_null($this->getInput('edition')) && !is_null($this->getInput('category'))) { if (!is_null($this->getInput('edition')) && !is_null($this->getInput('category'))) {
return self::URI . '/' . $this->getInput('edition') . '/' . $this->getInput('category'); return self::URI . '/' . $this->getInput('edition') . '/' . $this->getInput('category');
} }
@ -92,8 +94,8 @@ EOD;
return parent::getURI(); return parent::getURI();
} }
public function getName() { public function getName()
{
if (!is_null($this->getInput('edition')) && !is_null($this->getInput('category'))) { if (!is_null($this->getInput('edition')) && !is_null($this->getInput('category'))) {
$parameters = $this->getParameters(); $parameters = $this->getParameters();
@ -110,8 +112,8 @@ EOD;
/** /**
* Extract JSON from page * Extract JSON from page
*/ */
private function extractJson($html) { private function extractJson($html)
{
if (!preg_match($this->jsonRegex, $html, $parts)) { if (!preg_match($this->jsonRegex, $html, $parts)) {
returnServerError('Failed to extract data from page'); returnServerError('Failed to extract data from page');
} }

View file

@ -1,65 +1,69 @@
<?php <?php
class BugzillaBridge extends BridgeAbstract { class BugzillaBridge extends BridgeAbstract
{
const NAME = 'Bugzilla Bridge'; const NAME = 'Bugzilla Bridge';
const URI = 'https://www.bugzilla.org/'; const URI = 'https://www.bugzilla.org/';
const DESCRIPTION = 'Bridge for any Bugzilla instance'; const DESCRIPTION = 'Bridge for any Bugzilla instance';
const MAINTAINER = 'Yaman Qalieh'; const MAINTAINER = 'Yaman Qalieh';
const PARAMETERS = array( const PARAMETERS = [
'global' => array( 'global' => [
'instance' => array( 'instance' => [
'name' => 'Instance URL', 'name' => 'Instance URL',
'required' => true, 'required' => true,
'exampleValue' => 'https://bugzilla.mozilla.org' 'exampleValue' => 'https://bugzilla.mozilla.org'
) ]
), ],
'Bug comments' => array( 'Bug comments' => [
'id' => array( 'id' => [
'name' => 'Bug tracking ID', 'name' => 'Bug tracking ID',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'title' => 'Insert bug tracking ID', 'title' => 'Insert bug tracking ID',
'exampleValue' => 121241 'exampleValue' => 121241
), ],
'limit' => array( 'limit' => [
'name' => 'Number of comments to return', 'name' => 'Number of comments to return',
'type' => 'number', 'type' => 'number',
'required' => false, 'required' => false,
'title' => 'Specify number of comments to return', 'title' => 'Specify number of comments to return',
'defaultValue' => -1 'defaultValue' => -1
), ],
'skiptags' => array( 'skiptags' => [
'name' => 'Skip offtopic comments', 'name' => 'Skip offtopic comments',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Excludes comments tagged as advocacy, metoo, or offtopic from the feed' 'title' => 'Excludes comments tagged as advocacy, metoo, or offtopic from the feed'
) ]
) ]
); ];
const SKIPPED_ACTIVITY = array( const SKIPPED_ACTIVITY = [
'cc' => true, 'cc' => true,
'comment_tag' => true 'comment_tag' => true
); ];
const SKIPPED_TAGS = array('advocacy', 'metoo', 'offtopic'); const SKIPPED_TAGS = ['advocacy', 'metoo', 'offtopic'];
private $instance; private $instance;
private $bugid; private $bugid;
private $buguri; private $buguri;
private $title; private $title;
public function getName() { public function getName()
{
if (!is_null($this->title)) { if (!is_null($this->title)) {
return $this->title; return $this->title;
} }
return parent::getName(); return parent::getName();
} }
public function getURI() { public function getURI()
{
return $this->buguri ?? parent::getURI(); return $this->buguri ?? parent::getURI();
} }
public function collectData() { public function collectData()
{
$this->instance = rtrim($this->getInput('instance'), '/'); $this->instance = rtrim($this->getInput('instance'), '/');
$this->bugid = $this->getInput('id'); $this->bugid = $this->getInput('id');
$this->buguri = $this->instance . '/show_bug.cgi?id=' . $this->bugid; $this->buguri = $this->instance . '/show_bug.cgi?id=' . $this->bugid;
@ -69,7 +73,7 @@ class BugzillaBridge extends BridgeAbstract {
$this->collectComments($url . '/comment'); $this->collectComments($url . '/comment');
$this->collectUpdates($url . '/history'); $this->collectUpdates($url . '/history');
usort($this->items, function($a, $b) { usort($this->items, function ($a, $b) {
return $b['timestamp'] <=> $a['timestamp']; return $b['timestamp'] <=> $a['timestamp'];
}); });
@ -78,7 +82,8 @@ class BugzillaBridge extends BridgeAbstract {
} }
} }
protected function getTitle($url) { protected function getTitle($url)
{
// Only request the summary for a faster request // Only request the summary for a faster request
$json = json_decode(getContents($url . '?include_fields=summary'), true); $json = json_decode(getContents($url . '?include_fields=summary'), true);
$this->title = 'Bug ' . $this->bugid . ' - ' . $this->title = 'Bug ' . $this->bugid . ' - ' .
@ -87,7 +92,8 @@ class BugzillaBridge extends BridgeAbstract {
substr($this->instance, 8); substr($this->instance, 8);
} }
protected function collectComments($url) { protected function collectComments($url)
{
$json = json_decode(getContents($url), true); $json = json_decode(getContents($url), true);
// Array of comments is here // Array of comments is here
@ -95,10 +101,12 @@ class BugzillaBridge extends BridgeAbstract {
returnClientError('Cannot find REST endpoint'); returnClientError('Cannot find REST endpoint');
} }
foreach($json['bugs'][$this->bugid]['comments'] as $comment) { foreach ($json['bugs'][$this->bugid]['comments'] as $comment) {
$item = array(); $item = [];
if ($this->getInput('skiptags') and if (
array_intersect(self::SKIPPED_TAGS, $comment['tags'])) { $this->getInput('skiptags') and
array_intersect(self::SKIPPED_TAGS, $comment['tags'])
) {
continue; continue;
} }
$item['categories'] = $comment['tags']; $item['categories'] = $comment['tags'];
@ -111,13 +119,14 @@ class BugzillaBridge extends BridgeAbstract {
$item['content'] = markdownToHtml($item['content']); $item['content'] = markdownToHtml($item['content']);
} }
if (!is_null($comment['attachment_id'])) { if (!is_null($comment['attachment_id'])) {
$item['enclosures'] = array($this->instance . '/attachment.cgi?id=' . $comment['attachment_id']); $item['enclosures'] = [$this->instance . '/attachment.cgi?id=' . $comment['attachment_id']];
} }
$this->items[] = $item; $this->items[] = $item;
} }
} }
protected function collectUpdates($url) { protected function collectUpdates($url)
{
$json = json_decode(getContents($url), true); $json = json_decode(getContents($url), true);
// Array of changesets which contain an array of changes // Array of changesets which contain an array of changes
@ -125,16 +134,16 @@ class BugzillaBridge extends BridgeAbstract {
returnClientError('Cannot find REST endpoint'); returnClientError('Cannot find REST endpoint');
} }
foreach($json['bugs']['0']['history'] as $changeset) { foreach ($json['bugs']['0']['history'] as $changeset) {
$author = $this->getUser($changeset['who']); $author = $this->getUser($changeset['who']);
$timestamp = $changeset['when']; $timestamp = $changeset['when'];
foreach($changeset['changes'] as $change) { foreach ($changeset['changes'] as $change) {
// Skip updates to the cc list and comment tagging // Skip updates to the cc list and comment tagging
if (isset(self::SKIPPED_ACTIVITY[$change['field_name']])) { if (isset(self::SKIPPED_ACTIVITY[$change['field_name']])) {
continue; continue;
} }
$item = array(); $item = [];
$item['uri'] = $this->buguri; $item['uri'] = $this->buguri;
$item['title'] = 'Updated'; $item['title'] = 'Updated';
$item['timestamp'] = $timestamp; $item['timestamp'] = $timestamp;
@ -147,7 +156,8 @@ class BugzillaBridge extends BridgeAbstract {
} }
} }
protected function getUser($user) { protected function getUser($user)
{
// Check if the user endpoint is available // Check if the user endpoint is available
if ($this->loadCacheValue($this->instance . 'userEndpointClosed')) { if ($this->loadCacheValue($this->instance . 'userEndpointClosed')) {
return $user; return $user;
@ -162,7 +172,7 @@ class BugzillaBridge extends BridgeAbstract {
try { try {
$json = json_decode(getContents($url), true); $json = json_decode(getContents($url), true);
if (isset($json['error']) and $json['error']) { if (isset($json['error']) and $json['error']) {
throw new Exception; throw new Exception();
} }
} catch (Exception $e) { } catch (Exception $e) {
$this->saveCacheValue($this->instance . 'userEndpointClosed', true); $this->saveCacheValue($this->instance . 'userEndpointClosed', true);

View file

@ -6,13 +6,13 @@ class BukowskisBridge extends BridgeAbstract
const URI = 'https://www.bukowskis.com'; const URI = 'https://www.bukowskis.com';
const DESCRIPTION = 'Fetches info about auction objects from Bukowskis auction house'; const DESCRIPTION = 'Fetches info about auction objects from Bukowskis auction house';
const MAINTAINER = 'Qluxzz'; const MAINTAINER = 'Qluxzz';
const PARAMETERS = array(array( const PARAMETERS = [[
'category' => array( 'category' => [
'name' => 'Category', 'name' => 'Category',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'All categories' => '', 'All categories' => '',
'Art' => array( 'Art' => [
'All' => 'art', 'All' => 'art',
'Classic Art' => 'art.classic-art', 'Classic Art' => 'art.classic-art',
'Classic Finnish Art' => 'art.classic-finnish-art', 'Classic Finnish Art' => 'art.classic-finnish-art',
@ -27,31 +27,31 @@ class BukowskisBridge extends BridgeAbstract
'Prints' => 'art.prints', 'Prints' => 'art.prints',
'Sculpture' => 'art.sculpture', 'Sculpture' => 'art.sculpture',
'Swedish Old Masters' => 'art.swedish-old-masters', 'Swedish Old Masters' => 'art.swedish-old-masters',
), ],
'Asian Ceramics & Works of Art' => array( 'Asian Ceramics & Works of Art' => [
'All' => 'asian-ceramics-works-of-art', 'All' => 'asian-ceramics-works-of-art',
'Other' => 'asian-ceramics-works-of-art.other', 'Other' => 'asian-ceramics-works-of-art.other',
'Porcelain' => 'asian-ceramics-works-of-art.porcelain', 'Porcelain' => 'asian-ceramics-works-of-art.porcelain',
), ],
'Books & Manuscripts' => array( 'Books & Manuscripts' => [
'All' => 'books-manuscripts', 'All' => 'books-manuscripts',
'Books' => 'books-manuscripts.books', 'Books' => 'books-manuscripts.books',
), ],
'Carpets, rugs & textiles' => array( 'Carpets, rugs & textiles' => [
'All' => 'carpets-rugs-textiles', 'All' => 'carpets-rugs-textiles',
'European' => 'carpets-rugs-textiles.european', 'European' => 'carpets-rugs-textiles.european',
'Oriental' => 'carpets-rugs-textiles.oriental', 'Oriental' => 'carpets-rugs-textiles.oriental',
'Rest of the world' => 'carpets-rugs-textiles.rest-of-the-world', 'Rest of the world' => 'carpets-rugs-textiles.rest-of-the-world',
'Scandinavian' => 'carpets-rugs-textiles.scandinavian', 'Scandinavian' => 'carpets-rugs-textiles.scandinavian',
), ],
'Ceramics & porcelain' => array( 'Ceramics & porcelain' => [
'All' => 'ceramics-porcelain', 'All' => 'ceramics-porcelain',
'Ceramic ware' => 'ceramics-porcelain.ceramic-ware', 'Ceramic ware' => 'ceramics-porcelain.ceramic-ware',
'European' => 'ceramics-porcelain.european', 'European' => 'ceramics-porcelain.european',
'Rest of the world' => 'ceramics-porcelain.rest-of-the-world', 'Rest of the world' => 'ceramics-porcelain.rest-of-the-world',
'Scandinavian' => 'ceramics-porcelain.scandinavian', 'Scandinavian' => 'ceramics-porcelain.scandinavian',
), ],
'Collectibles' => array( 'Collectibles' => [
'All' => 'collectibles', 'All' => 'collectibles',
'Advertising & Retail' => 'collectibles.advertising-retail', 'Advertising & Retail' => 'collectibles.advertising-retail',
'Memorabilia' => 'collectibles.memorabilia', 'Memorabilia' => 'collectibles.memorabilia',
@ -60,18 +60,18 @@ class BukowskisBridge extends BridgeAbstract
'Retro & Popular Culture' => 'collectibles.retro-popular-culture', 'Retro & Popular Culture' => 'collectibles.retro-popular-culture',
'Technica & Nautica' => 'collectibles.technica-nautica', 'Technica & Nautica' => 'collectibles.technica-nautica',
'Toys' => 'collectibles.toys', 'Toys' => 'collectibles.toys',
), ],
'Design' => array( 'Design' => [
'All' => 'design', 'All' => 'design',
'Art glass' => 'design.art-glass', 'Art glass' => 'design.art-glass',
'Furniture' => 'design.furniture', 'Furniture' => 'design.furniture',
'Other' => 'design.other', 'Other' => 'design.other',
), ],
'Folk art' => array( 'Folk art' => [
'All' => 'folk-art', 'All' => 'folk-art',
'All categories' => 'lots', 'All categories' => 'lots',
), ],
'Furniture' => array( 'Furniture' => [
'All' => 'furniture', 'All' => 'furniture',
'Armchairs & Sofas' => 'furniture.armchairs-sofas', 'Armchairs & Sofas' => 'furniture.armchairs-sofas',
'Cabinets & Bureaus' => 'furniture.cabinets-bureaus', 'Cabinets & Bureaus' => 'furniture.cabinets-bureaus',
@ -81,13 +81,13 @@ class BukowskisBridge extends BridgeAbstract
'Other' => 'furniture.other', 'Other' => 'furniture.other',
'Shelves & Book cases' => 'furniture.shelves-book-cases', 'Shelves & Book cases' => 'furniture.shelves-book-cases',
'Tables' => 'furniture.tables', 'Tables' => 'furniture.tables',
), ],
'Glassware' => array( 'Glassware' => [
'All' => 'glassware', 'All' => 'glassware',
'Glassware' => 'glassware.glassware', 'Glassware' => 'glassware.glassware',
'Other' => 'glassware.other', 'Other' => 'glassware.other',
), ],
'Jewellery' => array( 'Jewellery' => [
'All' => 'jewellery', 'All' => 'jewellery',
'Bracelets' => 'jewellery.bracelets', 'Bracelets' => 'jewellery.bracelets',
'Brooches' => 'jewellery.brooches', 'Brooches' => 'jewellery.brooches',
@ -95,8 +95,8 @@ class BukowskisBridge extends BridgeAbstract
'Necklaces & Pendants' => 'jewellery.necklaces-pendants', 'Necklaces & Pendants' => 'jewellery.necklaces-pendants',
'Other' => 'jewellery.other', 'Other' => 'jewellery.other',
'Rings' => 'jewellery.rings', 'Rings' => 'jewellery.rings',
), ],
'Lighting' => array( 'Lighting' => [
'All' => 'lighting', 'All' => 'lighting',
'Candle sticks & Candelabras' => 'lighting.candle-sticks-candelabras', 'Candle sticks & Candelabras' => 'lighting.candle-sticks-candelabras',
'Ceiling lights' => 'lighting.ceiling-lights', 'Ceiling lights' => 'lighting.ceiling-lights',
@ -105,46 +105,46 @@ class BukowskisBridge extends BridgeAbstract
'Other' => 'lighting.other', 'Other' => 'lighting.other',
'Table lights' => 'lighting.table-lights', 'Table lights' => 'lighting.table-lights',
'Wall lights' => 'lighting.wall-lights', 'Wall lights' => 'lighting.wall-lights',
), ],
'Militaria' => array( 'Militaria' => [
'All' => 'militaria', 'All' => 'militaria',
'Honors & Medals' => 'militaria.honors-medals', 'Honors & Medals' => 'militaria.honors-medals',
'Other militaria' => 'militaria.other-militaria', 'Other militaria' => 'militaria.other-militaria',
'Weaponry' => 'militaria.weaponry', 'Weaponry' => 'militaria.weaponry',
), ],
'Miscellaneous' => array( 'Miscellaneous' => [
'All' => 'miscellaneous', 'All' => 'miscellaneous',
'Brass, Copper & Pewter' => 'miscellaneous.brass-copper-pewter', 'Brass, Copper & Pewter' => 'miscellaneous.brass-copper-pewter',
'Nickel silver' => 'miscellaneous.nickel-silver', 'Nickel silver' => 'miscellaneous.nickel-silver',
'Oriental' => 'miscellaneous.oriental', 'Oriental' => 'miscellaneous.oriental',
'Other' => 'miscellaneous.other', 'Other' => 'miscellaneous.other',
), ],
'Silver' => array( 'Silver' => [
'All' => 'silver', 'All' => 'silver',
'Candle sticks' => 'silver.candle-sticks', 'Candle sticks' => 'silver.candle-sticks',
'Cups & Bowls' => 'silver.cups-bowls', 'Cups & Bowls' => 'silver.cups-bowls',
'Cutlery' => 'silver.cutlery', 'Cutlery' => 'silver.cutlery',
'Other' => 'silver.other', 'Other' => 'silver.other',
), ],
'Timepieces' => array( 'Timepieces' => [
'All' => 'timepieces', 'All' => 'timepieces',
'Other' => 'timepieces.other', 'Other' => 'timepieces.other',
'Pocket watches' => 'timepieces.pocket-watches', 'Pocket watches' => 'timepieces.pocket-watches',
'Table clocks' => 'timepieces.table-clocks', 'Table clocks' => 'timepieces.table-clocks',
'Wrist watches' => 'timepieces.wrist-watches', 'Wrist watches' => 'timepieces.wrist-watches',
), ],
'Vintage & Fashion' => array( 'Vintage & Fashion' => [
'All' => 'vintage-fashion', 'All' => 'vintage-fashion',
'Accessories' => 'vintage-fashion.accessories', 'Accessories' => 'vintage-fashion.accessories',
'Bags & Trunks' => 'vintage-fashion.bags-trunks', 'Bags & Trunks' => 'vintage-fashion.bags-trunks',
'Clothes' => 'vintage-fashion.clothes', 'Clothes' => 'vintage-fashion.clothes',
), ],
) ]
), ],
'sort_order' => array( 'sort_order' => [
'name' => 'Sort order', 'name' => 'Sort order',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Ending soon' => 'ending', 'Ending soon' => 'ending',
'Most recent' => 'recent', 'Most recent' => 'recent',
'Most bids' => 'most', 'Most bids' => 'most',
@ -154,18 +154,18 @@ class BukowskisBridge extends BridgeAbstract
'Lowest estimate' => 'low', 'Lowest estimate' => 'low',
'Highest estimate' => 'high', 'Highest estimate' => 'high',
'Alphabetical' => 'alphabetical', 'Alphabetical' => 'alphabetical',
), ],
), ],
'language' => array( 'language' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'English' => 'en', 'English' => 'en',
'Swedish' => 'sv', 'Swedish' => 'sv',
'Finnish' => 'fi' 'Finnish' => 'fi'
), ],
), ],
)); ]];
const CACHE_TIMEOUT = 3600; // 1 hour const CACHE_TIMEOUT = 3600; // 1 hour
@ -180,11 +180,13 @@ class BukowskisBridge extends BridgeAbstract
$url = $baseUrl . '/' . $language . '/lots'; $url = $baseUrl . '/' . $language . '/lots';
if ($category) if ($category) {
$url = $url . '/category/' . $category; $url = $url . '/category/' . $category;
}
if ($sort_order) if ($sort_order) {
$url = $url . '/sort/' . $sort_order; $url = $url . '/sort/' . $sort_order;
}
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
@ -201,13 +203,13 @@ class BukowskisBridge extends BridgeAbstract
) )
); );
$this->items[] = array( $this->items[] = [
'title' => $title, 'title' => $title,
'uri' => $baseUrl . $relative_url, 'uri' => $baseUrl . $relative_url,
'uid' => $lot->getAttribute('data-lot-id'), 'uid' => $lot->getAttribute('data-lot-id'),
'content' => count($images) > 0 ? "<img src='$images[0]'/><br/>$title" : $title, 'content' => count($images) > 0 ? "<img src='$images[0]'/><br/>$title" : $title,
'enclosures' => array_slice($images, 1), 'enclosures' => array_slice($images, 1),
); ];
} }
} }

View file

@ -1,6 +1,7 @@
<?php <?php
class BundesbankBridge extends BridgeAbstract {
class BundesbankBridge extends BridgeAbstract
{
const PARAM_LANG = 'lang'; const PARAM_LANG = 'lang';
const LANG_EN = 'en'; const LANG_EN = 'en';
@ -12,48 +13,52 @@ class BundesbankBridge extends BridgeAbstract {
const MAINTAINER = 'logmanoriginal'; const MAINTAINER = 'logmanoriginal';
const CACHE_TIMEOUT = 86400; // 24 hours const CACHE_TIMEOUT = 86400; // 24 hours
const PARAMETERS = array( const PARAMETERS = [
array( [
self::PARAM_LANG => array( self::PARAM_LANG => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'defaultValue' => self::LANG_DE, 'defaultValue' => self::LANG_DE,
'values' => array( 'values' => [
'English' => self::LANG_EN, 'English' => self::LANG_EN,
'Deutsch' => self::LANG_DE 'Deutsch' => self::LANG_DE
) ]
) ]
) ]
); ];
public function getIcon() { public function getIcon()
{
return self::URI . 'resource/crblob/1890/a7f48ee0ae35348748121770ba3ca009/mL/favicon-ico-data.ico'; return self::URI . 'resource/crblob/1890/a7f48ee0ae35348748121770ba3ca009/mL/favicon-ico-data.ico';
} }
public function getURI() { public function getURI()
switch($this->getInput(self::PARAM_LANG)) { {
case self::LANG_EN: return self::URI . 'en/publications/reports/studies'; switch ($this->getInput(self::PARAM_LANG)) {
case self::LANG_DE: return self::URI . 'de/publikationen/berichte/studien'; case self::LANG_EN:
return self::URI . 'en/publications/reports/studies';
case self::LANG_DE:
return self::URI . 'de/publikationen/berichte/studien';
} }
return parent::getURI(); return parent::getURI();
} }
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
$html = defaultLinkTo($html, $this->getURI()); $html = defaultLinkTo($html, $this->getURI());
foreach($html->find('ul.resultlist li') as $study) { foreach ($html->find('ul.resultlist li') as $study) {
$item = array(); $item = [];
$item['uri'] = $study->find('.teasable__link', 0)->href; $item['uri'] = $study->find('.teasable__link', 0)->href;
// Get title without child elements (i.e. subtitle) // Get title without child elements (i.e. subtitle)
$title = $study->find('.teasable__title div.h2', 0); $title = $study->find('.teasable__title div.h2', 0);
foreach($title->children as &$child) { foreach ($title->children as &$child) {
$child->outertext = ''; $child->outertext = '';
} }
@ -62,7 +67,7 @@ class BundesbankBridge extends BridgeAbstract {
// Add subtitle to the content if it exists // Add subtitle to the content if it exists
$item['content'] = ''; $item['content'] = '';
if($subtitle = $study->find('.teasable__subtitle', 0)) { if ($subtitle = $study->find('.teasable__subtitle', 0)) {
$item['content'] .= '<strong>' . $study->find('.teasable__subtitle', 0)->plaintext . '</strong>'; $item['content'] .= '<strong>' . $study->find('.teasable__subtitle', 0)->plaintext . '</strong>';
} }
@ -71,14 +76,13 @@ class BundesbankBridge extends BridgeAbstract {
$item['timestamp'] = strtotime($study->find('.teasable__date', 0)->plaintext); $item['timestamp'] = strtotime($study->find('.teasable__date', 0)->plaintext);
// Downloads and older studies don't have images // Downloads and older studies don't have images
if($study->find('.teasable__image', 0)) { if ($study->find('.teasable__image', 0)) {
$item['enclosures'] = array( $item['enclosures'] = [
$study->find('.teasable__image img', 0)->src $study->find('.teasable__image img', 0)->src
); ];
} }
$this->items[] = $item; $this->items[] = $item;
} }
} }
} }

View file

@ -1,5 +1,7 @@
<?php <?php
class BundestagParteispendenBridge extends BridgeAbstract {
class BundestagParteispendenBridge extends BridgeAbstract
{
const MAINTAINER = 'mibe'; const MAINTAINER = 'mibe';
const NAME = 'Deutscher Bundestag - Parteispenden'; const NAME = 'Deutscher Bundestag - Parteispenden';
const URI = 'https://www.bundestag.de/parlament/praesidium/parteienfinanzierung/fundstellen50000'; const URI = 'https://www.bundestag.de/parlament/praesidium/parteienfinanzierung/fundstellen50000';
@ -40,7 +42,7 @@ URI;
$rows = $html->find('table.table > tbody > tr') $rows = $html->find('table.table > tbody > tr')
or returnServerError('Could not find the proper HTML elements.'); or returnServerError('Could not find the proper HTML elements.');
foreach($rows as $row) { foreach ($rows as $row) {
$item = $this->generateItemFromRow($row); $item = $this->generateItemFromRow($row);
if (is_array($item)) { if (is_array($item)) {
$item['uri'] = $url; $item['uri'] = $url;
@ -52,10 +54,11 @@ URI;
private function generateItemFromRow(simple_html_dom_node $row) private function generateItemFromRow(simple_html_dom_node $row)
{ {
// The row must have 5 columns. There are monthly header rows, which are ignored here. // The row must have 5 columns. There are monthly header rows, which are ignored here.
if(count($row->children) != 5) if (count($row->children) != 5) {
return null; return null;
}
$item = array(); $item = [];
// | column | paragraph inside column // | column | paragraph inside column
$party = $row->children[0]->children[0]->innertext; $party = $row->children[0]->children[0]->innertext;
@ -69,20 +72,22 @@ URI;
$content = sprintf(self::CONTENT_TEMPLATE, $party, $amount, $donor, $date); $content = sprintf(self::CONTENT_TEMPLATE, $party, $amount, $donor, $date);
$item = array( $item = [
'title' => $party . ': ' . $amount, 'title' => $party . ': ' . $amount,
'content' => $content, 'content' => $content,
'uid' => sha1($content), 'uid' => sha1($content),
); ];
// Try to get the link to the official document // Try to get the link to the official document
if ($dip != null) if ($dip != null) {
$item['enclosures'] = array($dip->href); $item['enclosures'] = [$dip->href];
}
// Try to parse the date // Try to parse the date
$dateTime = DateTime::createFromFormat('d.m.Y', $date); $dateTime = DateTime::createFromFormat('d.m.Y', $date);
if ($dateTime !== false) if ($dateTime !== false) {
$item['timestamp'] = $dateTime->getTimestamp(); $item['timestamp'] = $dateTime->getTimestamp();
}
return $item; return $item;
} }

View file

@ -1,16 +1,18 @@
<?php <?php
class CBCEditorsBlogBridge extends BridgeAbstract {
class CBCEditorsBlogBridge extends BridgeAbstract
{
const MAINTAINER = 'quickwick'; const MAINTAINER = 'quickwick';
const NAME = 'CBC Editors Blog'; const NAME = 'CBC Editors Blog';
const URI = 'https://www.cbc.ca/news/editorsblog'; const URI = 'https://www.cbc.ca/news/editorsblog';
const DESCRIPTION = 'Recent CBC Editor\'s Blog posts'; const DESCRIPTION = 'Recent CBC Editor\'s Blog posts';
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
// Loop on each blog post entry // Loop on each blog post entry
foreach($html->find('div.contentListCards', 0)->find('a[data-test=type-story]') as $element) { foreach ($html->find('div.contentListCards', 0)->find('a[data-test=type-story]') as $element) {
$headline = ($element->find('.headline', 0))->innertext; $headline = ($element->find('.headline', 0))->innertext;
$timestamp = ($element->find('time', 0))->datetime; $timestamp = ($element->find('time', 0))->datetime;
$articleUri = 'https://www.cbc.ca' . $element->href; $articleUri = 'https://www.cbc.ca' . $element->href;
@ -19,7 +21,7 @@ class CBCEditorsBlogBridge extends BridgeAbstract {
$thumbnailUri = rtrim(explode(',', $thumbnailUris)[0], ' 300w'); $thumbnailUri = rtrim(explode(',', $thumbnailUris)[0], ' 300w');
// Fill item // Fill item
$item = array(); $item = [];
$item['uri'] = $articleUri; $item['uri'] = $articleUri;
$item['id'] = $item['uri']; $item['id'] = $item['uri'];
$item['timestamp'] = $timestamp; $item['timestamp'] = $timestamp;
@ -28,7 +30,7 @@ class CBCEditorsBlogBridge extends BridgeAbstract {
. $thumbnailUri . '" /><br>' . $summary; . $thumbnailUri . '" /><br>' . $summary;
$item['author'] = 'Editor\'s Blog'; $item['author'] = 'Editor\'s Blog';
if(isset($item['title'])) { if (isset($item['title'])) {
$this->items[] = $item; $this->items[] = $item;
} }
} }

View file

@ -1,17 +1,18 @@
<?php <?php
class CNETBridge extends BridgeAbstract {
class CNETBridge extends BridgeAbstract
{
const MAINTAINER = 'ORelio'; const MAINTAINER = 'ORelio';
const NAME = 'CNET News'; const NAME = 'CNET News';
const URI = 'https://www.cnet.com/'; const URI = 'https://www.cnet.com/';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'Returns the newest articles.'; const DESCRIPTION = 'Returns the newest articles.';
const PARAMETERS = array( const PARAMETERS = [
array( [
'topic' => array( 'topic' => [
'name' => 'Topic', 'name' => 'Topic',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'All articles' => '', 'All articles' => '',
'Apple' => 'apple', 'Apple' => 'apple',
'Google' => 'google', 'Google' => 'google',
@ -22,12 +23,13 @@ class CNETBridge extends BridgeAbstract {
'Security' => 'topics-security', 'Security' => 'topics-security',
'Internet' => 'topics-internet', 'Internet' => 'topics-internet',
'Tech Industry' => 'topics-tech-industry' 'Tech Industry' => 'topics-tech-industry'
) ]
) ]
) ]
); ];
private function cleanArticle($article_html) { private function cleanArticle($article_html)
{
$offset_p = strpos($article_html, '<p>'); $offset_p = strpos($article_html, '<p>');
$offset_figure = strpos($article_html, '<figure'); $offset_figure = strpos($article_html, '<figure');
$offset = ($offset_figure < $offset_p ? $offset_figure : $offset_p); $offset = ($offset_figure < $offset_p ? $offset_figure : $offset_p);
@ -44,21 +46,21 @@ class CNETBridge extends BridgeAbstract {
return $article_html; return $article_html;
} }
public function collectData() { public function collectData()
{
// Retrieve and check user input // Retrieve and check user input
$topic = str_replace('-', '/', $this->getInput('topic')); $topic = str_replace('-', '/', $this->getInput('topic'));
if (!empty($topic) && (substr_count($topic, '/') > 1 || !ctype_alpha(str_replace('/', '', $topic)))) if (!empty($topic) && (substr_count($topic, '/') > 1 || !ctype_alpha(str_replace('/', '', $topic)))) {
returnClientError('Invalid topic: ' . $topic); returnClientError('Invalid topic: ' . $topic);
}
// Retrieve webpage // Retrieve webpage
$pageUrl = self::URI . (empty($topic) ? 'news/' : $topic . '/'); $pageUrl = self::URI . (empty($topic) ? 'news/' : $topic . '/');
$html = getSimpleHTMLDOM($pageUrl); $html = getSimpleHTMLDOM($pageUrl);
// Process articles // Process articles
foreach($html->find('div.assetBody, div.riverPost') as $element) { foreach ($html->find('div.assetBody, div.riverPost') as $element) {
if (count($this->items) >= 10) {
if(count($this->items) >= 10) {
break; break;
} }
@ -69,37 +71,41 @@ class CNETBridge extends BridgeAbstract {
$article_author = trim($element->find('a[rel=author], a.name', 0)->plaintext); $article_author = trim($element->find('a[rel=author], a.name', 0)->plaintext);
$article_content = '<p><b>' . trim($element->find('p.dek', 0)->plaintext) . '</b></p>'; $article_content = '<p><b>' . trim($element->find('p.dek', 0)->plaintext) . '</b></p>';
if (is_null($article_thumbnail)) if (is_null($article_thumbnail)) {
$article_thumbnail = extractFromDelimiters($element->innertext, '<img src="', '"'); $article_thumbnail = extractFromDelimiters($element->innertext, '<img src="', '"');
}
if (!empty($article_title) && !empty($article_uri) && strpos($article_uri, self::URI . 'news/') !== false) { if (!empty($article_title) && !empty($article_uri) && strpos($article_uri, self::URI . 'news/') !== false) {
$article_html = getSimpleHTMLDOMCached($article_uri) or $article_html = null; $article_html = getSimpleHTMLDOMCached($article_uri) or $article_html = null;
if (!is_null($article_html)) { if (!is_null($article_html)) {
if (empty($article_thumbnail)) {
if (empty($article_thumbnail))
$article_thumbnail = $article_html->find('div.originalImage', 0); $article_thumbnail = $article_html->find('div.originalImage', 0);
if (empty($article_thumbnail)) }
if (empty($article_thumbnail)) {
$article_thumbnail = $article_html->find('span.imageContainer', 0); $article_thumbnail = $article_html->find('span.imageContainer', 0);
if (is_object($article_thumbnail)) }
if (is_object($article_thumbnail)) {
$article_thumbnail = $article_thumbnail->find('img', 0)->src; $article_thumbnail = $article_thumbnail->find('img', 0)->src;
}
$article_content .= trim( $article_content .= trim(
$this->cleanArticle( $this->cleanArticle(
extractFromDelimiters( extractFromDelimiters(
$article_html, '<article', '<footer' $article_html,
'<article',
'<footer'
) )
) )
); );
} }
$item = array(); $item = [];
$item['uri'] = $article_uri; $item['uri'] = $article_uri;
$item['title'] = $article_title; $item['title'] = $article_title;
$item['author'] = $article_author; $item['author'] = $article_author;
$item['timestamp'] = $article_timestamp; $item['timestamp'] = $article_timestamp;
$item['enclosures'] = array($article_thumbnail); $item['enclosures'] = [$article_thumbnail];
$item['content'] = $article_content; $item['content'] = $article_content;
$this->items[] = $item; $this->items[] = $item;
} }

View file

@ -1,4 +1,5 @@
<?php <?php
class CNETFranceBridge extends FeedExpander class CNETFranceBridge extends FeedExpander
{ {
const MAINTAINER = 'leomaradan'; const MAINTAINER = 'leomaradan';
@ -6,25 +7,25 @@ class CNETFranceBridge extends FeedExpander
const URI = 'https://www.cnetfrance.fr/'; const URI = 'https://www.cnetfrance.fr/';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'CNET France RSS with filters'; const DESCRIPTION = 'CNET France RSS with filters';
const PARAMETERS = array( const PARAMETERS = [
'filters' => array( 'filters' => [
'title' => array( 'title' => [
'name' => 'Exclude by title', 'name' => 'Exclude by title',
'required' => false, 'required' => false,
'title' => 'Title term, separated by semicolon (;)', 'title' => 'Title term, separated by semicolon (;)',
'exampleValue' => 'bon plan;bons plans;au meilleur prix;des meilleures offres;Amazon Prime Day;RED by SFR ou B&You' 'exampleValue' => 'bon plan;bons plans;au meilleur prix;des meilleures offres;Amazon Prime Day;RED by SFR ou B&You'
), ],
'url' => array( 'url' => [
'name' => 'Exclude by url', 'name' => 'Exclude by url',
'required' => false, 'required' => false,
'title' => 'URL term, separated by semicolon (;)', 'title' => 'URL term, separated by semicolon (;)',
'exampleValue' => 'bon-plan;bons-plans' 'exampleValue' => 'bon-plan;bons-plans'
) ]
) ]
); ];
private $bannedTitle = array(); private $bannedTitle = [];
private $bannedURL = array(); private $bannedURL = [];
public function collectData() public function collectData()
{ {

View file

@ -7,29 +7,30 @@
// it is not reliable and contain no useful information. This bridge create a // it is not reliable and contain no useful information. This bridge create a
// sane feed with additional information like tags and a link to the CWE // sane feed with additional information like tags and a link to the CWE
// a description of the vulnerability. // a description of the vulnerability.
class CVEDetailsBridge extends BridgeAbstract { class CVEDetailsBridge extends BridgeAbstract
{
const MAINTAINER = 'Aaron Fischer'; const MAINTAINER = 'Aaron Fischer';
const NAME = 'CVE Details'; const NAME = 'CVE Details';
const CACHE_TIMEOUT = 60 * 60 * 6; // 6 hours const CACHE_TIMEOUT = 60 * 60 * 6; // 6 hours
const DESCRIPTION = 'Report new CVE vulnerabilities for a given vendor (and product)'; const DESCRIPTION = 'Report new CVE vulnerabilities for a given vendor (and product)';
const URI = 'https://www.cvedetails.com'; const URI = 'https://www.cvedetails.com';
const PARAMETERS = array(array( const PARAMETERS = [[
// The Vendor ID can be taken from the URL // The Vendor ID can be taken from the URL
'vendor_id' => array( 'vendor_id' => [
'name' => 'Vendor ID', 'name' => 'Vendor ID',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'exampleValue' => 74, // PHP 'exampleValue' => 74, // PHP
), ],
// The optional Product ID can be taken from the URL as well // The optional Product ID can be taken from the URL as well
'product_id' => array( 'product_id' => [
'name' => 'Product ID', 'name' => 'Product ID',
'type' => 'number', 'type' => 'number',
'required' => false, 'required' => false,
'exampleValue' => 128, // PHP 'exampleValue' => 128, // PHP
), ],
)); ]];
private $html = null; private $html = null;
private $vendor = ''; private $vendor = '';
@ -39,7 +40,8 @@ class CVEDetailsBridge extends BridgeAbstract {
// Because of the optional product ID, we need to attach it if it is // Because of the optional product ID, we need to attach it if it is
// set. The search result page has the exact same structure (with and // set. The search result page has the exact same structure (with and
// without the product ID). // without the product ID).
private function buildUrl() { private function buildUrl()
{
$url = self::URI . '/vulnerability-list/vendor_id-' . $this->getInput('vendor_id'); $url = self::URI . '/vulnerability-list/vendor_id-' . $this->getInput('vendor_id');
if ($this->getInput('product_id') !== '') { if ($this->getInput('product_id') !== '') {
$url .= '/product_id-' . $this->getInput('product_id'); $url .= '/product_id-' . $this->getInput('product_id');
@ -54,7 +56,8 @@ class CVEDetailsBridge extends BridgeAbstract {
// Make the actual request to cvedetails.com and stores the response // Make the actual request to cvedetails.com and stores the response
// (HTML) for later use and extract vendor and product from it. // (HTML) for later use and extract vendor and product from it.
private function fetchContent() { private function fetchContent()
{
$html = getSimpleHTMLDOM($this->buildUrl()); $html = getSimpleHTMLDOM($this->buildUrl());
$this->html = defaultLinkTo($html, self::URI); $this->html = defaultLinkTo($html, self::URI);
@ -74,7 +77,8 @@ class CVEDetailsBridge extends BridgeAbstract {
} }
// Build the name of the feed. // Build the name of the feed.
public function getName() { public function getName()
{
if ($this->getInput('vendor_id') == '') { if ($this->getInput('vendor_id') == '') {
return self::NAME; return self::NAME;
} }
@ -92,7 +96,8 @@ class CVEDetailsBridge extends BridgeAbstract {
} }
// Pull the data from the HTML response and fill the items.. // Pull the data from the HTML response and fill the items..
public function collectData() { public function collectData()
{
if ($this->html == null) { if ($this->html == null) {
$this->fetchContent(); $this->fetchContent();
} }
@ -101,8 +106,8 @@ class CVEDetailsBridge extends BridgeAbstract {
// There are some optional vulnerability types, which will be // There are some optional vulnerability types, which will be
// added to the categories as well as the CWE number -- which is // added to the categories as well as the CWE number -- which is
// always given. // always given.
$categories = array($this->vendor); $categories = [$this->vendor];
$enclosures = array(); $enclosures = [];
$cwe = $tr->find('td', 2)->find('a', 0); $cwe = $tr->find('td', 2)->find('a', 0);
if ($cwe != null) { if ($cwe != null) {
@ -121,7 +126,7 @@ class CVEDetailsBridge extends BridgeAbstract {
// The CVE number itself // The CVE number itself
$title = $tr->find('td', 1)->find('a', 0)->innertext; $title = $tr->find('td', 1)->find('a', 0)->innertext;
$this->items[] = array( $this->items[] = [
'uri' => $tr->find('td', 1)->find('a', 0)->href, 'uri' => $tr->find('td', 1)->find('a', 0)->href,
'title' => $title, 'title' => $title,
'timestamp' => $tr->find('td', 5)->innertext, 'timestamp' => $tr->find('td', 5)->innertext,
@ -129,7 +134,7 @@ class CVEDetailsBridge extends BridgeAbstract {
'categories' => $categories, 'categories' => $categories,
'enclosures' => $enclosures, 'enclosures' => $enclosures,
'uid' => $tr->find('td', 1)->find('a', 0)->innertext, 'uid' => $tr->find('td', 1)->find('a', 0)->innertext,
); ];
// We only want to fetch the latest 10 CVEs // We only want to fetch the latest 10 CVEs
if (count($this->items) >= 10) { if (count($this->items) >= 10) {

View file

@ -1,30 +1,32 @@
<?php <?php
class CachetBridge extends BridgeAbstract { class CachetBridge extends BridgeAbstract
{
const NAME = 'Cachet Bridge'; const NAME = 'Cachet Bridge';
const URI = 'https://cachethq.io/'; const URI = 'https://cachethq.io/';
const DESCRIPTION = 'Returns status updates from any Cachet installation'; const DESCRIPTION = 'Returns status updates from any Cachet installation';
const MAINTAINER = 'klimplant'; const MAINTAINER = 'klimplant';
const PARAMETERS = array( const PARAMETERS = [
array( [
'host' => array( 'host' => [
'name' => 'Cachet installation', 'name' => 'Cachet installation',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'title' => 'The URL of the Cachet installation', 'title' => 'The URL of the Cachet installation',
'exampleValue' => 'https://demo.cachethq.io/', 'exampleValue' => 'https://demo.cachethq.io/',
), 'additional_info' => array( ], 'additional_info' => [
'name' => 'Additional Timestamps', 'name' => 'Additional Timestamps',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Whether to include the given timestamps' 'title' => 'Whether to include the given timestamps'
) ]
) ]
); ];
const CACHE_TIMEOUT = 300; const CACHE_TIMEOUT = 300;
private $componentCache = array(); private $componentCache = [];
public function getURI() { public function getURI()
{
return $this->getInput('host') === null ? 'https://cachethq.io/' : $this->getInput('host'); return $this->getInput('host') === null ? 'https://cachethq.io/' : $this->getInput('host');
} }
@ -34,7 +36,8 @@ class CachetBridge extends BridgeAbstract {
* @param string $ping * @param string $ping
* @return boolean * @return boolean
*/ */
private function validatePing($ping) { private function validatePing($ping)
{
$ping = json_decode($ping); $ping = json_decode($ping);
if ($ping === null) { if ($ping === null) {
return false; return false;
@ -48,7 +51,8 @@ class CachetBridge extends BridgeAbstract {
* @param integer $id * @param integer $id
* @return string * @return string
*/ */
private function getComponentName($id) { private function getComponentName($id)
{
if ($id === 0) { if ($id === 0) {
return ''; return '';
} }
@ -64,7 +68,8 @@ class CachetBridge extends BridgeAbstract {
return $component->data->name; return $component->data->name;
} }
public function collectData() { public function collectData()
{
$ping = getContents(urljoin($this->getURI(), '/api/v1/ping')); $ping = getContents(urljoin($this->getURI(), '/api/v1/ping'));
if (!$this->validatePing($ping)) { if (!$this->validatePing($ping)) {
returnClientError('Provided URI is invalid!'); returnClientError('Provided URI is invalid!');
@ -84,7 +89,6 @@ class CachetBridge extends BridgeAbstract {
}); });
foreach ($incidents->data as $incident) { foreach ($incidents->data as $incident) {
if (isset($incident->permalink)) { if (isset($incident->permalink)) {
$permalink = $incident->permalink; $permalink = $incident->permalink;
} else { } else {
@ -114,13 +118,13 @@ class CachetBridge extends BridgeAbstract {
$uidOrig = $permalink . $incident->created_at; $uidOrig = $permalink . $incident->created_at;
$uid = hash('sha512', $uidOrig); $uid = hash('sha512', $uidOrig);
$timestamp = strtotime($incident->created_at); $timestamp = strtotime($incident->created_at);
$categories = array(); $categories = [];
$categories[] = $incident->human_status; $categories[] = $incident->human_status;
if ($componentName !== '') { if ($componentName !== '') {
$categories[] = $componentName; $categories[] = $componentName;
} }
$item = array(); $item = [];
$item['uri'] = $permalink; $item['uri'] = $permalink;
$item['title'] = $title; $item['title'] = $title;
$item['timestamp'] = $timestamp; $item['timestamp'] = $timestamp;

View file

@ -1,15 +1,19 @@
<?php <?php
class CarThrottleBridge extends FeedExpander {
class CarThrottleBridge extends FeedExpander
{
const NAME = 'Car Throttle '; const NAME = 'Car Throttle ';
const URI = 'https://www.carthrottle.com'; const URI = 'https://www.carthrottle.com';
const DESCRIPTION = 'Get the latest car-related news from Car Throttle.'; const DESCRIPTION = 'Get the latest car-related news from Car Throttle.';
const MAINTAINER = 't0stiman'; const MAINTAINER = 't0stiman';
public function collectData() { public function collectData()
{
$this->collectExpandableDatas('https://www.carthrottle.com/rss', 10); $this->collectExpandableDatas('https://www.carthrottle.com/rss', 10);
} }
protected function parseItem($feedItem) { protected function parseItem($feedItem)
{
$item = parent::parseItem($feedItem); $item = parent::parseItem($feedItem);
//fetch page //fetch page
@ -22,8 +26,7 @@ class CarThrottleBridge extends FeedExpander {
$item['content'] = str_get_html($subtitle . $article); $item['content'] = str_get_html($subtitle . $article);
//convert <iframe>s to <a>s. meant for embedded videos. //convert <iframe>s to <a>s. meant for embedded videos.
foreach($item['content']->find('iframe') as $found) { foreach ($item['content']->find('iframe') as $found) {
$iframeUrl = $found->getAttribute('src'); $iframeUrl = $found->getAttribute('src');
if ($iframeUrl) { if ($iframeUrl) {

View file

@ -1,63 +1,71 @@
<?php <?php
class CastorusBridge extends BridgeAbstract {
class CastorusBridge extends BridgeAbstract
{
const MAINTAINER = 'logmanoriginal'; const MAINTAINER = 'logmanoriginal';
const NAME = 'Castorus Bridge'; const NAME = 'Castorus Bridge';
const URI = 'https://www.castorus.com'; const URI = 'https://www.castorus.com';
const CACHE_TIMEOUT = 600; // 10min const CACHE_TIMEOUT = 600; // 10min
const DESCRIPTION = 'Returns the latest changes'; const DESCRIPTION = 'Returns the latest changes';
const PARAMETERS = array( const PARAMETERS = [
'Get latest changes' => array(), 'Get latest changes' => [],
'Get latest changes via ZIP code' => array( 'Get latest changes via ZIP code' => [
'zip' => array( 'zip' => [
'name' => 'ZIP code', 'name' => 'ZIP code',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => '7', 'exampleValue' => '7',
'title' => 'Insert ZIP code (complete or partial). e.g: 78125 OR 781 OR 7' 'title' => 'Insert ZIP code (complete or partial). e.g: 78125 OR 781 OR 7'
) ]
), ],
'Get latest changes via city name' => array( 'Get latest changes via city name' => [
'city' => array( 'city' => [
'name' => 'City name', 'name' => 'City name',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'Paris', 'exampleValue' => 'Paris',
'title' => 'Insert city name (complete or partial). e.g: Paris OR Par OR P' 'title' => 'Insert city name (complete or partial). e.g: Paris OR Par OR P'
) ]
) ]
); ];
// Extracts the title from an actitiy // Extracts the title from an actitiy
private function extractActivityTitle($activity){ private function extractActivityTitle($activity)
{
$title = $activity->find('a', 0); $title = $activity->find('a', 0);
if(!$title) if (!$title) {
returnServerError('Cannot find title!'); returnServerError('Cannot find title!');
}
return trim($title->plaintext); return trim($title->plaintext);
} }
// Extracts the url from an actitiy // Extracts the url from an actitiy
private function extractActivityUrl($activity){ private function extractActivityUrl($activity)
{
$url = $activity->find('a', 0); $url = $activity->find('a', 0);
if(!$url) if (!$url) {
returnServerError('Cannot find url!'); returnServerError('Cannot find url!');
}
return self::URI . $url->href; return self::URI . $url->href;
} }
// Extracts the time from an activity // Extracts the time from an activity
private function extractActivityTime($activity){ private function extractActivityTime($activity)
{
// Unfortunately the time is part of the parent node, // Unfortunately the time is part of the parent node,
// so we have to clear all child nodes first // so we have to clear all child nodes first
$nodes = $activity->find('*'); $nodes = $activity->find('*');
if(!$nodes) if (!$nodes) {
returnServerError('Cannot find nodes!'); returnServerError('Cannot find nodes!');
}
foreach($nodes as $node) { foreach ($nodes as $node) {
$node->outertext = ''; $node->outertext = '';
} }
@ -65,31 +73,36 @@ class CastorusBridge extends BridgeAbstract {
} }
// Extracts the price change // Extracts the price change
private function extractActivityPrice($activity){ private function extractActivityPrice($activity)
{
$price = $activity->find('span', 1); $price = $activity->find('span', 1);
if(!$price) if (!$price) {
returnServerError('Cannot find price!'); returnServerError('Cannot find price!');
}
return $price->innertext; return $price->innertext;
} }
public function collectData(){ public function collectData()
{
$zip_filter = trim($this->getInput('zip')); $zip_filter = trim($this->getInput('zip'));
$city_filter = trim($this->getInput('city')); $city_filter = trim($this->getInput('city'));
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
if(!$html) if (!$html) {
returnServerError('Could not load data from ' . self::URI . '!'); returnServerError('Could not load data from ' . self::URI . '!');
}
$activities = $html->find('div#activite > li'); $activities = $html->find('div#activite > li');
if(!$activities) if (!$activities) {
returnServerError('Failed to find activities!'); returnServerError('Failed to find activities!');
}
foreach($activities as $activity) { foreach ($activities as $activity) {
$item = array(); $item = [];
$item['title'] = $this->extractActivityTitle($activity); $item['title'] = $this->extractActivityTitle($activity);
$item['uri'] = $this->extractActivityUrl($activity); $item['uri'] = $this->extractActivityUrl($activity);
@ -102,13 +115,17 @@ class CastorusBridge extends BridgeAbstract {
. $this->extractActivityPrice($activity) . $this->extractActivityPrice($activity)
. '</p>'; . '</p>';
if(isset($zip_filter) if (
&& !(substr($item['title'], 0, strlen($zip_filter)) === $zip_filter)) { isset($zip_filter)
&& !(substr($item['title'], 0, strlen($zip_filter)) === $zip_filter)
) {
continue; // Skip this item continue; // Skip this item
} }
if(isset($city_filter) if (
&& !(substr($item['title'], strpos($item['title'], ' ') + 1, strlen($city_filter)) === $city_filter)) { isset($city_filter)
&& !(substr($item['title'], strpos($item['title'], ' ') + 1, strlen($city_filter)) === $city_filter)
) {
continue; // Skip this item continue; // Skip this item
} }

View file

@ -1,40 +1,42 @@
<?php <?php
class CdactionBridge extends BridgeAbstract { class CdactionBridge extends BridgeAbstract
{
const NAME = 'CD-ACTION bridge'; const NAME = 'CD-ACTION bridge';
const URI = 'https://cdaction.pl'; const URI = 'https://cdaction.pl';
const DESCRIPTION = 'Fetches the latest posts from given category.'; const DESCRIPTION = 'Fetches the latest posts from given category.';
const MAINTAINER = 'tomaszkane'; const MAINTAINER = 'tomaszkane';
const PARAMETERS = array( array( const PARAMETERS = [ [
'category' => array( 'category' => [
'name' => 'Kategoria', 'name' => 'Kategoria',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Najnowsze (wszystkie)' => 'najnowsze', 'Najnowsze (wszystkie)' => 'najnowsze',
'Newsy' => 'newsy', 'Newsy' => 'newsy',
'Recenzje' => 'recenzje', 'Recenzje' => 'recenzje',
'Teksty' => array( 'Teksty' => [
'Publicystyka' => 'publicystyka', 'Publicystyka' => 'publicystyka',
'Zapowiedzi' => 'zapowiedzi', 'Zapowiedzi' => 'zapowiedzi',
'Już graliśmy' => 'juz-gralismy', 'Już graliśmy' => 'juz-gralismy',
'Poradniki' => 'poradniki', 'Poradniki' => 'poradniki',
), ],
'Kultura' => 'kultura', 'Kultura' => 'kultura',
'Wideo' => 'wideo', 'Wideo' => 'wideo',
'Czasopismo' => 'czasopismo', 'Czasopismo' => 'czasopismo',
'Technologie' => array( 'Technologie' => [
'Artykuły' => 'artykuly', 'Artykuły' => 'artykuly',
'Testy' => 'testy', 'Testy' => 'testy',
), ],
'Na luzie' => array( 'Na luzie' => [
'Konkursy' => 'konkursy', 'Konkursy' => 'konkursy',
'Nadgodziny' => 'nadgodziny', 'Nadgodziny' => 'nadgodziny',
) ]
) ]
)) ]]
); ];
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI() . '/' . $this->getInput('category')); $html = getSimpleHTMLDOM($this->getURI() . '/' . $this->getInput('category'));
$newsJson = $html->find('script#__NEXT_DATA__', 0)->innertext; $newsJson = $html->find('script#__NEXT_DATA__', 0)->innertext;
@ -44,7 +46,7 @@ class CdactionBridge extends BridgeAbstract {
$queriesIndex = $this->getInput('category') === 'najnowsze' ? 0 : 1; $queriesIndex = $this->getInput('category') === 'najnowsze' ? 0 : 1;
foreach ($newsJson->props->pageProps->dehydratedState->queries[$queriesIndex]->state->data->results as $news) { foreach ($newsJson->props->pageProps->dehydratedState->queries[$queriesIndex]->state->data->results as $news) {
$item = array(); $item = [];
$item['uri'] = $this->getURI() . '/' . $news->category->slug . '/' . $news->slug; $item['uri'] = $this->getURI() . '/' . $news->category->slug . '/' . $news->slug;
$item['title'] = $news->title; $item['title'] = $news->title;
$item['timestamp'] = $news->publishedAt; $item['timestamp'] = $news->publishedAt;

View file

@ -1,28 +1,30 @@
<?php <?php
class CeskaTelevizeBridge extends BridgeAbstract { class CeskaTelevizeBridge extends BridgeAbstract
{
const NAME = 'Česká televize Bridge'; const NAME = 'Česká televize Bridge';
const URI = 'https://www.ceskatelevize.cz'; const URI = 'https://www.ceskatelevize.cz';
const CACHE_TIMEOUT = 3600; const CACHE_TIMEOUT = 3600;
const DESCRIPTION = 'Return newest videos'; const DESCRIPTION = 'Return newest videos';
const MAINTAINER = 'kolarcz'; const MAINTAINER = 'kolarcz';
const PARAMETERS = array( const PARAMETERS = [
array( [
'url' => array( 'url' => [
'name' => 'url to the show', 'name' => 'url to the show',
'required' => true, 'required' => true,
'exampleValue' => 'https://www.ceskatelevize.cz/porady/1097181328-udalosti/' 'exampleValue' => 'https://www.ceskatelevize.cz/porady/1097181328-udalosti/'
) ]
) ]
); ];
private function fixChars($text) { private function fixChars($text)
{
return html_entity_decode($text, ENT_QUOTES, 'UTF-8'); return html_entity_decode($text, ENT_QUOTES, 'UTF-8');
} }
private function getUploadTimeFromString($string) { private function getUploadTimeFromString($string)
{
if (strpos($string, 'dnes') !== false) { if (strpos($string, 'dnes') !== false) {
return strtotime('today'); return strtotime('today');
} elseif (strpos($string, 'včera') !== false) { } elseif (strpos($string, 'včera') !== false) {
@ -35,7 +37,8 @@ class CeskaTelevizeBridge extends BridgeAbstract {
return strtotime($date); return strtotime($date);
} }
public function collectData() { public function collectData()
{
$url = $this->getInput('url'); $url = $this->getInput('url');
$validUrl = '/^(https:\/\/www\.ceskatelevize\.cz\/porady\/\d+-[a-z0-9-]+\/)(bonus\/)?$/'; $validUrl = '/^(https:\/\/www\.ceskatelevize\.cz\/porady\/\d+-[a-z0-9-]+\/)(bonus\/)?$/';
@ -61,23 +64,25 @@ class CeskaTelevizeBridge extends BridgeAbstract {
$itemThumbnail = $element->find('img', 0); $itemThumbnail = $element->find('img', 0);
$itemUri = self::URI . $element->getAttribute('href'); $itemUri = self::URI . $element->getAttribute('href');
$item = array( $item = [
'title' => $this->fixChars($itemTitle->plaintext), 'title' => $this->fixChars($itemTitle->plaintext),
'uri' => $itemUri, 'uri' => $itemUri,
'content' => '<img src="' . $itemThumbnail->getAttribute('src') . '" /><br />' 'content' => '<img src="' . $itemThumbnail->getAttribute('src') . '" /><br />'
. $this->fixChars($itemContent->plaintext), . $this->fixChars($itemContent->plaintext),
'timestamp' => $this->getUploadTimeFromString($itemDate->plaintext) 'timestamp' => $this->getUploadTimeFromString($itemDate->plaintext)
); ];
$this->items[] = $item; $this->items[] = $item;
} }
} }
public function getURI() { public function getURI()
{
return isset($this->feedUri) ? $this->feedUri : parent::getURI(); return isset($this->feedUri) ? $this->feedUri : parent::getURI();
} }
public function getName() { public function getName()
{
return isset($this->feedName) ? $this->feedName : parent::getName(); return isset($this->feedName) ? $this->feedName : parent::getName();
} }
} }

View file

@ -1,69 +1,71 @@
<?php <?php
class CodebergBridge extends BridgeAbstract {
class CodebergBridge extends BridgeAbstract
{
const NAME = 'Codeberg Bridge'; const NAME = 'Codeberg Bridge';
const URI = 'https://codeberg.org/'; const URI = 'https://codeberg.org/';
const DESCRIPTION = 'Returns commits, issues, pull requests or releases for a repository.'; const DESCRIPTION = 'Returns commits, issues, pull requests or releases for a repository.';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array( const PARAMETERS = [
'Commits' => array( 'Commits' => [
'branch' => array( 'branch' => [
'name' => 'branch', 'name' => 'branch',
'type' => 'text', 'type' => 'text',
'exampleValue' => 'main', 'exampleValue' => 'main',
'required' => false, 'required' => false,
'title' => 'Optional, main branch is used by default.', 'title' => 'Optional, main branch is used by default.',
), ],
), ],
'Issues' => array(), 'Issues' => [],
'Issue Comments' => array( 'Issue Comments' => [
'issueId' => array( 'issueId' => [
'name' => 'Issue ID', 'name' => 'Issue ID',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => '513', 'exampleValue' => '513',
) ]
), ],
'Pull Requests' => array(), 'Pull Requests' => [],
'Releases' => array(), 'Releases' => [],
'global' => array( 'global' => [
'username' => array( 'username' => [
'name' => 'Username', 'name' => 'Username',
'type' => 'text', 'type' => 'text',
'exampleValue' => 'Codeberg', 'exampleValue' => 'Codeberg',
'title' => 'Username of account that the repository belongs to.', 'title' => 'Username of account that the repository belongs to.',
'required' => true, 'required' => true,
), ],
'repo' => array( 'repo' => [
'name' => 'Repository', 'name' => 'Repository',
'type' => 'text', 'type' => 'text',
'exampleValue' => 'Community', 'exampleValue' => 'Community',
'required' => true, 'required' => true,
) ]
) ]
); ];
const CACHE_TIMEOUT = 1800; const CACHE_TIMEOUT = 1800;
const TEST_DETECT_PARAMETERS = array( const TEST_DETECT_PARAMETERS = [
'https://codeberg.org/Codeberg/Community/issues/507' => array( 'https://codeberg.org/Codeberg/Community/issues/507' => [
'context' => 'Issue Comments', 'username' => 'Codeberg', 'repo' => 'Community', 'issueId' => '507' 'context' => 'Issue Comments', 'username' => 'Codeberg', 'repo' => 'Community', 'issueId' => '507'
), ],
'https://codeberg.org/Codeberg/Community/issues' => array( 'https://codeberg.org/Codeberg/Community/issues' => [
'context' => 'Issues', 'username' => 'Codeberg', 'repo' => 'Community' 'context' => 'Issues', 'username' => 'Codeberg', 'repo' => 'Community'
), ],
'https://codeberg.org/Codeberg/Community/pulls' => array( 'https://codeberg.org/Codeberg/Community/pulls' => [
'context' => 'Pull Requests', 'username' => 'Codeberg', 'repo' => 'Community' 'context' => 'Pull Requests', 'username' => 'Codeberg', 'repo' => 'Community'
), ],
'https://codeberg.org/Codeberg/Community/releases' => array( 'https://codeberg.org/Codeberg/Community/releases' => [
'context' => 'Releases', 'username' => 'Codeberg', 'repo' => 'Community' 'context' => 'Releases', 'username' => 'Codeberg', 'repo' => 'Community'
), ],
'https://codeberg.org/Codeberg/Community/commits/branch/master' => array( 'https://codeberg.org/Codeberg/Community/commits/branch/master' => [
'context' => 'Commits', 'username' => 'Codeberg', 'repo' => 'Community', 'branch' => 'master' 'context' => 'Commits', 'username' => 'Codeberg', 'repo' => 'Community', 'branch' => 'master'
), ],
'https://codeberg.org/Codeberg/Community/commits' => array( 'https://codeberg.org/Codeberg/Community/commits' => [
'context' => 'Commits', 'username' => 'Codeberg', 'repo' => 'Community' 'context' => 'Commits', 'username' => 'Codeberg', 'repo' => 'Community'
) ]
); ];
private $defaultBranch = 'main'; private $defaultBranch = 'main';
private $issueTitle = ''; private $issueTitle = '';
@ -74,11 +76,12 @@ class CodebergBridge extends BridgeAbstract {
private $releasesUrlRegex = '/codeberg\.org\/([\w]+)\/([\w]+)\/releases/'; private $releasesUrlRegex = '/codeberg\.org\/([\w]+)\/([\w]+)\/releases/';
private $issueCommentsUrlRegex = '/codeberg\.org\/([\w]+)\/([\w]+)\/issues\/([0-9]+)/'; private $issueCommentsUrlRegex = '/codeberg\.org\/([\w]+)\/([\w]+)\/issues\/([0-9]+)/';
public function detectParameters($url) { public function detectParameters($url)
$params = array(); {
$params = [];
// Issue Comments // Issue Comments
if(preg_match($this->issueCommentsUrlRegex, $url, $matches)) { if (preg_match($this->issueCommentsUrlRegex, $url, $matches)) {
$params['context'] = 'Issue Comments'; $params['context'] = 'Issue Comments';
$params['username'] = $matches[1]; $params['username'] = $matches[1];
$params['repo'] = $matches[2]; $params['repo'] = $matches[2];
@ -88,7 +91,7 @@ class CodebergBridge extends BridgeAbstract {
} }
// Issues // Issues
if(preg_match($this->issuesUrlRegex, $url, $matches)) { if (preg_match($this->issuesUrlRegex, $url, $matches)) {
$params['context'] = 'Issues'; $params['context'] = 'Issues';
$params['username'] = $matches[1]; $params['username'] = $matches[1];
$params['repo'] = $matches[2]; $params['repo'] = $matches[2];
@ -97,7 +100,7 @@ class CodebergBridge extends BridgeAbstract {
} }
// Pull Requests // Pull Requests
if(preg_match($this->pullsUrlRegex, $url, $matches)) { if (preg_match($this->pullsUrlRegex, $url, $matches)) {
$params['context'] = 'Pull Requests'; $params['context'] = 'Pull Requests';
$params['username'] = $matches[1]; $params['username'] = $matches[1];
$params['repo'] = $matches[2]; $params['repo'] = $matches[2];
@ -106,7 +109,7 @@ class CodebergBridge extends BridgeAbstract {
} }
// Releases // Releases
if(preg_match($this->releasesUrlRegex, $url, $matches)) { if (preg_match($this->releasesUrlRegex, $url, $matches)) {
$params['context'] = 'Releases'; $params['context'] = 'Releases';
$params['username'] = $matches[1]; $params['username'] = $matches[1];
$params['repo'] = $matches[2]; $params['repo'] = $matches[2];
@ -115,7 +118,7 @@ class CodebergBridge extends BridgeAbstract {
} }
// Commits // Commits
if(preg_match($this->urlRegex, $url, $matches)) { if (preg_match($this->urlRegex, $url, $matches)) {
$params['context'] = 'Commits'; $params['context'] = 'Commits';
$params['username'] = $matches[1]; $params['username'] = $matches[1];
$params['repo'] = $matches[2]; $params['repo'] = $matches[2];
@ -130,12 +133,13 @@ class CodebergBridge extends BridgeAbstract {
return null; return null;
} }
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
$html = defaultLinkTo($html, $this->getURI()); $html = defaultLinkTo($html, $this->getURI());
switch($this->queriedContext) { switch ($this->queriedContext) {
case 'Commits': case 'Commits':
$this->extractCommits($html); $this->extractCommits($html);
break; break;
@ -156,8 +160,9 @@ class CodebergBridge extends BridgeAbstract {
} }
} }
public function getName() { public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Commits': case 'Commits':
if ($this->getBranch() === $this->defaultBranch) { if ($this->getBranch() === $this->defaultBranch) {
return $this->getRepo() . ' Commits'; return $this->getRepo() . ' Commits';
@ -177,8 +182,9 @@ class CodebergBridge extends BridgeAbstract {
} }
} }
public function getURI() { public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Commits': case 'Commits':
return self::URI . $this->getRepo() . '/commits/branch/' . $this->getBranch(); return self::URI . $this->getRepo() . '/commits/branch/' . $this->getBranch();
case 'Issues': case 'Issues':
@ -194,7 +200,8 @@ class CodebergBridge extends BridgeAbstract {
} }
} }
private function getBranch() { private function getBranch()
{
if ($this->getInput('branch')) { if ($this->getInput('branch')) {
return $this->getInput('branch'); return $this->getInput('branch');
} }
@ -202,19 +209,21 @@ class CodebergBridge extends BridgeAbstract {
return $this->defaultBranch; return $this->defaultBranch;
} }
private function getRepo() { private function getRepo()
{
return $this->getInput('username') . '/' . $this->getInput('repo'); return $this->getInput('username') . '/' . $this->getInput('repo');
} }
/** /**
* Extract commits * Extract commits
*/ */
private function extractCommits($html) { private function extractCommits($html)
{
$table = $html->find('table#commits-table', 0); $table = $html->find('table#commits-table', 0);
$tbody = $table->find('tbody.commit-list', 0); $tbody = $table->find('tbody.commit-list', 0);
foreach ($tbody->find('tr') as $tr) { foreach ($tbody->find('tr') as $tr) {
$item = array(); $item = [];
$message = $tr->find('td.message', 0); $message = $tr->find('td.message', 0);
@ -238,11 +247,12 @@ class CodebergBridge extends BridgeAbstract {
/** /**
* Extract issues * Extract issues
*/ */
private function extractIssues($html) { private function extractIssues($html)
{
$div = $html->find('div.issue.list', 0); $div = $html->find('div.issue.list', 0);
foreach ($div->find('li.item') as $li) { foreach ($div->find('li.item') as $li) {
$item = array(); $item = [];
$number = trim($li->find('a.index,ml-0.mr-2', 0)->plaintext); $number = trim($li->find('a.index,ml-0.mr-2', 0)->plaintext);
@ -268,12 +278,13 @@ class CodebergBridge extends BridgeAbstract {
/** /**
* Extract issue comments * Extract issue comments
*/ */
private function extractIssueComments($html) { private function extractIssueComments($html)
{
$this->issueTitle = $html->find('span#issue-title', 0)->plaintext $this->issueTitle = $html->find('span#issue-title', 0)->plaintext
. ' (' . $html->find('span.index', 0)->plaintext . ')'; . ' (' . $html->find('span.index', 0)->plaintext . ')';
foreach ($html->find('div.timeline-item.comment') as $div) { foreach ($html->find('div.timeline-item.comment') as $div) {
$item = array(); $item = [];
if ($div->class === 'timeline-item comment merge box') { if ($div->class === 'timeline-item comment merge box') {
continue; continue;
@ -297,11 +308,12 @@ class CodebergBridge extends BridgeAbstract {
/** /**
* Extract pulls * Extract pulls
*/ */
private function extractPulls($html) { private function extractPulls($html)
{
$div = $html->find('div.issue.list', 0); $div = $html->find('div.issue.list', 0);
foreach ($div->find('li.item') as $li) { foreach ($div->find('li.item') as $li) {
$item = array(); $item = [];
$number = trim($li->find('a.index,ml-0.mr-2', 0)->plaintext); $number = trim($li->find('a.index,ml-0.mr-2', 0)->plaintext);
@ -327,11 +339,12 @@ class CodebergBridge extends BridgeAbstract {
/** /**
* Extract releases * Extract releases
*/ */
private function extractReleases($html) { private function extractReleases($html)
{
$ul = $html->find('ul#release-list', 0); $ul = $html->find('ul#release-list', 0);
foreach ($ul->find('li.ui.grid') as $li) { foreach ($ul->find('li.ui.grid') as $li) {
$item = array(); $item = [];
$item['title'] = $li->find('h4', 0)->plaintext; $item['title'] = $li->find('h4', 0)->plaintext;
$item['uri'] = $li->find('h4', 0)->find('a', 0)->href; $item['uri'] = $li->find('h4', 0)->find('a', 0)->href;
@ -358,7 +371,8 @@ HTML;
/** /**
* Extract downloads for a releases * Extract downloads for a releases
*/ */
private function extractDownloads($html, $skipFirst = false) { private function extractDownloads($html, $skipFirst = false)
{
$downloads = ''; $downloads = '';
foreach ($html->find('a') as $index => $a) { foreach ($html->find('a') as $index => $a) {
@ -380,7 +394,8 @@ EOD;
/** /**
* Ellipsis title to first 100 characters * Ellipsis title to first 100 characters
*/ */
private function ellipsisTitle($text) { private function ellipsisTitle($text)
{
$length = 100; $length = 100;
if (strlen($text) > $length) { if (strlen($text) > $length) {
@ -393,7 +408,8 @@ EOD;
/** /**
* Strip SVG tag * Strip SVG tag
*/ */
private function stripSvg($html) { private function stripSvg($html)
{
if ($html->find('svg', 0)) { if ($html->find('svg', 0)) {
$html->find('svg', 0)->outertext = ''; $html->find('svg', 0)->outertext = '';
} }

View file

@ -1,14 +1,16 @@
<?php <?php
class CollegeDeFranceBridge extends BridgeAbstract {
class CollegeDeFranceBridge extends BridgeAbstract
{
const MAINTAINER = 'pit-fgfjiudghdf'; const MAINTAINER = 'pit-fgfjiudghdf';
const NAME = 'CollegeDeFrance'; const NAME = 'CollegeDeFrance';
const URI = 'https://www.college-de-france.fr/'; const URI = 'https://www.college-de-france.fr/';
const CACHE_TIMEOUT = 10800; // 3h const CACHE_TIMEOUT = 10800; // 3h
const DESCRIPTION = 'Returns the latest audio and video from CollegeDeFrance'; const DESCRIPTION = 'Returns the latest audio and video from CollegeDeFrance';
public function collectData(){ public function collectData()
$months = array( {
$months = [
'01' => 'janv.', '01' => 'janv.',
'02' => 'févr.', '02' => 'févr.',
'03' => 'mars', '03' => 'mars',
@ -21,7 +23,7 @@ class CollegeDeFranceBridge extends BridgeAbstract {
'10' => 'oct.', '10' => 'oct.',
'11' => 'nov.', '11' => 'nov.',
'12' => 'déc.' '12' => 'déc.'
); ];
// The "API" used by the site returns a list of partial HTML in this form // The "API" used by the site returns a list of partial HTML in this form
/* <li> /* <li>
@ -36,8 +38,8 @@ class CollegeDeFranceBridge extends BridgeAbstract {
$html = getSimpleHTMLDOM(self::URI $html = getSimpleHTMLDOM(self::URI
. 'components/search-audiovideo.jsp?fulltext=&siteid=1156951719600&lang=FR&type=all'); . 'components/search-audiovideo.jsp?fulltext=&siteid=1156951719600&lang=FR&type=all');
foreach($html->find('a[data-target]') as $element) { foreach ($html->find('a[data-target]') as $element) {
$item = array(); $item = [];
$item['title'] = $element->find('.title', 0)->plaintext; $item['title'] = $element->find('.title', 0)->plaintext;
// Most relative URLs contains an hour in addition to the date, so let's use it // Most relative URLs contains an hour in addition to the date, so let's use it
@ -59,7 +61,7 @@ class CollegeDeFranceBridge extends BridgeAbstract {
$timezone $timezone
); );
if(!$d) { if (!$d) {
$d = DateTime::createFromFormat( $d = DateTime::createFromFormat(
'!d m Y', '!d m Y',
trim(str_replace( trim(str_replace(

View file

@ -1,20 +1,23 @@
<?php <?php
class ComboiosDePortugalBridge extends BridgeAbstract {
class ComboiosDePortugalBridge extends BridgeAbstract
{
const NAME = 'CP | Avisos'; const NAME = 'CP | Avisos';
const BASE_URI = 'https://www.cp.pt'; const BASE_URI = 'https://www.cp.pt';
const URI = self::BASE_URI . '/passageiros/pt'; const URI = self::BASE_URI . '/passageiros/pt';
const DESCRIPTION = 'Comboios de Portugal | Avisos'; const DESCRIPTION = 'Comboios de Portugal | Avisos';
const MAINTAINER = 'somini'; const MAINTAINER = 'somini';
public function collectData() { public function collectData()
{
# Do not verify SSL certificate (the server doesn't send the intermediate) # Do not verify SSL certificate (the server doesn't send the intermediate)
# https://github.com/RSS-Bridge/rss-bridge/issues/2397 # https://github.com/RSS-Bridge/rss-bridge/issues/2397
$html = getSimpleHTMLDOM($this->getURI() . '/consultar-horarios/avisos', array(), array( $html = getSimpleHTMLDOM($this->getURI() . '/consultar-horarios/avisos', [], [
CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_SSL_VERIFYPEER => 0,
)); ]);
foreach($html->find('.warnings-table a') as $element) { foreach ($html->find('.warnings-table a') as $element) {
$item = array(); $item = [];
$item['title'] = $element->innertext; $item['title'] = $element->innertext;
$item['uri'] = self::BASE_URI . implode('/', array_map('urlencode', explode('/', $element->href))); $item['uri'] = self::BASE_URI . implode('/', array_map('urlencode', explode('/', $element->href)));

View file

@ -1,31 +1,34 @@
<?php <?php
class ComicsKingdomBridge extends BridgeAbstract {
class ComicsKingdomBridge extends BridgeAbstract
{
const MAINTAINER = 'stjohnjohnson'; const MAINTAINER = 'stjohnjohnson';
const NAME = 'Comics Kingdom Unofficial RSS'; const NAME = 'Comics Kingdom Unofficial RSS';
const URI = 'https://comicskingdom.com/'; const URI = 'https://comicskingdom.com/';
const CACHE_TIMEOUT = 21600; // 6h const CACHE_TIMEOUT = 21600; // 6h
const DESCRIPTION = 'Comics Kingdom Unofficial RSS'; const DESCRIPTION = 'Comics Kingdom Unofficial RSS';
const PARAMETERS = array( array( const PARAMETERS = [ [
'comicname' => array( 'comicname' => [
'name' => 'comicname', 'name' => 'comicname',
'type' => 'text', 'type' => 'text',
'exampleValue' => 'mutts', 'exampleValue' => 'mutts',
'title' => 'The name of the comic in the URL after https://comicskingdom.com/', 'title' => 'The name of the comic in the URL after https://comicskingdom.com/',
'required' => true 'required' => true
) ]
)); ]];
public function collectData(){ public function collectData()
$html = getSimpleHTMLDOM($this->getURI(), array(), array(), true, false); {
$html = getSimpleHTMLDOM($this->getURI(), [], [], true, false);
// Get author from first page // Get author from first page
$author = $html->find('div.author p', 0);; $author = $html->find('div.author p', 0);
;
// Get current date/link // Get current date/link
$link = $html->find('meta[property=og:url]', -1)->content; $link = $html->find('meta[property=og:url]', -1)->content;
for($i = 0; $i < 3; $i++) { for ($i = 0; $i < 3; $i++) {
$item = array(); $item = [];
$page = getSimpleHTMLDOM($link); $page = getSimpleHTMLDOM($link);
@ -42,20 +45,24 @@ class ComicsKingdomBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
$link = $page->find('div.comic-viewer-inline a', 0)->href; $link = $page->find('div.comic-viewer-inline a', 0)->href;
if (empty($link)) break; // allow bridge to continue if there's less than 3 comics if (empty($link)) {
break; // allow bridge to continue if there's less than 3 comics
}
} }
} }
public function getURI(){ public function getURI()
if(!is_null($this->getInput('comicname'))) { {
if (!is_null($this->getInput('comicname'))) {
return self::URI . urlencode($this->getInput('comicname')); return self::URI . urlencode($this->getInput('comicname'));
} }
return parent::getURI(); return parent::getURI();
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('comicname'))) { {
if (!is_null($this->getInput('comicname'))) {
return $this->getInput('comicname') . ' - Comics Kingdom'; return $this->getInput('comicname') . ' - Comics Kingdom';
} }

View file

@ -1,26 +1,30 @@
<?php <?php
class CommonDreamsBridge extends FeedExpander {
class CommonDreamsBridge extends FeedExpander
{
const MAINTAINER = 'nyutag'; const MAINTAINER = 'nyutag';
const NAME = 'CommonDreams Bridge'; const NAME = 'CommonDreams Bridge';
const URI = 'https://www.commondreams.org/'; const URI = 'https://www.commondreams.org/';
const DESCRIPTION = 'Returns the newest articles.'; const DESCRIPTION = 'Returns the newest articles.';
public function collectData(){ public function collectData()
{
$this->collectExpandableDatas('http://www.commondreams.org/rss.xml', 10); $this->collectExpandableDatas('http://www.commondreams.org/rss.xml', 10);
} }
protected function parseItem($newsItem){ protected function parseItem($newsItem)
{
$item = parent::parseItem($newsItem); $item = parent::parseItem($newsItem);
$item['content'] = $this->extractContent($item['uri']); $item['content'] = $this->extractContent($item['uri']);
return $item; return $item;
} }
private function extractContent($url){ private function extractContent($url)
{
$html3 = getSimpleHTMLDOMCached($url); $html3 = getSimpleHTMLDOMCached($url);
$text = $html3->find('div[class=field--type-text-with-summary]', 0)->innertext; $text = $html3->find('div[class=field--type-text-with-summary]', 0)->innertext;
$html3->clear(); $html3->clear();
unset ($html3); unset($html3);
return $text; return $text;
} }
} }

View file

@ -1,27 +1,29 @@
<?php <?php
class CopieDoubleBridge extends BridgeAbstract {
class CopieDoubleBridge extends BridgeAbstract
{
const MAINTAINER = 'superbaillot.net'; const MAINTAINER = 'superbaillot.net';
const NAME = 'CopieDouble'; const NAME = 'CopieDouble';
const URI = 'http://www.copie-double.com/'; const URI = 'http://www.copie-double.com/';
const CACHE_TIMEOUT = 14400; // 4h const CACHE_TIMEOUT = 14400; // 4h
const DESCRIPTION = 'CopieDouble'; const DESCRIPTION = 'CopieDouble';
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
$table = $html->find('table table', 2); $table = $html->find('table table', 2);
foreach($table->find('tr') as $element) { foreach ($table->find('tr') as $element) {
$td = $element->find('td', 0); $td = $element->find('td', 0);
if($td->class === 'couleur_1') { if ($td->class === 'couleur_1') {
$item = array(); $item = [];
$title = $td->innertext; $title = $td->innertext;
$pos = strpos($title, '<a'); $pos = strpos($title, '<a');
$title = substr($title, 0, $pos); $title = substr($title, 0, $pos);
$item['title'] = $title; $item['title'] = $title;
} elseif(strpos($element->innertext, '/images/suivant.gif') === false) { } elseif (strpos($element->innertext, '/images/suivant.gif') === false) {
$a = $element->find('a', 0); $a = $element->find('a', 0);
$item['uri'] = self::URI . $a->href; $item['uri'] = self::URI . $a->href;
$content = str_replace('src="/', 'src="/' . self::URI, $element->find('td', 0)->innertext); $content = str_replace('src="/', 'src="/' . self::URI, $element->find('td', 0)->innertext);

View file

@ -1,17 +1,20 @@
<?php <?php
class CourrierInternationalBridge extends FeedExpander {
class CourrierInternationalBridge extends FeedExpander
{
const MAINTAINER = 'teromene'; const MAINTAINER = 'teromene';
const NAME = 'Courrier International Bridge'; const NAME = 'Courrier International Bridge';
const URI = 'https://www.courrierinternational.com/'; const URI = 'https://www.courrierinternational.com/';
const CACHE_TIMEOUT = 300; // 5 min const CACHE_TIMEOUT = 300; // 5 min
const DESCRIPTION = 'Returns the newest articles'; const DESCRIPTION = 'Returns the newest articles';
public function collectData(){ public function collectData()
{
$this->collectExpandableDatas(static::URI . 'feed/all/rss.xml', 20); $this->collectExpandableDatas(static::URI . 'feed/all/rss.xml', 20);
} }
protected function parseItem($feedItem){ protected function parseItem($feedItem)
{
$item = parent::parseItem($feedItem); $item = parent::parseItem($feedItem);
$articlePage = getSimpleHTMLDOMCached($feedItem->link); $articlePage = getSimpleHTMLDOMCached($feedItem->link);

View file

@ -1,51 +1,55 @@
<?php <?php
class CraigslistBridge extends BridgeAbstract {
class CraigslistBridge extends BridgeAbstract
{
const NAME = 'Craigslist Bridge'; const NAME = 'Craigslist Bridge';
const URI = 'https://craigslist.org/'; const URI = 'https://craigslist.org/';
const DESCRIPTION = 'Returns craigslist search results'; const DESCRIPTION = 'Returns craigslist search results';
const PARAMETERS = array( array( const PARAMETERS = [ [
'region' => array( 'region' => [
'name' => 'Region', 'name' => 'Region',
'title' => 'The subdomain before craigslist.org in the URL', 'title' => 'The subdomain before craigslist.org in the URL',
'exampleValue' => 'sfbay', 'exampleValue' => 'sfbay',
'required' => true 'required' => true
), ],
'search' => array( 'search' => [
'name' => 'Search Query', 'name' => 'Search Query',
'title' => 'Everything in the URL after /search/', 'title' => 'Everything in the URL after /search/',
'exampleValue' => 'sya?query=laptop', 'exampleValue' => 'sya?query=laptop',
'required' => true 'required' => true
), ],
'limit' => array( 'limit' => [
'name' => 'Number of Posts', 'name' => 'Number of Posts',
'type' => 'number', 'type' => 'number',
'title' => 'The maximum number of posts is 120. Use 0 for unlimited posts.', 'title' => 'The maximum number of posts is 120. Use 0 for unlimited posts.',
'defaultValue' => '25' 'defaultValue' => '25'
) ]
)); ]];
const TEST_DETECT_PARAMETERS = array( const TEST_DETECT_PARAMETERS = [
'https://sfbay.craigslist.org/search/sya?query=laptop' => array( 'https://sfbay.craigslist.org/search/sya?query=laptop' => [
'region' => 'sfbay', 'search' => 'sya?query=laptop' 'region' => 'sfbay', 'search' => 'sya?query=laptop'
), ],
'https://newyork.craigslist.org/search/sss?query=32gb+flash+drive&bundleDuplicates=1&max_price=20' => array( 'https://newyork.craigslist.org/search/sss?query=32gb+flash+drive&bundleDuplicates=1&max_price=20' => [
'region' => 'newyork', 'search' => 'sss?query=32gb+flash+drive&bundleDuplicates=1&max_price=20' 'region' => 'newyork', 'search' => 'sss?query=32gb+flash+drive&bundleDuplicates=1&max_price=20'
), ],
); ];
const URL_REGEX = '/^https:\/\/(?<region>\w+).craigslist.org\/search\/(?<search>.+)/'; const URL_REGEX = '/^https:\/\/(?<region>\w+).craigslist.org\/search\/(?<search>.+)/';
public function detectParameters($url) { public function detectParameters($url)
if(preg_match(self::URL_REGEX, $url, $matches)) { {
$params = array(); if (preg_match(self::URL_REGEX, $url, $matches)) {
$params = [];
$params['region'] = $matches['region']; $params['region'] = $matches['region'];
$params['search'] = $matches['search']; $params['search'] = $matches['search'];
return $params; return $params;
} }
} }
public function getURI() { public function getURI()
{
if (!is_null($this->getInput('region'))) { if (!is_null($this->getInput('region'))) {
$domain = 'https://' . $this->getInput('region') . '.craigslist.org/search/'; $domain = 'https://' . $this->getInput('region') . '.craigslist.org/search/';
return urljoin($domain, $this->getInput('search')); return urljoin($domain, $this->getInput('search'));
@ -53,7 +57,8 @@ class CraigslistBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
public function collectData() { public function collectData()
{
$uri = $this->getURI(); $uri = $this->getURI();
$html = getSimpleHTMLDOM($uri); $html = getSimpleHTMLDOM($uri);
@ -70,15 +75,14 @@ class CraigslistBridge extends BridgeAbstract {
$results = array_slice($results, 0, $this->getInput('limit')); $results = array_slice($results, 0, $this->getInput('limit'));
} }
foreach($results as $post) { foreach ($results as $post) {
// Skip "nearby results" banner and results // Skip "nearby results" banner and results
// This only appears when searchNearby is not specified // This only appears when searchNearby is not specified
if ($post->tag == 'h4') { if ($post->tag == 'h4') {
break; break;
} }
$item = array(); $item = [];
$heading = $post->find('.result-heading a', 0); $heading = $post->find('.result-heading a', 0);
$item['uri'] = $heading->href; $item['uri'] = $heading->href;
@ -92,7 +96,7 @@ class CraigslistBridge extends BridgeAbstract {
$images = $post->find('.result-image[data-ids]', 0); $images = $post->find('.result-image[data-ids]', 0);
if (!is_null($images)) { if (!is_null($images)) {
$item['content'] .= '<br>'; $item['content'] .= '<br>';
foreach(explode(',', $images->getAttribute('data-ids')) as $image) { foreach (explode(',', $images->getAttribute('data-ids')) as $image) {
// Remove leading 3: from each image id // Remove leading 3: from each image id
$id = substr($image, 2); $id = substr($image, 2);
$image_uri = 'https://images.craigslist.org/' . $id . '_300x300.jpg'; $image_uri = 'https://images.craigslist.org/' . $id . '_300x300.jpg';

View file

@ -1,39 +1,41 @@
<?php <?php
class CrewbayBridge extends BridgeAbstract {
class CrewbayBridge extends BridgeAbstract
{
const MAINTAINER = 'couraudt'; const MAINTAINER = 'couraudt';
const NAME = 'Crewbay Bridge'; const NAME = 'Crewbay Bridge';
const URI = 'https://www.crewbay.com'; const URI = 'https://www.crewbay.com';
const DESCRIPTION = 'Returns the newest sailing offers.'; const DESCRIPTION = 'Returns the newest sailing offers.';
const PARAMETERS = array( const PARAMETERS = [
array( [
'keyword' => array( 'keyword' => [
'name' => 'Filter by keyword', 'name' => 'Filter by keyword',
'title' => 'Enter the keyword to filter here' 'title' => 'Enter the keyword to filter here'
), ],
'type' => array( 'type' => [
'name' => 'Type of search', 'name' => 'Type of search',
'title' => 'Choose between finding a boat or a crew', 'title' => 'Choose between finding a boat or a crew',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Find a boat' => 'boats', 'Find a boat' => 'boats',
'Find a crew' => 'crew' 'Find a crew' => 'crew'
) ]
), ],
'status' => array( 'status' => [
'name' => 'Status on the boat', 'name' => 'Status on the boat',
'title' => 'Choose between recreational or professional classified ads', 'title' => 'Choose between recreational or professional classified ads',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Recreational' => 'recreational', 'Recreational' => 'recreational',
'Professional' => 'professional' 'Professional' => 'professional'
) ]
), ],
'recreational_position' => array( 'recreational_position' => [
'name' => 'Recreational position wanted', 'name' => 'Recreational position wanted',
'title' => 'Filter by recreational position you wanted aboard', 'title' => 'Filter by recreational position you wanted aboard',
'required' => false, 'required' => false,
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'' => '', '' => '',
'Amateur Crew' => 'Amateur Crew', 'Amateur Crew' => 'Amateur Crew',
'Friendship' => 'Friendship', 'Friendship' => 'Friendship',
@ -41,14 +43,14 @@ class CrewbayBridge extends BridgeAbstract {
'Racing' => 'Racing', 'Racing' => 'Racing',
'Voluntary work' => 'Voluntary work', 'Voluntary work' => 'Voluntary work',
'Mile building' => 'Mile building' 'Mile building' => 'Mile building'
) ]
), ],
'professional_position' => array( 'professional_position' => [
'name' => 'Professional position wanted', 'name' => 'Professional position wanted',
'title' => 'Filter by professional position you wanted aboard', 'title' => 'Filter by professional position you wanted aboard',
'required' => false, 'required' => false,
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'' => '', '' => '',
'1st Engineer' => '1st Engineer', '1st Engineer' => '1st Engineer',
'1st Mate' => '1st Mate', '1st Mate' => '1st Mate',
@ -99,12 +101,13 @@ class CrewbayBridge extends BridgeAbstract {
'Stew/Masseuse' => 'Stew/Masseuse', 'Stew/Masseuse' => 'Stew/Masseuse',
'Manager' => 'Manager', 'Manager' => 'Manager',
'Sailing instructor' => 'Sailing instructor' 'Sailing instructor' => 'Sailing instructor'
) ]
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$url = $this->getURI(); $url = $this->getURI();
$html = getSimpleHTMLDOM($url) or returnClientError('No results for this query.'); $html = getSimpleHTMLDOM($url) or returnClientError('No results for this query.');
@ -118,9 +121,9 @@ class CrewbayBridge extends BridgeAbstract {
if (!empty($this->getInput('recreational_position')) || !empty($this->getInput('professional_position'))) { if (!empty($this->getInput('recreational_position')) || !empty($this->getInput('professional_position'))) {
if ($this->getInput('type') == 'boats') { if ($this->getInput('type') == 'boats') {
if ($this->getInput('status') == 'professional') { if ($this->getInput('status') == 'professional') {
$positions = array($annonce->find('.title .position', 0)->plaintext); $positions = [$annonce->find('.title .position', 0)->plaintext];
} else { } else {
$positions = array(str_replace('Wanted:', '', $annonce->find('.content li', 0)->plaintext)); $positions = [str_replace('Wanted:', '', $annonce->find('.content li', 0)->plaintext)];
} }
} else { } else {
$list = $htmlDetail->find('.viewer-details .viewer-list'); $list = $htmlDetail->find('.viewer-details .viewer-list');
@ -141,7 +144,7 @@ class CrewbayBridge extends BridgeAbstract {
} }
} }
$item = array(); $item = [];
if ($this->getInput('type') == 'boats') { if ($this->getInput('type') == 'boats') {
$titleSelector = '.title h2'; $titleSelector = '.title h2';
@ -158,7 +161,7 @@ class CrewbayBridge extends BridgeAbstract {
$item['uri'] = $detail->href; $item['uri'] = $detail->href;
$images = $annonce->find('.avatar img'); $images = $annonce->find('.avatar img');
$item['enclosures'] = array(end($images)->getAttribute('src')); $item['enclosures'] = [end($images)->getAttribute('src')];
$content = $htmlDetail->find('.viewer-intro--info', 0)->innertext; $content = $htmlDetail->find('.viewer-intro--info', 0)->innertext;
@ -166,7 +169,7 @@ class CrewbayBridge extends BridgeAbstract {
foreach ($sections as $section) { foreach ($sections as $section) {
if ($section->find('.viewer-section-title', 0)) { if ($section->find('.viewer-section-title', 0)) {
$class = str_replace('viewer-', '', explode(' ', $section->getAttribute('class'))[0]); $class = str_replace('viewer-', '', explode(' ', $section->getAttribute('class'))[0]);
if (!in_array($class, array('apply', 'photos', 'reviews', 'contact', 'experience', 'qa'))) { if (!in_array($class, ['apply', 'photos', 'reviews', 'contact', 'experience', 'qa'])) {
// Basic sections // Basic sections
$content .= $section->find('.viewer-section-title h3', 0)->outertext; $content .= $section->find('.viewer-section-title h3', 0)->outertext;
$content .= $section->find('.viewer-section-content', 0)->innertext; $content .= $section->find('.viewer-section-content', 0)->innertext;
@ -192,7 +195,7 @@ class CrewbayBridge extends BridgeAbstract {
$tags = $htmlDetail->find('li.viewer-tags--tag'); $tags = $htmlDetail->find('li.viewer-tags--tag');
foreach ($tags as $tag) { foreach ($tags as $tag) {
if (!isset($item['categories'])) { if (!isset($item['categories'])) {
$item['categories'] = array(); $item['categories'] = [];
} }
$text = trim($tag->plaintext); $text = trim($tag->plaintext);
if (!in_array($text, $item['categories'])) { if (!in_array($text, $item['categories'])) {
@ -203,11 +206,14 @@ class CrewbayBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
$limit += 1; $limit += 1;
if ($limit == 10) break; if ($limit == 10) {
break;
}
} }
} }
public function getURI() { public function getURI()
{
$uri = parent::getURI(); $uri = parent::getURI();
if ($this->getInput('type') == 'boats') { if ($this->getInput('type') == 'boats') {

View file

@ -1,35 +1,38 @@
<?php <?php
class CryptomeBridge extends BridgeAbstract {
class CryptomeBridge extends BridgeAbstract
{
const MAINTAINER = 'BoboTiG'; const MAINTAINER = 'BoboTiG';
const NAME = 'Cryptome'; const NAME = 'Cryptome';
const URI = 'https://cryptome.org/'; const URI = 'https://cryptome.org/';
const CACHE_TIMEOUT = 21600; // 6h const CACHE_TIMEOUT = 21600; // 6h
const DESCRIPTION = 'Returns the N most recent documents.'; const DESCRIPTION = 'Returns the N most recent documents.';
const PARAMETERS = array( array( const PARAMETERS = [ [
'n' => array( 'n' => [
'name' => 'number of elements', 'name' => 'number of elements',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'exampleValue' => 10 'exampleValue' => 10
) ]
)); ]];
public function getIcon() { public function getIcon()
{
return self::URI . '/favicon.ico'; return self::URI . '/favicon.ico';
} }
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
$number = $this->getInput('n'); $number = $this->getInput('n');
if(!empty($number)) { if (!empty($number)) {
$num = min($number, 20); $num = min($number, 20);
} }
$i = 0; $i = 0;
foreach($html->find('pre', 1)->find('b') as $element) { foreach ($html->find('pre', 1)->find('b') as $element) {
foreach($element->find('a') as $element1) { foreach ($element->find('a') as $element1) {
$item = array(); $item = [];
$item['uri'] = $element1->href; $item['uri'] = $element1->href;
$item['title'] = $element->plaintext; $item['title'] = $element->plaintext;
$this->items[] = $item; $this->items[] = $item;

View file

@ -1,36 +1,39 @@
<?php <?php
class CubariBridge extends BridgeAbstract class CubariBridge extends BridgeAbstract
{ {
const NAME = 'Cubari'; const NAME = 'Cubari';
const URI = 'https://cubari.moe'; const URI = 'https://cubari.moe';
const DESCRIPTION = 'Parses given cubari-formatted JSON file for updates.'; const DESCRIPTION = 'Parses given cubari-formatted JSON file for updates.';
const MAINTAINER = 'KamaleiZestri'; const MAINTAINER = 'KamaleiZestri';
const PARAMETERS = array(array( const PARAMETERS = [[
'gist' => array( 'gist' => [
'name' => 'Gist/Raw Url', 'name' => 'Gist/Raw Url',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'https://raw.githubusercontent.com/kurisumx/baka/main/ikedan' 'exampleValue' => 'https://raw.githubusercontent.com/kurisumx/baka/main/ikedan'
) ]
)); ]];
private $mangaTitle = ''; private $mangaTitle = '';
public function getName() public function getName()
{ {
if (!empty($this->mangaTitle)) if (!empty($this->mangaTitle)) {
return $this->mangaTitle . ' - ' . self::NAME; return $this->mangaTitle . ' - ' . self::NAME;
else } else {
return self::NAME; return self::NAME;
} }
}
public function getURI() public function getURI()
{ {
if ($this->getInput('gist') != '') if ($this->getInput('gist') != '') {
return self::URI . '/read/gist/' . $this->getEncodedGist(); return self::URI . '/read/gist/' . $this->getEncodedGist();
else } else {
return self::URI; return self::URI;
} }
}
/** /**
* The Cubari bridge. * The Cubari bridge.
@ -78,12 +81,13 @@ class CubariBridge extends BridgeAbstract
protected function getItemFromChapter($chapnum, $chapter) protected function getItemFromChapter($chapnum, $chapter)
{ {
$item = array(); $item = [];
$item['uri'] = $this->getURI() . '/' . $chapnum; $item['uri'] = $this->getURI() . '/' . $chapnum;
$item['title'] = 'Chapter ' . $chapnum . ' - ' . $chapter['title'] . ' - ' . $this->mangaTitle; $item['title'] = 'Chapter ' . $chapnum . ' - ' . $chapter['title'] . ' - ' . $this->mangaTitle;
foreach ($chapter['groups'] as $key => $value) foreach ($chapter['groups'] as $key => $value) {
$item['author'] = $key; $item['author'] = $key;
}
$item['timestamp'] = $chapter['last_updated']; $item['timestamp'] = $chapter['last_updated'];
$item['content'] = '<p>Manga: <a href=' . $this->getURI() . '>' . $this->mangaTitle . '</a> </p> $item['content'] = '<p>Manga: <a href=' . $this->getURI() . '>' . $this->mangaTitle . '</a> </p>

View file

@ -1,30 +1,32 @@
<?php <?php
class CuriousCatBridge extends BridgeAbstract {
class CuriousCatBridge extends BridgeAbstract
{
const NAME = 'Curious Cat Bridge'; const NAME = 'Curious Cat Bridge';
const URI = 'https://curiouscat.me'; const URI = 'https://curiouscat.me';
const DESCRIPTION = 'Returns list of newest questions and answers for a user profile'; const DESCRIPTION = 'Returns list of newest questions and answers for a user profile';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array(array( const PARAMETERS = [[
'username' => array( 'username' => [
'name' => 'Username', 'name' => 'Username',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'koethekoethe', 'exampleValue' => 'koethekoethe',
) ]
)); ]];
const CACHE_TIMEOUT = 3600; const CACHE_TIMEOUT = 3600;
public function collectData() { public function collectData()
{
$url = self::URI . '/api/v2/profile?username=' . urlencode($this->getInput('username')); $url = self::URI . '/api/v2/profile?username=' . urlencode($this->getInput('username'));
$apiJson = getContents($url); $apiJson = getContents($url);
$apiData = json_decode($apiJson, true); $apiData = json_decode($apiJson, true);
foreach($apiData['posts'] as $post) { foreach ($apiData['posts'] as $post) {
$item = array(); $item = [];
$item['author'] = 'Anonymous'; $item['author'] = 'Anonymous';
@ -42,8 +44,8 @@ class CuriousCatBridge extends BridgeAbstract {
} }
} }
public function getURI() { public function getURI()
{
if (!is_null($this->getInput('username'))) { if (!is_null($this->getInput('username'))) {
return self::URI . '/' . $this->getInput('username'); return self::URI . '/' . $this->getInput('username');
} }
@ -51,8 +53,8 @@ class CuriousCatBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
public function getName() { public function getName()
{
if (!is_null($this->getInput('username'))) { if (!is_null($this->getInput('username'))) {
return $this->getInput('username') . ' - Curious Cat'; return $this->getInput('username') . ' - Curious Cat';
} }
@ -60,8 +62,8 @@ class CuriousCatBridge extends BridgeAbstract {
return parent::getName(); return parent::getName();
} }
private function processContent($post) { private function processContent($post)
{
$author = 'Anonymous'; $author = 'Anonymous';
if ($post['senderData']['id'] !== false) { if ($post['senderData']['id'] !== false) {
@ -85,7 +87,8 @@ EOD;
return $content; return $content;
} }
private function ellipsisTitle($text) { private function ellipsisTitle($text)
{
$length = 150; $length = 150;
if (strlen($text) > $length) { if (strlen($text) > $length) {
@ -96,13 +99,12 @@ EOD;
return $text; return $text;
} }
private function formatUrls($content) { private function formatUrls($content)
{
return preg_replace( return preg_replace(
'/(http[s]{0,1}\:\/\/[a-zA-Z0-9.\/\?\&=\-_]{4,})/ims', '/(http[s]{0,1}\:\/\/[a-zA-Z0-9.\/\?\&=\-_]{4,})/ims',
'<a target="_blank" href="$1" target="_blank">$1</a> ', '<a target="_blank" href="$1" target="_blank">$1</a> ',
$content $content
); );
} }
} }

View file

@ -1,20 +1,25 @@
<?php <?php
class CyanideAndHappinessBridge extends BridgeAbstract {
class CyanideAndHappinessBridge extends BridgeAbstract
{
const NAME = 'Cyanide & Happiness'; const NAME = 'Cyanide & Happiness';
const URI = 'https://explosm.net/'; const URI = 'https://explosm.net/';
const DESCRIPTION = 'The Webcomic from Explosm.'; const DESCRIPTION = 'The Webcomic from Explosm.';
const MAINTAINER = 'sal0max'; const MAINTAINER = 'sal0max';
const CACHE_TIMEOUT = 60 * 60 * 2; // 2 hours const CACHE_TIMEOUT = 60 * 60 * 2; // 2 hours
public function getIcon() { public function getIcon()
{
return self::URI . 'favicon-32x32.png'; return self::URI . 'favicon-32x32.png';
} }
public function getURI(){ public function getURI()
{
return self::URI . 'comics/latest#comic'; return self::URI . 'comics/latest#comic';
} }
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM($this->getUri()); $html = getSimpleHTMLDOM($this->getUri());
foreach ($html->find('[class*=ComicImage]') as $element) { foreach ($html->find('[class*=ComicImage]') as $element) {
@ -23,14 +28,14 @@ class CyanideAndHappinessBridge extends BridgeAbstract {
$image = $element->find('img', 0)->src; $image = $element->find('img', 0)->src;
$link = $html->find('[rel=canonical]', 0)->href; $link = $html->find('[rel=canonical]', 0)->href;
$item = array( $item = [
'uid' => $link, 'uid' => $link,
'author' => $author, 'author' => $author,
'title' => $date, 'title' => $date,
'uri' => $link . '#comic', 'uri' => $link . '#comic',
'timestamp' => str_replace('.', '-', $date) . 'T00:00:00Z', 'timestamp' => str_replace('.', '-', $date) . 'T00:00:00Z',
'content' => "<img src=\"$image\" />" 'content' => "<img src=\"$image\" />"
); ];
$this->items[] = $item; $this->items[] = $item;
} }
} }

View file

@ -1,54 +1,55 @@
<?php <?php
class DailymotionBridge extends BridgeAbstract {
class DailymotionBridge extends BridgeAbstract
{
const MAINTAINER = 'mitsukarenai'; const MAINTAINER = 'mitsukarenai';
const NAME = 'Dailymotion Bridge'; const NAME = 'Dailymotion Bridge';
const URI = 'https://www.dailymotion.com/'; const URI = 'https://www.dailymotion.com/';
const CACHE_TIMEOUT = 3600; // 1h const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'Returns the 5 newest videos by username/playlist or search'; const DESCRIPTION = 'Returns the 5 newest videos by username/playlist or search';
const PARAMETERS = array ( const PARAMETERS = [
'By username' => array( 'By username' => [
'u' => array( 'u' => [
'name' => 'username', 'name' => 'username',
'required' => true, 'required' => true,
'exampleValue' => 'moviepilot', 'exampleValue' => 'moviepilot',
) ]
), ],
'By playlist id' => array( 'By playlist id' => [
'p' => array( 'p' => [
'name' => 'playlist id', 'name' => 'playlist id',
'required' => true, 'required' => true,
'exampleValue' => 'x6xyc6', 'exampleValue' => 'x6xyc6',
) ]
), ],
'From search results' => array( 'From search results' => [
's' => array( 's' => [
'name' => 'Search keyword', 'name' => 'Search keyword',
'required' => true, 'required' => true,
'exampleValue' => 'matrix', 'exampleValue' => 'matrix',
), ],
'pa' => array( 'pa' => [
'name' => 'Page', 'name' => 'Page',
'type' => 'number', 'type' => 'number',
'defaultValue' => 1, 'defaultValue' => 1,
) ]
) ]
); ];
private $feedName = ''; private $feedName = '';
private $apiUrl = 'https://api.dailymotion.com'; private $apiUrl = 'https://api.dailymotion.com';
private $apiFields = 'created_time,description,id,owner.screenname,tags,thumbnail_url,title,url'; private $apiFields = 'created_time,description,id,owner.screenname,tags,thumbnail_url,title,url';
public function getIcon() { public function getIcon()
{
return 'https://static1-ssl.dmcdn.net/images/neon/favicons/android-icon-36x36.png.vf806ca4ed0deed812'; return 'https://static1-ssl.dmcdn.net/images/neon/favicons/android-icon-36x36.png.vf806ca4ed0deed812';
} }
public function collectData() { public function collectData()
{
if ($this->queriedContext === 'By username' || $this->queriedContext === 'By playlist id') { if ($this->queriedContext === 'By username' || $this->queriedContext === 'By playlist id') {
$apiJson = getContents($this->getApiUrl()); $apiJson = getContents($this->getApiUrl());
$apiData = json_decode($apiJson, true); $apiData = json_decode($apiJson, true);
@ -56,7 +57,7 @@ class DailymotionBridge extends BridgeAbstract {
$this->feedName = $this->getPlaylistTitle($this->getInput('p')); $this->feedName = $this->getPlaylistTitle($this->getInput('p'));
foreach ($apiData['list'] as $apiItem) { foreach ($apiData['list'] as $apiItem) {
$item = array(); $item = [];
$item['uri'] = $apiItem['url']; $item['uri'] = $apiItem['url'];
$item['uid'] = $apiItem['id']; $item['uid'] = $apiItem['id'];
@ -73,16 +74,15 @@ class DailymotionBridge extends BridgeAbstract {
} }
if ($this->queriedContext === 'From search results') { if ($this->queriedContext === 'From search results') {
$html = getSimpleHTMLDOM($this->getURI()); $html = getSimpleHTMLDOM($this->getURI());
foreach($html->find('div.media a.preview_link') as $element) { foreach ($html->find('div.media a.preview_link') as $element) {
$item = array(); $item = [];
$item['id'] = str_replace('/video/', '', strtok($element->href, '_')); $item['id'] = str_replace('/video/', '', strtok($element->href, '_'));
$metadata = $this->getMetadata($item['id']); $metadata = $this->getMetadata($item['id']);
if(empty($metadata)) { if (empty($metadata)) {
continue; continue;
} }
@ -109,8 +109,9 @@ class DailymotionBridge extends BridgeAbstract {
} }
} }
public function getName() { public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'By username': case 'By username':
$specific = $this->getInput('u'); $specific = $this->getInput('u');
break; break;
@ -125,15 +126,17 @@ class DailymotionBridge extends BridgeAbstract {
case 'From search results': case 'From search results':
$specific = $this->getInput('s'); $specific = $this->getInput('s');
break; break;
default: return parent::getName(); default:
return parent::getName();
} }
return $specific . ' : Dailymotion'; return $specific . ' : Dailymotion';
} }
public function getURI(){ public function getURI()
{
$uri = self::URI; $uri = self::URI;
switch($this->queriedContext) { switch ($this->queriedContext) {
case 'By username': case 'By username':
$uri .= 'user/' . urlencode($this->getInput('u')); $uri .= 'user/' . urlencode($this->getInput('u'));
break; break;
@ -143,7 +146,7 @@ class DailymotionBridge extends BridgeAbstract {
case 'From search results': case 'From search results':
$uri .= 'search/' . urlencode($this->getInput('s')); $uri .= 'search/' . urlencode($this->getInput('s'));
if(!is_null($this->getInput('pa'))) { if (!is_null($this->getInput('pa'))) {
$pa = $this->getInput('pa'); $pa = $this->getInput('pa');
if ($this->getInput('pa') < 1) { if ($this->getInput('pa') < 1) {
@ -153,17 +156,19 @@ class DailymotionBridge extends BridgeAbstract {
$uri .= '/' . $pa; $uri .= '/' . $pa;
} }
break; break;
default: return parent::getURI(); default:
return parent::getURI();
} }
return $uri; return $uri;
} }
private function getMetadata($id) { private function getMetadata($id)
$metadata = array(); {
$metadata = [];
$html = getSimpleHTMLDOM(self::URI . 'video/' . $id); $html = getSimpleHTMLDOM(self::URI . 'video/' . $id);
if(!$html) { if (!$html) {
return $metadata; return $metadata;
} }
@ -176,7 +181,8 @@ class DailymotionBridge extends BridgeAbstract {
return $metadata; return $metadata;
} }
private function getPlaylistTitle($id) { private function getPlaylistTitle($id)
{
$title = ''; $title = '';
$url = self::URI . 'playlist/' . $id; $url = self::URI . 'playlist/' . $id;
@ -187,9 +193,9 @@ class DailymotionBridge extends BridgeAbstract {
return $title; return $title;
} }
private function getApiUrl() { private function getApiUrl()
{
switch($this->queriedContext) { switch ($this->queriedContext) {
case 'By username': case 'By username':
return $this->apiUrl . '/user/' . $this->getInput('u') return $this->apiUrl . '/user/' . $this->getInput('u')
. '/videos?fields=' . urlencode($this->apiFields) . '&availability=1&sort=recent&limit=5'; . '/videos?fields=' . urlencode($this->apiFields) . '&availability=1&sort=recent&limit=5';

View file

@ -1,47 +1,51 @@
<?php <?php
class DanbooruBridge extends BridgeAbstract {
class DanbooruBridge extends BridgeAbstract
{
const MAINTAINER = 'mitsukarenai, logmanoriginal'; const MAINTAINER = 'mitsukarenai, logmanoriginal';
const NAME = 'Danbooru'; const NAME = 'Danbooru';
const URI = 'http://donmai.us/'; const URI = 'http://donmai.us/';
const CACHE_TIMEOUT = 1800; // 30min const CACHE_TIMEOUT = 1800; // 30min
const DESCRIPTION = 'Returns images from given page'; const DESCRIPTION = 'Returns images from given page';
const PARAMETERS = array( const PARAMETERS = [
'global' => array( 'global' => [
'p' => array( 'p' => [
'name' => 'page', 'name' => 'page',
'defaultValue' => 1, 'defaultValue' => 1,
'type' => 'number' 'type' => 'number'
), ],
't' => array( 't' => [
'type' => 'text', 'type' => 'text',
'name' => 'tags', 'name' => 'tags',
'exampleValue' => 'cosplay', 'exampleValue' => 'cosplay',
) ]
), ],
0 => array() 0 => []
); ];
const PATHTODATA = 'article'; const PATHTODATA = 'article';
const IDATTRIBUTE = 'data-id'; const IDATTRIBUTE = 'data-id';
const TAGATTRIBUTE = 'alt'; const TAGATTRIBUTE = 'alt';
protected function getFullURI(){ protected function getFullURI()
{
return $this->getURI() return $this->getURI()
. 'posts?&page=' . $this->getInput('p') . 'posts?&page=' . $this->getInput('p')
. '&tags=' . urlencode($this->getInput('t')); . '&tags=' . urlencode($this->getInput('t'));
} }
protected function getTags($element){ protected function getTags($element)
{
return $element->find('img', 0)->getAttribute(static::TAGATTRIBUTE); return $element->find('img', 0)->getAttribute(static::TAGATTRIBUTE);
} }
protected function getItemFromElement($element){ protected function getItemFromElement($element)
{
// Fix links // Fix links
defaultLinkTo($element, $this->getURI()); defaultLinkTo($element, $this->getURI());
$item = array(); $item = [];
$item['uri'] = html_entity_decode($element->find('a', 0)->href); $item['uri'] = html_entity_decode($element->find('a', 0)->href);
$item['postid'] = (int)preg_replace('/[^0-9]/', '', $element->getAttribute(static::IDATTRIBUTE)); $item['postid'] = (int)preg_replace('/[^0-9]/', '', $element->getAttribute(static::IDATTRIBUTE));
$item['timestamp'] = time(); $item['timestamp'] = time();
@ -58,10 +62,11 @@ class DanbooruBridge extends BridgeAbstract {
return $item; return $item;
} }
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOMCached($this->getFullURI()); $html = getSimpleHTMLDOMCached($this->getFullURI());
foreach($html->find(static::PATHTODATA) as $element) { foreach ($html->find(static::PATHTODATA) as $element) {
$this->items[] = $this->getItemFromElement($element); $this->items[] = $this->getItemFromElement($element);
} }
} }

View file

@ -1,21 +1,22 @@
<?php <?php
class DansTonChatBridge extends BridgeAbstract {
class DansTonChatBridge extends BridgeAbstract
{
const MAINTAINER = 'Astalaseven'; const MAINTAINER = 'Astalaseven';
const NAME = 'DansTonChat Bridge'; const NAME = 'DansTonChat Bridge';
const URI = 'https://danstonchat.com/'; const URI = 'https://danstonchat.com/';
const CACHE_TIMEOUT = 21600; //6h const CACHE_TIMEOUT = 21600; //6h
const DESCRIPTION = 'Returns latest quotes from DansTonChat.'; const DESCRIPTION = 'Returns latest quotes from DansTonChat.';
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI . 'latest.html'); $html = getSimpleHTMLDOM(self::URI . 'latest.html');
foreach($html->find('div.item') as $element) { foreach ($html->find('div.item') as $element) {
$item = array(); $item = [];
$item['uri'] = $element->find('a', 0)->href; $item['uri'] = $element->find('a', 0)->href;
$titleContent = $element->find('h3 a', 0); $titleContent = $element->find('h3 a', 0);
if($titleContent) { if ($titleContent) {
$item['title'] = 'DansTonChat ' . html_entity_decode($titleContent->plaintext, ENT_QUOTES); $item['title'] = 'DansTonChat ' . html_entity_decode($titleContent->plaintext, ENT_QUOTES);
} else { } else {
$item['title'] = 'DansTonChat'; $item['title'] = 'DansTonChat';

View file

@ -1,15 +1,17 @@
<?php <?php
class DarkReadingBridge extends FeedExpander {
class DarkReadingBridge extends FeedExpander
{
const MAINTAINER = 'ORelio'; const MAINTAINER = 'ORelio';
const NAME = 'Dark Reading Bridge'; const NAME = 'Dark Reading Bridge';
const URI = 'https://www.darkreading.com/'; const URI = 'https://www.darkreading.com/';
const DESCRIPTION = 'Returns the newest articles from Dark Reading'; const DESCRIPTION = 'Returns the newest articles from Dark Reading';
const PARAMETERS = array( array( const PARAMETERS = [ [
'feed' => array( 'feed' => [
'name' => 'Feed', 'name' => 'Feed',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'All Dark Reading Stories' => '000_AllArticles', 'All Dark Reading Stories' => '000_AllArticles',
'Attacks/Breaches' => '644_Attacks/Breaches', 'Attacks/Breaches' => '644_Attacks/Breaches',
'Application Security' => '645_Application%20Security', 'Application Security' => '645_Application%20Security',
@ -32,17 +34,18 @@ class DarkReadingBridge extends FeedExpander {
'Advanced Threats' => '662_Advanced%20Threats', 'Advanced Threats' => '662_Advanced%20Threats',
'Insider Threats' => '663_Insider%20Threats', 'Insider Threats' => '663_Insider%20Threats',
'Vulnerability Management' => '664_Vulnerability%20Management', 'Vulnerability Management' => '664_Vulnerability%20Management',
) ]
), ],
'limit' => self::LIMIT, 'limit' => self::LIMIT,
)); ]];
public function collectData(){ public function collectData()
{
$feed = $this->getInput('feed'); $feed = $this->getInput('feed');
$feed_splitted = explode('_', $feed); $feed_splitted = explode('_', $feed);
$feed_id = $feed_splitted[0]; $feed_id = $feed_splitted[0];
$feed_name = $feed_splitted[1]; $feed_name = $feed_splitted[1];
if(empty($feed) || !ctype_digit($feed_id) || !preg_match('/[A-Za-z%20\/]/', $feed_name)) { if (empty($feed) || !ctype_digit($feed_id) || !preg_match('/[A-Za-z%20\/]/', $feed_name)) {
returnClientError('Invalid feed, please check the "feed" parameter.'); returnClientError('Invalid feed, please check the "feed" parameter.');
} }
$feed_url = $this->getURI() . 'rss_simple.asp'; $feed_url = $this->getURI() . 'rss_simple.asp';
@ -53,28 +56,32 @@ class DarkReadingBridge extends FeedExpander {
$this->collectExpandableDatas($feed_url, $limit); $this->collectExpandableDatas($feed_url, $limit);
} }
protected function parseItem($newsItem){ protected function parseItem($newsItem)
{
$item = parent::parseItem($newsItem); $item = parent::parseItem($newsItem);
$article = getSimpleHTMLDOMCached($item['uri']); $article = getSimpleHTMLDOMCached($item['uri']);
$item['content'] = $this->extractArticleContent($article); $item['content'] = $this->extractArticleContent($article);
$item['enclosures'] = array(); //remove author profile picture $item['enclosures'] = []; //remove author profile picture
$image = $article->find('meta[property="og:image"]', 0); $image = $article->find('meta[property="og:image"]', 0);
if (is_object($image)) { if (is_object($image)) {
$image = $image->content; $image = $image->content;
$item['enclosures'] = array($image); $item['enclosures'] = [$image];
} }
return $item; return $item;
} }
private function extractArticleContent($article){ private function extractArticleContent($article)
{
$content = $article->find('div.article-content', 0)->innertext; $content = $article->find('div.article-content', 0)->innertext;
foreach (array( foreach (
[
'<div class="divsplitter', '<div class="divsplitter',
'<div style="float: left; margin-right: 2px;', '<div style="float: left; margin-right: 2px;',
'<div class="more-insights', '<div class="more-insights',
'<div id="more-insights', '<div id="more-insights',
) as $div_start) { ] as $div_start
) {
$content = stripRecursiveHTMLSection($content, 'div', $div_start); $content = stripRecursiveHTMLSection($content, 'div', $div_start);
} }

View file

@ -1,17 +1,18 @@
<?php <?php
class DauphineLibereBridge extends FeedExpander {
class DauphineLibereBridge extends FeedExpander
{
const MAINTAINER = 'qwertygc'; const MAINTAINER = 'qwertygc';
const NAME = 'Dauphine Bridge'; const NAME = 'Dauphine Bridge';
const URI = 'https://www.ledauphine.com/'; const URI = 'https://www.ledauphine.com/';
const CACHE_TIMEOUT = 7200; // 2h const CACHE_TIMEOUT = 7200; // 2h
const DESCRIPTION = 'Returns the newest articles.'; const DESCRIPTION = 'Returns the newest articles.';
const PARAMETERS = array( array( const PARAMETERS = [ [
'u' => array( 'u' => [
'name' => 'Catégorie de l\'article', 'name' => 'Catégorie de l\'article',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'À la une' => '', 'À la une' => '',
'France Monde' => 'france-monde', 'France Monde' => 'france-monde',
'Faits Divers' => 'faits-divers', 'Faits Divers' => 'faits-divers',
@ -27,27 +28,30 @@ class DauphineLibereBridge extends FeedExpander {
'Savoie' => 'savoie', 'Savoie' => 'savoie',
'Haute-Savoie' => 'haute-savoie', 'Haute-Savoie' => 'haute-savoie',
'Vaucluse' => 'vaucluse' 'Vaucluse' => 'vaucluse'
) ]
) ]
)); ]];
public function collectData(){ public function collectData()
{
$url = self::URI . 'rss'; $url = self::URI . 'rss';
if(empty($this->getInput('u'))) { if (empty($this->getInput('u'))) {
$url = self::URI . $this->getInput('u') . '/rss'; $url = self::URI . $this->getInput('u') . '/rss';
} }
$this->collectExpandableDatas($url, 10); $this->collectExpandableDatas($url, 10);
} }
protected function parseItem($newsItem){ protected function parseItem($newsItem)
{
$item = parent::parseItem($newsItem); $item = parent::parseItem($newsItem);
$item['content'] = $this->extractContent($item['uri']); $item['content'] = $this->extractContent($item['uri']);
return $item; return $item;
} }
private function extractContent($url){ private function extractContent($url)
{
$html2 = getSimpleHTMLDOMCached($url); $html2 = getSimpleHTMLDOMCached($url);
foreach ($html2->find('.noprint, link, script, iframe, .shareTool, .contentInfo') as $remove) { foreach ($html2->find('.noprint, link, script, iframe, .shareTool, .contentInfo') as $remove) {
$remove->outertext = ''; $remove->outertext = '';

View file

@ -1,11 +1,14 @@
<?php <?php
class DavesTrailerPageBridge extends BridgeAbstract {
class DavesTrailerPageBridge extends BridgeAbstract
{
const MAINTAINER = 'johnnygroovy'; const MAINTAINER = 'johnnygroovy';
const NAME = 'Daves Trailer Page Bridge'; const NAME = 'Daves Trailer Page Bridge';
const URI = 'https://www.davestrailerpage.co.uk/'; const URI = 'https://www.davestrailerpage.co.uk/';
const DESCRIPTION = 'Last trailers in HD thanks to Dave.'; const DESCRIPTION = 'Last trailers in HD thanks to Dave.';
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(static::URI) $html = getSimpleHTMLDOM(static::URI)
or returnClientError('No results for this query.'); or returnClientError('No results for this query.');
@ -17,7 +20,7 @@ class DavesTrailerPageBridge extends BridgeAbstract {
continue; continue;
} }
$item = array(); $item = [];
// title // title
$item['title'] = $tr->find('td', 0)->find('b', 0)->plaintext; $item['title'] = $tr->find('td', 0)->find('b', 0)->plaintext;

View file

@ -1,47 +1,48 @@
<?php <?php
class DealabsBridge extends PepperBridgeAbstract {
class DealabsBridge extends PepperBridgeAbstract
{
const NAME = 'Dealabs Bridge'; const NAME = 'Dealabs Bridge';
const URI = 'https://www.dealabs.com/'; const URI = 'https://www.dealabs.com/';
const DESCRIPTION = 'Affiche les Deals de Dealabs'; const DESCRIPTION = 'Affiche les Deals de Dealabs';
const MAINTAINER = 'sysadminstory'; const MAINTAINER = 'sysadminstory';
const PARAMETERS = array( const PARAMETERS = [
'Recherche par Mot(s) clé(s)' => array ( 'Recherche par Mot(s) clé(s)' => [
'q' => array( 'q' => [
'name' => 'Mot(s) clé(s)', 'name' => 'Mot(s) clé(s)',
'type' => 'text', 'type' => 'text',
'exampleValue' => 'lampe', 'exampleValue' => 'lampe',
'required' => true 'required' => true
), ],
'hide_expired' => array( 'hide_expired' => [
'name' => 'Masquer les éléments expirés', 'name' => 'Masquer les éléments expirés',
'type' => 'checkbox', 'type' => 'checkbox',
), ],
'hide_local' => array( 'hide_local' => [
'name' => 'Masquer les deals locaux', 'name' => 'Masquer les deals locaux',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Masquer les deals en magasins physiques', 'title' => 'Masquer les deals en magasins physiques',
), ],
'priceFrom' => array( 'priceFrom' => [
'name' => 'Prix minimum', 'name' => 'Prix minimum',
'type' => 'text', 'type' => 'text',
'title' => 'Prix mnimum en euros', 'title' => 'Prix mnimum en euros',
'required' => false 'required' => false
), ],
'priceTo' => array( 'priceTo' => [
'name' => 'Prix maximum', 'name' => 'Prix maximum',
'type' => 'text', 'type' => 'text',
'title' => 'Prix maximum en euros', 'title' => 'Prix maximum en euros',
'required' => false 'required' => false
), ],
), ],
'Deals par groupe' => array( 'Deals par groupe' => [
'group' => array( 'group' => [
'name' => 'Groupe', 'name' => 'Groupe',
'type' => 'list', 'type' => 'list',
'title' => 'Groupe dont il faut afficher les deals', 'title' => 'Groupe dont il faut afficher les deals',
'values' => array( 'values' => [
'Abattants WC' => 'abattants-wc', 'Abattants WC' => 'abattants-wc',
'Abonnement PlayStation Plus' => 'playstation-plus', 'Abonnement PlayStation Plus' => 'playstation-plus',
'Abonnements cinéma' => 'abonnements-cinema', 'Abonnements cinéma' => 'abonnements-cinema',
@ -1868,42 +1869,42 @@ class DealabsBridge extends PepperBridgeAbstract {
'Yeelight' => 'xiaomi-yeelight', 'Yeelight' => 'xiaomi-yeelight',
'Yoshi&#039;s Crafted World' => 'yoshi-crafted-world', 'Yoshi&#039;s Crafted World' => 'yoshi-crafted-world',
'Zoos' => 'zoos', 'Zoos' => 'zoos',
) ]
), ],
'order' => array( 'order' => [
'name' => 'Trier par', 'name' => 'Trier par',
'type' => 'list', 'type' => 'list',
'title' => 'Ordre de tri des deals', 'title' => 'Ordre de tri des deals',
'values' => array( 'values' => [
'Du deal le plus Hot au moins Hot' => '-hot', 'Du deal le plus Hot au moins Hot' => '-hot',
'Du deal le plus récent au plus ancien' => '-nouveaux', 'Du deal le plus récent au plus ancien' => '-nouveaux',
) ]
) ]
), ],
'Surveillance Discussion' => array( 'Surveillance Discussion' => [
'url' => array( 'url' => [
'name' => 'URL de la discussion', 'name' => 'URL de la discussion',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'title' => 'URL discussion à surveiller: https://www.dealabs.com/discussions/titre-1234', 'title' => 'URL discussion à surveiller: https://www.dealabs.com/discussions/titre-1234',
'exampleValue' => 'https://www.dealabs.com/discussions/jeux-steam-gratuits-gleam-woobox-etc-1071415', 'exampleValue' => 'https://www.dealabs.com/discussions/jeux-steam-gratuits-gleam-woobox-etc-1071415',
), ],
'only_with_url' => array( 'only_with_url' => [
'name' => 'Exclure les commentaires sans URL', 'name' => 'Exclure les commentaires sans URL',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Exclure les commentaires ne contenant pas d\'URL dans le flux', 'title' => 'Exclure les commentaires ne contenant pas d\'URL dans le flux',
'defaultValue' => false, 'defaultValue' => false,
) ]
) ]
); ];
public $lang = array( public $lang = [
'bridge-uri' => SELF::URI, 'bridge-uri' => self::URI,
'bridge-name' => SELF::NAME, 'bridge-name' => self::NAME,
'context-keyword' => 'Recherche par Mot(s) clé(s)', 'context-keyword' => 'Recherche par Mot(s) clé(s)',
'context-group' => 'Deals par groupe', 'context-group' => 'Deals par groupe',
'context-talk' => 'Surveillance Discussion', 'context-talk' => 'Surveillance Discussion',
@ -1911,9 +1912,9 @@ class DealabsBridge extends PepperBridgeAbstract {
'request-error' => 'Impossible de joindre Dealabs', 'request-error' => 'Impossible de joindre Dealabs',
'thread-error' => 'Impossible de déterminer l\'ID de la discussion. Vérifiez l\'URL que vous avez entré', 'thread-error' => 'Impossible de déterminer l\'ID de la discussion. Vérifiez l\'URL que vous avez entré',
'no-results' => 'Il n&#039;y a rien à afficher pour le moment :(', 'no-results' => 'Il n&#039;y a rien à afficher pour le moment :(',
'relative-date-indicator' => array( 'relative-date-indicator' => [
'il y a', 'il y a',
), ],
'price' => 'Prix', 'price' => 'Prix',
'shipping' => 'Livraison', 'shipping' => 'Livraison',
'origin' => 'Origine', 'origin' => 'Origine',
@ -1921,7 +1922,7 @@ class DealabsBridge extends PepperBridgeAbstract {
'title-keyword' => 'Recherche', 'title-keyword' => 'Recherche',
'title-group' => 'Groupe', 'title-group' => 'Groupe',
'title-talk' => 'Surveillance Discussion', 'title-talk' => 'Surveillance Discussion',
'local-months' => array( 'local-months' => [
'janvier', 'janvier',
'février', 'février',
'mars', 'mars',
@ -1934,8 +1935,8 @@ class DealabsBridge extends PepperBridgeAbstract {
'octobre', 'octobre',
'novembre', 'novembre',
'décembre' 'décembre'
), ],
'local-time-relative' => array( 'local-time-relative' => [
'il y a ', 'il y a ',
'min', 'min',
'h', 'h',
@ -1944,22 +1945,19 @@ class DealabsBridge extends PepperBridgeAbstract {
'mois', 'mois',
'ans', 'ans',
'et ' 'et '
), ],
'date-prefixes' => array( 'date-prefixes' => [
'Actualisé ', 'Actualisé ',
), ],
'relative-date-alt-prefixes' => array( 'relative-date-alt-prefixes' => [
'Actualisé ', 'Actualisé ',
), ],
'relative-date-ignore-suffix' => array( 'relative-date-ignore-suffix' => [
), ],
'localdeal' => array( 'localdeal' => [
'Local', 'Local',
'Pays d\'expédition' 'Pays d\'expédition'
), ],
); ];
} }

View file

@ -1,40 +1,41 @@
<?php <?php
class DemoBridge extends BridgeAbstract {
class DemoBridge extends BridgeAbstract
{
const MAINTAINER = 'teromene'; const MAINTAINER = 'teromene';
const NAME = 'DemoBridge'; const NAME = 'DemoBridge';
const URI = 'http://github.com/rss-bridge/rss-bridge'; const URI = 'http://github.com/rss-bridge/rss-bridge';
const DESCRIPTION = 'Bridge used for demos'; const DESCRIPTION = 'Bridge used for demos';
const PARAMETERS = array( const PARAMETERS = [
'testCheckbox' => array( 'testCheckbox' => [
'testCheckbox' => array( 'testCheckbox' => [
'type' => 'checkbox', 'type' => 'checkbox',
'name' => 'test des checkbox' 'name' => 'test des checkbox'
) ]
), ],
'testList' => array( 'testList' => [
'testList' => array( 'testList' => [
'type' => 'list', 'type' => 'list',
'name' => 'test des listes', 'name' => 'test des listes',
'values' => array( 'values' => [
'Test' => 'test', 'Test' => 'test',
'Test 2' => 'test2' 'Test 2' => 'test2'
) ]
) ]
), ],
'testNumber' => array( 'testNumber' => [
'testNumber' => array( 'testNumber' => [
'type' => 'number', 'type' => 'number',
'name' => 'test des numéros', 'name' => 'test des numéros',
'exampleValue' => '1515632' 'exampleValue' => '1515632'
) ]
) ]
); ];
public function collectData(){ public function collectData()
{
$item = array(); $item = [];
$item['author'] = 'Me!'; $item['author'] = 'Me!';
$item['title'] = 'Test'; $item['title'] = 'Test';
$item['content'] = 'Awesome content !'; $item['content'] = 'Awesome content !';

View file

@ -1,48 +1,51 @@
<?php <?php
class DerpibooruBridge extends BridgeAbstract {
class DerpibooruBridge extends BridgeAbstract
{
const NAME = 'Derpibooru Bridge'; const NAME = 'Derpibooru Bridge';
const URI = 'https://derpibooru.org/'; const URI = 'https://derpibooru.org/';
const DESCRIPTION = 'Returns newest images from a Derpibooru search'; const DESCRIPTION = 'Returns newest images from a Derpibooru search';
const CACHE_TIMEOUT = 300; // 5min const CACHE_TIMEOUT = 300; // 5min
const MAINTAINER = 'Roliga'; const MAINTAINER = 'Roliga';
const PARAMETERS = array( const PARAMETERS = [
array( [
'f' => array( 'f' => [
'name' => 'Filter', 'name' => 'Filter',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Everything' => 56027, 'Everything' => 56027,
'18+ R34' => 37432, '18+ R34' => 37432,
'Legacy Default' => 37431, 'Legacy Default' => 37431,
'18+ Dark' => 37429, '18+ Dark' => 37429,
'Maximum Spoilers' => 37430, 'Maximum Spoilers' => 37430,
'Default' => 100073 'Default' => 100073
), ],
'defaultValue' => 56027 'defaultValue' => 56027
), ],
'q' => array( 'q' => [
'name' => 'Query', 'name' => 'Query',
'required' => true, 'required' => true,
'exampleValue' => 'dog', 'exampleValue' => 'dog',
) ]
) ]
); ];
public function detectParameters($url){ public function detectParameters($url)
$params = array(); {
$params = [];
// Search page e.g. https://derpibooru.org/search?q=cute // Search page e.g. https://derpibooru.org/search?q=cute
$regex = '/^(https?:\/\/)?(www\.)?derpibooru.org\/search.+q=([^\/&?\n]+)/'; $regex = '/^(https?:\/\/)?(www\.)?derpibooru.org\/search.+q=([^\/&?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
$params['q'] = urldecode($matches[3]); $params['q'] = urldecode($matches[3]);
return $params; return $params;
} }
// Tag page, e.g. https://derpibooru.org/tags/artist-colon-devinian // Tag page, e.g. https://derpibooru.org/tags/artist-colon-devinian
$regex = '/^(https?:\/\/)?(www\.)?derpibooru.org\/tags\/([^\/&?\n]+)/'; $regex = '/^(https?:\/\/)?(www\.)?derpibooru.org\/tags\/([^\/&?\n]+)/';
if(preg_match($regex, $url, $matches) > 0) { if (preg_match($regex, $url, $matches) > 0) {
$params['q'] = str_replace('-colon-', ':', urldecode($matches[3])); $params['q'] = str_replace('-colon-', ':', urldecode($matches[3]));
return $params; return $params;
} }
@ -50,8 +53,9 @@ class DerpibooruBridge extends BridgeAbstract {
return null; return null;
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('q'))) { {
if (!is_null($this->getInput('q'))) {
return 'Derpibooru search for: ' return 'Derpibooru search for: '
. $this->getInput('q'); . $this->getInput('q');
} else { } else {
@ -59,8 +63,9 @@ class DerpibooruBridge extends BridgeAbstract {
} }
} }
public function getURI(){ public function getURI()
if(!is_null($this->getInput('f')) && !is_null($this->getInput('q'))) { {
if (!is_null($this->getInput('f')) && !is_null($this->getInput('q'))) {
return self::URI return self::URI
. 'search?filter_id=' . 'search?filter_id='
. urlencode($this->getInput('f')) . urlencode($this->getInput('f'))
@ -71,7 +76,8 @@ class DerpibooruBridge extends BridgeAbstract {
} }
} }
public function collectData(){ public function collectData()
{
$queryJson = json_decode(getContents( $queryJson = json_decode(getContents(
self::URI self::URI
. 'api/v1/json/search/images?filter_id=' . 'api/v1/json/search/images?filter_id='
@ -80,8 +86,8 @@ class DerpibooruBridge extends BridgeAbstract {
. urlencode($this->getInput('q')) . urlencode($this->getInput('q'))
)); ));
foreach($queryJson->images as $post) { foreach ($queryJson->images as $post) {
$item = array(); $item = [];
$postUri = self::URI . $post->id; $postUri = self::URI . $post->id;
@ -89,7 +95,7 @@ class DerpibooruBridge extends BridgeAbstract {
$item['title'] = $post->name; $item['title'] = $post->name;
$item['timestamp'] = strtotime($post->created_at); $item['timestamp'] = strtotime($post->created_at);
$item['author'] = $post->uploader; $item['author'] = $post->uploader;
$item['enclosures'] = array($post->view_url); $item['enclosures'] = [$post->view_url];
$item['categories'] = $post->tags; $item['categories'] = $post->tags;
$item['content'] = '<p><a href="' // image preview $item['content'] = '<p><a href="' // image preview

View file

@ -1,6 +1,7 @@
<?php <?php
class DesoutterBridge extends BridgeAbstract {
class DesoutterBridge extends BridgeAbstract
{
const CATEGORY_NEWS = 'News & Events'; const CATEGORY_NEWS = 'News & Events';
const CATEGORY_INDUSTRY = 'Industry 4.0 News'; const CATEGORY_INDUSTRY = 'Industry 4.0 News';
@ -10,14 +11,14 @@ class DesoutterBridge extends BridgeAbstract {
const MAINTAINER = 'logmanoriginal'; const MAINTAINER = 'logmanoriginal';
const CACHE_TIMEOUT = 86400; // 24 hours const CACHE_TIMEOUT = 86400; // 24 hours
const PARAMETERS = array( const PARAMETERS = [
self::CATEGORY_NEWS => array( self::CATEGORY_NEWS => [
'news_lang' => array( 'news_lang' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'title' => 'Select your language', 'title' => 'Select your language',
'defaultValue' => 'https://www.desouttertools.com/about-desoutter/news-events', 'defaultValue' => 'https://www.desouttertools.com/about-desoutter/news-events',
'values' => array( 'values' => [
'Corporate' 'Corporate'
=> 'https://www.desouttertools.com/about-desoutter/news-events', => 'https://www.desouttertools.com/about-desoutter/news-events',
'Česko' 'Česko'
@ -58,16 +59,16 @@ class DesoutterBridge extends BridgeAbstract {
=> 'https://www.desoutter.com.tr/desoutter-hakkinda/haberler-etkinlikler', => 'https://www.desoutter.com.tr/desoutter-hakkinda/haberler-etkinlikler',
'中国' '中国'
=> 'https://www.desouttertools.com.cn/guan-yu-ma-tou/xin-wen-he-huo-dong', => 'https://www.desouttertools.com.cn/guan-yu-ma-tou/xin-wen-he-huo-dong',
) ]
), ],
), ],
self::CATEGORY_INDUSTRY => array( self::CATEGORY_INDUSTRY => [
'industry_lang' => array( 'industry_lang' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'title' => 'Select your language', 'title' => 'Select your language',
'defaultValue' => 'Corporate', 'defaultValue' => 'Corporate',
'values' => array( 'values' => [
'Corporate' 'Corporate'
=> 'https://www.desouttertools.com/industry-4-0/news', => 'https://www.desouttertools.com/industry-4-0/news',
'Česko' 'Česko'
@ -108,29 +109,30 @@ class DesoutterBridge extends BridgeAbstract {
=> 'https://www.desoutter.com.tr/endustri-4-0/haberler', => 'https://www.desoutter.com.tr/endustri-4-0/haberler',
'中国' '中国'
=> 'https://www.desouttertools.com.cn/industry-4-0/news', => 'https://www.desouttertools.com.cn/industry-4-0/news',
) ]
), ],
), ],
'global' => array( 'global' => [
'full' => array( 'full' => [
'name' => 'Load full articles', 'name' => 'Load full articles',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Enable to load the full article for each item' 'title' => 'Enable to load the full article for each item'
), ],
'limit' => array( 'limit' => [
'name' => 'Limit', 'name' => 'Limit',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'defaultValue' => 3, 'defaultValue' => 3,
'title' => "Maximum number of items to return in the feed.\n0 = unlimited" 'title' => "Maximum number of items to return in the feed.\n0 = unlimited"
) ]
) ]
); ];
private $title; private $title;
public function getURI() { public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case self::CATEGORY_NEWS: case self::CATEGORY_NEWS:
return $this->getInput('news_lang') ?: parent::getURI(); return $this->getInput('news_lang') ?: parent::getURI();
case self::CATEGORY_INDUSTRY: case self::CATEGORY_INDUSTRY:
@ -140,12 +142,13 @@ class DesoutterBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
public function getName() { public function getName()
{
return isset($this->title) ? $this->title . ' - ' . parent::getName() : parent::getName(); return isset($this->title) ? $this->title . ' - ' . parent::getName() : parent::getName();
} }
public function collectData() { public function collectData()
{
// Uncomment to generate list of languages automtically (dev mode) // Uncomment to generate list of languages automtically (dev mode)
/* /*
switch($this->queriedContext) { switch($this->queriedContext) {
@ -164,13 +167,13 @@ class DesoutterBridge extends BridgeAbstract {
$limit = $this->getInput('limit') ?: 0; $limit = $this->getInput('limit') ?: 0;
foreach($html->find('article') as $article) { foreach ($html->find('article') as $article) {
$item = array(); $item = [];
$item['uri'] = $article->find('a', 0)->href; $item['uri'] = $article->find('a', 0)->href;
$item['title'] = $article->find('a[title]', 0)->title; $item['title'] = $article->find('a[title]', 0)->title;
if($this->getInput('full')) { if ($this->getInput('full')) {
$item['content'] = $this->getFullNewsArticle($item['uri']); $item['content'] = $this->getFullNewsArticle($item['uri']);
} else { } else {
$item['content'] = $article->find('div.tile-body p', 0)->plaintext; $item['content'] = $article->find('div.tile-body p', 0)->plaintext;
@ -178,12 +181,14 @@ class DesoutterBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
if ($limit > 0 && count($this->items) >= $limit) break; if ($limit > 0 && count($this->items) >= $limit) {
break;
}
}
} }
} private function getFullNewsArticle($uri)
{
private function getFullNewsArticle($uri) {
$html = getSimpleHTMLDOMCached($uri); $html = getSimpleHTMLDOMCached($uri);
$html = defaultLinkTo($html, $this->getURI()); $html = defaultLinkTo($html, $this->getURI());
@ -197,7 +202,8 @@ class DesoutterBridge extends BridgeAbstract {
* on the 'Corporate' site. * on the 'Corporate' site.
* @return void * @return void
*/ */
private function extractNewsLanguages() { private function extractNewsLanguages()
{
$html = getSimpleHTMLDOMCached('https://www.desouttertools.com/about-desoutter/news-events'); $html = getSimpleHTMLDOMCached('https://www.desouttertools.com/about-desoutter/news-events');
$html = defaultLinkTo($html, static::URI); $html = defaultLinkTo($html, static::URI);
@ -206,7 +212,7 @@ class DesoutterBridge extends BridgeAbstract {
$list = "\t'Corporate'\n\t=> 'https://www.desouttertools.com/about-desoutter/news-events',\n"; $list = "\t'Corporate'\n\t=> 'https://www.desouttertools.com/about-desoutter/news-events',\n";
foreach($items as $item) { foreach ($items as $item) {
$lang = trim($item->plaintext); $lang = trim($item->plaintext);
$uri = $item->find('a', 0)->href; $uri = $item->find('a', 0)->href;
@ -222,7 +228,8 @@ class DesoutterBridge extends BridgeAbstract {
* on the 'Corporate' site. * on the 'Corporate' site.
* @return void * @return void
*/ */
private function extractIndustryLanguages() { private function extractIndustryLanguages()
{
$html = getSimpleHTMLDOMCached('https://www.desouttertools.com/industry-4-0/news'); $html = getSimpleHTMLDOMCached('https://www.desouttertools.com/industry-4-0/news');
$html = defaultLinkTo($html, static::URI); $html = defaultLinkTo($html, static::URI);
@ -231,7 +238,7 @@ class DesoutterBridge extends BridgeAbstract {
$list = "\t'Corporate'\n\t=> 'https://www.desouttertools.com/industry-4-0/news',\n"; $list = "\t'Corporate'\n\t=> 'https://www.desouttertools.com/industry-4-0/news',\n";
foreach($items as $item) { foreach ($items as $item) {
$lang = trim($item->plaintext); $lang = trim($item->plaintext);
$uri = $item->find('a', 0)->href; $uri = $item->find('a', 0)->href;

View file

@ -1,6 +1,7 @@
<?php <?php
class DevToBridge extends BridgeAbstract {
class DevToBridge extends BridgeAbstract
{
const CONTEXT_BY_TAG = 'By tag'; const CONTEXT_BY_TAG = 'By tag';
const NAME = 'dev.to Bridge'; const NAME = 'dev.to Bridge';
@ -9,28 +10,29 @@ class DevToBridge extends BridgeAbstract {
const MAINTAINER = 'logmanoriginal'; const MAINTAINER = 'logmanoriginal';
const CACHE_TIMEOUT = 10800; // 15 min. const CACHE_TIMEOUT = 10800; // 15 min.
const PARAMETERS = array( const PARAMETERS = [
self::CONTEXT_BY_TAG => array( self::CONTEXT_BY_TAG => [
'tag' => array( 'tag' => [
'name' => 'Tag', 'name' => 'Tag',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'title' => 'Insert your tag', 'title' => 'Insert your tag',
'exampleValue' => 'python' 'exampleValue' => 'python'
), ],
'full' => array( 'full' => [
'name' => 'Full article', 'name' => 'Full article',
'type' => 'checkbox', 'type' => 'checkbox',
'required' => false, 'required' => false,
'title' => 'Enable to receive the full article for each item' 'title' => 'Enable to receive the full article for each item'
) ]
) ]
); ];
public function getURI() { public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case self::CONTEXT_BY_TAG: case self::CONTEXT_BY_TAG:
if($tag = $this->getInput('tag')) { if ($tag = $this->getInput('tag')) {
return static::URI . '/t/' . urlencode($tag); return static::URI . '/t/' . urlencode($tag);
} }
break; break;
@ -39,12 +41,14 @@ class DevToBridge extends BridgeAbstract {
return parent::getURI(); return parent::getURI();
} }
public function getIcon() { public function getIcon()
{
return 'https://practicaldev-herokuapp-com.freetls.fastly.net/assets/ return 'https://practicaldev-herokuapp-com.freetls.fastly.net/assets/
apple-icon-5c6fa9f2bce280428589c6195b7f1924206a53b782b371cfe2d02da932c8c173.png'; apple-icon-5c6fa9f2bce280428589c6195b7f1924206a53b782b371cfe2d02da932c8c173.png';
} }
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOMCached($this->getURI()); $html = getSimpleHTMLDOMCached($this->getURI());
$html = defaultLinkTo($html, static::URI); $html = defaultLinkTo($html, static::URI);
@ -52,8 +56,8 @@ apple-icon-5c6fa9f2bce280428589c6195b7f1924206a53b782b371cfe2d02da932c8c173.png'
$articles = $html->find('div.crayons-story') $articles = $html->find('div.crayons-story')
or returnServerError('Could not find articles!'); or returnServerError('Could not find articles!');
foreach($articles as $article) { foreach ($articles as $article) {
$item = array(); $item = [];
$item['uri'] = $article->find('a[id*=article-link]', 0)->href; $item['uri'] = $article->find('a[id*=article-link]', 0)->href;
$item['title'] = $article->find('h2 > a', 0)->plaintext; $item['title'] = $article->find('h2 > a', 0)->plaintext;
@ -62,9 +66,9 @@ apple-icon-5c6fa9f2bce280428589c6195b7f1924206a53b782b371cfe2d02da932c8c173.png'
$item['author'] = $article->find('a.crayons-story__secondary.fw-medium', 0)->plaintext; $item['author'] = $article->find('a.crayons-story__secondary.fw-medium', 0)->plaintext;
// Profile image // Profile image
$item['enclosures'] = array($article->find('img', 0)->src); $item['enclosures'] = [$article->find('img', 0)->src];
if($this->getInput('full')) { if ($this->getInput('full')) {
$fullArticle = $this->getFullArticle($item['uri']); $fullArticle = $this->getFullArticle($item['uri']);
$item['content'] = <<<EOD $item['content'] = <<<EOD
<p>{$fullArticle}</p> <p>{$fullArticle}</p>
@ -85,7 +89,8 @@ EOD;
} }
} }
public function getName() { public function getName()
{
if (!is_null($this->getInput('tag'))) { if (!is_null($this->getInput('tag'))) {
return ucfirst($this->getInput('tag')) . ' - dev.to'; return ucfirst($this->getInput('tag')) . ' - dev.to';
} }
@ -93,7 +98,8 @@ EOD;
return parent::getName(); return parent::getName();
} }
private function getFullArticle($url) { private function getFullArticle($url)
{
$html = getSimpleHTMLDOMCached($url); $html = getSimpleHTMLDOMCached($url);
$html = defaultLinkTo($html, static::URI); $html = defaultLinkTo($html, static::URI);

View file

@ -2,7 +2,6 @@
class DeveloppezDotComBridge extends FeedExpander class DeveloppezDotComBridge extends FeedExpander
{ {
const MAINTAINER = 'Binnette'; const MAINTAINER = 'Binnette';
const NAME = 'Developpez.com Actus (FR)'; const NAME = 'Developpez.com Actus (FR)';
const URI = 'https://www.developpez.com/'; const URI = 'https://www.developpez.com/';
@ -11,20 +10,20 @@ class DeveloppezDotComBridge extends FeedExpander
const CACHE_TIMEOUT = 1800; // 30min const CACHE_TIMEOUT = 1800; // 30min
const DESCRIPTION = 'Returns complete posts from developpez.com'; const DESCRIPTION = 'Returns complete posts from developpez.com';
// Encodings used by Developpez.com in their articles body // Encodings used by Developpez.com in their articles body
const ENCONDINGS = array('Windows-1252', 'UTF-8'); const ENCONDINGS = ['Windows-1252', 'UTF-8'];
const PARAMETERS = array( const PARAMETERS = [
array( [
'limit' => array( 'limit' => [
'name' => 'Max items', 'name' => 'Max items',
'type' => 'number', 'type' => 'number',
'defaultValue' => 5, 'defaultValue' => 5,
), ],
// list of the differents RSS availables // list of the differents RSS availables
'domain' => array( 'domain' => [
'type' => 'list', 'type' => 'list',
'name' => 'Domaine', 'name' => 'Domaine',
'title' => 'Chosissez un sous-domaine', 'title' => 'Chosissez un sous-domaine',
'values' => array( 'values' => [
'= Domaine principal =' => 'www', '= Domaine principal =' => 'www',
'4d' => '4d', '4d' => '4d',
'abbyy' => 'abbyy', 'abbyy' => 'abbyy',
@ -159,10 +158,10 @@ class DeveloppezDotComBridge extends FeedExpander
'xhtml' => 'xhtml', 'xhtml' => 'xhtml',
'xml' => 'xml', 'xml' => 'xml',
'zend-framework' => 'zend-framework' 'zend-framework' => 'zend-framework'
), ],
) ]
) ]
); ];
/** /**
* Return the RSS url for selected domain * Return the RSS url for selected domain
@ -364,7 +363,7 @@ class DeveloppezDotComBridge extends FeedExpander
private function getAllVideoUrl($item) private function getAllVideoUrl($item)
{ {
// Array of video url // Array of video url
$url = array(); $url = [];
// Developpez use a div with the class video-container // Developpez use a div with the class video-container
$divsVideo = $item->find('div.video-container'); $divsVideo = $item->find('div.video-container');

View file

@ -1,20 +1,22 @@
<?php <?php
class DiarioDeNoticiasBridge extends BridgeAbstract {
class DiarioDeNoticiasBridge extends BridgeAbstract
{
const NAME = 'Diário de Notícias (PT)'; const NAME = 'Diário de Notícias (PT)';
const URI = 'https://dn.pt'; const URI = 'https://dn.pt';
const DESCRIPTION = 'Diário de Notícias (DN.PT)'; const DESCRIPTION = 'Diário de Notícias (DN.PT)';
const MAINTAINER = 'somini'; const MAINTAINER = 'somini';
const PARAMETERS = array( const PARAMETERS = [
'Tag' => array( 'Tag' => [
'n' => array( 'n' => [
'name' => 'Tag Name', 'name' => 'Tag Name',
'required' => true, 'required' => true,
'exampleValue' => 'rogerio-casanova', 'exampleValue' => 'rogerio-casanova',
) ]
) ]
); ];
const MONPT = array( const MONPT = [
'jan', 'jan',
'fev', 'fev',
'mar', 'mar',
@ -27,14 +29,16 @@ class DiarioDeNoticiasBridge extends BridgeAbstract {
'out', 'out',
'nov', 'nov',
'dez', 'dez',
); ];
public function getIcon() { public function getIcon()
{
return 'https://static.globalnoticias.pt/dn/common/images/favicons/favicon-128.png'; return 'https://static.globalnoticias.pt/dn/common/images/favicons/favicon-128.png';
} }
public function getName() { public function getName()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Tag': case 'Tag':
$name = self::NAME . ' | Tag | ' . $this->getInput('n'); $name = self::NAME . ' | Tag | ' . $this->getInput('n');
break; break;
@ -44,8 +48,9 @@ class DiarioDeNoticiasBridge extends BridgeAbstract {
return $name; return $name;
} }
public function getURI() { public function getURI()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
case 'Tag': case 'Tag':
$url = self::URI . '/tag/' . $this->getInput('n') . '.html'; $url = self::URI . '/tag/' . $this->getInput('n') . '.html';
break; break;
@ -55,12 +60,13 @@ class DiarioDeNoticiasBridge extends BridgeAbstract {
return $url; return $url;
} }
public function collectData() { public function collectData()
{
$archives = self::getURI(); $archives = self::getURI();
$html = getSimpleHTMLDOMCached($archives); $html = getSimpleHTMLDOMCached($archives);
foreach($html->find('article') as $element) { foreach ($html->find('article') as $element) {
$item = array(); $item = [];
$title = $element->find('.t-am-title', 0); $title = $element->find('.t-am-title', 0);
$link = $element->find('a.t-am-text', 0); $link = $element->find('a.t-am-text', 0);
@ -79,6 +85,5 @@ class DiarioDeNoticiasBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
} }
} }
} }

View file

@ -1,5 +1,7 @@
<?php <?php
class DiarioDoAlentejoBridge extends BridgeAbstract {
class DiarioDoAlentejoBridge extends BridgeAbstract
{
const MAINTAINER = 'somini'; const MAINTAINER = 'somini';
const NAME = 'Diário do Alentejo'; const NAME = 'Diário do Alentejo';
const URI = 'https://www.diariodoalentejo.pt'; const URI = 'https://www.diariodoalentejo.pt';
@ -7,7 +9,7 @@ class DiarioDoAlentejoBridge extends BridgeAbstract {
const CACHE_TIMEOUT = 28800; // 8h const CACHE_TIMEOUT = 28800; // 8h
/* This is used to hack around obtaining a timestamp. It's just a list of Month names in Portuguese ... */ /* This is used to hack around obtaining a timestamp. It's just a list of Month names in Portuguese ... */
const PT_MONTH_NAMES = array( const PT_MONTH_NAMES = [
'janeiro', 'janeiro',
'fevereiro', 'fevereiro',
'março', 'março',
@ -19,18 +21,20 @@ class DiarioDoAlentejoBridge extends BridgeAbstract {
'setembro', 'setembro',
'outubro', 'outubro',
'novembro', 'novembro',
'dezembro'); 'dezembro'];
public function getIcon() { public function getIcon()
{
return 'https://www.diariodoalentejo.pt/images/favicon/apple-touch-icon.png'; return 'https://www.diariodoalentejo.pt/images/favicon/apple-touch-icon.png';
} }
public function collectData(){ public function collectData()
{
/* This is slow as molasses (>30s!), keep the cache timeout high to avoid killing the host */ /* This is slow as molasses (>30s!), keep the cache timeout high to avoid killing the host */
$html = getSimpleHTMLDOMCached($this->getURI() . '/pt/noticias-listagem.aspx'); $html = getSimpleHTMLDOMCached($this->getURI() . '/pt/noticias-listagem.aspx');
foreach($html->find('.list_news .item') as $element) { foreach ($html->find('.list_news .item') as $element) {
$item = array(); $item = [];
$item_link = $element->find('.body h2.title a', 0); $item_link = $element->find('.body h2.title a', 0);
/* Another broken URL, see also `bridges/ComboiosDePortugalBridge.php` */ /* Another broken URL, see also `bridges/ComboiosDePortugalBridge.php` */
@ -38,9 +42,14 @@ class DiarioDoAlentejoBridge extends BridgeAbstract {
$item['title'] = $item_link->innertext; $item['title'] = $item_link->innertext;
$item['timestamp'] = str_ireplace( $item['timestamp'] = str_ireplace(
array_map(function($name) { return ' ' . $name . ' '; }, self::PT_MONTH_NAMES), array_map(function ($name) {
array_map(function($num) { return sprintf('-%02d-', $num); }, range(1, sizeof(self::PT_MONTH_NAMES))), return ' ' . $name . ' ';
$element->find('span.date', 0)->innertext); }, self::PT_MONTH_NAMES),
array_map(function ($num) {
return sprintf('-%02d-', $num);
}, range(1, sizeof(self::PT_MONTH_NAMES))),
$element->find('span.date', 0)->innertext
);
/* Fix the Image URL */ /* Fix the Image URL */
$item_image = $element->find('img.thumb', 0); $item_image = $element->find('img.thumb', 0);

View file

@ -1,46 +1,47 @@
<?php <?php
class DiceBridge extends BridgeAbstract {
class DiceBridge extends BridgeAbstract
{
const MAINTAINER = 'rogerdc'; const MAINTAINER = 'rogerdc';
const NAME = 'Dice Unofficial RSS'; const NAME = 'Dice Unofficial RSS';
const URI = 'https://www.dice.com/'; const URI = 'https://www.dice.com/';
const DESCRIPTION = 'The Unofficial Dice RSS'; const DESCRIPTION = 'The Unofficial Dice RSS';
// const CACHE_TIMEOUT = 86400; // 1 day // const CACHE_TIMEOUT = 86400; // 1 day
const PARAMETERS = array(array( const PARAMETERS = [[
'for_one' => array( 'for_one' => [
'name' => 'With at least one of the words', 'name' => 'With at least one of the words',
'required' => false, 'required' => false,
), ],
'for_all' => array( 'for_all' => [
'name' => 'With all of the words', 'name' => 'With all of the words',
'required' => false, 'required' => false,
), ],
'for_exact' => array( 'for_exact' => [
'name' => 'With the exact phrase', 'name' => 'With the exact phrase',
'required' => false, 'required' => false,
), ],
'for_none' => array( 'for_none' => [
'name' => 'With none of these words', 'name' => 'With none of these words',
'required' => false, 'required' => false,
), ],
'for_jt' => array( 'for_jt' => [
'name' => 'Within job title', 'name' => 'Within job title',
'required' => false, 'required' => false,
), ],
'for_com' => array( 'for_com' => [
'name' => 'Within company name', 'name' => 'Within company name',
'required' => false, 'required' => false,
), ],
'for_loc' => array( 'for_loc' => [
'name' => 'City, State, or ZIP code', 'name' => 'City, State, or ZIP code',
'required' => false, 'required' => false,
), ],
'radius' => array( 'radius' => [
'name' => 'Radius in miles', 'name' => 'Radius in miles',
'type' => 'list', 'type' => 'list',
'required' => false, 'required' => false,
'values' => array( 'values' => [
'Exact Location' => 'El', 'Exact Location' => 'El',
'Within 5 miles' => '5', 'Within 5 miles' => '5',
'Within 10 miles' => '10', 'Within 10 miles' => '10',
@ -50,14 +51,14 @@ class DiceBridge extends BridgeAbstract {
'Within 50 miles' => '50', 'Within 50 miles' => '50',
'Within 75 miles' => '75', 'Within 75 miles' => '75',
'Within 100 miles' => '100', 'Within 100 miles' => '100',
), ],
'defaultValue' => '0', 'defaultValue' => '0',
), ],
'jtype' => array( 'jtype' => [
'name' => 'Job type', 'name' => 'Job type',
'type' => 'list', 'type' => 'list',
'required' => false, 'required' => false,
'values' => array( 'values' => [
'Full-Time' => 'Full Time', 'Full-Time' => 'Full Time',
'Part-Time' => 'Part Time', 'Part-Time' => 'Part Time',
'Contract - Independent' => 'Contract Independent', 'Contract - Independent' => 'Contract Independent',
@ -66,20 +67,22 @@ class DiceBridge extends BridgeAbstract {
'Contract to Hire - W2' => 'C2H W2', 'Contract to Hire - W2' => 'C2H W2',
'Third Party - Contract - Corp-to-Corp' => 'Contract Corp-To-Corp', 'Third Party - Contract - Corp-to-Corp' => 'Contract Corp-To-Corp',
'Third Party - Contract to Hire - Corp-to-Corp' => 'C2H Corp-To-Corp', 'Third Party - Contract to Hire - Corp-to-Corp' => 'C2H Corp-To-Corp',
), ],
'defaultValue' => 'Full Time', 'defaultValue' => 'Full Time',
), ],
'telecommute' => array( 'telecommute' => [
'name' => 'Telecommute', 'name' => 'Telecommute',
'type' => 'checkbox', 'type' => 'checkbox',
), ],
)); ]];
public function getIcon() { public function getIcon()
{
return 'https://assets.dice.com/techpro/img/favicons/favicon.ico'; return 'https://assets.dice.com/techpro/img/favicons/favicon.ico';
} }
public function collectData() { public function collectData()
{
$uri = 'https://www.dice.com/jobs/advancedResult.html'; $uri = 'https://www.dice.com/jobs/advancedResult.html';
$uri .= '?for_one=' . urlencode($this->getInput('for_one')); $uri .= '?for_one=' . urlencode($this->getInput('for_one'));
$uri .= '&for_all=' . urlencode($this->getInput('for_all')); $uri .= '&for_all=' . urlencode($this->getInput('for_all'));
@ -98,8 +101,8 @@ class DiceBridge extends BridgeAbstract {
} }
$html = getSimpleHTMLDOM($uri); $html = getSimpleHTMLDOM($uri);
foreach($html->find('div.complete-serp-result-div') as $element) { foreach ($html->find('div.complete-serp-result-div') as $element) {
$item = array(); $item = [];
// Title // Title
$masterLink = $element->find('a[id^=position]', 0); $masterLink = $element->find('a[id^=position]', 0);
$item['title'] = $masterLink->title; $item['title'] = $masterLink->title;
@ -111,8 +114,9 @@ class DiceBridge extends BridgeAbstract {
$item['id'] = $masterLink->value; $item['id'] = $masterLink->value;
// Image // Image
$image = $element->find('img', 0); $image = $element->find('img', 0);
if ($image) if ($image) {
$item['image'] = $image->getAttribute('src'); $item['image'] = $image->getAttribute('src');
}
// Content // Content
$shortdesc = $element->find('.shortdesc', '0'); $shortdesc = $element->find('.shortdesc', '0');
$shortdesc = ($shortdesc) ? $shortdesc->innertext : ''; $shortdesc = ($shortdesc) ? $shortdesc->innertext : '';

View file

@ -1,29 +1,30 @@
<?php <?php
class DilbertBridge extends BridgeAbstract {
class DilbertBridge extends BridgeAbstract
{
const MAINTAINER = 'kranack'; const MAINTAINER = 'kranack';
const NAME = 'Dilbert Daily Strip'; const NAME = 'Dilbert Daily Strip';
const URI = 'https://dilbert.com'; const URI = 'https://dilbert.com';
const CACHE_TIMEOUT = 21600; // 6h const CACHE_TIMEOUT = 21600; // 6h
const DESCRIPTION = 'The Unofficial Dilbert Daily Comic Strip'; const DESCRIPTION = 'The Unofficial Dilbert Daily Comic Strip';
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
foreach($html->find('section.comic-item') as $element) { foreach ($html->find('section.comic-item') as $element) {
$img = $element->find('img', 0); $img = $element->find('img', 0);
$link = $element->find('a', 0); $link = $element->find('a', 0);
$comic = $img->src; $comic = $img->src;
$title = $img->alt; $title = $img->alt;
$url = $link->href; $url = $link->href;
$date = substr(strrchr($url, '/'), 1); $date = substr(strrchr($url, '/'), 1);
if (empty($title)) if (empty($title)) {
$title = 'Dilbert Comic Strip on ' . $date; $title = 'Dilbert Comic Strip on ' . $date;
}
$date = strtotime($date); $date = strtotime($date);
$item = array(); $item = [];
$item['uri'] = $url; $item['uri'] = $url;
$item['title'] = $title; $item['title'] = $title;
$item['author'] = 'Scott Adams'; $item['author'] = 'Scott Adams';

View file

@ -1,91 +1,86 @@
<?php <?php
class DiscogsBridge extends BridgeAbstract { class DiscogsBridge extends BridgeAbstract
{
const MAINTAINER = 'teromene'; const MAINTAINER = 'teromene';
const NAME = 'DiscogsBridge'; const NAME = 'DiscogsBridge';
const URI = 'https://www.discogs.com/'; const URI = 'https://www.discogs.com/';
const DESCRIPTION = 'Returns releases from discogs'; const DESCRIPTION = 'Returns releases from discogs';
const PARAMETERS = array( const PARAMETERS = [
'Artist Releases' => array( 'Artist Releases' => [
'artistid' => array( 'artistid' => [
'name' => 'Artist ID', 'name' => 'Artist ID',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'exampleValue' => '28104', 'exampleValue' => '28104',
'title' => 'Only the ID from an artist page. EG /artist/28104-Aesop-Rock is 28104' 'title' => 'Only the ID from an artist page. EG /artist/28104-Aesop-Rock is 28104'
) ]
), ],
'Label Releases' => array( 'Label Releases' => [
'labelid' => array( 'labelid' => [
'name' => 'Label ID', 'name' => 'Label ID',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'exampleValue' => '8201', 'exampleValue' => '8201',
'title' => 'Only the ID from a label page. EG /label/8201-Rhymesayers-Entertainment is 8201' 'title' => 'Only the ID from a label page. EG /label/8201-Rhymesayers-Entertainment is 8201'
) ]
), ],
'User Wantlist' => array( 'User Wantlist' => [
'username_wantlist' => array( 'username_wantlist' => [
'name' => 'Username', 'name' => 'Username',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'TheBlindMaster', 'exampleValue' => 'TheBlindMaster',
) ]
), ],
'User Folder' => array( 'User Folder' => [
'username_folder' => array( 'username_folder' => [
'name' => 'Username', 'name' => 'Username',
'type' => 'text', 'type' => 'text',
), ],
'folderid' => array( 'folderid' => [
'name' => 'Folder ID', 'name' => 'Folder ID',
'type' => 'number', 'type' => 'number',
) ]
) ]
); ];
public function collectData() { public function collectData()
{
if(!empty($this->getInput('artistid')) || !empty($this->getInput('labelid'))) { if (!empty($this->getInput('artistid')) || !empty($this->getInput('labelid'))) {
if (!empty($this->getInput('artistid'))) {
if(!empty($this->getInput('artistid'))) {
$data = getContents('https://api.discogs.com/artists/' $data = getContents('https://api.discogs.com/artists/'
. $this->getInput('artistid') . $this->getInput('artistid')
. '/releases?sort=year&sort_order=desc'); . '/releases?sort=year&sort_order=desc');
} elseif(!empty($this->getInput('labelid'))) { } elseif (!empty($this->getInput('labelid'))) {
$data = getContents('https://api.discogs.com/labels/' $data = getContents('https://api.discogs.com/labels/'
. $this->getInput('labelid') . $this->getInput('labelid')
. '/releases?sort=year&sort_order=desc'); . '/releases?sort=year&sort_order=desc');
} }
$jsonData = json_decode($data, true); $jsonData = json_decode($data, true);
foreach($jsonData['releases'] as $release) { foreach ($jsonData['releases'] as $release) {
$item = [];
$item = array();
$item['author'] = $release['artist']; $item['author'] = $release['artist'];
$item['title'] = $release['title']; $item['title'] = $release['title'];
$item['id'] = $release['id']; $item['id'] = $release['id'];
$resId = array_key_exists('main_release', $release) ? $release['main_release'] : $release['id']; $resId = array_key_exists('main_release', $release) ? $release['main_release'] : $release['id'];
$item['uri'] = self::URI . $this->getInput('artistid') . '/release/' . $resId; $item['uri'] = self::URI . $this->getInput('artistid') . '/release/' . $resId;
if(isset($release['year'])) { if (isset($release['year'])) {
$item['timestamp'] = DateTime::createFromFormat('Y', $release['year'])->getTimestamp(); $item['timestamp'] = DateTime::createFromFormat('Y', $release['year'])->getTimestamp();
} }
$item['content'] = $item['author'] . ' - ' . $item['title']; $item['content'] = $item['author'] . ' - ' . $item['title'];
$this->items[] = $item; $this->items[] = $item;
} }
} elseif (!empty($this->getInput('username_wantlist')) || !empty($this->getInput('username_folder'))) {
} elseif(!empty($this->getInput('username_wantlist')) || !empty($this->getInput('username_folder'))) { if (!empty($this->getInput('username_wantlist'))) {
if(!empty($this->getInput('username_wantlist'))) {
$data = getContents('https://api.discogs.com/users/' $data = getContents('https://api.discogs.com/users/'
. $this->getInput('username_wantlist') . $this->getInput('username_wantlist')
. '/wants?sort=added&sort_order=desc'); . '/wants?sort=added&sort_order=desc');
$jsonData = json_decode($data, true)['wants']; $jsonData = json_decode($data, true)['wants'];
} elseif (!empty($this->getInput('username_folder'))) {
} elseif(!empty($this->getInput('username_folder'))) {
$data = getContents('https://api.discogs.com/users/' $data = getContents('https://api.discogs.com/users/'
. $this->getInput('username_folder') . $this->getInput('username_folder')
. '/collection/folders/' . '/collection/folders/'
@ -93,10 +88,9 @@ class DiscogsBridge extends BridgeAbstract {
. '/releases?sort=added&sort_order=desc'); . '/releases?sort=added&sort_order=desc');
$jsonData = json_decode($data, true)['releases']; $jsonData = json_decode($data, true)['releases'];
} }
foreach($jsonData as $element) { foreach ($jsonData as $element) {
$infos = $element['basic_information']; $infos = $element['basic_information'];
$item = array(); $item = [];
$item['title'] = $infos['title']; $item['title'] = $infos['title'];
$item['author'] = $infos['artists'][0]['name']; $item['author'] = $infos['artists'][0]['name'];
$item['id'] = $infos['artists'][0]['id']; $item['id'] = $infos['artists'][0]['id'];
@ -104,17 +98,17 @@ class DiscogsBridge extends BridgeAbstract {
$item['timestamp'] = strtotime($element['date_added']); $item['timestamp'] = strtotime($element['date_added']);
$item['content'] = $item['author'] . ' - ' . $item['title']; $item['content'] = $item['author'] . ' - ' . $item['title'];
$this->items[] = $item; $this->items[] = $item;
}
} }
} }
} public function getURI()
{
public function getURI() {
return self::URI; return self::URI;
} }
public function getName() { public function getName()
{
return static::NAME; return static::NAME;
} }
} }

View file

@ -1,33 +1,35 @@
<?php <?php
class DockerHubBridge extends BridgeAbstract {
class DockerHubBridge extends BridgeAbstract
{
const NAME = 'Docker Hub Bridge'; const NAME = 'Docker Hub Bridge';
const URI = 'https://hub.docker.com'; const URI = 'https://hub.docker.com';
const DESCRIPTION = 'Returns new images for a container'; const DESCRIPTION = 'Returns new images for a container';
const MAINTAINER = 'VerifiedJoseph'; const MAINTAINER = 'VerifiedJoseph';
const PARAMETERS = array( const PARAMETERS = [
'User Submitted Image' => array( 'User Submitted Image' => [
'user' => array( 'user' => [
'name' => 'User', 'name' => 'User',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'rssbridge', 'exampleValue' => 'rssbridge',
), ],
'repo' => array( 'repo' => [
'name' => 'Repository', 'name' => 'Repository',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'rss-bridge', 'exampleValue' => 'rss-bridge',
) ]
), ],
'Official Image' => array( 'Official Image' => [
'repo' => array( 'repo' => [
'name' => 'Repository', 'name' => 'Repository',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'postgres', 'exampleValue' => 'postgres',
) ]
), ],
); ];
const CACHE_TIMEOUT = 3600; // 1 hour const CACHE_TIMEOUT = 3600; // 1 hour
@ -35,11 +37,12 @@ class DockerHubBridge extends BridgeAbstract {
private $imageUrlRegex = '/hub\.docker\.com\/r\/([\w]+)\/([\w-]+)\/?/'; private $imageUrlRegex = '/hub\.docker\.com\/r\/([\w]+)\/([\w-]+)\/?/';
private $officialImageUrlRegex = '/hub\.docker\.com\/_\/([\w-]+)\/?/'; private $officialImageUrlRegex = '/hub\.docker\.com\/_\/([\w-]+)\/?/';
public function detectParameters($url) { public function detectParameters($url)
$params = array(); {
$params = [];
// user submitted image // user submitted image
if(preg_match($this->imageUrlRegex, $url, $matches)) { if (preg_match($this->imageUrlRegex, $url, $matches)) {
$params['context'] = 'User Submitted Image'; $params['context'] = 'User Submitted Image';
$params['user'] = $matches[1]; $params['user'] = $matches[1];
$params['repo'] = $matches[2]; $params['repo'] = $matches[2];
@ -47,7 +50,7 @@ class DockerHubBridge extends BridgeAbstract {
} }
// official image // official image
if(preg_match($this->officialImageUrlRegex, $url, $matches)) { if (preg_match($this->officialImageUrlRegex, $url, $matches)) {
$params['context'] = 'Official Image'; $params['context'] = 'Official Image';
$params['repo'] = $matches[1]; $params['repo'] = $matches[1];
return $params; return $params;
@ -56,13 +59,14 @@ class DockerHubBridge extends BridgeAbstract {
return null; return null;
} }
public function collectData() { public function collectData()
{
$json = getContents($this->getApiUrl()); $json = getContents($this->getApiUrl());
$data = json_decode($json, false); $data = json_decode($json, false);
foreach ($data->results as $result) { foreach ($data->results as $result) {
$item = array(); $item = [];
$lastPushed = date('Y-m-d H:i:s', strtotime($result->tag_last_pushed)); $lastPushed = date('Y-m-d H:i:s', strtotime($result->tag_last_pushed));
@ -82,10 +86,10 @@ EOD;
$this->items[] = $item; $this->items[] = $item;
} }
} }
public function getURI() { public function getURI()
{
if ($this->queriedContext === 'Official Image') { if ($this->queriedContext === 'Official Image') {
return self::URI . '/_/' . $this->getRepo(); return self::URI . '/_/' . $this->getRepo();
} }
@ -97,7 +101,8 @@ EOD;
return parent::getURI(); return parent::getURI();
} }
public function getName() { public function getName()
{
if ($this->getInput('repo')) { if ($this->getInput('repo')) {
return $this->getRepo() . ' - Docker Hub'; return $this->getRepo() . ' - Docker Hub';
} }
@ -105,7 +110,8 @@ EOD;
return parent::getName(); return parent::getName();
} }
private function getRepo() { private function getRepo()
{
if ($this->queriedContext === 'Official Image') { if ($this->queriedContext === 'Official Image') {
return $this->getInput('repo'); return $this->getInput('repo');
} }
@ -113,7 +119,8 @@ EOD;
return $this->getInput('user') . '/' . $this->getInput('repo'); return $this->getInput('user') . '/' . $this->getInput('repo');
} }
private function getApiUrl() { private function getApiUrl()
{
if ($this->queriedContext === 'Official Image') { if ($this->queriedContext === 'Official Image') {
return $this->apiURL . 'library/' . $this->getRepo() . '/tags/?page_size=25&page=1'; return $this->apiURL . 'library/' . $this->getRepo() . '/tags/?page_size=25&page=1';
} }
@ -121,7 +128,8 @@ EOD;
return $this->apiURL . $this->getRepo() . '/tags/?page_size=25&page=1'; return $this->apiURL . $this->getRepo() . '/tags/?page_size=25&page=1';
} }
private function getLayerUrl($name, $digest) { private function getLayerUrl($name, $digest)
{
if ($this->queriedContext === 'Official Image') { if ($this->queriedContext === 'Official Image') {
return self::URI . '/layers/' . $this->getRepo() . '/library/' . return self::URI . '/layers/' . $this->getRepo() . '/library/' .
$this->getRepo() . '/' . $name . '/images/' . $digest; $this->getRepo() . '/' . $name . '/images/' . $digest;
@ -130,7 +138,8 @@ EOD;
return self::URI . '/layers/' . $this->getRepo() . '/' . $name . '/images/' . $digest; return self::URI . '/layers/' . $this->getRepo() . '/' . $name . '/images/' . $digest;
} }
private function getTagUrl($name) { private function getTagUrl($name)
{
if ($this->queriedContext === 'Official Image') { if ($this->queriedContext === 'Official Image') {
return self::URI . '/_/' . $this->getRepo() . '?tab=tags&name=' . $name; return self::URI . '/_/' . $this->getRepo() . '?tab=tags&name=' . $name;
} }
@ -138,7 +147,8 @@ EOD;
return self::URI . '/r/' . $this->getRepo() . '/tags?name=' . $name; return self::URI . '/r/' . $this->getRepo() . '/tags?name=' . $name;
} }
private function getImages($result) { private function getImages($result)
{
$html = <<<EOD $html = <<<EOD
<table style="width:300px;"><thead><tr><th>Digest</th><th>OS/architecture</th></tr></thead></tbody> <table style="width:300px;"><thead><tr><th>Digest</th><th>OS/architecture</th></tr></thead></tbody>
EOD; EOD;
@ -158,7 +168,8 @@ EOD;
return $html . '</tbody></table>'; return $html . '</tbody></table>';
} }
private function getShortDigestId($digest) { private function getShortDigestId($digest)
{
$parts = explode(':', $digest); $parts = explode(':', $digest);
return substr($parts[1], 0, 12); return substr($parts[1], 0, 12);
} }

View file

@ -1,54 +1,57 @@
<?php <?php
/** /**
* Retourne les dons d'une recherche filtrée sur le site Donnons.org * Retourne les dons d'une recherche filtrée sur le site Donnons.org
* Example: https://donnons.org/Sport/Ile-de-France * Example: https://donnons.org/Sport/Ile-de-France
*/ */
class DonnonsBridge extends BridgeAbstract { class DonnonsBridge extends BridgeAbstract
{
const MAINTAINER = 'Binnette'; const MAINTAINER = 'Binnette';
const NAME = 'Donnons.org'; const NAME = 'Donnons.org';
const URI = 'https://donnons.org'; const URI = 'https://donnons.org';
const CACHE_TIMEOUT = 1800; // 30min const CACHE_TIMEOUT = 1800; // 30min
const DESCRIPTION = 'Retourne les dons depuis le site Donnons.org.'; const DESCRIPTION = 'Retourne les dons depuis le site Donnons.org.';
const PARAMETERS = array( const PARAMETERS = [
array( [
'q' => array( 'q' => [
'name' => 'Url de recherche', 'name' => 'Url de recherche',
'required' => true, 'required' => true,
'exampleValue' => '/Sport/Ile-de-France', 'exampleValue' => '/Sport/Ile-de-France',
'pattern' => '\/.*', 'pattern' => '\/.*',
'title' => 'Faites une recherche sur le site. Puis copiez ici la fin de lurl. Doit commencer par /', 'title' => 'Faites une recherche sur le site. Puis copiez ici la fin de lurl. Doit commencer par /',
), ],
'p' => array( 'p' => [
'name' => 'Nombre de pages à scanner', 'name' => 'Nombre de pages à scanner',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'defaultValue' => 5, 'defaultValue' => 5,
'title' => 'Indique le nombre de pages de donnons.org qui seront scannées' 'title' => 'Indique le nombre de pages de donnons.org qui seront scannées'
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$pages = $this->getInput('p'); $pages = $this->getInput('p');
for($i = 1; $i <= $pages; $i++) { for ($i = 1; $i <= $pages; $i++) {
$this->collectDataByPage($i); $this->collectDataByPage($i);
} }
} }
private function collectDataByPage($page) { private function collectDataByPage($page)
{
$uri = $this->getPageURI($page); $uri = $this->getPageURI($page);
$html = getSimpleHTMLDOM($uri); $html = getSimpleHTMLDOM($uri);
$searchDiv = $html->find('div[id=search]', 0); $searchDiv = $html->find('div[id=search]', 0);
if(!is_null($searchDiv)) { if (!is_null($searchDiv)) {
$elements = $searchDiv->find('a.lst-annonce'); $elements = $searchDiv->find('a.lst-annonce');
foreach($elements as $element) { foreach ($elements as $element) {
$item = array(); $item = [];
// Lien vers le don // Lien vers le don
$item['uri'] = self::URI . $element->href; $item['uri'] = self::URI . $element->href;
@ -89,34 +92,37 @@ class DonnonsBridge extends BridgeAbstract {
$item['timestamp'] = $date; $item['timestamp'] = $date;
$item['author'] = $author; $item['author'] = $author;
$item['content'] = $content; $item['content'] = $content;
$item['enclosures'] = array($image); $item['enclosures'] = [$image];
$this->items[] = $item; $this->items[] = $item;
} }
} }
} }
private function getPageURI($page) { private function getPageURI($page)
{
$uri = $this->getURI(); $uri = $this->getURI();
$haveQueryParams = strpos($uri, '?') !== false; $haveQueryParams = strpos($uri, '?') !== false;
if($haveQueryParams) { if ($haveQueryParams) {
return $uri . '&page=' . $page; return $uri . '&page=' . $page;
} else { } else {
return $uri . '?page=' . $page; return $uri . '?page=' . $page;
} }
} }
public function getURI() { public function getURI()
if(!is_null($this->getInput('q'))) { {
if (!is_null($this->getInput('q'))) {
return self::URI . $this->getInput('q'); return self::URI . $this->getInput('q');
} }
return parent::getURI(); return parent::getURI();
} }
public function getName() { public function getName()
if(!is_null($this->getInput('q'))) { {
if (!is_null($this->getInput('q'))) {
return 'Donnons.org - ' . $this->getInput('q'); return 'Donnons.org - ' . $this->getInput('q');
} }

View file

@ -1,24 +1,27 @@
<?php <?php
class DribbbleBridge extends BridgeAbstract {
class DribbbleBridge extends BridgeAbstract
{
const MAINTAINER = 'quentinus95'; const MAINTAINER = 'quentinus95';
const NAME = 'Dribbble popular shots'; const NAME = 'Dribbble popular shots';
const URI = 'https://dribbble.com'; const URI = 'https://dribbble.com';
const CACHE_TIMEOUT = 1800; const CACHE_TIMEOUT = 1800;
const DESCRIPTION = 'Returns the newest popular shots from Dribbble.'; const DESCRIPTION = 'Returns the newest popular shots from Dribbble.';
public function getIcon() { public function getIcon()
{
return 'https://cdn.dribbble.com/assets/ return 'https://cdn.dribbble.com/assets/
favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico'; favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico';
} }
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
$json = $this->loadEmbeddedJsonData($html); $json = $this->loadEmbeddedJsonData($html);
foreach($html->find('li[id^="screenshot-"]') as $shot) { foreach ($html->find('li[id^="screenshot-"]') as $shot) {
$item = array(); $item = [];
$additional_data = $this->findJsonForShot($shot, $json); $additional_data = $this->findJsonForShot($shot, $json);
if ($additional_data === null) { if ($additional_data === null) {
@ -37,18 +40,19 @@ favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico';
$preview_path = $shot->find('figure img', 1)->attr['data-srcset']; $preview_path = $shot->find('figure img', 1)->attr['data-srcset'];
$item['content'] .= $this->getImageTag($preview_path, $item['title']); $item['content'] .= $this->getImageTag($preview_path, $item['title']);
$item['enclosures'] = array($this->getFullSizeImagePath($preview_path)); $item['enclosures'] = [$this->getFullSizeImagePath($preview_path)];
$this->items[] = $item; $this->items[] = $item;
} }
} }
private function loadEmbeddedJsonData($html){ private function loadEmbeddedJsonData($html)
$json = array(); {
$json = [];
$scripts = $html->find('script'); $scripts = $html->find('script');
foreach($scripts as $script) { foreach ($scripts as $script) {
if(strpos($script->innertext, 'newestShots') !== false) { if (strpos($script->innertext, 'newestShots') !== false) {
// fix single quotes // fix single quotes
$script->innertext = preg_replace('/\'(.*)\'(,?)$/im', '"\1"\2', $script->innertext); $script->innertext = preg_replace('/\'(.*)\'(,?)$/im', '"\1"\2', $script->innertext);
@ -73,9 +77,10 @@ favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico';
return $json; return $json;
} }
private function findJsonForShot($shot, $json){ private function findJsonForShot($shot, $json)
foreach($json as $element) { {
if(strpos($shot->getAttribute('id'), (string)$element['id']) !== false) { foreach ($json as $element) {
if (strpos($shot->getAttribute('id'), (string)$element['id']) !== false) {
return $element; return $element;
} }
} }
@ -83,7 +88,8 @@ favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico';
return null; return null;
} }
private function getImageTag($preview_path, $title){ private function getImageTag($preview_path, $title)
{
return sprintf( return sprintf(
'<br /> <a href="%s"><img srcset="%s" alt="%s" /></a>', '<br /> <a href="%s"><img srcset="%s" alt="%s" /></a>',
$this->getFullSizeImagePath($preview_path), $this->getFullSizeImagePath($preview_path),
@ -92,7 +98,8 @@ favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico';
); );
} }
private function getFullSizeImagePath($preview_path){ private function getFullSizeImagePath($preview_path)
{
// Get last image from srcset // Get last image from srcset
$src_set_urls = explode(',', $preview_path); $src_set_urls = explode(',', $preview_path);
$url = end($src_set_urls); $url = end($src_set_urls);

View file

@ -1,35 +1,37 @@
<?php <?php
class Drive2ruBridge extends BridgeAbstract {
class Drive2ruBridge extends BridgeAbstract
{
const MAINTAINER = 'dotter-ak'; const MAINTAINER = 'dotter-ak';
const NAME = 'Drive2.ru'; const NAME = 'Drive2.ru';
const URI = 'https://drive2.ru/'; const URI = 'https://drive2.ru/';
const DESCRIPTION = 'Лента новостей и тестдрайвов, бортжурналов по выбранной марке или модели const DESCRIPTION = 'Лента новостей и тестдрайвов, бортжурналов по выбранной марке или модели
(также работает с фильтром по категориям), блогов пользователей и публикаций по темам.'; (также работает с фильтром по категориям), блогов пользователей и публикаций по темам.';
const PARAMETERS = array( const PARAMETERS = [
'Новости и тест-драйвы' => array(), 'Новости и тест-драйвы' => [],
'Бортжурналы (По модели или марке)' => array( 'Бортжурналы (По модели или марке)' => [
'url' => array( 'url' => [
'name' => 'Ссылка на страницу с бортжурналом', 'name' => 'Ссылка на страницу с бортжурналом',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'title' => 'Например: https://www.drive2.ru/experience/suzuki/g4895/', 'title' => 'Например: https://www.drive2.ru/experience/suzuki/g4895/',
'exampleValue' => 'https://www.drive2.ru/experience/suzuki/g4895/' 'exampleValue' => 'https://www.drive2.ru/experience/suzuki/g4895/'
), ],
), ],
'Личные блоги' => array( 'Личные блоги' => [
'username' => array( 'username' => [
'name' => 'Никнейм пользователя на сайте', 'name' => 'Никнейм пользователя на сайте',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'title' => 'Например: Mickey', 'title' => 'Например: Mickey',
'exampleValue' => 'Mickey' 'exampleValue' => 'Mickey'
) ]
), ],
'Публикации по темам (Стоит почитать)' => array( 'Публикации по темам (Стоит почитать)' => [
'topic' => array( 'topic' => [
'name' => 'Темы', 'name' => 'Темы',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'Автозвук' => '16', 'Автозвук' => '16',
'Автомобильный дизайн' => '10', 'Автомобильный дизайн' => '10',
'Автоспорт' => '11', 'Автоспорт' => '11',
@ -62,29 +64,30 @@ class Drive2ruBridge extends BridgeAbstract {
'Шины и диски' => '140', 'Шины и диски' => '140',
'Электрика' => '130', 'Электрика' => '130',
'Электромобили' => '131' 'Электромобили' => '131'
), ],
'defaultValue' => '16', 'defaultValue' => '16',
) ]
), ],
'global' => array( 'global' => [
'full_articles' => array( 'full_articles' => [
'name' => 'Загружать в ленту полный текст', 'name' => 'Загружать в ленту полный текст',
'type' => 'checkbox' 'type' => 'checkbox'
) ]
) ]
); ];
private $title; private $title;
private function getUserContent($url) { private function getUserContent($url)
{
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
$this->title = $html->find('title', 0)->innertext; $this->title = $html->find('title', 0)->innertext;
$articles = $html->find('div.js-entity'); $articles = $html->find('div.js-entity');
foreach ($articles as $article) { foreach ($articles as $article) {
$item = array(); $item = [];
$item['title'] = $article->find('a.c-link--text', 0)->plaintext; $item['title'] = $article->find('a.c-link--text', 0)->plaintext;
$item['uri'] = urljoin(self::URI, $article->find('a.c-link--text', 0)->href); $item['uri'] = urljoin(self::URI, $article->find('a.c-link--text', 0)->href);
if($this->getInput('full_articles')) { if ($this->getInput('full_articles')) {
$item['content'] = $this->addCommentsLink( $item['content'] = $this->addCommentsLink(
$this->adjustContent(getSimpleHTMLDomCached($item['uri'])->find('div.c-post__body', 0))->innertext, $this->adjustContent(getSimpleHTMLDomCached($item['uri'])->find('div.c-post__body', 0))->innertext,
$item['uri'] $item['uri']
@ -93,20 +96,23 @@ class Drive2ruBridge extends BridgeAbstract {
$item['content'] = $this->addReadMoreLink($article->find('div.c-post-preview__lead', 0), $item['uri']); $item['content'] = $this->addReadMoreLink($article->find('div.c-post-preview__lead', 0), $item['uri']);
} }
$item['author'] = $article->find('a.c-username--wrap', 0)->plaintext; $item['author'] = $article->find('a.c-username--wrap', 0)->plaintext;
if (!is_null($article->find('img', 1))) $item['enclosures'][] = $article->find('img', 1)->src; if (!is_null($article->find('img', 1))) {
$item['enclosures'][] = $article->find('img', 1)->src;
}
$this->items[] = $item; $this->items[] = $item;
} }
} }
private function getLogbooksContent($url) { private function getLogbooksContent($url)
{
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
$this->title = $html->find('title', 0)->innertext; $this->title = $html->find('title', 0)->innertext;
$articles = $html->find('div.js-entity'); $articles = $html->find('div.js-entity');
foreach ($articles as $article) { foreach ($articles as $article) {
$item = array(); $item = [];
$item['title'] = $article->find('a.c-link--text', 1)->plaintext; $item['title'] = $article->find('a.c-link--text', 1)->plaintext;
$item['uri'] = urljoin(self::URI, $article->find('a.c-link--text', 1)->href); $item['uri'] = urljoin(self::URI, $article->find('a.c-link--text', 1)->href);
if($this->getInput('full_articles')) { if ($this->getInput('full_articles')) {
$item['content'] = $this->addCommentsLink( $item['content'] = $this->addCommentsLink(
$this->adjustContent(getSimpleHTMLDomCached($item['uri'])->find('div.c-post__body', 0))->innertext, $this->adjustContent(getSimpleHTMLDomCached($item['uri'])->find('div.c-post__body', 0))->innertext,
$item['uri'] $item['uri']
@ -115,20 +121,23 @@ class Drive2ruBridge extends BridgeAbstract {
$item['content'] = $this->addReadMoreLink($article->find('div.c-post-preview__lead', 0), $item['uri']); $item['content'] = $this->addReadMoreLink($article->find('div.c-post-preview__lead', 0), $item['uri']);
} }
$item['author'] = $article->find('a.c-username--wrap', 0)->plaintext; $item['author'] = $article->find('a.c-username--wrap', 0)->plaintext;
if (!is_null($article->find('img', 1))) $item['enclosures'][] = $article->find('img', 1)->src; if (!is_null($article->find('img', 1))) {
$item['enclosures'][] = $article->find('img', 1)->src;
}
$this->items[] = $item; $this->items[] = $item;
} }
} }
private function getNews() { private function getNews()
{
$html = getSimpleHTMLDOM('https://www.drive2.ru/editorial/'); $html = getSimpleHTMLDOM('https://www.drive2.ru/editorial/');
$this->title = $html->find('title', 0)->innertext; $this->title = $html->find('title', 0)->innertext;
$articles = $html->find('div.c-article-card'); $articles = $html->find('div.c-article-card');
foreach ($articles as $article) { foreach ($articles as $article) {
$item = array(); $item = [];
$item['title'] = $article->find('a.c-link--text', 0)->plaintext; $item['title'] = $article->find('a.c-link--text', 0)->plaintext;
$item['uri'] = urljoin(self::URI, $article->find('a.c-link--text', 0)->href); $item['uri'] = urljoin(self::URI, $article->find('a.c-link--text', 0)->href);
if($this->getInput('full_articles')) { if ($this->getInput('full_articles')) {
$item['content'] = $this->addCommentsLink( $item['content'] = $this->addCommentsLink(
$this->adjustContent(getSimpleHTMLDomCached($item['uri'])->find('div.article', 0))->innertext, $this->adjustContent(getSimpleHTMLDomCached($item['uri'])->find('div.article', 0))->innertext,
$item['uri'] $item['uri']
@ -137,23 +146,32 @@ class Drive2ruBridge extends BridgeAbstract {
$item['content'] = $this->addReadMoreLink($article->find('div.c-article-card__lead', 0), $item['uri']); $item['content'] = $this->addReadMoreLink($article->find('div.c-article-card__lead', 0), $item['uri']);
} }
$item['author'] = 'Новости и тест-драйвы на Drive2.ru'; $item['author'] = 'Новости и тест-драйвы на Drive2.ru';
if (!is_null($article->find('img', 0))) $item['enclosures'][] = $article->find('img', 0)->src; if (!is_null($article->find('img', 0))) {
$item['enclosures'][] = $article->find('img', 0)->src;
}
$this->items[] = $item; $this->items[] = $item;
} }
} }
private function adjustContent($content) { private function adjustContent($content)
foreach ($content->find('div.o-group') as $node) {
foreach ($content->find('div.o-group') as $node) {
$node->outertext = ''; $node->outertext = '';
foreach($content->find('div, span') as $attrs) }
foreach ($attrs->getAllAttributes() as $attr => $val) foreach ($content->find('div, span') as $attrs) {
foreach ($attrs->getAllAttributes() as $attr => $val) {
$attrs->removeAttribute($attr); $attrs->removeAttribute($attr);
foreach ($content->getElementsByTagName('figcaption') as $attrs) }
}
foreach ($content->getElementsByTagName('figcaption') as $attrs) {
$attrs->setAttribute( $attrs->setAttribute(
'style', 'style',
'font-style: italic; font-size: small; margin: 0 100px 75px;'); 'font-style: italic; font-size: small; margin: 0 100px 75px;'
foreach ($content->find('script') as $node) );
}
foreach ($content->find('script') as $node) {
$node->outertext = ''; $node->outertext = '';
}
foreach ($content->find('iframe') as $node) { foreach ($content->find('iframe') as $node) {
preg_match('/embed\/(.*?)\?/', $node->src, $match); preg_match('/embed\/(.*?)\?/', $node->src, $match);
$node->outertext = '<a href="https://www.youtube.com/watch?v=' . $match[1] . $node->outertext = '<a href="https://www.youtube.com/watch?v=' . $match[1] .
@ -162,31 +180,38 @@ class Drive2ruBridge extends BridgeAbstract {
return $content; return $content;
} }
private function addCommentsLink ($content, $url) { private function addCommentsLink($content, $url)
{
return $content . '<br><a href="' . $url . '#comments">Перейти к комментариям</a>'; return $content . '<br><a href="' . $url . '#comments">Перейти к комментариям</a>';
} }
private function addReadMoreLink ($content, $url) { private function addReadMoreLink($content, $url)
if (!is_null($content)) {
if (!is_null($content)) {
return preg_replace('!\s+!', ' ', str_replace('Читать дальше', '', $content->plaintext)) . return preg_replace('!\s+!', ' ', str_replace('Читать дальше', '', $content->plaintext)) .
'<br><a href="' . $url . '">Читать далее</a>'; '<br><a href="' . $url . '">Читать далее</a>';
else return ''; } else {
return '';
}
} }
public function collectData() { public function collectData()
switch($this->queriedContext) { {
switch ($this->queriedContext) {
default: default:
case 'Новости и тест-драйвы': case 'Новости и тест-драйвы':
$this->getNews(); $this->getNews();
break; break;
case 'Бортжурналы (По модели или марке)': case 'Бортжурналы (По модели или марке)':
if (!preg_match('/^https:\/\/www.drive2.ru\/experience/', $this->getInput('url'))) if (!preg_match('/^https:\/\/www.drive2.ru\/experience/', $this->getInput('url'))) {
returnServerError('Invalid url'); returnServerError('Invalid url');
}
$this->getLogbooksContent($this->getInput('url')); $this->getLogbooksContent($this->getInput('url'));
break; break;
case 'Личные блоги': case 'Личные блоги':
if (!preg_match('/^[a-zA-Z0-9-]{3,16}$/', $this->getInput('username'))) if (!preg_match('/^[a-zA-Z0-9-]{3,16}$/', $this->getInput('username'))) {
returnServerError('Invalid username'); returnServerError('Invalid username');
}
$this->getUserContent('https://www.drive2.ru/users/' . $this->getInput('username')); $this->getUserContent('https://www.drive2.ru/users/' . $this->getInput('username'));
break; break;
case 'Публикации по темам (Стоит почитать)': case 'Публикации по темам (Стоит почитать)':
@ -195,11 +220,13 @@ class Drive2ruBridge extends BridgeAbstract {
} }
} }
public function getName() { public function getName()
{
return $this->title ?: parent::getName(); return $this->title ?: parent::getName();
} }
public function getIcon() { public function getIcon()
{
return 'https://www.drive2.ru/favicon.ico'; return 'https://www.drive2.ru/favicon.ico';
} }
} }

View file

@ -1,6 +1,7 @@
<?php <?php
class DuckDuckGoBridge extends BridgeAbstract {
class DuckDuckGoBridge extends BridgeAbstract
{
const MAINTAINER = 'Astalaseven'; const MAINTAINER = 'Astalaseven';
const NAME = 'DuckDuckGo'; const NAME = 'DuckDuckGo';
const URI = 'https://duckduckgo.com/'; const URI = 'https://duckduckgo.com/';
@ -10,29 +11,30 @@ class DuckDuckGoBridge extends BridgeAbstract {
const SORT_DATE = '+sort:date'; const SORT_DATE = '+sort:date';
const SORT_RELEVANCE = ''; const SORT_RELEVANCE = '';
const PARAMETERS = array( array( const PARAMETERS = [ [
'u' => array( 'u' => [
'name' => 'keyword', 'name' => 'keyword',
'exampleValue' => 'duck', 'exampleValue' => 'duck',
'required' => true 'required' => true
), ],
'sort' => array( 'sort' => [
'name' => 'sort by', 'name' => 'sort by',
'type' => 'list', 'type' => 'list',
'required' => false, 'required' => false,
'values' => array( 'values' => [
'date' => self::SORT_DATE, 'date' => self::SORT_DATE,
'relevance' => self::SORT_RELEVANCE 'relevance' => self::SORT_RELEVANCE
), ],
'defaultValue' => self::SORT_DATE 'defaultValue' => self::SORT_DATE
) ]
)); ]];
public function collectData(){ public function collectData()
{
$html = getSimpleHTMLDOM(self::URI . 'html/?kd=-1&q=' . $this->getInput('u') . $this->getInput('sort')); $html = getSimpleHTMLDOM(self::URI . 'html/?kd=-1&q=' . $this->getInput('u') . $this->getInput('sort'));
foreach($html->find('div.result') as $element) { foreach ($html->find('div.result') as $element) {
$item = array(); $item = [];
$item['uri'] = $element->find('a.result__a', 0)->href; $item['uri'] = $element->find('a.result__a', 0)->href;
$item['title'] = $element->find('h2.result__title', 0)->plaintext; $item['title'] = $element->find('h2.result__title', 0)->plaintext;
$item['content'] = $element->find('a.result__snippet', 0)->plaintext; $item['content'] = $element->find('a.result__snippet', 0)->plaintext;

View file

@ -1,51 +1,53 @@
<?php <?php
class EZTVBridge extends BridgeAbstract {
class EZTVBridge extends BridgeAbstract
{
const MAINTAINER = 'alexAubin'; const MAINTAINER = 'alexAubin';
const NAME = 'EZTV'; const NAME = 'EZTV';
const URI = 'https://eztv.re/'; const URI = 'https://eztv.re/';
const DESCRIPTION = 'Returns list of torrents for specific show(s) const DESCRIPTION = 'Returns list of torrents for specific show(s)
on EZTV. Get IMDB IDs from IMDB.'; on EZTV. Get IMDB IDs from IMDB.';
const PARAMETERS = array( const PARAMETERS = [
array( [
'ids' => array( 'ids' => [
'name' => 'Show IMDB IDs', 'name' => 'Show IMDB IDs',
'exampleValue' => '8740790,1733785', 'exampleValue' => '8740790,1733785',
'required' => true, 'required' => true,
'title' => 'One or more IMDB show IDs (can be found in the IMDB show URL)' 'title' => 'One or more IMDB show IDs (can be found in the IMDB show URL)'
), ],
'no480' => array( 'no480' => [
'name' => 'No 480p', 'name' => 'No 480p',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Activate to exclude 480p torrents' 'title' => 'Activate to exclude 480p torrents'
), ],
'no720' => array( 'no720' => [
'name' => 'No 720p', 'name' => 'No 720p',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Activate to exclude 720p torrents' 'title' => 'Activate to exclude 720p torrents'
), ],
'no1080' => array( 'no1080' => [
'name' => 'No 1080p', 'name' => 'No 1080p',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Activate to exclude 1080p torrents' 'title' => 'Activate to exclude 1080p torrents'
), ],
'no2160' => array( 'no2160' => [
'name' => 'No 2160p', 'name' => 'No 2160p',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Activate to exclude 2160p torrents' 'title' => 'Activate to exclude 2160p torrents'
), ],
'noUnknownRes' => array( 'noUnknownRes' => [
'name' => 'No Unknown resolution', 'name' => 'No Unknown resolution',
'type' => 'checkbox', 'type' => 'checkbox',
'title' => 'Activate to exclude unknown resolution torrents' 'title' => 'Activate to exclude unknown resolution torrents'
), ],
) ]
); ];
// Shamelessly lifted from https://stackoverflow.com/a/2510459 // Shamelessly lifted from https://stackoverflow.com/a/2510459
protected function formatBytes($bytes, $precision = 2) { protected function formatBytes($bytes, $precision = 2)
$units = array('B', 'KB', 'MB', 'GB', 'TB'); {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0); $bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
@ -55,8 +57,9 @@ on EZTV. Get IMDB IDs from IMDB.';
return round($bytes, $precision) . ' ' . $units[$pow]; return round($bytes, $precision) . ' ' . $units[$pow];
} }
protected function getItemFromTorrent($torrent){ protected function getItemFromTorrent($torrent)
$item = array(); {
$item = [];
$item['uri'] = $torrent->episode_url; $item['uri'] = $torrent->episode_url;
$item['author'] = $torrent->imdb_id; $item['author'] = $torrent->imdb_id;
$item['timestamp'] = date('d F Y H:i:s', $torrent->date_released_unix); $item['timestamp'] = date('d F Y H:i:s', $torrent->date_released_unix);
@ -74,18 +77,20 @@ on EZTV. Get IMDB IDs from IMDB.';
return $item; return $item;
} }
private static function compareDate($torrent1, $torrent2) { private static function compareDate($torrent1, $torrent2)
{
return (strtotime($torrent1['timestamp']) < strtotime($torrent2['timestamp']) ? 1 : -1); return (strtotime($torrent1['timestamp']) < strtotime($torrent2['timestamp']) ? 1 : -1);
} }
public function collectData(){ public function collectData()
{
$showIds = explode(',', $this->getInput('ids')); $showIds = explode(',', $this->getInput('ids'));
foreach($showIds as $showId) { foreach ($showIds as $showId) {
$eztvUri = $this->getURI() . 'api/get-torrents?imdb_id=' . $showId; $eztvUri = $this->getURI() . 'api/get-torrents?imdb_id=' . $showId;
$content = getContents($eztvUri); $content = getContents($eztvUri);
$torrents = json_decode($content)->torrents; $torrents = json_decode($content)->torrents;
foreach($torrents as $torrent) { foreach ($torrents as $torrent) {
$title = $torrent->title; $title = $torrent->title;
$regex480 = '/480p/'; $regex480 = '/480p/';
$regex720 = '/720p/'; $regex720 = '/720p/';
@ -93,11 +98,13 @@ on EZTV. Get IMDB IDs from IMDB.';
$regex2160 = '/2160p/'; $regex2160 = '/2160p/';
$regexUnknown = '/(480p|720p|1080p|2160p)/'; $regexUnknown = '/(480p|720p|1080p|2160p)/';
// Skip unwanted resolution torrents // Skip unwanted resolution torrents
if ((preg_match($regex480, $title) === 1 && $this->getInput('no480')) if (
(preg_match($regex480, $title) === 1 && $this->getInput('no480'))
|| (preg_match($regex720, $title) === 1 && $this->getInput('no720')) || (preg_match($regex720, $title) === 1 && $this->getInput('no720'))
|| (preg_match($regex1080, $title) === 1 && $this->getInput('no1080')) || (preg_match($regex1080, $title) === 1 && $this->getInput('no1080'))
|| (preg_match($regex2160, $title) === 1 && $this->getInput('no2160')) || (preg_match($regex2160, $title) === 1 && $this->getInput('no2160'))
|| (preg_match($regexUnknown, $title) !== 1 && $this->getInput('noUnknownRes'))) { || (preg_match($regexUnknown, $title) !== 1 && $this->getInput('noUnknownRes'))
) {
continue; continue;
} }
@ -106,6 +113,6 @@ on EZTV. Get IMDB IDs from IMDB.';
} }
// Sort all torrents in array by date // Sort all torrents in array by date
usort($this->items, array('EZTVBridge', 'compareDate')); usort($this->items, ['EZTVBridge', 'compareDate']);
} }
} }

View file

@ -1,29 +1,30 @@
<?php <?php
class EconomistBridge extends FeedExpander {
class EconomistBridge extends FeedExpander
{
const MAINTAINER = 'bockiii'; const MAINTAINER = 'bockiii';
const NAME = 'Economist Bridge'; const NAME = 'Economist Bridge';
const URI = 'https://www.economist.com/'; const URI = 'https://www.economist.com/';
const CACHE_TIMEOUT = 3600; //1hour const CACHE_TIMEOUT = 3600; //1hour
const DESCRIPTION = 'Returns the latest articles for the selected category'; const DESCRIPTION = 'Returns the latest articles for the selected category';
const PARAMETERS = array( const PARAMETERS = [
'global' => array( 'global' => [
'limit' => array( 'limit' => [
'name' => 'Feed Item Limit', 'name' => 'Feed Item Limit',
'required' => true, 'required' => true,
'type' => 'number', 'type' => 'number',
'defaultValue' => 10, 'defaultValue' => 10,
'title' => 'Maximum number of returned feed items. Maximum 30, default 10' 'title' => 'Maximum number of returned feed items. Maximum 30, default 10'
) ]
), ],
'Topics' => array( 'Topics' => [
'topic' => array( 'topic' => [
'name' => 'Topics', 'name' => 'Topics',
'type' => 'list', 'type' => 'list',
'title' => 'Select a Topic', 'title' => 'Select a Topic',
'defaultValue' => 'latest', 'defaultValue' => 'latest',
'values' => array( 'values' => [
'Latest' => 'latest', 'Latest' => 'latest',
'The world this week' => 'the-world-this-week', 'The world this week' => 'the-world-this-week',
'Letters' => 'letters', 'Letters' => 'letters',
@ -45,15 +46,15 @@ class EconomistBridge extends FeedExpander {
'Obituaries' => 'obituary', 'Obituaries' => 'obituary',
'Graphic detail' => 'graphic-detail', 'Graphic detail' => 'graphic-detail',
'Indicators' => 'economic-and-financial-indicators', 'Indicators' => 'economic-and-financial-indicators',
) ]
) ]
), ],
'Blogs' => array( 'Blogs' => [
'blog' => array( 'blog' => [
'name' => 'Blogs', 'name' => 'Blogs',
'type' => 'list', 'type' => 'list',
'title' => 'Select a Blog', 'title' => 'Select a Blog',
'values' => array( 'values' => [
'Bagehots notebook' => 'bagehots-notebook', 'Bagehots notebook' => 'bagehots-notebook',
'Bartleby' => 'bartleby', 'Bartleby' => 'bartleby',
'Buttonwoods notebook' => 'buttonwoods-notebook', 'Buttonwoods notebook' => 'buttonwoods-notebook',
@ -66,12 +67,13 @@ class EconomistBridge extends FeedExpander {
'Kaffeeklatsch' => 'kaffeeklatsch', 'Kaffeeklatsch' => 'kaffeeklatsch',
'Prospero' => 'prospero', 'Prospero' => 'prospero',
'The Economist Explains' => 'the-economist-explains', 'The Economist Explains' => 'the-economist-explains',
) ]
) ]
) ]
); ];
public function collectData(){ public function collectData()
{
// get if topics or blogs were selected and store the selected category // get if topics or blogs were selected and store the selected category
switch ($this->queriedContext) { switch ($this->queriedContext) {
case 'Topics': case 'Topics':
@ -93,7 +95,8 @@ class EconomistBridge extends FeedExpander {
$this->collectExpandableDatas('https://www.economist.com/' . $category . '/rss.xml', $limit); $this->collectExpandableDatas('https://www.economist.com/' . $category . '/rss.xml', $limit);
} }
protected function parseItem($feedItem){ protected function parseItem($feedItem)
{
$item = parent::parseItem($feedItem); $item = parent::parseItem($feedItem);
$article = getSimpleHTMLDOM($item['uri']); $article = getSimpleHTMLDOM($item['uri']);
// before the article can be added, it needs to be cleaned up, thus, the extra function // before the article can be added, it needs to be cleaned up, thus, the extra function
@ -124,13 +127,16 @@ class EconomistBridge extends FeedExpander {
return $item; return $item;
} }
private function cleanContent($article, $contentNode){ private function cleanContent($article, $contentNode)
{
// the actual article is in this div // the actual article is in this div
$content = $article->find($contentNode, 0)->innertext; $content = $article->find($contentNode, 0)->innertext;
// clean the article content. Remove all div's since the text is in paragraph elements // clean the article content. Remove all div's since the text is in paragraph elements
foreach (array( foreach (
[
'<div ' '<div '
) as $tag_start) { ] as $tag_start
) {
$content = stripRecursiveHTMLSection($content, 'div', $tag_start); $content = stripRecursiveHTMLSection($content, 'div', $tag_start);
} }
// now remove embedded iframes. The podcast postings contain these for example // now remove embedded iframes. The podcast postings contain these for example

View file

@ -1,4 +1,5 @@
<?php <?php
class EconomistWorldInBriefBridge extends BridgeAbstract class EconomistWorldInBriefBridge extends BridgeAbstract
{ {
const MAINTAINER = 'sqrtminusone'; const MAINTAINER = 'sqrtminusone';
@ -8,35 +9,35 @@ class EconomistWorldInBriefBridge extends BridgeAbstract
const CACHE_TIMEOUT = 3600; // 1 hour const CACHE_TIMEOUT = 3600; // 1 hour
const DESCRIPTION = 'Returns stories from the World in Brief section'; const DESCRIPTION = 'Returns stories from the World in Brief section';
const PARAMETERS = array( const PARAMETERS = [
'' => array( '' => [
'splitGobbets' => array( 'splitGobbets' => [
'name' => 'Split the short stories', 'name' => 'Split the short stories',
'type' => 'checkbox', 'type' => 'checkbox',
'defaultValue' => false, 'defaultValue' => false,
'title' => 'Whether to split the short stories into separate entries' 'title' => 'Whether to split the short stories into separate entries'
), ],
'limit' => array( 'limit' => [
'name' => 'Truncate headers for the short stories', 'name' => 'Truncate headers for the short stories',
'type' => 'number', 'type' => 'number',
'defaultValue' => 100 'defaultValue' => 100
), ],
'agenda' => array( 'agenda' => [
'name' => 'Add agenda for the day', 'name' => 'Add agenda for the day',
'type' => 'checkbox', 'type' => 'checkbox',
'defaultValue' => 'checked' 'defaultValue' => 'checked'
), ],
'agendaPictures' => array( 'agendaPictures' => [
'name' => 'Include pictures to the agenda', 'name' => 'Include pictures to the agenda',
'type' => 'checkbox', 'type' => 'checkbox',
'defaultValue' => 'checked' 'defaultValue' => 'checked'
), ],
'quote' => array( 'quote' => [
'name' => 'Include the quote of the day', 'name' => 'Include the quote of the day',
'type' => 'checkbox' 'type' => 'checkbox'
) ]
) ]
); ];
public function collectData() public function collectData()
{ {
@ -72,13 +73,13 @@ class EconomistWorldInBriefBridge extends BridgeAbstract
if ($limit && mb_strlen($title) > $limit) { if ($limit && mb_strlen($title) > $limit) {
$title = mb_substr($title, 0, $limit) . '...'; $title = mb_substr($title, 0, $limit) . '...';
} }
$item = array( $item = [
'uri' => self::URI, 'uri' => self::URI,
'title' => $title, 'title' => $title,
'content' => $gobbet->innertext, 'content' => $gobbet->innertext,
'timestamp' => $today->format('U'), 'timestamp' => $today->format('U'),
'uid' => md5($gobbet->plaintext) 'uid' => md5($gobbet->plaintext)
); ];
$this->items[] = $item; $this->items[] = $item;
} }
} }
@ -91,13 +92,13 @@ class EconomistWorldInBriefBridge extends BridgeAbstract
foreach ($gobbets->find('._gobbet') as $gobbet) { foreach ($gobbets->find('._gobbet') as $gobbet) {
$contents .= "<p>{$gobbet->innertext}"; $contents .= "<p>{$gobbet->innertext}";
} }
$this->items[] = array( $this->items[] = [
'uri' => self::URI, 'uri' => self::URI,
'title' => 'World in brief at ' . $today->format('Y.m.d'), 'title' => 'World in brief at ' . $today->format('Y.m.d'),
'content' => $contents, 'content' => $contents,
'timestamp' => $today->format('U'), 'timestamp' => $today->format('U'),
'uid' => 'world-in-brief-' . $today->format('U') 'uid' => 'world-in-brief-' . $today->format('U')
); ];
} }
private function collectArticles($articles) private function collectArticles($articles)
@ -116,26 +117,27 @@ class EconomistWorldInBriefBridge extends BridgeAbstract
$res_content .= '<img src="' . $img->src . '" />'; $res_content .= '<img src="' . $img->src . '" />';
} }
$res_content .= $content->innertext; $res_content .= $content->innertext;
$this->items[] = array( $this->items[] = [
'uri' => self::URI, 'uri' => self::URI,
'title' => $title, 'title' => $title,
'content' => $res_content, 'content' => $res_content,
'timestamp' => $today->format('U'), 'timestamp' => $today->format('U'),
'uid' => 'story-' . $today->format('U') . "{$i}", 'uid' => 'story-' . $today->format('U') . "{$i}",
); ];
$i++; $i++;
} }
} }
private function addQuote($quote) { private function addQuote($quote)
{
$today = new Datetime(); $today = new Datetime();
$today->setTime(0, 0, 0, 0); $today->setTime(0, 0, 0, 0);
$this->items[] = array( $this->items[] = [
'uri' => self::URI, 'uri' => self::URI,
'title' => 'Quote of the day ' . $today->format('Y.m.d'), 'title' => 'Quote of the day ' . $today->format('Y.m.d'),
'content' => $quote->innertext, 'content' => $quote->innertext,
'timestamp' => $today->format('U'), 'timestamp' => $today->format('U'),
'uid' => 'quote-' . $today->format('U') 'uid' => 'quote-' . $today->format('U')
); ];
} }
} }

View file

@ -1,34 +1,36 @@
<?php <?php
class EliteDangerousGalnetBridge extends BridgeAbstract {
class EliteDangerousGalnetBridge extends BridgeAbstract
{
const MAINTAINER = 'corenting'; const MAINTAINER = 'corenting';
const NAME = 'Elite: Dangerous Galnet'; const NAME = 'Elite: Dangerous Galnet';
const URI = 'https://community.elitedangerous.com/galnet/'; const URI = 'https://community.elitedangerous.com/galnet/';
const CACHE_TIMEOUT = 7200; // 2h const CACHE_TIMEOUT = 7200; // 2h
const DESCRIPTION = 'Returns the latest page of news from Galnet'; const DESCRIPTION = 'Returns the latest page of news from Galnet';
const PARAMETERS = array( const PARAMETERS = [
array( [
'language' => array( 'language' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'English' => 'en', 'English' => 'en',
'French' => 'fr', 'French' => 'fr',
'German' => 'de' 'German' => 'de'
), ],
'defaultValue' => 'en' 'defaultValue' => 'en'
) ]
) ]
); ];
public function collectData(){ public function collectData()
{
$language = $this->getInput('language'); $language = $this->getInput('language');
$url = 'https://community.elitedangerous.com/'; $url = 'https://community.elitedangerous.com/';
$url = $url . $language . '/galnet'; $url = $url . $language . '/galnet';
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
foreach($html->find('div.article') as $element) { foreach ($html->find('div.article') as $element) {
$item = array(); $item = [];
$uri = $element->find('h3 a', 0)->href; $uri = $element->find('h3 a', 0)->href;
$uri = 'https://community.elitedangerous.com/' . $language . $uri; $uri = 'https://community.elitedangerous.com/' . $language . $uri;

View file

@ -1,38 +1,39 @@
<?php <?php
class ElloBridge extends BridgeAbstract {
class ElloBridge extends BridgeAbstract
{
const MAINTAINER = 'teromene'; const MAINTAINER = 'teromene';
const NAME = 'Ello Bridge'; const NAME = 'Ello Bridge';
const URI = 'https://ello.co/'; const URI = 'https://ello.co/';
const CACHE_TIMEOUT = 4800; //2hours const CACHE_TIMEOUT = 4800; //2hours
const DESCRIPTION = 'Returns the newest posts for Ello'; const DESCRIPTION = 'Returns the newest posts for Ello';
const PARAMETERS = array( const PARAMETERS = [
'By User' => array( 'By User' => [
'u' => array( 'u' => [
'name' => 'Username', 'name' => 'Username',
'required' => true, 'required' => true,
'exampleValue' => 'zteph', 'exampleValue' => 'zteph',
'title' => 'Username' 'title' => 'Username'
) ]
), ],
'Search' => array( 'Search' => [
's' => array( 's' => [
'name' => 'Search', 'name' => 'Search',
'required' => true, 'required' => true,
'exampleValue' => 'bird', 'exampleValue' => 'bird',
'title' => 'Search' 'title' => 'Search'
) ]
) ]
); ];
public function collectData() { public function collectData()
{
$header = array( $header = [
'Authorization: Bearer ' . $this->getAPIKey() 'Authorization: Bearer ' . $this->getAPIKey()
); ];
if(!empty($this->getInput('u'))) { if (!empty($this->getInput('u'))) {
$postData = getContents(self::URI . 'api/v2/users/~' . urlencode($this->getInput('u')) . '/posts', $header) or $postData = getContents(self::URI . 'api/v2/users/~' . urlencode($this->getInput('u')) . '/posts', $header) or
returnServerError('Unable to query Ello API.'); returnServerError('Unable to query Ello API.');
} else { } else {
@ -42,9 +43,8 @@ class ElloBridge extends BridgeAbstract {
$postData = json_decode($postData); $postData = json_decode($postData);
$count = 0; $count = 0;
foreach($postData->posts as $post) { foreach ($postData->posts as $post) {
$item = [];
$item = array();
$item['author'] = $this->getUsername($post, $postData); $item['author'] = $this->getUsername($post, $postData);
$item['timestamp'] = strtotime($post->created_at); $item['timestamp'] = strtotime($post->created_at);
$item['title'] = strip_tags($this->findText($post->summary)); $item['title'] = strip_tags($this->findText($post->summary));
@ -55,52 +55,44 @@ class ElloBridge extends BridgeAbstract {
$this->items[] = $item; $this->items[] = $item;
$count += 1; $count += 1;
}
} }
} private function findText($path)
{
private function findText($path) { foreach ($path as $summaryElement) {
if ($summaryElement->kind == 'text') {
foreach($path as $summaryElement) {
if($summaryElement->kind == 'text') {
return $summaryElement->data; return $summaryElement->data;
} }
} }
return ''; return '';
} }
private function getPostContent($path) { private function getPostContent($path)
{
$content = ''; $content = '';
foreach($path as $summaryElement) { foreach ($path as $summaryElement) {
if ($summaryElement->kind == 'text') {
if($summaryElement->kind == 'text') {
$content .= $summaryElement->data; $content .= $summaryElement->data;
} elseif ($summaryElement->kind == 'image') { } elseif ($summaryElement->kind == 'image') {
$alt = ''; $alt = '';
if(property_exists($summaryElement->data, 'alt')) { if (property_exists($summaryElement->data, 'alt')) {
$alt = $summaryElement->data->alt; $alt = $summaryElement->data->alt;
} }
$content .= '<img src="' . $summaryElement->data->url . '" alt="' . $alt . '" />'; $content .= '<img src="' . $summaryElement->data->url . '" alt="' . $alt . '" />';
} }
} }
return $content; return $content;
} }
private function getEnclosures($post, $postData) { private function getEnclosures($post, $postData)
{
$assets = array(); $assets = [];
foreach($post->links->assets as $asset) { foreach ($post->links->assets as $asset) {
foreach($postData->linked->assets as $assetLink) { foreach ($postData->linked->assets as $assetLink) {
if($asset == $assetLink->id) { if ($asset == $assetLink->id) {
$assets[] = $assetLink->attachment->original->url; $assets[] = $assetLink->attachment->original->url;
break; break;
} }
@ -108,28 +100,27 @@ class ElloBridge extends BridgeAbstract {
} }
return $assets; return $assets;
} }
private function getUsername($post, $postData) { private function getUsername($post, $postData)
{
foreach($postData->linked->users as $user) { foreach ($postData->linked->users as $user) {
if($user->id == $post->links->author->id) { if ($user->id == $post->links->author->id) {
return $user->username; return $user->username;
} }
} }
} }
private function getAPIKey() { private function getAPIKey()
{
$cacheFac = new CacheFactory(); $cacheFac = new CacheFactory();
$cache = $cacheFac->create(Configuration::getConfig('cache', 'type')); $cache = $cacheFac->create(Configuration::getConfig('cache', 'type'));
$cache->setScope(get_called_class()); $cache->setScope(get_called_class());
$cache->setKey(array('key')); $cache->setKey(['key']);
$key = $cache->loadData(); $key = $cache->loadData();
if($key == null) { if ($key == null) {
$keyInfo = getContents(self::URI . 'api/webapp-token') or $keyInfo = getContents(self::URI . 'api/webapp-token') or
returnServerError('Unable to get token.'); returnServerError('Unable to get token.');
$key = json_decode($keyInfo)->token->access_token; $key = json_decode($keyInfo)->token->access_token;
@ -137,11 +128,11 @@ class ElloBridge extends BridgeAbstract {
} }
return $key; return $key;
} }
public function getName(){ public function getName()
if(!is_null($this->getInput('u'))) { {
if (!is_null($this->getInput('u'))) {
return $this->getInput('u') . ' - Ello Bridge'; return $this->getInput('u') . ' - Ello Bridge';
} }

View file

@ -1,27 +1,29 @@
<?php <?php
class ElsevierBridge extends BridgeAbstract {
class ElsevierBridge extends BridgeAbstract
{
const MAINTAINER = 'dvikan'; const MAINTAINER = 'dvikan';
const NAME = 'Elsevier journals recent articles'; const NAME = 'Elsevier journals recent articles';
const URI = 'https://www.journals.elsevier.com/'; const URI = 'https://www.journals.elsevier.com/';
const CACHE_TIMEOUT = 43200; //12h const CACHE_TIMEOUT = 43200; //12h
const DESCRIPTION = 'Returns the recent articles published in Elsevier journals'; const DESCRIPTION = 'Returns the recent articles published in Elsevier journals';
const PARAMETERS = array( array( const PARAMETERS = [ [
'j' => array( 'j' => [
'name' => 'Journal name', 'name' => 'Journal name',
'required' => true, 'required' => true,
'exampleValue' => 'academic-pediatrics', 'exampleValue' => 'academic-pediatrics',
'title' => 'Insert html-part of your journal' 'title' => 'Insert html-part of your journal'
) ]
)); ]];
public function collectData(){ public function collectData()
{
// Not all journals have the /recent-articles page // Not all journals have the /recent-articles page
$url = sprintf('https://www.journals.elsevier.com/%s/recent-articles/', $this->getInput('j')); $url = sprintf('https://www.journals.elsevier.com/%s/recent-articles/', $this->getInput('j'));
$html = getSimpleHTMLDOM($url); $html = getSimpleHTMLDOM($url);
foreach($html->find('article') as $recentArticle) { foreach ($html->find('article') as $recentArticle) {
$item = []; $item = [];
$item['uri'] = $recentArticle->find('a', 0)->getAttribute('href'); $item['uri'] = $recentArticle->find('a', 0)->getAttribute('href');
$item['title'] = $recentArticle->find('h2', 0)->plaintext; $item['title'] = $recentArticle->find('h2', 0)->plaintext;
@ -35,7 +37,8 @@ class ElsevierBridge extends BridgeAbstract {
} }
} }
public function getIcon(): string { public function getIcon(): string
{
return 'https://cdn.elsevier.io/verona/includes/favicons/favicon-32x32.png'; return 'https://cdn.elsevier.io/verona/includes/favicons/favicon-32x32.png';
} }
} }

View file

@ -1,25 +1,29 @@
<?php <?php
class EngadgetBridge extends FeedExpander {
class EngadgetBridge extends FeedExpander
{
const MAINTAINER = 'IceWreck'; const MAINTAINER = 'IceWreck';
const NAME = 'Engadget Bridge'; const NAME = 'Engadget Bridge';
const URI = 'https://www.engadget.com/'; const URI = 'https://www.engadget.com/';
const CACHE_TIMEOUT = 3600; const CACHE_TIMEOUT = 3600;
const DESCRIPTION = 'Article content for Engadget.'; const DESCRIPTION = 'Article content for Engadget.';
public function collectData(){ public function collectData()
{
$this->collectExpandableDatas(static::URI . 'rss.xml', 15); $this->collectExpandableDatas(static::URI . 'rss.xml', 15);
} }
protected function parseItem($newsItem){ protected function parseItem($newsItem)
{
$item = parent::parseItem($newsItem); $item = parent::parseItem($newsItem);
// $articlePage gets the entire page's contents // $articlePage gets the entire page's contents
$articlePage = getSimpleHTMLDOM($newsItem->link); $articlePage = getSimpleHTMLDOM($newsItem->link);
// figure contain's the main article image // figure contain's the main article image
$article = $articlePage->find('figure', 0); $article = $articlePage->find('figure', 0);
// .article-text has the actual article // .article-text has the actual article
foreach($articlePage->find('.article-text') as $element) foreach ($articlePage->find('.article-text') as $element) {
$article = $article . $element; $article = $article . $element;
}
$item['content'] = $article; $item['content'] = $article;
return $item; return $item;
} }

View file

@ -1,24 +1,25 @@
<?php <?php
class EpicgamesBridge extends BridgeAbstract {
class EpicgamesBridge extends BridgeAbstract
{
const NAME = 'Epic Games Store News'; const NAME = 'Epic Games Store News';
const MAINTAINER = 'otakuf'; const MAINTAINER = 'otakuf';
const URI = 'https://www.epicgames.com'; const URI = 'https://www.epicgames.com';
const DESCRIPTION = 'Returns the latest posts from epicgames.com'; const DESCRIPTION = 'Returns the latest posts from epicgames.com';
const CACHE_TIMEOUT = 3600; // 60min const CACHE_TIMEOUT = 3600; // 60min
const PARAMETERS = array( array( const PARAMETERS = [ [
'postcount' => array( 'postcount' => [
'name' => 'Limit', 'name' => 'Limit',
'type' => 'number', 'type' => 'number',
'required' => true, 'required' => true,
'title' => 'Maximum number of items to return', 'title' => 'Maximum number of items to return',
'defaultValue' => 10, 'defaultValue' => 10,
), ],
'language' => array( 'language' => [
'name' => 'Language', 'name' => 'Language',
'type' => 'list', 'type' => 'list',
'values' => array( 'values' => [
'English' => 'en', 'English' => 'en',
'العربية' => 'ar', 'العربية' => 'ar',
'Deutsch' => 'de', 'Deutsch' => 'de',
@ -35,13 +36,14 @@ class EpicgamesBridge extends BridgeAbstract {
'Türkçe' => 'tr', 'Türkçe' => 'tr',
'简体中文' => 'zh-CN', '简体中文' => 'zh-CN',
'繁體中文' => 'zh-Hant', '繁體中文' => 'zh-Hant',
), ],
'title' => 'Language of blog posts', 'title' => 'Language of blog posts',
'defaultValue' => 'en', 'defaultValue' => 'en',
), ],
)); ]];
public function collectData() { public function collectData()
{
$api = 'https://store-content.ak.epicgames.com/api/'; $api = 'https://store-content.ak.epicgames.com/api/';
// Get sticky posts first // Get sticky posts first
@ -57,19 +59,19 @@ class EpicgamesBridge extends BridgeAbstract {
// Merge data // Merge data
$decodedData = array_merge(json_decode($dataSticky), json_decode($dataBlog)); $decodedData = array_merge(json_decode($dataSticky), json_decode($dataBlog));
foreach($decodedData as $key => $value) { foreach ($decodedData as $key => $value) {
$item = array(); $item = [];
$item['uri'] = self::URI . $value->url; $item['uri'] = self::URI . $value->url;
$item['title'] = $value->title; $item['title'] = $value->title;
$item['timestamp'] = $value->date; $item['timestamp'] = $value->date;
$item['author'] = 'Epic Games Store'; $item['author'] = 'Epic Games Store';
if(!empty($value->author)) { if (!empty($value->author)) {
$item['author'] = $value->author; $item['author'] = $value->author;
} }
if(!empty($value->content)) { if (!empty($value->content)) {
$item['content'] = defaultLinkTo($value->content, self::URI); $item['content'] = defaultLinkTo($value->content, self::URI);
} }
if(!empty($value->image)) { if (!empty($value->image)) {
$item['enclosures'][] = $value->image; $item['enclosures'][] = $value->image;
} }
$item['uid'] = $value->_id; $item['uid'] = $value->_id;

View file

@ -1,40 +1,46 @@
<?php <?php
class EsquerdaNetBridge extends FeedExpander {
class EsquerdaNetBridge extends FeedExpander
{
const MAINTAINER = 'somini'; const MAINTAINER = 'somini';
const NAME = 'Esquerda.net'; const NAME = 'Esquerda.net';
const URI = 'https://www.esquerda.net'; const URI = 'https://www.esquerda.net';
const DESCRIPTION = 'Esquerda.net'; const DESCRIPTION = 'Esquerda.net';
const PARAMETERS = array( const PARAMETERS = [
array( [
'feed' => array( 'feed' => [
'name' => 'Feed', 'name' => 'Feed',
'type' => 'list', 'type' => 'list',
'defaultValue' => 'Geral', 'defaultValue' => 'Geral',
'values' => array( 'values' => [
'Geral' => 'geral', 'Geral' => 'geral',
'Dossier' => 'artigos-dossier', 'Dossier' => 'artigos-dossier',
'Vídeo' => 'video', 'Vídeo' => 'video',
'Opinião' => 'opinioes', 'Opinião' => 'opinioes',
'Rádio' => 'radio', 'Rádio' => 'radio',
) ]
) ]
) ]
); ];
public function getURI() { public function getURI()
{
$type = $this->getInput('feed'); $type = $this->getInput('feed');
return self::URI . '/rss/' . $type; return self::URI . '/rss/' . $type;
} }
public function getIcon() { public function getIcon()
{
return 'https://www.esquerda.net/sites/default/files/favicon_0.ico'; return 'https://www.esquerda.net/sites/default/files/favicon_0.ico';
} }
public function collectData(){ public function collectData()
{
parent::collectExpandableDatas($this->getURI()); parent::collectExpandableDatas($this->getURI());
} }
protected function parseItem($newsItem){ protected function parseItem($newsItem)
{
# Fix Publish date # Fix Publish date
$badDate = $newsItem->pubDate; $badDate = $newsItem->pubDate;
preg_match('|(?P<day>\d\d)/(?P<month>\d\d)/(?P<year>\d\d\d\d) - (?P<hour>\d\d):(?P<minute>\d\d)|', $badDate, $d); preg_match('|(?P<day>\d\d)/(?P<month>\d\d)/(?P<year>\d\d\d\d) - (?P<hour>\d\d):(?P<minute>\d\d)|', $badDate, $d);
@ -55,7 +61,7 @@ class EsquerdaNetBridge extends FeedExpander {
## Fix links ## Fix links
$content = defaultLinkTo($content, self::URI); $content = defaultLinkTo($content, self::URI);
## Fix Images ## Fix Images
foreach($content->find('img') as $img) { foreach ($content->find('img') as $img) {
$altSrc = $img->getAttribute('data-src'); $altSrc = $img->getAttribute('data-src');
if ($altSrc) { if ($altSrc) {
$img->setAttribute('src', $altSrc); $img->setAttribute('src', $altSrc);

View file

@ -1,16 +1,18 @@
<?php <?php
class EstCeQuonMetEnProdBridge extends BridgeAbstract {
class EstCeQuonMetEnProdBridge extends BridgeAbstract
{
const MAINTAINER = 'ORelio'; const MAINTAINER = 'ORelio';
const NAME = 'Est-ce qu\'on met en prod aujourd\'hui ?'; const NAME = 'Est-ce qu\'on met en prod aujourd\'hui ?';
const URI = 'https://www.estcequonmetenprodaujourdhui.info/'; const URI = 'https://www.estcequonmetenprodaujourdhui.info/';
const CACHE_TIMEOUT = 21600; // 6h const CACHE_TIMEOUT = 21600; // 6h
const DESCRIPTION = 'Should we put a website in production today? (French)'; const DESCRIPTION = 'Should we put a website in production today? (French)';
public function collectData() { public function collectData()
{
$html = getSimpleHTMLDOM(self::URI); $html = getSimpleHTMLDOM(self::URI);
$item = array(); $item = [];
$item['uri'] = $this->getURI() . '#' . date('Y-m-d'); $item['uri'] = $this->getURI() . '#' . date('Y-m-d');
$item['title'] = $this->getName(); $item['title'] = $this->getName();
$item['author'] = 'Nicolas Hoffmann'; $item['author'] = 'Nicolas Hoffmann';

Some files were not shown because too many files have changed in this diff Show more