From e0323f06cdfd20449c2c6f34a172121f14b06279 Mon Sep 17 00:00:00 2001 From: fluffy Date: Thu, 18 Oct 2018 07:43:39 -0700 Subject: [PATCH 001/199] update php-urljoin (#867) --- vendor/php-urljoin/src/urljoin.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vendor/php-urljoin/src/urljoin.php b/vendor/php-urljoin/src/urljoin.php index 4f62f906..ef84fbcd 100644 --- a/vendor/php-urljoin/src/urljoin.php +++ b/vendor/php-urljoin/src/urljoin.php @@ -26,6 +26,15 @@ function urljoin($base, $rel) { $pbase = parse_url($base); $prel = parse_url($rel); + if ($prel === false || preg_match('/^[a-z0-9\-.]*[^a-z0-9\-.:][a-z0-9\-.]*:/i', $rel)) { + /* + Either parse_url couldn't parse this, or the original URL + fragment had an invalid scheme character before the first :, + which can confuse parse_url + */ + $prel = array('path' => $rel); + } + if (array_key_exists('path', $pbase) && $pbase['path'] === '/') { unset($pbase['path']); } From 16f0ee71048459b5dd39ffc1b66a2f3786dd87be Mon Sep 17 00:00:00 2001 From: Eugene Molotov Date: Thu, 18 Oct 2018 19:45:03 +0500 Subject: [PATCH 002/199] [InstagramBridge] added caption existance check in getInstagramStory (#865) * [InstagramBridge] added caption existance check in getInstagramStory * [InstagramBridge] Coding policy fixes --- bridges/InstagramBridge.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bridges/InstagramBridge.php b/bridges/InstagramBridge.php index 2539da25..226d453e 100644 --- a/bridges/InstagramBridge.php +++ b/bridges/InstagramBridge.php @@ -101,7 +101,11 @@ class InstagramBridge extends BridgeAbstract { $mediaInfo = $data->entry_data->PostPage[0]->graphql->shortcode_media; //Process the first element, that isn't in the node graph - $caption = $mediaInfo->edge_media_to_caption->edges[0]->node->text; + if (count($mediaInfo->edge_media_to_caption->edges) > 0) { + $caption = $mediaInfo->edge_media_to_caption->edges[0]->node->text; + } else { + $caption = ''; + } $enclosures = [$mediaInfo->display_url]; $content = ''. $caption . ''; From 7596be65f22bce8e640f7d0b7c97fb764724dde2 Mon Sep 17 00:00:00 2001 From: teromene Date: Thu, 18 Oct 2018 18:07:07 +0200 Subject: [PATCH 003/199] Use a new URL for the cursor. Should fix #851. Remove the "...More" item in the output Remove the information card data --- bridges/FB2Bridge.php | 82 ++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 51 deletions(-) diff --git a/bridges/FB2Bridge.php b/bridges/FB2Bridge.php index cd4bb47f..be8168f6 100644 --- a/bridges/FB2Bridge.php +++ b/bridges/FB2Bridge.php @@ -65,14 +65,14 @@ class FB2Bridge extends BridgeAbstract { if($this->getInput('u') !== null) { $page = 'https://touch.facebook.com/' . $this->getInput('u'); $cookies = $this->getCookies($page); - $pageID = $this->getPageID($page, $cookies); + $pageInfo = $this->getPageInfos($page, $cookies); - if($pageID === null) { + if($pageInfo['userId'] === null) { echo <<buildContent($fileContent); - $author = $this->getInput('u'); + $author = $pageInfo['username']; foreach($html->find('article') as $content) { @@ -114,13 +111,17 @@ EOD; $content->find('footer', 0)->innertext = ''; } + if($content->find('._5rgu', 0) !== null) { + $content->find('._5rgu', 0)->innertext = ''; + } + // Replace emoticon images by their textual representation (part of the span) foreach($content->find('span[title*="emoticon"]') as $emoticon) { $emoticon->innertext = $emoticon->find('span[aria-hidden="true"]', 0)->innertext; } //Remove html nodes, keep only img, links, basic formatting - $content = strip_tags($content, '

'); + //$content = strip_tags($content, '

'); //Adapt link hrefs: convert relative links into absolute links and bypass external link redirection $content = preg_replace_callback('/ href=\"([^"]+)\"/i', $unescape_fb_link, $content); @@ -146,6 +147,11 @@ EOD; // "smile emoticon" back to ASCII emoticons eg ":)" $content = preg_replace_callback('/([^ <>]+) ([^<>]+)<\/u><\/i>/i', $unescape_fb_emote, $content); + //Remove the "...Plus" tag + $content = preg_replace( + '/… (|)","replaceifexists $regex = '/\\"html\\":(\".+\/div>"),"replace/'; preg_match($regex, $pageContent, $result); + return str_get_html(json_decode($result[1])); } @@ -237,8 +208,8 @@ EOD; return substr($cookies, 1); } - //Get the page ID from the Facebook page. - private function getPageID($page, $cookies){ + //Get the page ID and username from the Facebook page. + private function getPageInfos($page, $cookies){ $context = stream_context_create(array( 'http' => array( @@ -254,19 +225,28 @@ EOD; return -1; } + //Get the username + $usernameRegex = '/data-nt=\"FB:TEXT4\">(.*?)<\/div>/m'; + preg_match($usernameRegex, $pageContent, $usernameMatches); + if(count($usernameMatches) > 0) { + $username = $usernameMatches[1]; + } else { + $username = $this->getInput('u'); + } + //Get the page ID if we don't have a captcha $regex = '/page_id=([0-9]*)&/'; preg_match($regex, $pageContent, $matches); if(count($matches) > 0) { - return $matches[1]; + return array('userId' => $matches[1], 'username' => $username); } //Get the page ID if we do have a captcha $regex = '/"pageID":"([0-9]*)"/'; preg_match($regex, $pageContent, $matches); - return $matches[1]; + return array('userId' => $matches[1], 'username' => $username); } From 30bc5179c2d150d98405109ab71dd1511ca78ce7 Mon Sep 17 00:00:00 2001 From: teromene Date: Thu, 18 Oct 2018 18:44:11 +0200 Subject: [PATCH 004/199] Fix number of fetched items. Strip the username. --- bridges/FB2Bridge.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bridges/FB2Bridge.php b/bridges/FB2Bridge.php index be8168f6..98322714 100644 --- a/bridges/FB2Bridge.php +++ b/bridges/FB2Bridge.php @@ -83,8 +83,7 @@ EOD; //Build the string for the first request $requestString = 'https://touch.facebook.com/page_content_list_view/more/?page_id=' . $pageInfo['userId'] - . '&start_cursor=1&num_to_fetch=10&surface_type=timeline'; - + . '&start_cursor=1&num_to_fetch=105&surface_type=timeline'; $fileContent = getContents($requestString); $html = $this->buildContent($fileContent); @@ -229,7 +228,7 @@ EOD; $usernameRegex = '/data-nt=\"FB:TEXT4\">(.*?)<\/div>/m'; preg_match($usernameRegex, $pageContent, $usernameMatches); if(count($usernameMatches) > 0) { - $username = $usernameMatches[1]; + $username = strip_tags($usernameMatches[1]); } else { $username = $this->getInput('u'); } From afd5ef0f1d3585f29afa48ae0d7f22fe3668a3df Mon Sep 17 00:00:00 2001 From: teromene Date: Thu, 18 Oct 2018 21:10:02 +0200 Subject: [PATCH 005/199] [FB2Bridge] Add images support [FB2Bridge] Add basic "cards" support --- bridges/FB2Bridge.php | 46 +++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/bridges/FB2Bridge.php b/bridges/FB2Bridge.php index 98322714..91b575f7 100644 --- a/bridges/FB2Bridge.php +++ b/bridges/FB2Bridge.php @@ -85,14 +85,12 @@ EOD; . $pageInfo['userId'] . '&start_cursor=1&num_to_fetch=105&surface_type=timeline'; $fileContent = getContents($requestString); - $html = $this->buildContent($fileContent); $author = $pageInfo['username']; foreach($html->find('article') as $content) { $item = array(); - preg_match('/publish_time\\\":([0-9]+),/', $content->getAttribute('data-store', 0), $match); if(isset($match[1])) $timestamp = $match[1]; @@ -102,6 +100,12 @@ EOD; $item['uri'] = html_entity_decode('http://touch.facebook.com' . $content->find("div[class='_52jc _5qc4 _24u0 _36xo']", 0)->find('a', 0)->getAttribute('href'), ENT_QUOTES); + //Decode images + $imagecleaned = preg_replace_callback('/]* style="[^"]*url\(\'(.*?)\'\).*?><\/i>/m', function ($matches) { + return ""; + }, $content); + $content = str_get_html($imagecleaned); + if($content->find('header', 0) !== null) { $content->find('header', 0)->innertext = ''; } @@ -110,17 +114,13 @@ EOD; $content->find('footer', 0)->innertext = ''; } - if($content->find('._5rgu', 0) !== null) { - $content->find('._5rgu', 0)->innertext = ''; - } - // Replace emoticon images by their textual representation (part of the span) foreach($content->find('span[title*="emoticon"]') as $emoticon) { $emoticon->innertext = $emoticon->find('span[aria-hidden="true"]', 0)->innertext; } //Remove html nodes, keep only img, links, basic formatting - //$content = strip_tags($content, '

'); + $content = strip_tags($content, '

'); //Adapt link hrefs: convert relative links into absolute links and bypass external link redirection $content = preg_replace_callback('/ href=\"([^"]+)\"/i', $unescape_fb_link, $content); @@ -133,7 +133,6 @@ EOD; 'ajaxify', 'tabindex', 'class', - 'style', 'data-[^=]*', 'aria-[^=]*', 'role', @@ -151,6 +150,30 @@ EOD; '/… (|)getAttribute('href') . '">' . $sectionContent->innertext . ''; + $sectionContent->innertext = $fullLink; + } + } + + //Move the href tag upper if it is inside the section + foreach($content->find('section > a') as $sectionToFix) { + $sectionLink = $sectionToFix->getAttribute('href'); + $section = $sectionToFix->parent(); + $section->outertext = '' . $section . ''; + } + $item['content'] = html_entity_decode($content, ENT_QUOTES); $title = $author; @@ -164,9 +187,10 @@ EOD; $item['author'] = html_entity_decode($author, ENT_QUOTES); $item['timestamp'] = html_entity_decode($timestamp, ENT_QUOTES); - if($item['timestamp'] != 0) + //if($item['timestamp'] != 0) array_push($this->items, $item); } + } @@ -177,7 +201,9 @@ EOD; $regex = '/\\"html\\":(\".+\/div>"),"replace/'; preg_match($regex, $pageContent, $result); - return str_get_html(json_decode($result[1])); + $htmlContent = html_entity_decode(json_decode($result[1]), ENT_QUOTES, 'UTF-8'); + + return str_get_html($htmlContent); } From 87d218296e513c08a1a3ff71062b46a9bdcb1d1a Mon Sep 17 00:00:00 2001 From: Eugene Molotov Date: Sat, 20 Oct 2018 15:43:48 +0500 Subject: [PATCH 006/199] [YoutubeBridge] Fix playlist mode (#876) * Corrected duration text selector * Request YouTube page with English localization * Filter video items in the beginning of the loop --- bridges/YoutubeBridge.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/bridges/YoutubeBridge.php b/bridges/YoutubeBridge.php index c021fdc1..67e95668 100644 --- a/bridges/YoutubeBridge.php +++ b/bridges/YoutubeBridge.php @@ -147,12 +147,19 @@ class YoutubeBridge extends BridgeAbstract { $time = 0; $vid = str_replace('/watch?v=', '', $element->find('a', 0)->href); $vid = substr($vid, 0, strpos($vid, '&') ?: strlen($vid)); - $title = $this->ytBridgeFixTitle($element->find($title_selector, 0)->plaintext); + $title = trim($this->ytBridgeFixTitle($element->find($title_selector, 0)->plaintext)); + + if (strpos($vid, 'googleads') !== false + || $title == '[Private video]' + || $title == '[Deleted video]' + ) { + continue; + } // The duration comes in one of the formats: // hh:mm:ss / mm:ss / m:ss // 01:03:30 / 15:06 / 1:24 - $durationText = trim($element->find('span[class="video-time"]', 0)->plaintext); + $durationText = trim($element->find('div.timestamp span', 0)->plaintext); $durationText = preg_replace('/([\d]{1,2})\:([\d]{2})/', '00:$1:$2', $durationText); sscanf($durationText, '%d:%d:%d', $hours, $minutes, $seconds); @@ -162,13 +169,11 @@ class YoutubeBridge extends BridgeAbstract { continue; } - if($title != '[Private Video]' && strpos($vid, 'googleads') === false) { - if ($add_parsed_items) { - $this->ytBridgeQueryVideoInfo($vid, $author, $desc, $time); - $this->ytBridgeAddItem($vid, $title, $author, $desc, $time); - } - $count++; + if ($add_parsed_items) { + $this->ytBridgeQueryVideoInfo($vid, $author, $desc, $time); + $this->ytBridgeAddItem($vid, $title, $author, $desc, $time); } + $count++; } } return $count; @@ -181,7 +186,9 @@ class YoutubeBridge extends BridgeAbstract { private function ytGetSimpleHTMLDOM($url){ return getSimpleHTMLDOM($url, - $header = array(), + $header = array( + 'Accept-Language: en-US' + ), $opts = array(), $lowercase = true, $forceTagsClosed = true, From ea2d54523d20f7ea2f730868b2b6ebd832e7431d Mon Sep 17 00:00:00 2001 From: Antoine Turmel Date: Sat, 20 Oct 2018 13:08:03 +0200 Subject: [PATCH 007/199] [EtsyBridge] Fix bridge and correct typos (#873) --- bridges/EtsyBridge.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/bridges/EtsyBridge.php b/bridges/EtsyBridge.php index 311d9109..2671797f 100644 --- a/bridges/EtsyBridge.php +++ b/bridges/EtsyBridge.php @@ -17,7 +17,7 @@ class EtsyBridge extends BridgeAbstract { 'queryextension' => array( 'name' => 'Query extension', 'type' => 'text', - 'requied' => false, + 'required' => false, 'title' => 'Insert additional query parts here (anything after ?search=)', 'exampleValue' => '&explicit=1&locationQuery=2921044' @@ -25,9 +25,9 @@ class EtsyBridge extends BridgeAbstract { 'showimage' => array( 'name' => 'Show image in content', 'type' => 'checkbox', - 'requrired' => false, + 'required' => false, 'title' => 'Activate to show the image in the content', - 'defaultValue' => false + 'defaultValue' => 'checked' ) ) ); @@ -36,26 +36,27 @@ class EtsyBridge extends BridgeAbstract { $html = getSimpleHTMLDOM($this->getURI()) or returnServerError('Failed to receive ' . $this->getURI()); - $results = $html->find('div.block-grid-item'); + $results = $html->find('li.block-grid-item'); foreach($results as $result) { // Skip banner cards (ads for categories) - if($result->find('a.banner-card')) + if($result->find('span.ad-indicator')) continue; $item = array(); $item['title'] = $result->find('a', 0)->title; $item['uri'] = $result->find('a', 0)->href; - $item['author'] = $result->find('div.card-shop-name', 0)->plaintext; + $item['author'] = $result->find('p.text-gray-lighter', 0)->plaintext; $item['content'] = '

' - . $result->find('div.card-price', 0)->plaintext + . $result->find('span.currency-value', 0)->plaintext . ' ' + . $result->find('span.currency-symbol', 0)->plaintext . '

' - . $result->find('div.card-title', 0)->plaintext + . $result->find('a', 0)->title . '

'; - $image = $result->find('img.placeholder', 0)->src; + $image = $result->find('img.display-block', 0)->src; if($this->getInput('showimage')) { $item['content'] .= ''; From 9820ad5c0f4bc5c82608f03c5a54175fb574f19a Mon Sep 17 00:00:00 2001 From: Antoine Turmel Date: Sat, 20 Oct 2018 13:14:46 +0200 Subject: [PATCH 008/199] [BridgeCard] Fix checkbox default value (#874) The current solution just output "1" when checked instead of "checked" --- lib/BridgeCard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/BridgeCard.php b/lib/BridgeCard.php index 0233f075..28e74fe6 100644 --- a/lib/BridgeCard.php +++ b/lib/BridgeCard.php @@ -193,7 +193,7 @@ This bridge is not fetching its content through a secure connection'; . '" type="checkbox" name="' . $name . '" ' - . ($entry['defaultValue'] === 'checked' ?: '') + . ($entry['defaultValue'] === 'checked' ? 'checked' : '') . ' />' . PHP_EOL; } From cb488d9d8c0c79f6b263bbb4e023d8042cd6407d Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Sat, 20 Oct 2018 15:38:44 +0200 Subject: [PATCH 009/199] [FacebookBridge] Fix broken feeds This commit collects the original contents from a different tag to prevent this issue. The root cause is unknown but closely related to the regex. References #877 --- bridges/FacebookBridge.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bridges/FacebookBridge.php b/bridges/FacebookBridge.php index d7e8f913..277bc608 100644 --- a/bridges/FacebookBridge.php +++ b/bridges/FacebookBridge.php @@ -552,11 +552,7 @@ EOD; if(count($post->find('abbr')) > 0) { - //Retrieve post contents - $content = preg_replace( - '/(?i)>
]+)>(.+?)div\ class=\"userContent\"/i', - '', - $post); + $content = $post->find('.userContentWrapper', 0); $content = preg_replace( '/(?i)>
]+)>(.+?)<\/div><\/div> Date: Mon, 22 Oct 2018 22:14:49 +0500 Subject: [PATCH 010/199] [core] Fixed broken caching (#880) --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 2cb0286d..037b8b09 100644 --- a/index.php +++ b/index.php @@ -306,7 +306,7 @@ try { $format = Format::create($format); $format->setItems($items); $format->setExtraInfos($infos); - $format->setLastModified($mtime); + $format->setLastModified($cache->getTime()); $format->display(); } catch(Error $e) { http_response_code($e->getCode()); From b4b5340b7ee22a6d7098c70794532ed8864fad81 Mon Sep 17 00:00:00 2001 From: sysadminstory Date: Mon, 22 Oct 2018 19:22:02 +0200 Subject: [PATCH 011/199] [ZoneTelechargementBridge] Make the bridge more robust to URL change (#881) Using the classical www.zone-telechargement1.org as base URL, the bridge will always be redirected to the actual wwX.zone-telechargement1.org final URL. This makes the bridge more robust to URL changes. --- bridges/ZoneTelechargementBridge.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bridges/ZoneTelechargementBridge.php b/bridges/ZoneTelechargementBridge.php index 81539633..609ffc11 100644 --- a/bridges/ZoneTelechargementBridge.php +++ b/bridges/ZoneTelechargementBridge.php @@ -1,7 +1,7 @@ true, 'title' => 'URL d\'une série sans le https://ww4.zone-telechargement1.org/', 'exampleValue' => 'telecharger-series/31079-halt-and-catch-fire-saison-4-french-hd720p.html' - ) ) - ); + ) + ); public function collectData(){ $html = getSimpleHTMLDOM(self::URI . $this->getInput('url')) @@ -58,7 +58,7 @@ class ZoneTelechargementBridge extends BridgeAbstract { } } - public function getName(){ + public function getName() { switch($this->queriedContext) { case 'Suivre la publication des épisodes d\'une série en cours de diffusion': return $this->showTitle . ' - ' . self::NAME; @@ -68,8 +68,7 @@ class ZoneTelechargementBridge extends BridgeAbstract { } } - private function findLinkHoster($element) - { + private function findLinkHoster($element) { // The hoster name is one level higher than the link tag : get the parent element $element = $element->parent(); //echo "PARENT : $element \n"; From 89ca42da549bc399f21e4890f95873655665f896 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Wed, 24 Oct 2018 15:50:48 +0200 Subject: [PATCH 012/199] [index] Always write exceptions to error.log Exceptions are reported to users, but they do not necessarily appear in the error log on the server. Using 'error_log' we can explicitly write exceptions and error messages to the log file, using the standard PHP message format. For more information see https://stackoverflow.com/a/26867035 --- index.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/index.php b/index.php index 037b8b09..69e5009d 100644 --- a/index.php +++ b/index.php @@ -262,6 +262,8 @@ try { 'icon' => $bridge->getIcon() ); } catch(Error $e) { + error_log($e); + $item = array(); // Create "new" error message every 24 hours @@ -280,6 +282,8 @@ try { $items[] = $item; } catch(Exception $e) { + error_log($e); + $item = array(); // Create "new" error message every 24 hours @@ -309,10 +313,12 @@ try { $format->setLastModified($cache->getTime()); $format->display(); } catch(Error $e) { + error_log($e); http_response_code($e->getCode()); header('Content-Type: text/html'); die(buildTransformException($e, $bridge)); } catch(Exception $e) { + error_log($e); http_response_code($e->getCode()); header('Content-Type: text/html'); die(buildTransformException($e, $bridge)); @@ -321,9 +327,11 @@ try { echo BridgeList::create($whitelist_selection, $showInactive); } } catch(HttpException $e) { + error_log($e); http_response_code($e->getCode()); header('Content-Type: text/plain'); die($e->getMessage()); } catch(\Exception $e) { + error_log($e); die($e->getMessage()); } From dbd44f64dd7030a2013b6b7b7e7f561e8cee9121 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Wed, 24 Oct 2018 16:10:29 +0200 Subject: [PATCH 013/199] [contents] Add debug messages for 'getContents' Adds additional messages to the error log when fetching contents. The data is helpful in finding issues with receiving contents from servers. References: #879, #882, #884 --- lib/contents.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/contents.php b/lib/contents.php index 2acc7fc5..1d504f55 100644 --- a/lib/contents.php +++ b/lib/contents.php @@ -1,24 +1,37 @@ $value) { curl_setopt($ch, $key, $value); } + } if(defined('PROXY_URL') && !defined('NOPROXY')) { + + debugMessage('Setting proxy url: ' . PROXY_URL); curl_setopt($ch, CURLOPT_PROXY, PROXY_URL); + } // We always want the response header as part of the data! @@ -34,6 +47,9 @@ function getContents($url, $header = array(), $opts = array()){ $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $errorCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $header = substr($data, 0, $headerSize); + + debugMessage('Response header: ' . $header); + $headers = parseResponseHeader($header); $finalHeader = end($headers); From 953c6e1022eb1f772c92073b31ebe1f9d7b5bf8b Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Wed, 24 Oct 2018 16:28:26 +0200 Subject: [PATCH 014/199] [contents] Skip setting options on empty array --- lib/contents.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/contents.php b/lib/contents.php index 1d504f55..7e574ca5 100644 --- a/lib/contents.php +++ b/lib/contents.php @@ -17,7 +17,7 @@ function getContents($url, $header = array(), $opts = array()){ curl_setopt($ch, CURLOPT_ENCODING, ''); curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); - if(is_array($opts)) { + if(is_array($opts) && count($opts) !== 0) { debugMessage('Setting options: ' . json_encode($opts)); From e3030cbbfd62e4a6a6e0365e4319e06647de1f95 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Wed, 24 Oct 2018 16:33:49 +0200 Subject: [PATCH 015/199] [InstagramBridge] Reduce occurrence of HTTP error 301 Instagram returns "HTTP/1.1 301 Moved Permanently" on each request to "https://instagram.com/" because the correct location is "https://www.instagram.com/". Instagram will respond with "HTTP/1.1 301 Moved Permanently" if the URI for the requested user doesn't end with a slash. Notice: This is only a minor enhancement to prevent error 301 from happening. The previous version worked fine as is. --- bridges/InstagramBridge.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridges/InstagramBridge.php b/bridges/InstagramBridge.php index 226d453e..a4473822 100644 --- a/bridges/InstagramBridge.php +++ b/bridges/InstagramBridge.php @@ -3,7 +3,7 @@ class InstagramBridge extends BridgeAbstract { const MAINTAINER = 'pauder'; const NAME = 'Instagram Bridge'; - const URI = 'https://instagram.com/'; + const URI = 'https://www.instagram.com/'; const DESCRIPTION = 'Returns the newest images'; const PARAMETERS = array( @@ -143,7 +143,7 @@ class InstagramBridge extends BridgeAbstract { public function getURI(){ if(!is_null($this->getInput('u'))) { - return self::URI . urlencode($this->getInput('u')); + return self::URI . urlencode($this->getInput('u')) . '/'; } elseif(!is_null($this->getInput('h'))) { return self::URI . 'explore/tags/' . urlencode($this->getInput('h')); } From c56f7abc2a368b2bf1b7af80b499f8baebd1b86d Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Wed, 24 Oct 2018 17:23:09 +0200 Subject: [PATCH 016/199] [FacebookBridge] Reduce occurrence of HTTP error 302 Facebook returns "HTTP/1.1 302 Found" when requesting: https://www.facebook.com//pg/username/posts?_fb_noscript=1 Automatically redirecting to: https://www.facebook.com/username/posts/ We receive a positive response faster when directly requesting the correct page: https://www.facebook.com/username/posts?_fb_noscript=1 Notice: This is just a minor adjustment to improve performance while requesting data from the server. The previous version worked fine as well. --- bridges/FacebookBridge.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridges/FacebookBridge.php b/bridges/FacebookBridge.php index 277bc608..5160e3f2 100644 --- a/bridges/FacebookBridge.php +++ b/bridges/FacebookBridge.php @@ -95,7 +95,7 @@ class FacebookBridge extends BridgeAbstract { $user = $this->sanitizeUser($this->getInput('u')); if(!strpos($user, '/')) { - $uri .= '/pg/' . urlencode($user) . '/posts'; + $uri .= urlencode($user) . '/posts'; } else { $uri .= 'pages/' . $user; } From 1cfe939927ca2f62c063ba55b656f7211a5d9c6d Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Wed, 24 Oct 2018 18:33:07 +0200 Subject: [PATCH 017/199] [AskfmBridge] Fix broken bridge References #774 --- bridges/AskfmBridge.php | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/bridges/AskfmBridge.php b/bridges/AskfmBridge.php index e2274618..b76d51b3 100644 --- a/bridges/AskfmBridge.php +++ b/bridges/AskfmBridge.php @@ -1,7 +1,7 @@ getURI()) or returnServerError('Requested username can\'t be found.'); - foreach($html->find('div.streamItem-answer') as $element) { + $html = defaultLinkTo($html, self::URI); + + foreach($html->find('article.streamItem-answer') as $element) { $item = array(); - $item['uri'] = self::URI . $element->find('a.streamItemsAge', 0)->href; - $question = trim($element->find('h1.streamItemContent-question', 0)->innertext); + $item['uri'] = $element->find('a.streamItem_meta', 0)->href; + $question = trim($element->find('header.streamItem_header', 0)->innertext); $item['title'] = trim( - htmlspecialchars_decode($element->find('h1.streamItemContent-question', 0)->plaintext, + htmlspecialchars_decode($element->find('header.streamItem_header', 0)->plaintext, ENT_QUOTES ) ); - $answer = trim($element->find('p.streamItemContent-answer', 0)->innertext); + $item['timestamp'] = strtotime($element->find('time', 0)->datetime); - // Doesn't work, DOM parser doesn't seem to like data-hint, dunno why - #$item['update'] = $element->find('a.streamitemsage',0)->data-hint; + $answer = trim($element->find('div.streamItem_content', 0)->innertext); // This probably should be cleaned up, especially for YouTube embeds - $visual = $element->find('div.streamItemContent-visual', 0)->innertext; - //Fix tracking links, also doesn't work + if($visual = $element->find('div.streamItem_visual', 0)) { + $visual = $visual->innertext; + } + + // Fix tracking links, also doesn't work foreach($element->find('a') as $link) { if(strpos($link->href, 'l.ask.fm') !== false) { - - // Too slow - #$link->href = str_replace('#_=_', '', get_headers($link->href, 1)['Location']); - $link->href = $link->plaintext; } } - $content = '

' . $question . '

' . $answer . '

' . $visual . '

'; - // Fix relative links without breaking // scheme used by YouTube stuff - $content = preg_replace('#href="\/(?!\/)#', 'href="' . self::URI, $content); - $item['content'] = $content; + $item['content'] = '

' . $question + . '

' . $answer + . '

' . $visual . '

'; + $this->items[] = $item; } } @@ -66,7 +66,7 @@ class AskfmBridge extends BridgeAbstract { public function getURI(){ if(!is_null($this->getInput('u'))) { - return self::URI . urlencode($this->getInput('u')) . '/answers/more?page=0'; + return self::URI . urlencode($this->getInput('u')); } return parent::getURI(); From 7621784598b8a5e46e281e866d844ab13be947fd Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Fri, 26 Oct 2018 18:07:34 +0200 Subject: [PATCH 018/199] bridges: Add favicon to bridges missing it Adds favicon to bridges that support it. Some sites prevent downloading favicons, those bridges are left untouched. Affected bridges: - AutoJMBridge - BandcampBridge - BlaguesDeMerdeBridge - BloombergBridge - BundesbankBridge - ChristianDailyReporterBridge - ContainerLinuxReleasesBridge - DailymotionBridge - DiceBridge - DribbbleBridge - EliteDangerousGalnetBridge - ElsevierBridge - FacebookBridge - FB2Bridge - FDroidBridge - FierPandaBridge - GooglePlusPostBridge - JapanExpoBridge - KATBridge - KernelBugTrackerBridge - LegifranceJOBridge - NotAlwaysBridge - NyaaTorrentsBridge - PinterestBridge - RadioMelodieBridge - RainbowSixSiegeBridge - SupInfoBridge - TagBoardBridge - TebeoBridge - TheTVDBBridge - WhydBridge - ZoneTelechargementBridge --- bridges/AutoJMBridge.php | 5 ++++- bridges/BandcampBridge.php | 4 ++++ bridges/BlaguesDeMerdeBridge.php | 4 ++++ bridges/BloombergBridge.php | 4 ++++ bridges/BundesbankBridge.php | 4 ++++ bridges/ChristianDailyReporterBridge.php | 3 +++ bridges/ContainerLinuxReleasesBridge.php | 4 ++++ bridges/DailymotionBridge.php | 4 ++++ bridges/DiceBridge.php | 4 ++++ bridges/DribbbleBridge.php | 5 +++++ bridges/EliteDangerousGalnetBridge.php | 5 +++++ bridges/ElsevierBridge.php | 4 ++++ bridges/FB2Bridge.php | 4 ++++ bridges/FDroidBridge.php | 4 ++++ bridges/FacebookBridge.php | 4 ++++ bridges/FierPandaBridge.php | 4 ++++ bridges/GooglePlusPostBridge.php | 4 ++++ bridges/JapanExpoBridge.php | 4 ++++ bridges/KATBridge.php | 5 +++++ bridges/KernelBugTrackerBridge.php | 4 ++++ bridges/LegifranceJOBridge.php | 4 ++++ bridges/NotAlwaysBridge.php | 4 ++++ bridges/NyaaTorrentsBridge.php | 4 ++++ bridges/PinterestBridge.php | 4 ++++ bridges/RadioMelodieBridge.php | 4 ++++ bridges/RainbowSixSiegeBridge.php | 4 ++++ bridges/SupInfoBridge.php | 4 ++++ bridges/TagBoardBridge.php | 4 ++++ bridges/TebeoBridge.php | 4 ++++ bridges/TheTVDBBridge.php | 4 ++++ bridges/WhydBridge.php | 5 +++++ bridges/ZoneTelechargementBridge.php | 4 ++++ 32 files changed, 131 insertions(+), 1 deletion(-) diff --git a/bridges/AutoJMBridge.php b/bridges/AutoJMBridge.php index b48a22a5..665a4688 100644 --- a/bridges/AutoJMBridge.php +++ b/bridges/AutoJMBridge.php @@ -19,6 +19,10 @@ class AutoJMBridge extends BridgeAbstract { ); const CACHE_TIMEOUT = 3600; + public function getIcon() { + return self::URI . 'assets/images/favicon.ico'; + } + public function collectData() { $html = getSimpleHTMLDOM(self::URI . $this->getInput('url')) or returnServerError('Could not request AutoJM.'); @@ -59,4 +63,3 @@ class AutoJMBridge extends BridgeAbstract { } } -?> diff --git a/bridges/BandcampBridge.php b/bridges/BandcampBridge.php index 0527da03..9c8d436e 100644 --- a/bridges/BandcampBridge.php +++ b/bridges/BandcampBridge.php @@ -14,6 +14,10 @@ class BandcampBridge extends BridgeAbstract { ) )); + public function getIcon() { + return 'https://s4.bcbits.com/img/bc_favicon.ico'; + } + public function collectData(){ $html = getSimpleHTMLDOM($this->getURI()) or returnServerError('No results for this query.'); diff --git a/bridges/BlaguesDeMerdeBridge.php b/bridges/BlaguesDeMerdeBridge.php index 78deda0e..e4af8d59 100644 --- a/bridges/BlaguesDeMerdeBridge.php +++ b/bridges/BlaguesDeMerdeBridge.php @@ -7,6 +7,10 @@ class BlaguesDeMerdeBridge extends BridgeAbstract { const CACHE_TIMEOUT = 7200; // 2h const DESCRIPTION = 'Blagues De Merde'; + public function getIcon() { + return self::URI . 'assets/img/favicon.ico'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI) diff --git a/bridges/BloombergBridge.php b/bridges/BloombergBridge.php index 8aff0ec7..9eb12191 100644 --- a/bridges/BloombergBridge.php +++ b/bridges/BloombergBridge.php @@ -31,6 +31,10 @@ class BloombergBridge extends BridgeAbstract return parent::getName(); } + public function getIcon() { + return 'https://assets.bwbx.io/s3/javelin/public/hub/images/favicon-black-63fe5249d3.png'; + } + public function collectData() { switch($this->queriedContext) { diff --git a/bridges/BundesbankBridge.php b/bridges/BundesbankBridge.php index 972290bd..59c07e0c 100644 --- a/bridges/BundesbankBridge.php +++ b/bridges/BundesbankBridge.php @@ -27,6 +27,10 @@ class BundesbankBridge extends BridgeAbstract { ) ); + public function getIcon() { + return self::URI . 'resource/crblob/1890/a7f48ee0ae35348748121770ba3ca009/mL/favicon-ico-data.ico'; + } + public function getURI() { switch($this->getInput(self::PARAM_LANG)) { case self::LANG_EN: return self::URI . 'en/publications/reports/studies'; diff --git a/bridges/ChristianDailyReporterBridge.php b/bridges/ChristianDailyReporterBridge.php index b8cbf3c8..85f664df 100644 --- a/bridges/ChristianDailyReporterBridge.php +++ b/bridges/ChristianDailyReporterBridge.php @@ -7,6 +7,9 @@ class ChristianDailyReporterBridge extends BridgeAbstract { const DESCRIPTION = 'The Unofficial Christian Daily Reporter RSS'; // const CACHE_TIMEOUT = 86400; // 1 day + public function getIcon() { + return self::URI . 'images/cdrfavicon.png'; + } public function collectData() { $uri = 'https://www.christiandailyreporter.com/'; diff --git a/bridges/ContainerLinuxReleasesBridge.php b/bridges/ContainerLinuxReleasesBridge.php index a82ba7e2..ae438885 100644 --- a/bridges/ContainerLinuxReleasesBridge.php +++ b/bridges/ContainerLinuxReleasesBridge.php @@ -32,6 +32,10 @@ class ContainerLinuxReleasesBridge extends BridgeAbstract { return json_decode($json, true); } + public function getIcon() { + return 'https://coreos.com/assets/ico/favicon.png'; + } + public function collectData() { $data = $this->getReleaseFeed($this->getJsonUri()); diff --git a/bridges/DailymotionBridge.php b/bridges/DailymotionBridge.php index d075041c..ff8d4828 100644 --- a/bridges/DailymotionBridge.php +++ b/bridges/DailymotionBridge.php @@ -48,6 +48,10 @@ class DailymotionBridge extends BridgeAbstract { return $metadata; } + public function getIcon() { + return 'https://static1-ssl.dmcdn.net/images/neon/favicons/android-icon-36x36.png.vf806ca4ed0deed812'; + } + public function collectData(){ $html = ''; $limit = 5; diff --git a/bridges/DiceBridge.php b/bridges/DiceBridge.php index dc6ea15f..11218dfb 100644 --- a/bridges/DiceBridge.php +++ b/bridges/DiceBridge.php @@ -75,6 +75,10 @@ class DiceBridge extends BridgeAbstract { ), )); + public function getIcon() { + return 'https://assets.dice.com/techpro/img/favicons/favicon.ico'; + } + public function collectData() { $uri = 'https://www.dice.com/jobs/advancedResult.html'; $uri .= '?for_one=' . urlencode($this->getInput('for_one')); diff --git a/bridges/DribbbleBridge.php b/bridges/DribbbleBridge.php index 07c4c6ec..5058da63 100644 --- a/bridges/DribbbleBridge.php +++ b/bridges/DribbbleBridge.php @@ -7,6 +7,11 @@ class DribbbleBridge extends BridgeAbstract { const CACHE_TIMEOUT = 1800; const DESCRIPTION = 'Returns the newest popular shots from Dribbble.'; + public function getIcon() { + return 'https://cdn.dribbble.com/assets/ +favicon-63b2904a073c89b52b19aa08cebc16a154bcf83fee8ecc6439968b1e6db569c7.ico'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI . '/shots') or returnServerError('Error while downloading the website content'); diff --git a/bridges/EliteDangerousGalnetBridge.php b/bridges/EliteDangerousGalnetBridge.php index 86a1bbfc..d19b360b 100644 --- a/bridges/EliteDangerousGalnetBridge.php +++ b/bridges/EliteDangerousGalnetBridge.php @@ -7,6 +7,11 @@ class EliteDangerousGalnetBridge extends BridgeAbstract { const CACHE_TIMEOUT = 7200; // 2h const DESCRIPTION = 'Returns the latest page of news from Galnet'; + public function getIcon() { + return 'https://community.elitedangerous.com/sites/ +EDSITE_COMM/themes/bootstrap/bootstrap_community/favicon.ico'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI) or returnServerError('Error while downloading the website content'); diff --git a/bridges/ElsevierBridge.php b/bridges/ElsevierBridge.php index f6ba7ddb..080fe00f 100644 --- a/bridges/ElsevierBridge.php +++ b/bridges/ElsevierBridge.php @@ -57,6 +57,10 @@ class ElsevierBridge extends BridgeAbstract { return ''; } + public function getIcon() { + return 'https://cdn.elsevier.io/verona/includes/favicons/favicon-32x32.png'; + } + public function collectData(){ $uri = self::URI . $this->getInput('j') . '/recent-articles/'; $html = getSimpleHTMLDOM($uri) diff --git a/bridges/FB2Bridge.php b/bridges/FB2Bridge.php index 91b575f7..fbd547c6 100644 --- a/bridges/FB2Bridge.php +++ b/bridges/FB2Bridge.php @@ -15,6 +15,10 @@ class FB2Bridge extends BridgeAbstract { ) )); + public function getIcon() { + return 'https://static.xx.fbcdn.net/rsrc.php/yo/r/iRmz9lCMBD2.ico'; + } + public function collectData(){ //Utility function for cleaning a Facebook link diff --git a/bridges/FDroidBridge.php b/bridges/FDroidBridge.php index a1a37ef1..d5bbb002 100644 --- a/bridges/FDroidBridge.php +++ b/bridges/FDroidBridge.php @@ -19,6 +19,10 @@ class FDroidBridge extends BridgeAbstract { ) )); + public function getIcon() { + return self::URI . 'assets/favicon.ico?v=8j6PKzW9Mk'; + } + public function collectData(){ $url = self::URI; $html = getSimpleHTMLDOM($url) diff --git a/bridges/FacebookBridge.php b/bridges/FacebookBridge.php index 5160e3f2..73bc84df 100644 --- a/bridges/FacebookBridge.php +++ b/bridges/FacebookBridge.php @@ -56,6 +56,10 @@ class FacebookBridge extends BridgeAbstract { private $authorName = ''; private $groupName = ''; + public function getIcon() { + return 'https://static.xx.fbcdn.net/rsrc.php/yo/r/iRmz9lCMBD2.ico'; + } + public function getName(){ switch($this->queriedContext) { diff --git a/bridges/FierPandaBridge.php b/bridges/FierPandaBridge.php index 15d1cd76..75a02cf9 100644 --- a/bridges/FierPandaBridge.php +++ b/bridges/FierPandaBridge.php @@ -7,6 +7,10 @@ class FierPandaBridge extends BridgeAbstract { const CACHE_TIMEOUT = 21600; // 6h const DESCRIPTION = 'Returns latest articles from Fier Panda.'; + public function getIcon() { + return self::URI . 'wp-content/themes/fier-panda/img/favicon.png'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI) diff --git a/bridges/GooglePlusPostBridge.php b/bridges/GooglePlusPostBridge.php index 48949b23..cc3355e6 100644 --- a/bridges/GooglePlusPostBridge.php +++ b/bridges/GooglePlusPostBridge.php @@ -22,6 +22,10 @@ class GooglePlusPostBridge extends BridgeAbstract{ ) )); + public function getIcon() { + return 'https://ssl.gstatic.com/images/branding/product/ico/google_plus_alldp.ico'; + } + public function collectData(){ $username = $this->getInput('username'); diff --git a/bridges/JapanExpoBridge.php b/bridges/JapanExpoBridge.php index f2dd972a..17901711 100644 --- a/bridges/JapanExpoBridge.php +++ b/bridges/JapanExpoBridge.php @@ -13,6 +13,10 @@ class JapanExpoBridge extends BridgeAbstract { ) )); + public function getIcon() { + return 'https://s.japan-expo.com/katana/images/JES073/favicons/paris.png'; + } + public function collectData(){ function frenchPubDateToTimestamp($date_to_parse) { diff --git a/bridges/KATBridge.php b/bridges/KATBridge.php index c4325a60..55756bf8 100644 --- a/bridges/KATBridge.php +++ b/bridges/KATBridge.php @@ -36,6 +36,11 @@ class KATBridge extends BridgeAbstract { 'name' => 'Only get results from Elite or Verified uploaders ?', ), )); + + public function getIcon() { + return 'https://statuskatcrco-631f.kxcdn.com/assets/images/favicon.ico'; + } + public function collectData(){ function parseDateTimestamp($element){ $guessedDate = strptime($element, '%d-%m-%Y %H:%M:%S'); diff --git a/bridges/KernelBugTrackerBridge.php b/bridges/KernelBugTrackerBridge.php index f3135af6..5fdb2a53 100644 --- a/bridges/KernelBugTrackerBridge.php +++ b/bridges/KernelBugTrackerBridge.php @@ -38,6 +38,10 @@ class KernelBugTrackerBridge extends BridgeAbstract { private $bugid = ''; private $bugdesc = ''; + public function getIcon() { + return self::URI . '/images/favicon.ico'; + } + public function collectData(){ $limit = $this->getInput('limit'); $sorting = $this->getInput('sorting'); diff --git a/bridges/LegifranceJOBridge.php b/bridges/LegifranceJOBridge.php index d97fcff9..41a9b069 100644 --- a/bridges/LegifranceJOBridge.php +++ b/bridges/LegifranceJOBridge.php @@ -38,6 +38,10 @@ class LegifranceJOBridge extends BridgeAbstract { return $item; } + public function getIcon() { + return 'https://www.legifrance.gouv.fr/img/favicon.ico'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI) or $this->returnServer('Unable to download ' . self::URI); diff --git a/bridges/NotAlwaysBridge.php b/bridges/NotAlwaysBridge.php index f5efff4c..b2f4c35a 100644 --- a/bridges/NotAlwaysBridge.php +++ b/bridges/NotAlwaysBridge.php @@ -26,6 +26,10 @@ class NotAlwaysBridge extends BridgeAbstract { ) )); + public function getIcon() { + return self::URI . 'favicon_nar.png'; + } + public function collectData(){ $html = getSimpleHTMLDOM($this->getURI()) or returnServerError('Could not request NotAlways.'); diff --git a/bridges/NyaaTorrentsBridge.php b/bridges/NyaaTorrentsBridge.php index ba1cb9d2..b40b0f95 100644 --- a/bridges/NyaaTorrentsBridge.php +++ b/bridges/NyaaTorrentsBridge.php @@ -54,6 +54,10 @@ class NyaaTorrentsBridge extends BridgeAbstract { ) ); + public function getIcon() { + return self::URI . 'static/favicon.png'; + } + public function collectData() { // Build Search URL from user-provided parameters diff --git a/bridges/PinterestBridge.php b/bridges/PinterestBridge.php index d2dd8907..2917b267 100644 --- a/bridges/PinterestBridge.php +++ b/bridges/PinterestBridge.php @@ -25,6 +25,10 @@ class PinterestBridge extends FeedExpander { ) ); + public function getIcon() { + return 'https://s.pinimg.com/webapp/style/images/favicon-9f8f9adf.png'; + } + public function collectData(){ switch($this->queriedContext) { case 'By username and board': diff --git a/bridges/RadioMelodieBridge.php b/bridges/RadioMelodieBridge.php index 9b3772b2..69483435 100644 --- a/bridges/RadioMelodieBridge.php +++ b/bridges/RadioMelodieBridge.php @@ -5,6 +5,10 @@ class RadioMelodieBridge extends BridgeAbstract { const DESCRIPTION = 'Retourne les actualités publiées par Radio Melodie'; const MAINTAINER = 'sysadminstory'; + public function getIcon() { + return self::URI . 'img/favicon.png'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI . 'actu') or returnServerError('Could not request Radio Melodie.'); diff --git a/bridges/RainbowSixSiegeBridge.php b/bridges/RainbowSixSiegeBridge.php index d362bbda..c0be268b 100644 --- a/bridges/RainbowSixSiegeBridge.php +++ b/bridges/RainbowSixSiegeBridge.php @@ -7,6 +7,10 @@ class RainbowSixSiegeBridge extends BridgeAbstract { const CACHE_TIMEOUT = 7200; // 2h const DESCRIPTION = 'Latest articles from the Rainbow Six Siege blog'; + public function getIcon() { + return 'https://ubistatic19-a.akamaihd.net/resource/en-us/game/rainbow6/siege-v3/r6s-favicon_316592.ico'; + } + public function collectData(){ $dlUrl = 'https://prod-tridionservice.ubisoft.com/live/v1/News/Latest?templateId=tcm%3A152-7677'; $dlUrl .= '8-32&pageIndex=0&pageSize=10&language=en-US&detailPageId=tcm%3A152-194572-64'; diff --git a/bridges/SupInfoBridge.php b/bridges/SupInfoBridge.php index 9be5c6ad..697aadf7 100644 --- a/bridges/SupInfoBridge.php +++ b/bridges/SupInfoBridge.php @@ -13,6 +13,10 @@ class SupInfoBridge extends BridgeAbstract { ) )); + public function getIcon() { + return self::URI . '/favicon.png'; + } + public function collectData() { if(empty($this->getInput('tag'))) { diff --git a/bridges/TagBoardBridge.php b/bridges/TagBoardBridge.php index b79847e6..2a2f51ca 100644 --- a/bridges/TagBoardBridge.php +++ b/bridges/TagBoardBridge.php @@ -14,6 +14,10 @@ class TagBoardBridge extends BridgeAbstract { ) )); + public function getIcon() { + return 'https://static.tagboard.com/public/favicon-32x32.png'; + } + public function collectData(){ $link = 'https://post-cache.tagboard.com/search/' . $this->getInput('u'); diff --git a/bridges/TebeoBridge.php b/bridges/TebeoBridge.php index 9050439e..d408526a 100644 --- a/bridges/TebeoBridge.php +++ b/bridges/TebeoBridge.php @@ -21,6 +21,10 @@ class TebeoBridge extends FeedExpander { ) )); + public function getIcon() { + return self::URI . 'images/header_logo.png'; + } + public function collectData(){ $url = self::URI . '/le-replay/' . $this->getInput('cat'); $html = getSimpleHTMLDOM($url) diff --git a/bridges/TheTVDBBridge.php b/bridges/TheTVDBBridge.php index 63af1ea4..38b45a8b 100644 --- a/bridges/TheTVDBBridge.php +++ b/bridges/TheTVDBBridge.php @@ -158,6 +158,10 @@ class TheTVDBBridge extends BridgeAbstract { } } + public function getIcon() { + return self::URI . 'application/themes/thetvdb/images/logo.png'; + } + public function collectData(){ $serie_id = $this->getInput('serie_id'); $nbepisode = $this->getInput('nb_episode'); diff --git a/bridges/WhydBridge.php b/bridges/WhydBridge.php index 347db6ea..d14c22a8 100644 --- a/bridges/WhydBridge.php +++ b/bridges/WhydBridge.php @@ -16,6 +16,11 @@ class WhydBridge extends BridgeAbstract { private $userName = ''; + public function getIcon() { + return self::URI . 'assets/favicons/ +32-6b62a9f14d5e1a9213090d8f00f286bba3a6022381a76390d1d0926493b12593.png?v=6'; + } + public function collectData(){ $html = ''; if(strlen(preg_replace('/[^0-9a-f]/', '', $this->getInput('u'))) == 24) { diff --git a/bridges/ZoneTelechargementBridge.php b/bridges/ZoneTelechargementBridge.php index 609ffc11..da87f309 100644 --- a/bridges/ZoneTelechargementBridge.php +++ b/bridges/ZoneTelechargementBridge.php @@ -16,6 +16,10 @@ class ZoneTelechargementBridge extends BridgeAbstract { ) ); + public function getIcon() { + return 'https://ww7.zone-telechargement1.org/templates/Default/images/favicon.ico'; + } + public function collectData(){ $html = getSimpleHTMLDOM(self::URI . $this->getInput('url')) or returnServerError('Could not request Zone Telechargement.'); From c4896c7791cd76dd9905ad8ee64cb3ca2b340d1f Mon Sep 17 00:00:00 2001 From: Yardena Cohen Date: Sat, 27 Oct 2018 01:53:45 -0700 Subject: [PATCH 019/199] [Configuration] Fix open_basedir warnings (#887) If .git/HEAD isn't in open_basedir it'd throw ugly warnings. Suppress errors while checking if file is readable --- lib/Configuration.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index 04e2c4b5..b76744f5 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -107,7 +107,8 @@ class Configuration { $headFile = '.git/HEAD'; - if(file_exists($headFile)) { + // '@' is used to mute open_basedir warning + if(@is_readable($headFile)) { $revisionHashFile = '.git/' . substr(file_get_contents($headFile), 5, -1); $branchName = explode('/', $revisionHashFile)[3]; From e2dfea2b77fe0ad633bb0e0fc10d869bb6410d93 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Fri, 2 Nov 2018 11:05:46 +0100 Subject: [PATCH 020/199] [index.php] Filter parameter '_error_time' from queries The parameter is used in error feeds. Since RSS-Bridge returns valid feeds for error conditions, feed readers may attempt to access the URI returned for the feed item in order to collect additional data, thus including the parameter '_error_time' in the query. This results in another error message, because it is an invalid input parameter. Filtering the parameter allows RSS-Bridge to return the original feed. References #882 --- index.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.php b/index.php index 69e5009d..e658b040 100644 --- a/index.php +++ b/index.php @@ -202,6 +202,7 @@ try { 'format', '_noproxy', '_cache_timeout', + '_error_time' ), '') ); @@ -214,6 +215,7 @@ try { 'format', '_noproxy', '_cache_timeout', + '_error_time' ), '') ); From 2ac2f3dc66a2e0c4ddfc1fdb6c4649a80c388677 Mon Sep 17 00:00:00 2001 From: LogMANOriginal Date: Fri, 2 Nov 2018 11:45:45 +0100 Subject: [PATCH 021/199] [README] Add info about feed readers References #892 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1fcf6023..b72bb6a2 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ rss-bridge RSS-Bridge is a PHP project capable of generating RSS and Atom feeds for websites which don't have one. It can be used on webservers or as stand alone application in CLI mode. +**Important**: RSS-Bridge is __not__ a feed reader or feed aggregator, but a tool to generate feeds that are consumed by feed readers and feed aggregators. Find a list of feed aggregators on [Wikipedia](https://en.wikipedia.org/wiki/Comparison_of_feed_aggregators). + Supported sites/pages (examples) === From 2e6cbd1ce7510bd7fde874a593b1c519a156d6cb Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Sat, 3 Nov 2018 11:52:31 +0100 Subject: [PATCH 022/199] [GitHubGistBridge] Fix broken bridge `defaultLinkTo` makes anchors point to the correct path which broke parsing because it expected href to start with `#gistcomment`. This commit changes the implementation to make `defaultLinkTo` point to the correct page (using `getURI` instead of `self::URI`) and search with `*=` instead of `^=`. --- bridges/GitHubGistBridge.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bridges/GitHubGistBridge.php b/bridges/GitHubGistBridge.php index 6abd2ecd..98e40800 100644 --- a/bridges/GitHubGistBridge.php +++ b/bridges/GitHubGistBridge.php @@ -54,7 +54,7 @@ class GitHubGistBridge extends BridgeAbstract { DEFAULT_SPAN_TEXT) or returnServerError('Could not request ' . $this->getURI()); - $html = defaultLinkTo($html, static::URI); + $html = defaultLinkTo($html, $this->getURI()); $fileinfo = $html->find('[class="file-info"]', 0) or returnServerError('Could not find file info!'); @@ -69,7 +69,7 @@ class GitHubGistBridge extends BridgeAbstract { foreach($comments as $comment) { - $uri = $comment->find('a[href^=#gistcomment]', 0) + $uri = $comment->find('a[href*=#gistcomment]', 0) or returnServerError('Could not find comment anchor!'); $title = $comment->find('div[class="unminimized-comment"] h3[class="timeline-comment-header-text"]', 0) @@ -86,7 +86,7 @@ class GitHubGistBridge extends BridgeAbstract { $item = array(); - $item['uri'] = $this->getURI() . $uri->href; + $item['uri'] = $uri->href; $item['title'] = str_replace('commented', 'commented on', $title->plaintext); $item['timestamp'] = strtotime($datetime->datetime); $item['author'] = '
' . $author->plaintext . ''; From 07b4c72d5de4d970b461baa6b31309f484d44097 Mon Sep 17 00:00:00 2001 From: hunhejj Date: Sat, 3 Nov 2018 12:12:37 +0100 Subject: [PATCH 023/199] [InstagramBridge] Don't add duplicated urls when parsing Instagram stories (#715) --- bridges/InstagramBridge.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bridges/InstagramBridge.php b/bridges/InstagramBridge.php index a4473822..d41f6967 100644 --- a/bridges/InstagramBridge.php +++ b/bridges/InstagramBridge.php @@ -111,10 +111,11 @@ class InstagramBridge extends BridgeAbstract { $content = ''. $caption . ''; foreach($mediaInfo->edge_sidecar_to_children->edges as $media) { - - $content .= ''. $caption . ''; - $enclosures[] = $media->node->display_url; - + $display_url = $media->node->display_url; + if(!in_array($display_url, $enclosures)) { // add only if not added yet + $content .= ''. $caption . ''; + $enclosures[] = $display_url; + } } return [$content, $enclosures]; From b55ec51e0e4a31d7769053eea49fa1b813155f8b Mon Sep 17 00:00:00 2001 From: teromene Date: Sun, 4 Nov 2018 21:50:18 +0100 Subject: [PATCH 024/199] Fix timestamp decoding --- bridges/FB2Bridge.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bridges/FB2Bridge.php b/bridges/FB2Bridge.php index fbd547c6..39ca1108 100644 --- a/bridges/FB2Bridge.php +++ b/bridges/FB2Bridge.php @@ -95,7 +95,8 @@ EOD; foreach($html->find('article') as $content) { $item = array(); - preg_match('/publish_time\\\":([0-9]+),/', $content->getAttribute('data-store', 0), $match); + //echo $content; die(); + preg_match('/publish_time\\\":([0-9]+),/', $content->getAttribute('data-store', 0), $match); if(isset($match[1])) $timestamp = $match[1]; else @@ -205,7 +206,9 @@ EOD; $regex = '/\\"html\\":(\".+\/div>"),"replace/'; preg_match($regex, $pageContent, $result); - $htmlContent = html_entity_decode(json_decode($result[1]), ENT_QUOTES, 'UTF-8'); + $htmlContent = json_decode($result[1]); + $htmlContent = preg_replace('/(? Date: Mon, 5 Nov 2018 01:46:44 -0800 Subject: [PATCH 025/199] core: Display optional administrator email (#896) --- config.default.ini.php | 6 ++++++ lib/BridgeList.php | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/config.default.ini.php b/config.default.ini.php index 5909ad88..2d6fca12 100644 --- a/config.default.ini.php +++ b/config.default.ini.php @@ -11,6 +11,12 @@ ; false = disabled (default) custom_timeout = false +[admin] +; Advertise an email address where people can reach the administrator. +; This address is displayed on the main page, visible to everyone! +; "" = Disabled (default) +email = "" + [proxy] ; Sets the proxy url (i.e. "tcp://192.168.0.0:32") diff --git a/lib/BridgeList.php b/lib/BridgeList.php index c1756133..4c59f106 100644 --- a/lib/BridgeList.php +++ b/lib/BridgeList.php @@ -96,6 +96,18 @@ EOD; private static function getFooter($totalBridges, $totalActiveBridges, $showInactive) { $version = Configuration::getVersion(); + $email = Configuration::getConfig('admin', 'email'); + $admininfo = ''; + if (!empty($email)) { + $admininfo = << + + You may email the administrator of this RSS-Bridge instance + at {$email} + +EOD; + } + $inactive = ''; if($totalActiveBridges !== $totalBridges) { @@ -114,6 +126,7 @@ EOD;

{$version}

{$totalActiveBridges}/{$totalBridges} active bridges.
{$inactive} + {$admininfo}
EOD; } From 1a7a7bad98f7fb80f87adc4a244aae4fc07a9354 Mon Sep 17 00:00:00 2001 From: mr-flibble Date: Mon, 5 Nov 2018 11:10:32 +0100 Subject: [PATCH 026/199] [contents.php] Fix typo (#900) This fixes "The requested resouce cannot be found!" on line 67 --- lib/contents.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/contents.php b/lib/contents.php index 7e574ca5..a1343da9 100644 --- a/lib/contents.php +++ b/lib/contents.php @@ -64,7 +64,7 @@ EOD } returnError(<< Date: Mon, 5 Nov 2018 11:27:32 +0100 Subject: [PATCH 027/199] [ThingiverseBridge] Add new bridge (#869) --- bridges/ThingiverseBridge.php | 167 ++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 bridges/ThingiverseBridge.php diff --git a/bridges/ThingiverseBridge.php b/bridges/ThingiverseBridge.php new file mode 100644 index 00000000..2e108816 --- /dev/null +++ b/bridges/ThingiverseBridge.php @@ -0,0 +1,167 @@ + array( + 'name' => 'Search query', + 'type' => 'text', + 'required' => true, + 'title' => 'Insert your search term here', + 'exampleValue' => 'Enter your search term' + ), + 'sortby' => array( + 'name' => 'Sort by', + 'type' => 'list', + 'required' => false, + 'values' => array( + 'Relevant' => 'relevant', + 'Text' => 'text', + 'Popular' => 'popular', + '# of Makes' => 'makes', + 'Newest' => 'newest', + ), + 'defaultValue' => 'newest' + ), + 'category' => array( + 'name' => 'Category', + 'type' => 'list', + 'required' => false, + 'values' => array( + 'Any' => '', + '3D Printing' => '73', + 'Art' => '63', + 'Fashion' => '64', + 'Gadgets' => '65', + 'Hobby' => '66', + 'Household' => '67', + 'Learning' => '69', + 'Models' => '70', + 'Tools' => '71', + 'Toys & Games' => '72', + '2D Art' => '144', + 'Art Tools' => '75', + 'Coins & Badges' => '143', + 'Interactive Art' => '78', + 'Math Art' => '79', + 'Scans & Replicas' => '145', + 'Sculptures' => '80', + 'Signs & Logos' => '76', + 'Accessories' => '81', + 'Bracelets' => '82', + 'Costume' => '142', + 'Earrings' => '139', + 'Glasses' => '83', + 'Jewelry' => '84', + 'Keychains' => '130', + 'Rings' => '85', + 'Audio' => '141', + 'Camera' => '86', + 'Computer' => '87', + 'Mobile Phone' => '88', + 'Tablet' => '90', + 'Video Games' => '91', + 'Automotive' => '155', + 'DIY' => '93', + 'Electronics' => '92', + 'Music' => '94', + 'R/C Vehicles' => '95', + 'Robotics' => '96', + 'Sport & Outdoors' => '140', + 'Bathroom' => '147', + 'Containers' => '146', + 'Decor' => '97', + 'Household Supplies' => '99', + 'Kitchen & Dining' => '100', + 'Office' => '101', + 'Organization' => '102', + 'Outdoor & Garden' => '98', + 'Pets' => '103', + 'Replacement Parts' => '153', + 'Biology' => '106', + 'Engineering' => '104', + 'Math' => '105', + 'Physics & Astronomy' => '148', + 'Animals' => '107', + 'Buildings & Structures' => '108', + 'Creatures' => '109', + 'Food & Drink' => '110', + 'Model Furniture' => '111', + 'Model Robots' => '115', + 'People' => '112', + 'Props' => '114', + 'Vehicles' => '116', + 'Hand Tools' => '118', + 'Machine Tools' => '117', + 'Parts' => '119', + 'Tool Holders & Boxes' => '120', + 'Chess' => '151', + 'Construction Toys' => '121', + 'Dice' => '122', + 'Games' => '123', + 'Mechanical Toys' => '124', + 'Playsets' => '113', + 'Puzzles' => '125', + 'Toy & Game Accessories' => '149', + '3D Printer Accessories' => '127', + '3D Printer Extruders' => '152', + '3D Printer Parts' => '128', + '3D Printers' => '126', + '3D Printing Tests' => '129', + ), + 'defaultValue' => '' + ), + 'showimage' => array( + 'name' => 'Show image in content', + 'type' => 'checkbox', + 'required' => false, + 'title' => 'Activate to show the image in the content', + 'defaultValue' => 'checked' + ) + ) + ); + + public function collectData(){ + $html = getSimpleHTMLDOM($this->getURI()) + or returnServerError('Failed to receive ' . $this->getURI()); + + $results = $html->find('div.thing-card'); + + foreach($results as $result) { + + $item = array(); + + $item['title'] = $result->find('span.ellipsis', 0); + $item['uri'] = self::URI . $result->find('a', 1)->href; + $item['author'] = $result->find('span.item-creator', 0); + $item['content'] = ''; + + $image = $result->find('img.card-img', 0)->src; + + if($this->getInput('showimage')) { + $item['content'] .= ''; + } + + $item['enclosures'] = array($image); + + $this->items[] = $item; + } + } + + public function getURI(){ + if(!is_null($this->getInput('query'))) { + $uri = self::URI . '/search?q=' . urlencode($this->getInput('query')); + $uri .= '&sort=' . $this->getInput('sortby'); + $uri .= '&category_id=' . $this->getInput('category'); + + return $uri; + } + + return parent::getURI(); + } + +} From c58331f74d9a2a3039909add2c629e78f1c144de Mon Sep 17 00:00:00 2001 From: Thibault Couraud <1036233+couraudt@users.noreply.github.com> Date: Mon, 5 Nov 2018 10:38:22 +0000 Subject: [PATCH 028/199] [BAEBridge] Add bridge for bourse-aux-equipiers.com (#903) --- bridges/BAEBridge.php | 265 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 bridges/BAEBridge.php diff --git a/bridges/BAEBridge.php b/bridges/BAEBridge.php new file mode 100644 index 00000000..caa2cf72 --- /dev/null +++ b/bridges/BAEBridge.php @@ -0,0 +1,265 @@ + array( + 'name' => 'Filtrer par mots clés', + 'title' => 'Entrez le mot clé à filtrer ici' + ), + 'type' => array( + 'name' => 'Type de recherche', + 'title' => 'Afficher seuleument un certain type d\'annonce', + 'type' => 'list', + 'values' => array( + 'Toutes les annonces' => false, + 'Les embarquements' => 'boat', + 'Les skippers' => 'skipper', + 'Les équipiers' => 'crew' + ) + ) + ) + ); + + public function collectData() { + $url = $this->getURI(); + $html = getSimpleHTMLDOM($url) or returnClientError('No results for this query.'); + + $annonces = $html->find('main article'); + foreach ($annonces as $annonce) { + $detail = $annonce->find('footer a', 0); + + $htmlDetail = getSimpleHTMLDOMCached(parent::getURI() . $detail->href); + if (!$htmlDetail) + continue; + + $item = array(); + + $item['title'] = $annonce->find('header h2', 0)->plaintext; + $item['uri'] = parent::getURI() . $detail->href; + + $content = $htmlDetail->find('article p', 0)->innertext; + if (!empty($this->getInput('keyword'))) { + $keyword = $this->remove_accents(strtolower($this->getInput('keyword'))); + $cleanTitle = $this->remove_accents(strtolower($item['title'])); + if (strpos($cleanTitle, $keyword) === false) { + $cleanContent = $this->remove_accents(strtolower($content)); + if (strpos($cleanContent, $keyword) === false) { + continue; + } + } + } + + $content .= '
'; + $content .= $htmlDetail->find('section', 0)->innertext; + $content = str_replace('src="/', 'src="' . parent::getURI() . '/', $content); + $content = str_replace('href="/', 'href="' . parent::getURI() . '/', $content); + $item['content'] = $content; + $image = $htmlDetail->find('#zoom', 0); + if ($image) { + $item['enclosures'] = array(parent::getURI() . $image->getAttribute('src')); + } + $this->items[] = $item; + } + } + + public function getURI() { + $uri = parent::getURI(); + if (!empty($this->getInput('type'))) { + if ($this->getInput('type') == 'boat') { + $uri .= '/embarquements.html'; + } elseif ($this->getInput('type') == 'skipper') { + $uri .= '/skippers.html'; + } else { + $uri .= '/equipiers.html'; + } + } + + return $uri; + } + + private function remove_accents($string) { + $chars = array( + // Decompositions for Latin-1 Supplement + 'ª' => 'a', 'º' => 'o', + 'À' => 'A', 'Á' => 'A', + 'Â' => 'A', 'Ã' => 'A', + 'Ä' => 'A', 'Å' => 'A', + 'Æ' => 'AE', 'Ç' => 'C', + 'È' => 'E', 'É' => 'E', + 'Ê' => 'E', 'Ë' => 'E', + 'Ì' => 'I', 'Í' => 'I', + 'Î' => 'I', 'Ï' => 'I', + 'Ð' => 'D', 'Ñ' => 'N', + 'Ò' => 'O', 'Ó' => 'O', + 'Ô' => 'O', 'Õ' => 'O', + 'Ö' => 'O', 'Ù' => 'U', + 'Ú' => 'U', 'Û' => 'U', + 'Ü' => 'U', 'Ý' => 'Y', + 'Þ' => 'TH', 'ß' => 's', + 'à' => 'a', 'á' => 'a', + 'â' => 'a', 'ã' => 'a', + 'ä' => 'a', 'å' => 'a', + 'æ' => 'ae', 'ç' => 'c', + 'è' => 'e', 'é' => 'e', + 'ê' => 'e', 'ë' => 'e', + 'ì' => 'i', 'í' => 'i', + 'î' => 'i', 'ï' => 'i', + 'ð' => 'd', 'ñ' => 'n', + 'ò' => 'o', 'ó' => 'o', + 'ô' => 'o', 'õ' => 'o', + 'ö' => 'o', 'ø' => 'o', + 'ù' => 'u', 'ú' => 'u', + 'û' => 'u', 'ü' => 'u', + 'ý' => 'y', 'þ' => 'th', + 'ÿ' => 'y', 'Ø' => 'O', + // Decompositions for Latin Extended-A + 'Ā' => 'A', 'ā' => 'a', + 'Ă' => 'A', 'ă' => 'a', + 'Ą' => 'A', 'ą' => 'a', + 'Ć' => 'C', 'ć' => 'c', + 'Ĉ' => 'C', 'ĉ' => 'c', + 'Ċ' => 'C', 'ċ' => 'c', + 'Č' => 'C', 'č' => 'c', + 'Ď' => 'D', 'ď' => 'd', + 'Đ' => 'D', 'đ' => 'd', + 'Ē' => 'E', 'ē' => 'e', + 'Ĕ' => 'E', 'ĕ' => 'e', + 'Ė' => 'E', 'ė' => 'e', + 'Ę' => 'E', 'ę' => 'e', + 'Ě' => 'E', 'ě' => 'e', + 'Ĝ' => 'G', 'ĝ' => 'g', + 'Ğ' => 'G', 'ğ' => 'g', + 'Ġ' => 'G', 'ġ' => 'g', + 'Ģ' => 'G', 'ģ' => 'g', + 'Ĥ' => 'H', 'ĥ' => 'h', + 'Ħ' => 'H', 'ħ' => 'h', + 'Ĩ' => 'I', 'ĩ' => 'i', + 'Ī' => 'I', 'ī' => 'i', + 'Ĭ' => 'I', 'ĭ' => 'i', + 'Į' => 'I', 'į' => 'i', + 'İ' => 'I', 'ı' => 'i', + 'IJ' => 'IJ', 'ij' => 'ij', + 'Ĵ' => 'J', 'ĵ' => 'j', + 'Ķ' => 'K', 'ķ' => 'k', + 'ĸ' => 'k', 'Ĺ' => 'L', + 'ĺ' => 'l', 'Ļ' => 'L', + 'ļ' => 'l', 'Ľ' => 'L', + 'ľ' => 'l', 'Ŀ' => 'L', + 'ŀ' => 'l', 'Ł' => 'L', + 'ł' => 'l', 'Ń' => 'N', + 'ń' => 'n', 'Ņ' => 'N', + 'ņ' => 'n', 'Ň' => 'N', + 'ň' => 'n', 'ʼn' => 'n', + 'Ŋ' => 'N', 'ŋ' => 'n', + 'Ō' => 'O', 'ō' => 'o', + 'Ŏ' => 'O', 'ŏ' => 'o', + 'Ő' => 'O', 'ő' => 'o', + 'Œ' => 'OE', 'œ' => 'oe', + 'Ŕ' => 'R', 'ŕ' => 'r', + 'Ŗ' => 'R', 'ŗ' => 'r', + 'Ř' => 'R', 'ř' => 'r', + 'Ś' => 'S', 'ś' => 's', + 'Ŝ' => 'S', 'ŝ' => 's', + 'Ş' => 'S', 'ş' => 's', + 'Š' => 'S', 'š' => 's', + 'Ţ' => 'T', 'ţ' => 't', + 'Ť' => 'T', 'ť' => 't', + 'Ŧ' => 'T', 'ŧ' => 't', + 'Ũ' => 'U', 'ũ' => 'u', + 'Ū' => 'U', 'ū' => 'u', + 'Ŭ' => 'U', 'ŭ' => 'u', + 'Ů' => 'U', 'ů' => 'u', + 'Ű' => 'U', 'ű' => 'u', + 'Ų' => 'U', 'ų' => 'u', + 'Ŵ' => 'W', 'ŵ' => 'w', + 'Ŷ' => 'Y', 'ŷ' => 'y', + 'Ÿ' => 'Y', 'Ź' => 'Z', + 'ź' => 'z', 'Ż' => 'Z', + 'ż' => 'z', 'Ž' => 'Z', + 'ž' => 'z', 'ſ' => 's', + // Decompositions for Latin Extended-B + 'Ș' => 'S', 'ș' => 's', + 'Ț' => 'T', 'ț' => 't', + // Euro Sign + '€' => 'E', + // GBP (Pound) Sign + '£' => '', + // Vowels with diacritic (Vietnamese) + // unmarked + 'Ơ' => 'O', 'ơ' => 'o', + 'Ư' => 'U', 'ư' => 'u', + // grave accent + 'Ầ' => 'A', 'ầ' => 'a', + 'Ằ' => 'A', 'ằ' => 'a', + 'Ề' => 'E', 'ề' => 'e', + 'Ồ' => 'O', 'ồ' => 'o', + 'Ờ' => 'O', 'ờ' => 'o', + 'Ừ' => 'U', 'ừ' => 'u', + 'Ỳ' => 'Y', 'ỳ' => 'y', + // hook + 'Ả' => 'A', 'ả' => 'a', + 'Ẩ' => 'A', 'ẩ' => 'a', + 'Ẳ' => 'A', 'ẳ' => 'a', + 'Ẻ' => 'E', 'ẻ' => 'e', + 'Ể' => 'E', 'ể' => 'e', + 'Ỉ' => 'I', 'ỉ' => 'i', + 'Ỏ' => 'O', 'ỏ' => 'o', + 'Ổ' => 'O', 'ổ' => 'o', + 'Ở' => 'O', 'ở' => 'o', + 'Ủ' => 'U', 'ủ' => 'u', + 'Ử' => 'U', 'ử' => 'u', + 'Ỷ' => 'Y', 'ỷ' => 'y', + // tilde + 'Ẫ' => 'A', 'ẫ' => 'a', + 'Ẵ' => 'A', 'ẵ' => 'a', + 'Ẽ' => 'E', 'ẽ' => 'e', + 'Ễ' => 'E', 'ễ' => 'e', + 'Ỗ' => 'O', 'ỗ' => 'o', + 'Ỡ' => 'O', 'ỡ' => 'o', + 'Ữ' => 'U', 'ữ' => 'u', + 'Ỹ' => 'Y', 'ỹ' => 'y', + // acute accent + 'Ấ' => 'A', 'ấ' => 'a', + 'Ắ' => 'A', 'ắ' => 'a', + 'Ế' => 'E', 'ế' => 'e', + 'Ố' => 'O', 'ố' => 'o', + 'Ớ' => 'O', 'ớ' => 'o', + 'Ứ' => 'U', 'ứ' => 'u', + // dot below + 'Ạ' => 'A', 'ạ' => 'a', + 'Ậ' => 'A', 'ậ' => 'a', + 'Ặ' => 'A', 'ặ' => 'a', + 'Ẹ' => 'E', 'ẹ' => 'e', + 'Ệ' => 'E', 'ệ' => 'e', + 'Ị' => 'I', 'ị' => 'i', + 'Ọ' => 'O', 'ọ' => 'o', + 'Ộ' => 'O', 'ộ' => 'o', + 'Ợ' => 'O', 'ợ' => 'o', + 'Ụ' => 'U', 'ụ' => 'u', + 'Ự' => 'U', 'ự' => 'u', + 'Ỵ' => 'Y', 'ỵ' => 'y', + // Vowels with diacritic (Chinese, Hanyu Pinyin) + 'ɑ' => 'a', + // macron + 'Ǖ' => 'U', 'ǖ' => 'u', + // acute accent + 'Ǘ' => 'U', 'ǘ' => 'u', + // caron + 'Ǎ' => 'A', 'ǎ' => 'a', + 'Ǐ' => 'I', 'ǐ' => 'i', + 'Ǒ' => 'O', 'ǒ' => 'o', + 'Ǔ' => 'U', 'ǔ' => 'u', + 'Ǚ' => 'U', 'ǚ' => 'u', + // grave accent + 'Ǜ' => 'U', 'ǜ' => 'u', + ); + + $string = strtr($string, $chars); + + return $string; + } +} From 5fe943562a5efa703cff8f9258b3668ec2dc1811 Mon Sep 17 00:00:00 2001 From: triatic <42704418+triatic@users.noreply.github.com> Date: Mon, 5 Nov 2018 10:46:56 +0000 Subject: [PATCH 029/199] [FB2Bridge] Prevent shared post duplication (#904) Prevent shared posts appearing twice in feed. --- bridges/FB2Bridge.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridges/FB2Bridge.php b/bridges/FB2Bridge.php index 39ca1108..f404b589 100644 --- a/bridges/FB2Bridge.php +++ b/bridges/FB2Bridge.php @@ -192,7 +192,7 @@ EOD; $item['author'] = html_entity_decode($author, ENT_QUOTES); $item['timestamp'] = html_entity_decode($timestamp, ENT_QUOTES); - //if($item['timestamp'] != 0) + if($item['timestamp'] != 0) array_push($this->items, $item); } From 65da157fff0bbb877b35d0d15259e8353f9146be Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Mon, 5 Nov 2018 11:35:01 +0100 Subject: [PATCH 030/199] [XenForoBridge] Add new bridge Adds a bridge for forums powered by XenForo (see https://xenforo.com). Support between forums may vary due to ever changing versions with no clear distinction. Especially timestamps may not work depending on the supported language (should currently work on en-US and de-DE). Tested on - https://xenforo.com/community/ - http://www.ign.com/boards/ Notice: XenForo provides RSS feeds for forums (but not specific topics). For example: https://xenforo.com/community/forums/-/index.rss --- bridges/XenForoBridge.php | 464 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 bridges/XenForoBridge.php diff --git a/bridges/XenForoBridge.php b/bridges/XenForoBridge.php new file mode 100644 index 00000000..29aa77ed --- /dev/null +++ b/bridges/XenForoBridge.php @@ -0,0 +1,464 @@ + array( + 'url' => array( + 'name' => 'Thread URL', + 'type' => 'text', + 'required' => true, + 'title' => 'Insert URL to the thread for which the feed should be generated', + 'exampleValue' => 'https://xenforo.com/community/threads/guide-to-suggestions.2285/' + ) + ), + 'global' => array( + 'limit' => array( + 'name' => 'Limit', + 'type' => 'number', + 'required' => false, + 'title' => 'Specify maximum number of elements to return in the feed', + 'defaultValue' => 10 + ) + ) + ); + const CACHE_TIMEOUT = 7200; // 10 minutes + + private $title = ''; + private $threadurl = ''; + private $version; // Holds the XenForo version + + public function getName() { + + switch($this->queriedContext) { + case self::CONTEXT_THREAD: return $this->title . ' - ' . static::NAME; + } + + return parent::getName(); + + } + + public function getURI() { + + switch($this->queriedContext) { + case self::CONTEXT_THREAD: return $this->threadurl; + } + + return parent::getURI(); + + } + + public function collectData() { + + $this->threadurl = filter_var( + $this->getInput('url'), + FILTER_VALIDATE_URL, + FILTER_FLAG_SCHEME_REQUIRED | + FILTER_FLAG_HOST_REQUIRED | + FILTER_FLAG_PATH_REQUIRED); + + if($this->threadurl === false) { + returnClientError('The URL you provided is invalid!'); + } + + $urlparts = parse_url($this->threadurl, PHP_URL_SCHEME); + + // Scheme must be "http" or "https" + if(preg_match('/http[s]{0,1}/', parse_url($this->threadurl, PHP_URL_SCHEME)) == false) { + returnClientError('The URL you provided doesn\'t specify a valid scheme (http or https)!'); + } + + // Path cannot be root (../) + if(parse_url($this->threadurl, PHP_URL_PATH) === '/') { + returnClientError('The URL you provided doesn\'t link to a valid thread (root path)!'); + } + + // XenForo adds a thread ID to the URL, like "...-thread.454934283". It must be present + if(preg_match('/.+\.\d+[\/]{0,1}/', parse_URL($this->threadurl, PHP_URL_PATH)) == false) { + returnClientError('The URL you provided doesn\'t link to a valid thread (ID missing)!'); + } + + // We want to start at the first page in the thread. XenForo uses "../page-n" syntax + // to identify pages (except for the first page). + // Notice: XenForo uses the concept of "sentinels" to find and replace parts in the + // URL. Technically forum hosts can change the syntax! + if(preg_match('/.+\/(page-\d+.*)$/', $this->threadurl, $matches) != false) { + + // before: https://xenforo.com/community/threads/guide-to-suggestions.2285/page-5 + // after : https://xenforo.com/community/threads/guide-to-suggestions.2285/ + $this->threadurl = str_replace($matches[1], '', $this->threadurl); + + } + + $html = getSimpleHTMLDOMCached($this->threadurl) + or returnServerError('Failed loading data from "' . $this->threadurl . '"!'); + + $html = defaultLinkTo($html, $this->threadurl); + + // Notice: The DOM structure changes depending on the XenForo version used + if($mainContent = $html->find('div.mainContent', 0)) { + $this->version = self::XENFORO_VERSION_1; + } elseif ($mainContent = $html->find('div[class="p-body"]', 0)) { + $this->version = self::XENFORO_VERSION_2; + } else { + returnServerError('This forum is currently not supported!'); + } + + switch($this->version) { + case self::XENFORO_VERSION_1: + + $titleBar = $mainContent->find('div.titleBar h1', 0) + or returnServerError('Error finding title bar!'); + + $this->title = $titleBar->plaintext; + + // Store items from current page (we'll use $this->items as LIFO buffer) + $this->extractThreadPostsV1($html, $this->threadurl); + $this->extractPagesV1($html); + + break; + + case self::XENFORO_VERSION_2: + + $titleBar = $mainContent->find('div[class="p-title"] h1', 0) + or returnServerError('Error finding title bar!'); + + $this->title = $titleBar->plaintext; + $this->extractThreadPostsV2($html, $this->threadurl); + $this->extractPagesV2($html); + + break; + } + + while(count($this->items) > $this->getInput('limit')) { + array_shift($this->items); + } + + } + + /** + * Extracts thread posts + * @param $html A simplehtmldom object + * @param $url The url from which $html was loaded + */ + private function extractThreadPostsV1($html, $url) { + + $lang = $html->find('html', 0)->lang; + + // Posts are contained in an "ol" + $messageList = $html->find('#messageList li') + or returnServerError('Error finding message list!'); + + foreach($messageList as $post) { + + if(!isset($post->attr['id'])) { // Skip ads + continue; + } + + $item = array(); + + $item['uri'] = $url . '#' . $post->getAttribute('id'); + + $content = $post->find('.messageContent article', 0); + + // Add some style to quotes + foreach($content->find('.bbCodeQuote') as $quote) { + $quote->style = ' + color: #495566; + background-color: rgb(248,251,253); + border: 1px solid rgb(111, 140, 180); + border-color: rgb(111, 140, 180); + font-style: italic;'; + } + + // Remove script tags + foreach($content->find('script') as $script) { + $script->outertext = ''; + } + + $item['content'] = $content->innertext; + + // Remove quotes (for the title) + foreach($content->find('.bbCodeQuote') as $quote) { + $quote->innertext = ''; + } + + $title = trim($content->plaintext); + + if(strlen($title) > 70) { + $item['title'] = substr($title, 0, strpos($title, ' ', 70)) . '...'; + } else { + $item['title'] = $title; + } + + /** + * Timestamps are presented in two forms: + * + * 1) short version (for older posts?) + * 22 Oct. 2018 + * + * This form has to be interpreted depending on the current language. + * + * 2) long version (for newer posts?) + * Wednesday at 18:59 + * + * This form has the timestamp embedded (data-time) + */ + if($timestamp = $post->find('abbr.DateTime', 0)) { // long version (preffered) + $item['timestamp'] = $timestamp->{'data-time'}; + } elseif($timestamp = $post->find('span.DateTime', 0)) { // short version + $item['timestamp'] = $this->fixDate($timestamp->title, $lang); + } + + $item['author'] = $post->getAttribute('data-author'); + + // Bridge specific properties + $item['id'] = $post->getAttribute('id'); + + $this->items[] = $item; + + } + + } + + private function extractThreadPostsV2($html, $url) { + + $lang = $html->find('html', 0)->lang; + + $messageList = $html->find('div[class="block-body"] article') + or returnServerError('Error finding message list!'); + + foreach($messageList as $post) { + + if(!isset($post->attr['id'])) { // Skip ads + continue; + } + + $item = array(); + + $item['uri'] = $url . '#' . $post->getAttribute('id'); + + $title = $post->find('div[class="message-content"] article', 0)->plaintext; + $end = strpos($title, ' ', 70); + $item['title'] = substr($title, 0, $end); + + $item['timestamp'] = $this->fixDate($post->find('time', 0)->title, $lang); + $item['author'] = $post->getAttribute('data-author'); + $item['content'] = $post->find('div[class="message-content"] article', 0); + + // Bridge specific properties + $item['id'] = $post->getAttribute('id'); + + $this->items[] = $item; + + } + + } + + private function extractPagesV1($html) { + + // A navigation bar becomes available if the number of posts grows too + // high. When this happens we need to load further pages (from last backwards) + if(($pageNav = $html->find('div.PageNav', 0)) !== false) { + + $lastpage = $pageNav->{'data-last'}; + $baseurl = $pageNav->{'data-baseurl'}; + $sentinel = $pageNav->{'data-sentinel'}; + + $hosturl = parse_url($this->threadurl, PHP_URL_SCHEME) + . '://' + . parse_url($this->threadurl, PHP_URL_HOST) + . '/'; + + $page = $lastpage; + + // Load at least the last page + do { + + $pageurl = $hosturl . str_replace($sentinel, $lastpage, $baseurl); + + // We can optimize performance by caching all but the last page + if($page != $lastpage) { + $html = getSimpleHTMLDOMCached($pageurl) + or returnServerError('Error loading contents from ' . $pageurl . '!'); + } else { + $html = getSimpleHTMLDOM($pageurl) + or returnServerError('Error loading contents from ' . $pageurl . '!'); + } + + $html = defaultLinkTo($html, $hosturl); + + $this->extractThreadPostsV1($html, $pageurl); + + $page--; + + } while (count($this->items) < $this->getInput('limit') && $page != 1); + + } + + } + + private function extractPagesV2($html) { + + // A navigation bar becomes available if the number of posts grows too + // high. When this happens we need to load further pages (from last backwards) + if(($pageNav = $html->find('div.pageNav', 0)) !== false) { + + foreach($pageNav->find('li') as $nav) { + $lastpage = $nav->plaintext; + } + + // Manually extract baseurl and inject sentinel + $baseurl = $pageNav->find('li a', -1)->href; + $baseurl = str_replace('page-' . $lastpage, 'page-{{sentinel}}', $baseurl); + + $sentinel = '{{sentinel}}'; + + $hosturl = parse_url($this->threadurl, PHP_URL_SCHEME) + . '://' + . parse_url($this->threadurl, PHP_URL_HOST); + + $page = $lastpage; + + // Load at least the last page + do { + + $pageurl = $hosturl . str_replace($sentinel, $lastpage, $baseurl); + + // We can optimize performance by caching all but the last page + if($page != $lastpage) { + $html = getSimpleHTMLDOMCached($pageurl) + or returnServerError('Error loading contents from ' . $pageurl . '!'); + } else { + $html = getSimpleHTMLDOM($pageurl) + or returnServerError('Error loading contents from ' . $pageurl . '!'); + } + + $html = defaultLinkTo($html, $this->hosturl); + + $this->extractThreadPostsV2($html, $this->pageurl); + + $page--; + + } while (count($this->items) < $this->getInput('limit') && $page != 1); + + } + + } + + /** + * Fixes dates depending on the choosen language: + * + * de : dd.mm.yy + * en : dd.mm.yy + * it : dd/mm/yy + * + * Basically strtotime doesn't convert dates correctly due to formats + * being hard to interpret. So we use the DateTime object. + * + * We don't know the timezone, so just assume +00:00 (or whatever + * DateTime chooses) + */ + private function fixDate($date, $lang = 'en-US') { + + $mnamesen = [ + 'January', + 'Feburary', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' + ]; + + switch($lang) { + case 'en-US': // example: Jun 9, 2018 at 11:46 PM + + $df = date_create_from_format('M d, Y \a\t H:i A', $date); + break; + + case 'de-DE': // example: 19 Juli 2018 um 19:27 Uhr + + $mnamesde = [ + 'Januar', + 'Februar', + 'März', + 'April', + 'Mai', + 'Juni', + 'Juli', + 'August', + 'September', + 'Oktober', + 'November', + 'Dezember' + ]; + + $mnamesdeshort = [ + 'Jan.', + 'Feb.', + 'Mär.', + 'Apr.', + 'Mai', + 'Juni', + 'Juli', + 'Aug.', + 'Sep.', + 'Okt.', + 'Nov.', + 'Dez.' + ]; + + $date = str_ireplace($mnamesde, $mnamesen, $date); + $date = str_ireplace($mnamesdeshort, $mnamesen, $date); + + $df = date_create_from_format('d M Y \u\m H:i \U\h\r', $date); + break; + + } + + // debugMessage(date_format($df, 'U')); + + return date_format($df, 'U'); + + } + +} From 9c1c0f2974ca59308793a2936fb9cda5fc15050b Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Mon, 5 Nov 2018 12:05:14 +0100 Subject: [PATCH 031/199] [XenForoBridge] Fix broken checks --- bridges/XenForoBridge.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bridges/XenForoBridge.php b/bridges/XenForoBridge.php index 29aa77ed..e9ffe823 100644 --- a/bridges/XenForoBridge.php +++ b/bridges/XenForoBridge.php @@ -76,9 +76,7 @@ class XenForoBridge extends BridgeAbstract { $this->threadurl = filter_var( $this->getInput('url'), FILTER_VALIDATE_URL, - FILTER_FLAG_SCHEME_REQUIRED | - FILTER_FLAG_HOST_REQUIRED | - FILTER_FLAG_PATH_REQUIRED); + FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED | FILTER_FLAG_PATH_REQUIRED); if($this->threadurl === false) { returnClientError('The URL you provided is invalid!'); From b9f6bc81975bc931c824839d9943536f5a4f15b9 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Mon, 5 Nov 2018 12:15:01 +0100 Subject: [PATCH 032/199] [XenForoBridge] Fix broken conditions Restore functionality for https://xenforo.com/community/ --- bridges/XenForoBridge.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridges/XenForoBridge.php b/bridges/XenForoBridge.php index e9ffe823..75c0f6d0 100644 --- a/bridges/XenForoBridge.php +++ b/bridges/XenForoBridge.php @@ -290,7 +290,7 @@ class XenForoBridge extends BridgeAbstract { // A navigation bar becomes available if the number of posts grows too // high. When this happens we need to load further pages (from last backwards) - if(($pageNav = $html->find('div.PageNav', 0)) !== false) { + if(($pageNav = $html->find('div.PageNav', 0))) { $lastpage = $pageNav->{'data-last'}; $baseurl = $pageNav->{'data-baseurl'}; @@ -333,7 +333,7 @@ class XenForoBridge extends BridgeAbstract { // A navigation bar becomes available if the number of posts grows too // high. When this happens we need to load further pages (from last backwards) - if(($pageNav = $html->find('div.pageNav', 0)) !== false) { + if(($pageNav = $html->find('div.pageNav', 0))) { foreach($pageNav->find('li') as $nav) { $lastpage = $nav->plaintext; From e295dc5a79f83bde291e78501735b841d54235c4 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Mon, 5 Nov 2018 12:46:38 +0100 Subject: [PATCH 033/199] [phpcs] Add check for concatenation operator spacing The concatenation operator should have one space before and after --- phpcs.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/phpcs.xml b/phpcs.xml index a67262ce..119d4b2b 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -13,6 +13,13 @@ + + + + + + + From 392e3ff6c7b62c3080de640f71dcb199b2643cab Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Mon, 5 Nov 2018 12:55:58 +0100 Subject: [PATCH 034/199] phpcs: Fix violations --- bridges/ABCTabsBridge.php | 2 +- bridges/AllocineFRBridge.php | 2 +- bridges/AmazonBridge.php | 8 ++--- bridges/AnidexBridge.php | 4 +-- bridges/AutoJMBridge.php | 2 +- bridges/CNETBridge.php | 4 +-- bridges/DealabsBridge.php | 46 ++++++++++++++-------------- bridges/DiscogsBridge.php | 2 +- bridges/ETTVBridge.php | 2 +- bridges/FB2Bridge.php | 4 +-- bridges/FDroidBridge.php | 6 ++-- bridges/FourchanBridge.php | 2 +- bridges/GBAtempBridge.php | 2 +- bridges/GoogleSearchBridge.php | 2 +- bridges/InstagramBridge.php | 6 ++-- bridges/LWNprevBridge.php | 14 ++++----- bridges/NineGagBridge.php | 4 +-- bridges/PikabuBridge.php | 2 +- bridges/PixivBridge.php | 2 +- bridges/RTBFBridge.php | 2 +- bridges/RadioMelodieBridge.php | 2 +- bridges/SuperSmashBlogBridge.php | 2 +- bridges/TebeoBridge.php | 2 +- bridges/TheYeteeBridge.php | 6 ++-- bridges/UnsplashBridge.php | 2 +- bridges/VkBridge.php | 8 ++--- bridges/ZoneTelechargementBridge.php | 2 +- formats/AtomFormat.php | 2 +- formats/MrssFormat.php | 4 +-- lib/html.php | 4 +-- 30 files changed, 76 insertions(+), 76 deletions(-) diff --git a/bridges/ABCTabsBridge.php b/bridges/ABCTabsBridge.php index 2e451e28..ef2c75b1 100644 --- a/bridges/ABCTabsBridge.php +++ b/bridges/ABCTabsBridge.php @@ -8,7 +8,7 @@ class ABCTabsBridge extends BridgeAbstract { public function collectData(){ $html = ''; - $html = getSimpleHTMLDOM(static::URI.'tablatures/nouveautes.html') + $html = getSimpleHTMLDOM(static::URI . 'tablatures/nouveautes.html') or returnClientError('No results for this query.'); $table = $html->find('table#myTable', 0)->children(1); diff --git a/bridges/AllocineFRBridge.php b/bridges/AllocineFRBridge.php index 959d0efa..431ae58f 100644 --- a/bridges/AllocineFRBridge.php +++ b/bridges/AllocineFRBridge.php @@ -45,7 +45,7 @@ class AllocineFRBridge extends BridgeAbstract { public function getName(){ if(!is_null($this->getInput('category'))) { return self::NAME . ' : ' - .array_search( + . array_search( $this->getInput('category'), self::PARAMETERS[$this->queriedContext]['category']['values'] ); diff --git a/bridges/AmazonBridge.php b/bridges/AmazonBridge.php index cbc61190..b7933e85 100644 --- a/bridges/AmazonBridge.php +++ b/bridges/AmazonBridge.php @@ -52,7 +52,7 @@ class AmazonBridge extends BridgeAbstract { public function getName(){ 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'); } return parent::getName(); @@ -60,8 +60,8 @@ class AmazonBridge extends BridgeAbstract { public function collectData() { - $uri = 'https://www.amazon.'.$this->getInput('tld').'/'; - $uri .= 's/?field-keywords='.urlencode($this->getInput('q')).'&sort='.$this->getInput('sort'); + $uri = 'https://www.amazon.' . $this->getInput('tld') . '/'; + $uri .= 's/?field-keywords=' . urlencode($this->getInput('q')) . '&sort=' . $this->getInput('sort'); $html = getSimpleHTMLDOM($uri) or returnServerError('Could not request Amazon.'); @@ -86,7 +86,7 @@ class AmazonBridge extends BridgeAbstract { $price = $element->find('span.s-price', 0); $price = ($price) ? $price->innertext : ''; - $item['content'] = '
'.$price; + $item['content'] = '
' . $price; $this->items[] = $item; } diff --git a/bridges/AnidexBridge.php b/bridges/AnidexBridge.php index a89cb567..ae387c90 100644 --- a/bridges/AnidexBridge.php +++ b/bridges/AnidexBridge.php @@ -140,7 +140,7 @@ class AnidexBridge extends BridgeAbstract { if (strpos($link->href, '/torrent/') === 0 && !in_array($link->href, $results)) $results[] = $link->href; 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 foreach ($results as $element) { @@ -156,7 +156,7 @@ class AnidexBridge extends BridgeAbstract { if ($torrent_id != 0 && ctype_digit($torrent_id)) { //Retrieve data for this torrent ID - $item_uri = self::URI . 'torrent/'.$torrent_id; + $item_uri = self::URI . 'torrent/' . $torrent_id; //Retrieve full description from torrent page if ($item_html = getSimpleHTMLDOMCached($item_uri)) { diff --git a/bridges/AutoJMBridge.php b/bridges/AutoJMBridge.php index 665a4688..598f0431 100644 --- a/bridges/AutoJMBridge.php +++ b/bridges/AutoJMBridge.php @@ -47,7 +47,7 @@ class AutoJMBridge extends BridgeAbstract { $item = array(); $item['uri'] = $url; $item['title'] = $serie; - $item['content'] = '

'. $serie . '

'; + $item['content'] = '

' . $serie . '

'; $item['content'] .= '