Merge pull request #167 from teromene/new-attribute-system
New attribute system
This commit is contained in:
commit
98b2019831
15 changed files with 417 additions and 325 deletions
23
CREATE_BRIDGE.md
Normal file
23
CREATE_BRIDGE.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Howto create a bridge
|
||||
|
||||
A bridge is an interface that allows rss-bridge to create a RSS feed from a website.
|
||||
The bridge is a PHP file, located in the `bridges/` folder.
|
||||
|
||||
##Specifications
|
||||
|
||||
A rss bridge must extend the `BridgeAbstract` class, and implement the following functions :
|
||||
|
||||
* The `loadMetadatas` function, described below,
|
||||
* The `getCacheDuration` function, describing the time during which rss-bridge will output cached values instead of re-generating a RSS feed.
|
||||
* The `collectData` function, also described below.
|
||||
|
||||
##The `collectData` function
|
||||
|
||||
This function takes as a parameter an array called `$param`, that is automatically filled with values from the user, according to the values setted in `loadMetadatas`.
|
||||
This function is the place where all the website scrapping and the RSS feed generation process will go.
|
||||
|
||||
The RSS elements are stored in the class variable `items[]`.
|
||||
|
||||
Every RSS element is an instance of the `Item` class.
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* 2014-05-25
|
||||
*
|
||||
* @name Acrimed Bridge
|
||||
* @homepage http://www.acrimed.org/
|
||||
* @description Returns the newest articles.
|
||||
|
@ -8,7 +8,16 @@
|
|||
*/
|
||||
class AcrimedBridge extends BridgeAbstract{
|
||||
|
||||
public function collectData(array $param){
|
||||
public function loadMetadatas() {
|
||||
|
||||
$this->maintainer = "qwertygc";
|
||||
$this->name = "Acrimed Bridge";
|
||||
$this->uri = "http://www.acrimed.org/";
|
||||
$this->description = "Returns the newest articles.";
|
||||
$this->update = "2014-05-25";
|
||||
|
||||
}
|
||||
public function collectData(array $param){
|
||||
|
||||
function StripCDATA($string) {
|
||||
$string = str_replace('<![CDATA[', '', $string);
|
||||
|
@ -37,13 +46,6 @@ class AcrimedBridge extends BridgeAbstract{
|
|||
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return 'Acrimed Bridge';
|
||||
}
|
||||
|
||||
public function getURI(){
|
||||
return 'http://acrimed.org/';
|
||||
}
|
||||
|
||||
public function getCacheDuration(){
|
||||
return 3600*2; // 2 hours
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
*
|
||||
* @name Anime-Ultime
|
||||
* @homepage http://www.anime-ultime.net/
|
||||
* @description Returns the 10 newest releases posted on Anime-Ultime <br /> Type = A (Anime), D (Drama), T (Tokusatsu), or leave empty for everything
|
||||
* @description Returns the 10 newest releases posted on Anime-Ultime
|
||||
* @maintainer ORelio
|
||||
* @update 2015-09-07
|
||||
* @use1(type="A/D/T/Empty")
|
||||
* @update 2015-10-30
|
||||
* @use1(list|type="everything=>;Anime=>A;Drama=>D;Tokusatsu=>T")
|
||||
*/
|
||||
class AnimeUltimeBridge extends BridgeAbstract {
|
||||
|
||||
|
|
113
bridges/Arte7Bridge.php
Normal file
113
bridges/Arte7Bridge.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
/**
|
||||
* RssBridgeArte7
|
||||
*
|
||||
* @name Arte +7
|
||||
* @homepage http://www.arte.tv/
|
||||
* @description Returns newest videos from ARTE +7
|
||||
* @maintainer mitsukarenai
|
||||
* @update 2015-10-31
|
||||
* @use1(list|catfr="Toutes les vidéos (français)=>toutes-les-videos;Actu & société=>actu-société;Séries & fiction=>séries-fiction;Cinéma=>cinéma;Arts & spectacles classiques=>arts-spectacles-classiques;Culture pop=>culture-pop;Découverte=>découverte;Histoire=>histoire;Junior=>junior")
|
||||
* @use2(list|catde="Alle Videos (deutsch)=>alle-videos;Aktuelles & Gesellschaft=>aktuelles-gesellschaft;Fernsehfilme & Serien=>fernsehfilme-serien;Kino=>kino;Kunst & Kultur=>kunst-kultur;Popkultur & Alternativ=>popkultur-alternativ;Entdeckung=>entdeckung;Geschichte=>geschichte;Junior=>junior")
|
||||
*/
|
||||
class Arte7Bridge extends BridgeAbstract{
|
||||
|
||||
public function loadMetadatas() {
|
||||
|
||||
$this->maintainer = "mitsukarenai";
|
||||
$this->name = "Arte +7";
|
||||
$this->uri = "http://www.arte.tv/";
|
||||
$this->description = "Returns newest videos from ARTE +7";
|
||||
$this->update = "2015-10-31";
|
||||
$this->parameters["Catégorie (Français)"] =
|
||||
'[
|
||||
{
|
||||
"type" : "list",
|
||||
"identifier" : "catfr",
|
||||
"name" : "Catégorie",
|
||||
"values" : [
|
||||
{
|
||||
"name" : "Toutes les vidéos (français)",
|
||||
"value" : "toutes-les-videos"
|
||||
},
|
||||
{
|
||||
"name" : "Actu & société",
|
||||
"value" : "actu-société"
|
||||
},
|
||||
{
|
||||
"name" : "Séries & fiction",
|
||||
"value" : "séries-fiction"
|
||||
},
|
||||
{
|
||||
"name" : "Cinéma",
|
||||
"value" : "cinéma"
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
|
||||
]';
|
||||
}
|
||||
|
||||
|
||||
public function collectData(array $param){
|
||||
|
||||
function extractVideoset($category='toutes-les-videos', $lang='fr')
|
||||
{
|
||||
$url = 'http://www.arte.tv/guide/'.$lang.'/plus7/'.$category;
|
||||
$input = file_get_contents($url) or die('Could not request ARTE.');
|
||||
if(strpos($input, 'categoryVideoSet') !== FALSE)
|
||||
{
|
||||
$input = explode('categoryVideoSet: ', $input);
|
||||
$input = explode('}},', $input[1]);
|
||||
$input = $input[0].'}}';
|
||||
}
|
||||
else
|
||||
{
|
||||
$input = explode('videoSet: ', $input);
|
||||
$input = explode('}]},', $input[1]);
|
||||
$input = $input[0].'}]}';
|
||||
}
|
||||
$input = json_decode($input, TRUE);
|
||||
return $input;
|
||||
}
|
||||
|
||||
$category='toutes-les-videos'; $lang='fr';
|
||||
if (!empty($param['catfr']))
|
||||
$category=$param['catfr'];
|
||||
if (!empty($param['catde']))
|
||||
{ $category=$param['catde']; $lang='de'; }
|
||||
$input_json = extractVideoset($category, $lang);
|
||||
|
||||
foreach($input_json['videos'] as $element) {
|
||||
$item = new \Item();
|
||||
$item->uri = $element['url'];
|
||||
$item->id = $element['id'];
|
||||
$hack_broadcast_time = $element['rights_end'];
|
||||
$hack_broadcast_time = strtok($hack_broadcast_time, 'T');
|
||||
$hack_broadcast_time = strtok('T');
|
||||
$item->timestamp = strtotime($element['scheduled_on'].'T'.$hack_broadcast_time);
|
||||
$item->thumbnailUri = $element['thumbnail_url'];
|
||||
$item->title = $element['title'];
|
||||
if (!empty($element['subtitle']))
|
||||
$item->title = $element['title'].' | '.$element['subtitle'];
|
||||
$item->duration = round((int)$element['duration']/60);
|
||||
$item->content = $element['teaser'].'<br><br>'.$item->duration.'min<br><a href="'.$item->uri.'"><img src="' . $item->thumbnailUri . '" /></a>';
|
||||
$this->items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return 'Arte7';
|
||||
}
|
||||
|
||||
public function getURI(){
|
||||
return 'http://www.arte.tv/';
|
||||
}
|
||||
|
||||
public function getCacheDuration(){
|
||||
return 1800; // 30 minutes
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* RssBridgeArte7de
|
||||
* Returns images from given page and tags
|
||||
*
|
||||
* @name Arte +7 DE
|
||||
* @homepage http://www.arte.tv/guide/de/plus7
|
||||
* @description Returns newest videos from ARTE +7 (german)
|
||||
* @maintainer mitsukarenai
|
||||
* @update 2015-10-30
|
||||
* @use1(list|cat="Alle Videos=>alle-videos;Aktuelles & Gesellschaft=>aktuelles-gesellschaft;Fernsehfilme & Serien=>fernsehfilme-serien;Kino=>kino;Kunst & Kultur=>kunst-kultur;Popkultur & Alternativ=>popkultur-alternativ;Entdeckung=>entdeckung;Geschichte=>geschichte;Junior=>junior")
|
||||
*/
|
||||
class Arte7deBridge extends BridgeAbstract{
|
||||
|
||||
public function collectData(array $param){
|
||||
|
||||
function extractVideoset($category='alle-videos')
|
||||
{
|
||||
$url = 'http://www.arte.tv/guide/de/plus7/'.$category;
|
||||
$input = file_get_contents($url) or die('Could not request ARTE.');
|
||||
if(strpos($input, 'categoryVideoSet') !== FALSE)
|
||||
{
|
||||
$input = explode('categoryVideoSet: ', $input);
|
||||
$input = explode('}},', $input[1]);
|
||||
$input = $input[0].'}}';
|
||||
}
|
||||
else
|
||||
{
|
||||
$input = explode('videoSet: ', $input);
|
||||
$input = explode('}]},', $input[1]);
|
||||
$input = $input[0].'}]}';
|
||||
}
|
||||
$input = json_decode($input, TRUE);
|
||||
return $input;
|
||||
}
|
||||
|
||||
$category='alle-videos';
|
||||
if (!empty($param['cat']))
|
||||
$category=$param['cat'];
|
||||
$input_json = extractVideoset($category);
|
||||
|
||||
foreach($input_json['videos'] as $element) {
|
||||
$item = new \Item();
|
||||
$item->uri = $element['url'];
|
||||
$item->id = $element['id'];
|
||||
$hack_broadcast_time = $element['rights_end'];
|
||||
$hack_broadcast_time = strtok($hack_broadcast_time, 'T');
|
||||
$hack_broadcast_time = strtok('T');
|
||||
$item->timestamp = strtotime($element['scheduled_on'].'T'.$hack_broadcast_time);
|
||||
$item->thumbnailUri = $element['thumbnail_url'];
|
||||
$item->title = $element['title'];
|
||||
if (!empty($element['subtitle']))
|
||||
$item->title = $element['title'].' | '.$element['subtitle'];
|
||||
$item->duration = round((int)$element['duration']/60);
|
||||
$item->content = $element['teaser'].'<br><br>'.$item->duration.'min<br><a href="'.$item->uri.'"><img src="' . $item->thumbnailUri . '" /></a>';
|
||||
$this->items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return 'Arte7de';
|
||||
}
|
||||
|
||||
public function getURI(){
|
||||
return 'http://www.arte.tv/';
|
||||
}
|
||||
|
||||
public function getCacheDuration(){
|
||||
return 1800; // 30 minutes
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* RssBridgeArte7fr
|
||||
* Returns images from given page and tags
|
||||
*
|
||||
* @name Arte +7 FR
|
||||
* @homepage http://www.arte.tv/guide/fr/plus7
|
||||
* @description Returns newest videos from ARTE +7 (french)
|
||||
* @maintainer mitsukarenai
|
||||
* @update 2015-10-30
|
||||
* @use1(list|cat="Toutes les vidéos=>toutes-les-videos;Actu & société=>actu-société;Séries & fiction=>séries-fiction;Cinéma=>cinéma;Arts & spectacles classiques=>arts-spectacles-classiques;Culture pop=>culture-pop;Découverte=>découverte;Histoire=>histoire;Junior=>junior")
|
||||
*/
|
||||
class Arte7frBridge extends BridgeAbstract{
|
||||
|
||||
public function collectData(array $param){
|
||||
|
||||
function extractVideoset($category='toutes-les-videos')
|
||||
{
|
||||
$url = 'http://www.arte.tv/guide/fr/plus7/'.$category;
|
||||
$input = file_get_contents($url) or die('Could not request ARTE.');
|
||||
if(strpos($input, 'categoryVideoSet') !== FALSE)
|
||||
{
|
||||
$input = explode('categoryVideoSet: ', $input);
|
||||
$input = explode('}},', $input[1]);
|
||||
$input = $input[0].'}}';
|
||||
}
|
||||
else
|
||||
{
|
||||
$input = explode('videoSet: ', $input);
|
||||
$input = explode('}]},', $input[1]);
|
||||
$input = $input[0].'}]}';
|
||||
}
|
||||
$input = json_decode($input, TRUE);
|
||||
return $input;
|
||||
}
|
||||
|
||||
$category='toutes-les-videos';
|
||||
if (!empty($param['cat']))
|
||||
$category=$param['cat'];
|
||||
$input_json = extractVideoset($category);
|
||||
|
||||
foreach($input_json['videos'] as $element) {
|
||||
$item = new \Item();
|
||||
$item->uri = $element['url'];
|
||||
$item->id = $element['id'];
|
||||
$hack_broadcast_time = $element['rights_end'];
|
||||
$hack_broadcast_time = strtok($hack_broadcast_time, 'T');
|
||||
$hack_broadcast_time = strtok('T');
|
||||
$item->timestamp = strtotime($element['scheduled_on'].'T'.$hack_broadcast_time);
|
||||
$item->thumbnailUri = $element['thumbnail_url'];
|
||||
$item->title = $element['title'];
|
||||
if (!empty($element['subtitle']))
|
||||
$item->title = $element['title'].' | '.$element['subtitle'];
|
||||
$item->duration = round((int)$element['duration']/60);
|
||||
$item->content = $element['teaser'].'<br><br>'.$item->duration.'min<br><a href="'.$item->uri.'"><img src="' . $item->thumbnailUri . '" /></a>';
|
||||
$this->items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return 'Arte7fr';
|
||||
}
|
||||
|
||||
public function getURI(){
|
||||
return 'http://www.arte.tv/';
|
||||
}
|
||||
|
||||
public function getCacheDuration(){
|
||||
return 1800; // 30 minutes
|
||||
}
|
||||
}
|
72
bridges/DemoBridge.php
Normal file
72
bridges/DemoBridge.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/**
|
||||
* ABCTabsBridge
|
||||
* Returns the newest tabs
|
||||
*
|
||||
* @name ABC Tabs Bridge
|
||||
* @homepage http://www.abc-tabs.com/
|
||||
* @description Returns 22 newest tabs
|
||||
* @maintainer kranack
|
||||
* @update 2014-07-23
|
||||
*
|
||||
*/
|
||||
class DemoBridge extends BridgeAbstract{
|
||||
|
||||
public function loadMetadatas() {
|
||||
|
||||
$this->maintainer = "teromene";
|
||||
$this->name = "DemoBridge";
|
||||
$this->uri = "http://github.com/sebsauvage/rss-bridge";
|
||||
$this->description = "Bridge used for demos";
|
||||
$this->update = "2015-11-03";
|
||||
|
||||
$this->parameters['testCheckbox'] =
|
||||
'[
|
||||
{
|
||||
"type" : "checkbox",
|
||||
"identifier" : "testCheckbox",
|
||||
"name" : "test des checkbox"
|
||||
}
|
||||
|
||||
]';
|
||||
|
||||
$this->parameters['testList'] =
|
||||
'[
|
||||
{
|
||||
"type" : "list",
|
||||
"identifier" : "testList",
|
||||
"name" : "test des listes",
|
||||
"values" : [
|
||||
{
|
||||
"name" : "Test",
|
||||
"value" : "test"
|
||||
},
|
||||
{
|
||||
"name" : "Test 2",
|
||||
"value" : "test2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]';
|
||||
$this->parameters['testNumber'] =
|
||||
'[
|
||||
{
|
||||
"type" : "number",
|
||||
"identifier" : "testNumber",
|
||||
"name" : "test des numéros",
|
||||
"exampleValue" : "1515632"
|
||||
|
||||
}
|
||||
|
||||
]';
|
||||
|
||||
}
|
||||
|
||||
public function collectData(array $param){
|
||||
|
||||
}
|
||||
|
||||
public function getCacheDuration(){
|
||||
return 3600; // 1 hour
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
class FacebookBridge extends BridgeAbstract{
|
||||
|
||||
private $name;
|
||||
|
||||
|
||||
public function collectData(array $param){
|
||||
|
||||
|
|
|
@ -3,17 +3,13 @@
|
|||
* RssBridgeLeBonCoin
|
||||
* Search LeBonCoin for most recent ads in a specific region and topic.
|
||||
* Returns the most recent classified ads in results, sorting by date (most recent first).
|
||||
* Region identifiers : alsace, aquitaine, auvergne, basse_normandie, bourgogne, bretagne, centre,
|
||||
* champagne_ardenne, corse, franche_comte, haute_normandie, ile_de_france, languedoc_roussillon,
|
||||
* limousin, lorraine, midi_pyrenees, nord_pas_de_calais, pays_de_la_loire, picardie,
|
||||
* poitou_charentes, provence_alpes_cote_d_azur, rhone_alpes, guadeloupe, martinique, guyane, reunion.
|
||||
* 2014-07-22
|
||||
*
|
||||
* @name LeBonCoin
|
||||
* @homepage http://www.leboncoin.fr
|
||||
* @description Returns most recent results from LeBonCoin for a region and a keyword.
|
||||
* @maintainer 16mhz
|
||||
* @use1(r="Region identifier", k="Keyword")
|
||||
* @update 2015-10-30
|
||||
* @use1(list|r="Alsace=>alsace;Aquitaine=>aquitaine;Auvergne=>auvergne;Basse Normandie=>basse_normandie;Bourgogne=>bourgogne;Bretagne=>bretagne;Centre=>centre;Champagne Ardenne=>champagne_ardenne;Corse=>corse;Franche Comté=>franche_comte;Haute Normandie=>haute_normandie;Ile de France=>ile_de_france;Languedoc Roussillon=>languedoc_roussillon;Limousin=>limousin;Lorraine=>lorraine;Midi Pyrénées=>midi_pyrenees;Nord Pas De Calais=>nord_pas_de_calais;Pays de la Loire=>pays_de_la_loire;Picardie=>picardie;Poitou Charentes=>poitou_charentes;Provence Alpes Côte d'Azur=>provence_alpes_cote_d_azur;Rhône-Alpes=>rhone_alpes;Guadeloupe=>guadeloupe;Martinique=>martinique;Guyane=>guyane;Réunion=>reunion", text|k="Keyword")
|
||||
*/
|
||||
|
||||
class LeBonCoinBridge extends BridgeAbstract{
|
||||
|
|
|
@ -3,32 +3,32 @@
|
|||
* RssBridgeOpenClassrooms
|
||||
* Retrieve lastest tutorials from OpenClassrooms.
|
||||
* Returns the most recent tutorials, sorting by date (most recent first).
|
||||
* 2014-05-25
|
||||
*
|
||||
* @name OpenClassrooms Bridge
|
||||
* @homepage http://fr.openclassrooms.com/
|
||||
* @homepage https://openclassrooms.com/
|
||||
* @description Returns latest tutorials from OpenClassrooms.
|
||||
* @maintainer sebsauvage
|
||||
* @use1(u="informatique or sciences")
|
||||
* @update 2015-10-30
|
||||
* @use1(list|u="Arts & Culture=>arts;Code=>code;Design=>design;Entreprise=>business;Numérique=>digital;Sciences=>sciences;Sciences humaines=>humanities;Systèmes d'information=>it;Autres=>others")
|
||||
*/
|
||||
class OpenClassroomsBridge extends BridgeAbstract{
|
||||
|
||||
public function collectData(array $param){
|
||||
if ($param['u']!='informatique' && $param['u']!='sciences')
|
||||
if (empty($param['u']))
|
||||
{
|
||||
$this->returnError('Error: You must chose "informatique" or "science".', 404);
|
||||
$this->returnError('Error: You must chose a category.', 404);
|
||||
}
|
||||
|
||||
$html = '';
|
||||
$link = 'http://fr.openclassrooms.com/'.$param['u'].'/cours?title=&sort=updatedAt+desc';
|
||||
$link = 'https://openclassrooms.com/courses?categories='.$param['u'].'&title=&sort=updatedAt+desc';
|
||||
|
||||
$html = file_get_html($link) or $this->returnError('Could not request OpenClassrooms.', 404);
|
||||
|
||||
foreach($html->find('li.col6') as $element) {
|
||||
foreach($html->find('.courseListItem') as $element) {
|
||||
$item = new \Item();
|
||||
$item->uri = 'http://fr.openclassrooms.com'.$element->find('a', 0)->href;
|
||||
$item->title = $element->find('div.courses-content strong', 0)->innertext;
|
||||
$item->content = $element->find('span.course-tags', 0)->innertext;
|
||||
$item->uri = 'https://openclassrooms.com'.$element->find('a', 0)->href;
|
||||
$item->title = $element->find('h3', 0)->plaintext;
|
||||
$item->content = $element->find('slidingItem__descriptionContent', 0)->plaintext;
|
||||
$this->items[] = $item;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class OpenClassroomsBridge extends BridgeAbstract{
|
|||
}
|
||||
|
||||
public function getURI(){
|
||||
return 'http://fr.openclassrooms.com';
|
||||
return 'https://openclassrooms.com/';
|
||||
}
|
||||
|
||||
public function getCacheDuration(){
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
* @description Returns the newest broadcasts or highlights by channel name using the Twitch API (v3)
|
||||
* @maintainer logmanoriginal
|
||||
* @update 2015-07-14
|
||||
* @use1(channel="Channel", broadcasts="true|false")
|
||||
* @use2(channel="Channel", limit="Limit", broadcasts="true|false")
|
||||
* @use1(text|channel="Channel", list|broadcasts="Show broadcasts=>true;Don't show broadcasts=>false")
|
||||
* @use2(text|channel="Channel", text|limit="Limit", list|broadcasts="Show broadcasts=>true;Don't show broadcasts=>false")
|
||||
*
|
||||
* Description for the API is available on GitHub: https://github.com/justintv/twitch-api
|
||||
*/
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
/**
|
||||
*
|
||||
* @name World of Tanks
|
||||
* @description News about the tank slaughter game. Language can be fr, ?
|
||||
* @description News about the tank slaughter game.
|
||||
* @update 2015-09-12
|
||||
* @use1(lang="Searched language",category="Category id")
|
||||
* @use1(list|lang="Français=>fr;English=>en;Español=>es;Deutsch=>de;Čeština=>cs;Polski=>pl;Türkçe=>tr",text|category="Category id")
|
||||
*/
|
||||
define('WORLD_OF_TANKS', 'http://worldoftanks.eu/');
|
||||
define('NEWS', '/news/');
|
||||
|
|
|
@ -2,24 +2,69 @@
|
|||
/**
|
||||
* RssBridgeYoutube
|
||||
* Returns the newest videos
|
||||
*
|
||||
* @name Youtube Bridge
|
||||
* @homepage https://www.youtube.com/
|
||||
* @description Returns the 10 newest videos by username/channel/playlist or search
|
||||
* @maintainer mitsukarenai
|
||||
* @update 2015-07-08
|
||||
* @use1(u="username")
|
||||
* @use2(c="channel id")
|
||||
* @use3(p="playlist id")
|
||||
* @use4(s="search keyword",pa="page")
|
||||
*
|
||||
* WARNING: to parse big playlists (over ~90 videos), you need to edit simple_html_dom.php:
|
||||
* change: define('MAX_FILE_SIZE', 600000);
|
||||
* into: define('MAX_FILE_SIZE', 900000); (or more)
|
||||
*/
|
||||
class YoutubeBridge extends BridgeAbstract{
|
||||
class YoutubeBridge extends BridgeAbstract {
|
||||
|
||||
private $request;
|
||||
|
||||
public function loadMetadatas() {
|
||||
|
||||
$this->name = "Youtube Bridge";
|
||||
|
||||
$this->homepage = "https://youtube.com";
|
||||
$this->description = "Returns the 10 newest videos by username/channel/playlist or search";
|
||||
$this->maintainer = "mitsukarenai";
|
||||
|
||||
$this->parameters["By username"] =
|
||||
'[
|
||||
{
|
||||
"type" : "text",
|
||||
"identifier" : "u",
|
||||
"name" : "username",
|
||||
"exampleValue" : "test"
|
||||
}
|
||||
]';
|
||||
|
||||
$this->parameters['By channel id'] =
|
||||
'[
|
||||
{
|
||||
"type" : "number",
|
||||
"identifier" : "c",
|
||||
"name" : "channel id",
|
||||
"exampleValue" : "15"
|
||||
}
|
||||
]';
|
||||
|
||||
$this->parameters['By playlist Id'] =
|
||||
'[
|
||||
{
|
||||
"type" : "number",
|
||||
"identifier" : "c",
|
||||
"name" : "playlist id",
|
||||
"exampleValue" : "15"
|
||||
}
|
||||
]';
|
||||
|
||||
$this->parameters["Search result"] =
|
||||
'[
|
||||
{
|
||||
"type" : "text",
|
||||
"identifier" : "s",
|
||||
"name" : "search keyword",
|
||||
"exampleValue" : "test"
|
||||
|
||||
},
|
||||
{
|
||||
"type" : "number",
|
||||
"identifier" : "pa",
|
||||
"name" : "page",
|
||||
"exampleValue" : "1"
|
||||
|
||||
}
|
||||
]';
|
||||
}
|
||||
|
||||
public function collectData(array $param){
|
||||
|
||||
|
|
154
index.php
154
index.php
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
$time_start = microtime(true);
|
||||
/*
|
||||
TODO :
|
||||
- manage SSL detection because if library isn't loaded, some bridge crash !
|
||||
|
@ -13,7 +14,7 @@ TODO :
|
|||
|
||||
date_default_timezone_set('UTC');
|
||||
error_reporting(0);
|
||||
//ini_set('display_errors','1'); error_reporting(E_ALL); // For debugging only.
|
||||
ini_set('display_errors','1'); error_reporting(E_ALL); // For debugging only.
|
||||
|
||||
// extensions check
|
||||
if (!extension_loaded('openssl'))
|
||||
|
@ -52,6 +53,7 @@ if (!file_exists($whitelist_file)) {
|
|||
}
|
||||
else {
|
||||
$whitelist_selection = explode("\n", file_get_contents($whitelist_file));
|
||||
array_pop($whitelist_selection);
|
||||
}
|
||||
|
||||
// whitelist control function
|
||||
|
@ -94,14 +96,14 @@ try{
|
|||
$bridge->setCache($cache); // just add disable cache to your query to disable caching
|
||||
}
|
||||
$bridge->setDatas($_REQUEST);
|
||||
|
||||
$bridge->loadMetadatas();
|
||||
// Data transformation
|
||||
$format = Format::create($format);
|
||||
$format
|
||||
->setDatas($bridge->getDatas())
|
||||
->setExtraInfos(array(
|
||||
'name' => $bridge->getName(),
|
||||
'uri' => $bridge->getURI(),
|
||||
'name' => $bridge->name,
|
||||
'uri' => $bridge->uri,
|
||||
))
|
||||
->display();
|
||||
die;
|
||||
|
@ -135,86 +137,97 @@ function getHelperButtonsFormat($formats){
|
|||
return $buttons;
|
||||
}
|
||||
|
||||
function displayBridgeCard($bridgeReference, $bridgeInformations, $formats, $isActive = true)
|
||||
function displayBridgeCard($bridgeName, $formats, $isActive = true)
|
||||
{
|
||||
$name = isset($bridgeInformations['homepage']) ? '<a href="'.$bridgeInformations['homepage'].'">'.$bridgeInformations['name'].'</a>' : $bridgeInformations['name'];
|
||||
$description = isset($bridgeInformations['description']) ? $bridgeInformations['description'] : 'No description provided';
|
||||
|
||||
$bridgeElement = Bridge::create($bridgeName);
|
||||
$bridgeElement->loadMetadatas();
|
||||
|
||||
$name = '<a href="'.$bridgeElement->uri.'">'.$bridgeElement->name.'</a>';
|
||||
$description = $bridgeElement->description;
|
||||
|
||||
$card = <<<CARD
|
||||
<section id="bridge-{$bridgeReference}" data-ref="{$bridgeReference}">
|
||||
<section id="bridge-{$bridgeName}" data-ref="{$bridgeName}">
|
||||
<h2>{$name}</h2>
|
||||
<p class="description">
|
||||
{$description}
|
||||
</p>
|
||||
CARD;
|
||||
if( isset($bridgeInformations['use']) && count($bridgeInformations['use']) > 0 )
|
||||
|
||||
// If we don't have any parameter for the bridge, we print a generic form to load it.
|
||||
if(count($bridgeElement->parameters) == 0) {
|
||||
|
||||
$card .= '<form method="POST" action="?">
|
||||
<input type="hidden" name="action" value="display" />
|
||||
<input type="hidden" name="bridge" value="' . $bridgeName . '" />' . PHP_EOL;
|
||||
|
||||
if ($isActive)
|
||||
{
|
||||
$card .= '<ol class="list-use">' . PHP_EOL;
|
||||
foreach($bridgeInformations['use'] as $anUseNum => $anUse)
|
||||
{
|
||||
$card .= '<li data-use="' . $anUseNum . '">' . PHP_EOL;
|
||||
$card .= '<form method="GET" action="?">
|
||||
<input type="hidden" name="action" value="display" />
|
||||
<input type="hidden" name="bridge" value="' . $bridgeReference . '" />' . PHP_EOL;
|
||||
|
||||
foreach($anUse as $argValue)
|
||||
{
|
||||
$idArg = 'arg-' . $bridgeReference . '-' . $anUseNum . '-' . $argValue['query-name'];
|
||||
if($argValue['type'] == null || $argValue['type'] == "text") { //If we have no type, treat it as a text field for compatibility
|
||||
$card .= '<input id="' . $idArg . '" type="text" value="" placeholder="' . $argValue['value'] . '" name="' . $argValue['query-name'] . '" />' . PHP_EOL;
|
||||
} else if($argValue['type'] == "list") {
|
||||
$card .= '<select id="' . $idArg . '" name="' . $argValue['query-name'] . '" >' . PHP_EOL;
|
||||
$optionList = explode(";", $argValue['value']);
|
||||
|
||||
foreach($optionList as $option) {
|
||||
$option = explode("=>", $option);
|
||||
$card .= "<option value='".$option[1]."'>".$option[0]."</option>";
|
||||
}
|
||||
$card .= "</select>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$card .= '<br />';
|
||||
|
||||
if ($isActive)
|
||||
{
|
||||
$card .= getHelperButtonsFormat($formats);
|
||||
}
|
||||
else
|
||||
{
|
||||
$card .= '<span style="font-weight: bold;">Inactive</span>';
|
||||
}
|
||||
|
||||
$card .= '</form></li>' . PHP_EOL;
|
||||
}
|
||||
$card .= '</ol>' . PHP_EOL;
|
||||
$card .= getHelperButtonsFormat($formats);
|
||||
}
|
||||
else
|
||||
{
|
||||
$card .= '<form method="GET" action="?">
|
||||
<input type="hidden" name="action" value="display" />
|
||||
<input type="hidden" name="bridge" value="' . $bridgeReference . '" />' . PHP_EOL;
|
||||
|
||||
if ($isActive)
|
||||
{
|
||||
$card .= getHelperButtonsFormat($formats);
|
||||
}
|
||||
else
|
||||
{
|
||||
$card .= '<span style="font-weight: bold;">Inactive</span>';
|
||||
}
|
||||
$card .= '</form>' . PHP_EOL;
|
||||
$card .= '<span style="font-weight: bold;">Inactive</span>';
|
||||
}
|
||||
$card .= '</form>' . PHP_EOL;
|
||||
|
||||
}
|
||||
|
||||
$card .= isset($bridgeInformations['maintainer']) ? '<span class="maintainer">'.$bridgeInformations['maintainer'].'</span>' : '';
|
||||
foreach($bridgeElement->parameters as $parameterName => $parameter)
|
||||
{
|
||||
$card .= '<ol class="list-use">' . PHP_EOL;
|
||||
$card .= '<h5>'.$parameterName.'</h5>' . PHP_EOL;
|
||||
$card .= '<form method="POST" action="?">
|
||||
<input type="hidden" name="action" value="display" />
|
||||
<input type="hidden" name="bridge" value="' . $bridgeName . '" />' . PHP_EOL;
|
||||
|
||||
$parameter = json_decode($parameter, true);
|
||||
|
||||
foreach($parameter as $inputEntry) {
|
||||
|
||||
$idArg = 'arg-' . $bridgeName . '-' . $parameterName . '-' . $inputEntry['identifier'];
|
||||
|
||||
$card .= '<label for="' .$idArg. '">' .$inputEntry['name']. ' : </label>' . PHP_EOL;
|
||||
|
||||
if(!isset($inputEntry['type']) || $inputEntry['type'] == 'text') {
|
||||
$card .= '<input id="' . $idArg . '" type="text" value="" placeholder="' . $inputEntry['exampleValue'] . '" name="' . $inputEntry['identifier'] . '" /><br />' . PHP_EOL;
|
||||
} else if($inputEntry['type'] == 'number') {
|
||||
$card .= '<input id="' . $idArg . '" type="number" value="" placeholder="' . $inputEntry['exampleValue'] . '" name="' . $inputEntry['identifier'] . '" /><br />' . PHP_EOL;
|
||||
} else if($inputEntry['type'] == 'list') {
|
||||
$card .= '<select id="' . $idArg . '" name="' . $inputEntry['name'] . '" >';
|
||||
foreach($inputEntry['values'] as $listValues) {
|
||||
|
||||
$card .= "<option value='" . $listValues['value'] . "'>" . $listValues['name'] . "</option>";
|
||||
|
||||
}
|
||||
$card .= '</select><br >';
|
||||
} else if($inputEntry['type'] == 'checkbox') {
|
||||
|
||||
$card .= '<input id="' . $idArg . '" type="checkbox" name="' . $inputEntry['identifier'] . '" /><br />' . PHP_EOL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if ($isActive)
|
||||
{
|
||||
$card .= getHelperButtonsFormat($formats);
|
||||
}
|
||||
else
|
||||
{
|
||||
$card .= '<span style="font-weight: bold;">Inactive</span>';
|
||||
}
|
||||
$card .= '</form>' . PHP_EOL;
|
||||
|
||||
}
|
||||
|
||||
$card .= '<span class="maintainer">'.$bridgeElement->maintainer.'</span>';
|
||||
$card .= '</section>';
|
||||
|
||||
return $card;
|
||||
}
|
||||
|
||||
$bridges = Bridge::searchInformation();
|
||||
$formats = Format::searchInformation();
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
@ -239,24 +252,27 @@ $formats = Format::searchInformation();
|
|||
$activeFoundBridgeCount = 0;
|
||||
$showInactive = isset($_REQUEST['show_inactive']) && $_REQUEST['show_inactive'] == 1;
|
||||
$inactiveBridges = '';
|
||||
foreach($bridges as $bridgeReference => $bridgeInformations)
|
||||
foreach(Bridge::listBridges() as $bridgeName)
|
||||
{
|
||||
if(BridgeWhitelist($whitelist_selection, $bridgeReference))
|
||||
if(BridgeWhitelist($whitelist_selection, $bridgeName))
|
||||
{
|
||||
echo displayBridgeCard($bridgeReference, $bridgeInformations, $formats);
|
||||
echo displayBridgeCard($bridgeName, $formats);
|
||||
$activeFoundBridgeCount++;
|
||||
}
|
||||
elseif ($showInactive)
|
||||
{
|
||||
// inactive bridges
|
||||
$inactiveBridges .= displayBridgeCard($bridgeReference, $bridgeInformations, $formats, false) . PHP_EOL;
|
||||
$inactiveBridges .= displayBridgeCard($bridgeName, $formats, false) . PHP_EOL;
|
||||
}
|
||||
}
|
||||
echo '<hr />' . $inactiveBridges;
|
||||
?>
|
||||
<footer>
|
||||
<?= $activeFoundBridgeCount; ?>/<?= count($bridges) ?> active bridges (<a href="?show_inactive=1">Show inactive</a>)<br />
|
||||
<?= $activeFoundBridgeCount; ?>/<?= count($whitelist_selection) ?> active bridges (<a href="?show_inactive=1">Show inactive</a>)<br />
|
||||
<a href="https://github.com/sebsauvage/rss-bridge">RSS-Bridge alpha 0.1 ~ Public Domain</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
echo "Ran for ". (microtime(true) - $time_start);
|
||||
?>
|
||||
|
|
|
@ -6,15 +6,29 @@
|
|||
|
||||
interface BridgeInterface{
|
||||
public function collectData(array $param);
|
||||
public function getName();
|
||||
public function getURI();
|
||||
public function getCacheDuration();
|
||||
public function loadMetadatas();
|
||||
}
|
||||
|
||||
abstract class BridgeAbstract implements BridgeInterface{
|
||||
|
||||
protected $cache;
|
||||
protected $items = array();
|
||||
|
||||
public $name = "Bridge sans nom";
|
||||
public $uri = "";
|
||||
public $description = 'No description provided';
|
||||
public $maintainer = 'No maintainer';
|
||||
public $parameters = array();
|
||||
|
||||
/**
|
||||
* Loads the Bridge Metadatas
|
||||
*/
|
||||
public function loadMetadatas() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch probative exception
|
||||
*/
|
||||
|
@ -30,6 +44,8 @@ abstract class BridgeAbstract implements BridgeInterface{
|
|||
return $this->items;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Defined datas with parameters depending choose bridge
|
||||
* Note : you can defined a cache before with "setCache"
|
||||
|
@ -239,74 +255,25 @@ class Bridge{
|
|||
}
|
||||
|
||||
/**
|
||||
* Read bridge dir and catch informations about each bridge depending annotation
|
||||
* @return array Informations about each bridge
|
||||
* Lists the available bridges.
|
||||
* @return array List of the bridges
|
||||
*/
|
||||
static public function searchInformation(){
|
||||
static public function listBridges() {
|
||||
|
||||
$pathDirBridge = self::getDir();
|
||||
|
||||
$listBridge = array();
|
||||
$dirFiles = scandir($pathDirBridge);
|
||||
|
||||
$searchCommonPattern = array('maintainer', 'description', 'homepage', 'name');
|
||||
|
||||
$dirFiles = scandir($pathDirBridge);
|
||||
if( $dirFiles !== false ){
|
||||
foreach( $dirFiles as $fileName ){
|
||||
if( preg_match('@([^.]+)\.php@U', $fileName, $out) ){ // Is PHP file ?
|
||||
$infos = array(); // Information about the bridge
|
||||
$resParse = token_get_all(file_get_contents($pathDirBridge . $fileName)); // Parse PHP file
|
||||
foreach($resParse as $v){
|
||||
if( is_array($v) && $v[0] == T_DOC_COMMENT ){ // Lexer node is COMMENT ?
|
||||
$commentary = $v[1];
|
||||
foreach( $searchCommonPattern as $name){ // Catch information with common pattern
|
||||
preg_match('#@' . preg_quote($name, '#') . '\s+(.+)#', $commentary, $outComment);
|
||||
if( isset($outComment[1]) ){
|
||||
$infos[$name] = $outComment[1];
|
||||
}
|
||||
}
|
||||
if( preg_match('@([^.]+)\.php@U', $fileName, $out) ){
|
||||
$listBridge[] = $out[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preg_match_all('#@use(?<num>[1-9][0-9]*)\s?\((?<args>.+)\)(?:\r|\n)#', $commentary, $outComment); // Catch specific information about "use".
|
||||
return $listBridge;
|
||||
}
|
||||
|
||||
if( isset($outComment['args']) && is_array($outComment['args']) ){
|
||||
$infos['use'] = array();
|
||||
|
||||
foreach($outComment['args'] as $num => $args){ // Each use
|
||||
|
||||
preg_match_all('#(?<type>[a-z]+)\|(?<name>[a-z]+)="(?<value>.*)"(?:,|$)#U', $args, $outArg); // Catch arguments for current use
|
||||
|
||||
if(!isset($outArg['name']) || count($outArg['name']) == 0) {
|
||||
preg_match_all('#(?<name>[a-z]+)="(?<value>.*)"(?:,|$)#U', $args, $outArg); // Catch arguments
|
||||
}
|
||||
|
||||
|
||||
if( isset($outArg['name'])){
|
||||
$usePos = $outComment['num'][$num]; // Current use name
|
||||
if( !isset($infos['use'][$usePos]) ){ // Not information actually for this "use" ?
|
||||
$infos['use'][$usePos] = array();
|
||||
}
|
||||
|
||||
foreach($outArg['name'] as $numArg => $name){ // Each arguments
|
||||
$infos['use'][$usePos][$name] = array();
|
||||
|
||||
$infos['use'][$usePos][$name]['query-name'] = $name;
|
||||
$infos['use'][$usePos][$name]['value'] = $outArg['value'][$numArg];
|
||||
$infos['use'][$usePos][$name]['type'] = $outArg['type'][$numArg];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( isset($infos['name']) ){ // If informations containt at least a name
|
||||
$listBridge[$out[1]] = $infos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $listBridge;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue