Commit 31a47f08 authored by Erase's avatar Erase

Oups 1/2

parent 6de24331
This diff is collapsed.
RSS-Fusion
----------
**Fusion de flux RSS multiples.**
* Sans base de données
* Script auto hébergeable
* Gestion des flux RSS/ATOM
* Flux global
* Surcharge de personnalisation
Par défaut
----------
* Système de mise en cache des flux (durée par défaut = 1h)
* Données triées par date/heure décroissante
* Possibilité de spécifier des mots clés ("star and bad words")
Prérequis
---------
* Serveur Web (tel que Apache2)
* A partir de PHP 5.4 avec les modules suivants : `cUrl`, `JSON`, `SimpleXML`, `DOMDocument` (et potentiellement quelques autres selon votre configuration)
Installation
------------
Récupération des sources
```
$ git clone https://git.framasoft.org/Erase/RSS-Fusion.git
```
ou en [téléchargeant l'archive zip]
Vérifier/assigner les droits en écriture au sein du répertoire :
* `/data`
Personnalisation
----------
En se basant sur les paramètres précisés dans le fichier `/system/config/default.php`, il est possible de surcharger les informations en les précisant dans le fichier `/system/config/localconfig.php`, notamment les mots clés.
Le reste des traitements à personnaliser peuvent se baser sur ceux présents dans le fichier `index.php`
Informations annexes
--------
* RSS-Fusion utilise la librairie [SimplePie] pour parser les flux RSS.
* Les données en caches sont dans le répertoire `/system/cache`
* La recherche des mots-clés se fait sur le titre et la description de chaque élément des flux RSS
* Deux types de mots clés sont pris en charge : **star** pour des éléments à mettre en avant et **bad** pour des éléments à masquer
Structuration des éléments des flux
--------
```
array(11) {
["link"] => URL de l'élément
["title"] => Titre de l'élément
["permalink"] => Permalien de l'élément
["description"] => Description de l'élément
["pubdate"] => Timestamp de publication
["date_read"] => Date de publication au format jour-mois-année heures:minutes
["category"] => Catégorie de l'élément
["base"] => URL du flux RSS source
["show"] => true (default) | false (bad word) | star (star word)
["enclosure"] => Elément inclus
}
```
Licence
-------
En dehors des différentes licences spécifiques aux outils utilisés, le reste du code est distribué sous licence [Creative Commons BY-NC-SA 4.0]
Auteur
------
* [Un simple développeur paysagiste] :) avec un peu de temps libre et aucune prétention - contact_at_green-effect.fr
[//]: #
[téléchargeant l'archive zip]: <https://framagit.org/Erase/RSS-Fusion/repository/archive.zip>
[SimplePie]: <http://simplepie.org/>
[Creative Commons BY-NC-SA 4.0]: <http://creativecommons.org/licenses/by-nc-sa/4.0/>
[Un simple développeur paysagiste]: <http://www.green-effect.fr>
\ No newline at end of file
<?php
//~ Define the root path
define('TL_ROOT', dirname(__DIR__.'/RSS-Fusion'));
require TL_ROOT.'/system/classes/Config.php';
require TL_ROOT.'/system/classes/Date.php';
require TL_ROOT.'/system/classes/FeedReader.php';
require TL_ROOT.'/system/vendor/simplepie/SimplePie.php';
Config::preload();
//~ Adjust the error handling
ini_set('display_errors', (Config::get('displayErrors') ? 1 : 0));
error_reporting((Config::get('displayErrors') || Config::get('logErrors')) ? 1 : 0);
/*
$_links = array(
"http://www.lemonde.fr/rss/une.xml",
"https://rss.framasoft.org/"
);
$feeds = new FeedReader($_links);
echo "<pre>";
var_dump($feeds->objParseFeed->items)
*/
?>
<?php
/**
* Loads the local configuration file
*/
class Config
{
/**
* Object instance (Singleton)
* @var \Config
*/
protected static $objInstance;
/**
* Local file existance
* @var boolean
*/
protected static $blnHasLcf;
/**
* Top content
* @var string
*/
protected $strTop = '<?php';
/**
* Bottom content
* @var string
*/
protected $strBottom = '';
/**
* Data
* @var array
*/
public $arrData = array();
/**
* Default Data
* @var array
*/
public $arrDefaultData = array();
/**
* Prevent direct instantiation (Singleton)
*/
protected function __construct() {}
/**
* Prevent cloning of the object (Singleton)
*/
final public function __clone() {}
/**
* Return the current object instance (Singleton)
*
* @return \Config The object instance
*/
public static function getInstance()
{
if (static::$objInstance === null)
{
static::$objInstance = new static();
static::$objInstance->initialize();
}
return static::$objInstance;
}
/**
* Load all configuration files
*/
protected function initialize()
{
if (static::$blnHasLcf === null)
{
static::preload();
}
// Include the local configuration file again
if (static::$blnHasLcf)
{
include TL_ROOT.'/system/config/localconfig.php';
}
}
/**
* Return a configuration value
*
* @param string $strKey The short key (e.g. "displayErrors")
*
* @return mixed|null The configuration value
*/
public static function get($strKey)
{
if (isset($GLOBALS['TL_CONFIG'][$strKey]))
{
return $GLOBALS['TL_CONFIG'][$strKey];
}
return null;
}
/**
* Temporarily set a configuration value
*
* @param string $strKey The short key (e.g. "displayErrors")
* @param string $varValue The configuration value
*/
public static function set($strKey, $varValue)
{
$GLOBALS['TL_CONFIG'][$strKey] = $varValue;
}
/**
* Preload the default and local configuration
*/
public static function preload()
{
// Load the default files
include TL_ROOT.'/system/config/default.php';
include TL_ROOT.'/system/config/agents.php';
// Include the local configuration file
if (($blnHasLcf = file_exists(TL_ROOT.'/system/config/localconfig.php')) === true)
{
include TL_ROOT.'/system/config/localconfig.php';
}
static::$blnHasLcf = $blnHasLcf;
}
/**
* Read file and set array
*/
public function read()
{
// Parse the local configuration file
if (static::$blnHasLcf)
{
$resFile = fopen(TL_ROOT.'/system/config/localconfig.php', 'rb');
while (!feof($resFile))
{
$strLine = fgets($resFile);
$strTrim = trim($strLine);
if ($strTrim == '?>' OR $strTrim == $this->strTop)
{
continue;
}
if ($strTrim != '')
{
$arrChunks = array_map('trim', explode('=', $strLine, 2));
$this->arrData[$arrChunks[0]] = $arrChunks[1];
}
}
fclose($resFile);
}
}
/**
* Save the local configuration file
*/
public function save()
{
if ($this->strTop == '')
{
$this->strTop = '<?php';
}
$strFile = trim($this->strTop) . "\n\n";
foreach ($this->arrData as $k=>$v)
{
$strFile .= "$k = $v\n";
}
$this->strBottom = trim($this->strBottom);
if ($this->strBottom != '')
{
$strFile .= "\n" . $this->strBottom . "\n";
}
$strTemp = md5(uniqid(mt_rand(), true));
// Write to a temp file first
$objFile = fopen(TL_ROOT.'/system/cache/' . $strTemp, 'wb');
fputs($objFile, $strFile);
fclose($objFile);
// Make sure the file has been written
if (!filesize(TL_ROOT.'/system/cache/' . $strTemp))
{
return;
}
// Then move the file to its final destination
rename(TL_ROOT.'/system/cache/' . $strTemp, TL_ROOT.'/system/config/localconfig.php');
// Reset the Zend OPcache
if (function_exists('opcache_invalidate'))
{
opcache_invalidate(TL_ROOT.'/system/config/localconfig.php', true);
}
// Reset the Zend Optimizer+ cache (unfortunately no API to delete just a single file)
if (function_exists('accelerator_reset'))
{
accelerator_reset();
}
// Recompile the APC file
if (function_exists('apc_compile_file') && !ini_get('apc.stat'))
{
apc_compile_file(TL_ROOT.'/system/config/localconfig.php');
}
// Purge the eAccelerator cache
if (function_exists('eaccelerator_purge') && !ini_get('eaccelerator.check_mtime'))
{
@eaccelerator_purge();
}
// Purge the XCache cache (thanks to Trenker)
if (function_exists('xcache_count') && !ini_get('xcache.stat'))
{
if (($count = xcache_count(XC_TYPE_PHP)) > 0)
{
for ($id=0; $id<$count; $id++)
{
xcache_clear_cache(XC_TYPE_PHP, $id);
}
}
}
}
/**
* Add a configuration variable to the local configuration file
*
* @param string $strKey The full variable name
* @param mixed $varValue The configuration value
*/
public function add($strKey, $varValue)
{
$this->read();
$this->arrData[$strKey] = $this->escape($varValue) . ';';
}
/**
* Remove a configuration variable
*
* @param string $strKey The full variable name
*/
public function delete($strKey)
{
$this->read();
unset($this->arrData[$strKey]);
}
/**
* Permanently set a configuration value
*
* @param string $strKey The short key or full variable name
* @param mixed $varValue The configuration value
*/
public static function persist($strKey, $varValue)
{
$objConfig = static::getInstance();
if (strncmp($strKey, '$GLOBALS', 8) !== 0)
{
$strKey = "\$GLOBALS['TL_CONFIG']['$strKey']";
}
$objConfig->add($strKey, $varValue);
}
/**
* Escape a value depending on its type
*
* @param mixed $varValue The value
*
* @return mixed The escaped value
*/
protected function escape($varValue)
{
if (is_numeric($varValue) && !preg_match('/e|^00+/', $varValue) && $varValue < PHP_INT_MAX)
{
return $varValue;
}
if (is_bool($varValue))
{
return $varValue ? 'true' : 'false';
}
if ($varValue == 'true')
{
return 'true';
}
if ($varValue == 'false')
{
return 'false';
}
return "'" . str_replace('\\"', '"', preg_replace('/[\n\r\t ]+/', ' ', addslashes($varValue))) . "'";
}
}
This diff is collapsed.
<?php
/**
* Read RSS feeds
*
* The class provides an interface to read RSS feeds.
*
* Usage:
*
* $feed = new Feed('FEED_URL');
* echo $feed->objParseFeed->title
*
*/
class FeedReader
{
/**
* objParseFeed
* @var object
*/
public $objParseFeed;
/**
* Items
* @var array
*/
public $arrItems = array();
public $objFeed;
/**
* Store the feed name
*
* @param array $_urlFeeds The feed url
*/
public function __construct($_urlFeeds)
{
$this->objFeed = new SimplePie();
$this->objFeed->set_useragent(\Config::get('RssReaderReferer'));
if (count($_urlFeeds) > 1)
{
$this->objFeed->set_feed_url($_urlFeeds);
}
else
{
$this->objFeed->set_feed_url($_urlFeeds[0]);
}
$this->objFeed->set_output_encoding(\Config::get('characterSet'));
$this->objFeed->set_cache_location(TL_ROOT.'/system/cache/');
$this->objFeed->enable_cache(\Config::get('enableCache'));
$this->objFeed->set_cache_duration(\Config::get('cacheDuration'));
$this->objFeed->enable_order_by_date();
if (!$this->objFeed->init())
{
return '';
}
$this->objFeed->handle_content_type();
$this->objParseFeed = new \stdClass();
$this->objParseFeed->link = $this->objFeed->get_link();
$this->objParseFeed->title = $this->objFeed->get_title();
$this->objParseFeed->language = $this->objFeed->get_language();
$this->objParseFeed->description = $this->objFeed->get_description();
$this->objParseFeed->copyright = $this->objFeed->get_copyright();
// Add image
if ($this->objFeed->get_image_url())
{
$this->objParseFeed->image = true;
$this->objParseFeed->src = $this->objFeed->get_image_url();
$this->objParseFeed->alt = $this->objFeed->get_image_title();
$this->objParseFeed->href = $this->objFeed->get_image_link();
$this->objParseFeed->height = $this->objFeed->get_image_height();
$this->objParseFeed->width = $this->objFeed->get_image_width();
}
// Get the items
$this->arrItems = array_slice($this->objFeed->get_items(0, $GLOBALS['TL_CONFIG']['maxResultsPerBlock']), 0, $GLOBALS['TL_CONFIG']['maxResultsPerBlock']);
$limit = count($this->arrItems);
$offset = 0;
$items = array();
$last = min($limit, count($this->arrItems)) - 1;
for ($i=0; $i<$limit; $i++)
{
$items[$i] = array
(
'link' => $this->arrItems[$i]->get_link(),
'title' => $this->arrItems[$i]->get_title(),
'permalink' => $this->arrItems[$i]->get_permalink(),
'description' => str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $this->arrItems[$i]->get_description()),
'pubdate' => $this->arrItems[$i]->get_date('U'),
'date_read' => \Date::parse(Config::get('datimFormat'), $this->arrItems[$i]->get_date('U')),
'category' => $this->arrItems[$i]->get_category(0),
'base' => $this->arrItems[$i]->get_base(),
'show' => 'show' // show || hide || star
);
// Where
$where = \Config::get('where');
if(!is_null($where) && $where == 'title'){
$merge_str = strtolower($items[$i]['title']);
}elseif(!is_null($where) && $where == 'description'){
$merge_str = strtolower($items[$i]['description']);
}else{
$merge_str = strtolower($items[$i]['title']." ".$items[$i]['description']);
}
// Bad and star words
if(count(Config::get('_starWords'))){
if($this->isInStr($merge_str, Config::get('_starWords')))
{
$items[$i]['show'] = 'star';
}
}
if(count(Config::get('_badWords'))){
if($this->isInStr($merge_str, Config::get('_badWords')))
{
$items[$i]['show'] = 'hide';
}
}
// Add author
if (($objAuthor = $this->arrItems[$i]->get_author(0)) != false)
{
$items[$i]['author'] = trim($objAuthor->name . ' ' . $objAuthor->email);
}
// Add enclosure
if (($objEnclosure = $this->arrItems[$i]->get_enclosure(0)) != false)
{
$items[$i]['enclosure'] = $objEnclosure->get_link();
}
}
$this->objParseFeed->items = array_values($items);
}
public static function isInStr($strString, $varWords)
{
foreach ((array) $varWords as $strWord)
{
if(empty($strWord)){
continue;
}
$t = preg_match("/".preg_quote(htmlentities($strWord), '/')."/i", $strString);
if($t){
return true;
}
}
return false;
}
}
<?php
//~ Operating systems
$GLOBALS['TL_CONFIG']['os'] = array
(
'Macintosh' => array('os'=>'mac', 'mobile'=>false),
'Windows CE' => array('os'=>'win-ce', 'mobile'=>true),
'Windows Phone' => array('os'=>'win-ce', 'mobile'=>true),
'Windows' => array('os'=>'win', 'mobile'=>false),
'iPad' => array('os'=>'ios', 'mobile'=>false),
'iPhone' => array('os'=>'ios', 'mobile'=>true),
'iPod' => array('os'=>'ios', 'mobile'=>true),
'Android' => array('os'=>'android', 'mobile'=>true),
'BB10' => array('os'=>'blackberry', 'mobile'=>true),
'Blackberry' => array('os'=>'blackberry', 'mobile'=>true),
'Symbian' => array('os'=>'symbian', 'mobile'=>true),
'WebOS' => array('os'=>'webos', 'mobile'=>true),
'Linux' => array('os'=>'unix', 'mobile'=>false),
'FreeBSD' => array('os'=>'unix', 'mobile'=>false),
'OpenBSD' => array('os'=>'unix', 'mobile'=>false),
'NetBSD' => array('os'=>'unix', 'mobile'=>false),
);
//~ Browsers
$GLOBALS['TL_CONFIG']['browser'] = array
(
'MSIE' => array('browser'=>'ie', 'shorty'=>'ie', 'engine'=>'trident', 'version'=>'/^.*MSIE (\d+(\.\d+)*).*$/'),
'Trident' => array('browser'=>'ie', 'shorty'=>'ie', 'engine'=>'trident', 'version'=>'/^.*Trident\/\d+\.\d+; rv:(\d+(\.\d+)*).*$/'),
'Firefox' => array('browser'=>'firefox', 'shorty'=>'fx', 'engine'=>'gecko', 'version'=>'/^.*Firefox\/(\d+(\.\d+)*).*$/'),
'Chrome' => array('browser'=>'chrome', 'shorty'=>'ch', 'engine'=>'webkit', 'version'=>'/^.*Chrome\/(\d+(\.\d+)*).*$/'),
'OmniWeb' => array('browser'=>'omniweb', 'shorty'=>'ow', 'engine'=>'webkit', 'version'=>'/^.*Version\/(\d+(\.\d+)*).*$/'),
'Silk' => array('browser'=>'silk', 'shorty'=>'si', 'engine'=>'silk', 'version'=>'/^.*Silk\/(\d+(\.\d+)*).*$/'),
'Safari' => array('browser'=>'safari', 'shorty'=>'sf', 'engine'=>'webkit', 'version'=>'/^.*Version\/(\d+(\.\d+)*).*$/'),
'Opera Mini' => array('browser'=>'opera-mini', 'shorty'=>'oi', 'engine'=>'presto', 'version'=>'/^.*Opera Mini\/(\d+(\.\d+)*).*$/'),
'Opera Mobi' => array('browser'=>'opera-mobile', 'shorty'=>'om', 'engine'=>'presto', 'version'=>'/^.*Version\/(\d+(\.\d+)*).*$/'),
'Opera' => array('browser'=>'opera', 'shorty'=>'op', 'engine'=>'presto', 'version'=>'/^.*Version\/(\d+(\.\d+)*).*$/'),
'IEMobile' => array('browser'=>'ie-mobile', 'shorty'=>'im', 'engine'=>'trident', 'version'=>'/^.*IEMobile (\d+(\.\d+)*).*$/'),
'Camino' => array('browser'=>'camino', 'shorty'=>'ca', 'engine'=>'gecko', 'version'=>'/^.*Camino\/(\d+(\.\d+)*).*$/'),
'Konqueror' => array('browser'=>'konqueror', 'shorty'=>'ko', 'engine'=>'webkit', 'version'=>'/^.*Konqueror\/(\d+(\.\d+)*).*$/')
);
<?php
##############################################################
# #
# DO NOT CHANGE ANYTHING HERE! USE THE LOCAL CONFIGURATION #
# FILE localconfig.php TO MODIFY THE CONFIGURATION! #
# #
##############################################################
/**
* -------------------------------------------------------------------------
* GENERAL SETTINGS
* -------------------------------------------------------------------------
*/
$GLOBALS['TL_CONFIG']['characterSet'] = 'utf-8';
$GLOBALS['TL_CONFIG']['displayErrors'] = false;
$GLOBALS['TL_CONFIG']['logErrors'] = false;
/**
* -------------------------------------------------------------------------
* DATE AND TIME SETTINGS
* -------------------------------------------------------------------------
*
* datimFormat = show date and time
* dateFormat = show date only
* timeFormat = show time only
* timeZone = the server's default time zone
*
* See PHP function date() for more information.
*/
$GLOBALS['TL_CONFIG']['datimFormat'] = 'd-m-Y H:i';
$GLOBALS['TL_CONFIG']['dateFormat'] = 'd-m-Y';
$GLOBALS['TL_CONFIG']['timeFormat'] = 'H:i';
$GLOBALS['TL_CONFIG']['timeZone'] = (!is_null(ini_get('date.timezone')) ? ini_get('date.timezone') : 'GMT+1');
$GLOBALS['TL_CONFIG']['DAYS'] = array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');
$GLOBALS['TL_CONFIG']['DAYS_SHORT'] = array('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam');
$GLOBALS['TL_CONFIG']['MONTHS'] = array('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre');
$GLOBALS['TL_CONFIG']['MONTHS_SHORT'] = array('Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc');
/**
* -------------------------------------------------------------------------
* RSS SETTINGS
* -------------------------------------------------------------------------
*/
$GLOBALS['TL_CONFIG']['maxResultsPerBlock'] = 50;
$GLOBALS['TL_CONFIG']['enableCache'] = true;
$GLOBALS['TL_CONFIG']['cacheDuration'] = 3600; //~ 1h
$GLOBALS['TL_CONFIG']['RssReaderReferer'] = "RSS-Fusion with SimplePie";
/**