Browse Source

More PubSubHubbub

https://github.com/FreshRSS/FreshRSS/issues/312
Show whether PubSubHubbub is enabled in the Web interface of feed
configuration.
When PubSubHubbub is used, do not pull refresh so often (hard-coded to
max once per 24h for now).
Improved logic for lease renewal, and some detection of lease problems.
Updated read-me and changelog.
Alexandre Alapetite 11 years ago
parent
commit
3adab4b70f

+ 9 - 0
CHANGELOG

@@ -2,6 +2,15 @@
 
 ## 2015-xx-xx FreshRSS 1.1.1 (beta)
 
+* Features
+	* Support for PubSubHubbub for instant notifications from compatible Web sites.
+	* New option to detect and mark updated articles as unread.
+	* Support for internationalized domain name (IDN).
+* Misc.
+	* Improved logic for automatic deletion of old articles.
+	* Attempt to better handle encoded titles.
+
+
 ## 2015-01-31 FreshRSS 1.0.0 / 1.1.0 (beta)
 
 * UI

+ 10 - 12
README.fr.md

@@ -6,6 +6,7 @@ FreshRSS est un agrégateur de flux RSS à auto-héberger à l’image de [Leed]
 Il se veut léger et facile à prendre en main tout en étant un outil puissant et paramétrable.
 
 Il permet de gérer plusieurs utilisateurs, et dispose d’un mode de lecture anonyme.
+Il supporte [PubSubHubbub](https://code.google.com/p/pubsubhubbub/) pour des notifications instantanées depuis les sites compatibles.
 
 * Site officiel : http://freshrss.org
 * Démo : http://demo.freshrss.org/
@@ -14,28 +15,25 @@ Il permet de gérer plusieurs utilisateurs, et dispose d’un mode de lecture an
 ![Logo de FreshRSS](http://marienfressinaud.fr/data/images/freshrss/freshrss_title.png)
 
 # Note sur les branches
-**Ce logiciel est encore en développement !** Veuillez vous assurer d'utiliser la branche qui vous correspond :
+**Ce logiciel est en développement permanent !** Veuillez vous assurer d'utiliser la branche qui vous correspond :
 
 * Utilisez [la branche master](https://github.com/FreshRSS/FreshRSS/tree/master/) si vous visez la stabilité.
 * [La branche beta](https://github.com/FreshRSS/FreshRSS/tree/beta) est celle par défaut : les nouveautés y sont ajoutées environ tous les mois.
-* Pour les développeurs et ceux qui savent ce qu'ils font, [la branche dev](https://github.com/FreshRSS/FreshRSS/tree/dev) vous ouvre les bras !
+* Pour les développeurs et ceux qui veulent aider à tester les toutes dernières fonctionnalités, [la branche dev](https://github.com/FreshRSS/FreshRSS/tree/dev) vous ouvre les bras !
 
 # Disclaimer
-Cette application a été développée pour s’adapter à des besoins personnels et non professionnels.
-Je ne garantis en aucun cas la sécurité de celle-ci, ni son bon fonctionnement.
-Je m’engage néanmoins à répondre dans la mesure du possible aux demandes d’évolution si celles-ci me semblent justifiées.
-Privilégiez pour cela des demandes sur GitHub
-(https://github.com/FreshRSS/FreshRSS/issues).
+Cette application a été développée pour s’adapter principalement à des besoins personnels, et aucune garantie n'est fournie.
+Les demandes de fonctionnalités, rapports de bugs, et autres contributions sont les bienvenues. Privilégiez pour cela des [demandes sur GitHub](https://github.com/FreshRSS/FreshRSS/issues).
 
-# Pré-requis
+# Prérequis
 * Serveur modeste, par exemple sous Linux ou Windows
 	* Fonctionne même sur un Raspberry Pi avec des temps de réponse < 1s (testé sur 150 flux, 22k articles, soit 32Mo de données partiellement compressées)
 * Serveur Web Apache2 (recommandé), ou nginx, lighttpd (non testé sur les autres)
 * PHP 5.2.1+ (PHP 5.3.7+ recommandé)
-	* Requis : [PDO_MySQL](http://php.net/pdo-mysql) ou [PDO_SQLite](http://php.net/pdo-sqlite), [cURL](http://php.net/curl), [GMP](http://php.net/gmp) (pour accès API sur platformes < 64 bits), [IDN](http://php.net/intl.idn) (pour les noms de domaines internationalisés)
+	* Requis : [PDO_MySQL](http://php.net/pdo-mysql) ou [PDO_SQLite](http://php.net/pdo-sqlite), [cURL](http://php.net/curl), [GMP](http://php.net/gmp) (pour accès API sur plateformes < 64 bits), [IDN](http://php.net/intl.idn) (pour les noms de domaines internationalisés)
 	* Recommandés : [JSON](http://php.net/json), [mbstring](http://php.net/mbstring), [zlib](http://php.net/zlib), [Zip](http://php.net/zip)
 * MySQL 5.0.3+ (recommandé) ou SQLite 3.7.4+
-* Un navigateur Web récent tel Firefox 4+, Chrome, Opera, Safari, Internet Explorer 9+
+* Un navigateur Web récent tel Firefox, Chrome, Opera, Safari. [Internet Explorer ne fonctionne plus, mais ce sera corrigé](https://github.com/FreshRSS/FreshRSS/issues/772).
 	* Fonctionne aussi sur mobile
 
 ![Capture d’écran de FreshRSS](http://marienfressinaud.fr/data/images/freshrss/freshrss_default-design.png)
@@ -63,7 +61,7 @@ C’est une bonne idée d’utiliser le même utilisateur que votre serveur Web
 Par exemple, pour exécuter le script toutes les heures :
 
 ```
-7 * * * * php /chemin/vers/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1
+7 * * * * php /votre-chemin/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1
 ```
 
 # Conseils
@@ -75,7 +73,7 @@ Par exemple, pour exécuter le script toutes les heures :
 # Sauvegarde
 * Il faut conserver vos fichiers `./data/config.php` ainsi que `./data/*_user.php` et éventuellement `./data/persona/`
 * Vous pouvez exporter votre liste de flux depuis FreshRSS au format OPML
-* Pour sauvegarder les articles eux-même, vous pouvez utiliser [phpMyAdmin](http://www.phpmyadmin.net) ou les outils de MySQL :
+* Pour sauvegarder les articles eux-mêmes, vous pouvez utiliser [phpMyAdmin](http://www.phpmyadmin.net) ou les outils de MySQL :
 
 ```bash
 mysqldump -u utilisateur -p --databases freshrss > freshrss.sql

+ 16 - 18
README.md

@@ -1,11 +1,12 @@
 * [Version française](README.fr.md)
 
 # FreshRSS
-FreshRSS is a self-hosted RSS feed agregator like [Leed](http://projet.idleman.fr/leed/) or [Kriss Feed](http://tontof.net/kriss/feed/).
+FreshRSS is a self-hosted RSS feed aggregator such as [Leed](http://projet.idleman.fr/leed/) or [Kriss Feed](http://tontof.net/kriss/feed/).
 
-It is at the same time light-weight, easy to work with, powerful and customizable.
+It is at the same time lightweight, easy to work with, powerful and customizable.
 
 It is a multi-user application with an anonymous reading mode.
+It supports [PubSubHubbub](https://code.google.com/p/pubsubhubbub/) for instant notifications from compatible Web sites.
 
 * Official website: http://freshrss.org
 * Demo: http://demo.freshrss.org/
@@ -14,28 +15,25 @@ It is a multi-user application with an anonymous reading mode.
 ![FreshRSS logo](http://marienfressinaud.fr/data/images/freshrss/freshrss_title.png)
 
 # Note on branches
-**This application is still in development!** Please use the branch that suits your needs:
+**This application is under continuous development!** Please use the branch that suits your needs:
 
 * Use [the master branch](https://github.com/FreshRSS/FreshRSS/tree/master/) if you need a stable version.
 * [The beta branch](https://github.com/FreshRSS/FreshRSS/tree/beta) is the default branch: new features are added on a monthly basis.
-* For developers and tech savvy persons, [the dev branch](https://github.com/FreshRSS/FreshRSS/tree/dev) is waiting for you!
+* For developers and tech savvy persons willing to help testing the latest features, [the dev branch](https://github.com/FreshRSS/FreshRSS/tree/dev) is waiting for you!
 
 # Disclaimer
-This application was developed to fulfill personal needs not professional needs.
-There is no guarantee neither on its security nor its proper functioning.
-If there is feature requests which I think are good for the project, I'll do my best to include them.
-The best way is to open issues on GitHub
-(https://github.com/FreshRSS/FreshRSS/issues).
+This application was developed to fulfil personal needs primarily, and comes with absolutely no warranty.
+Feature requests, bug reports, and other contributions are welcome. The best way is to [open issues on GitHub](https://github.com/FreshRSS/FreshRSS/issues).
 
 # Requirements
 * Light server running Linux or Windows
 	* It even works on Raspberry Pi with response time under a second (tested with 150 feeds, 22k articles, or 32Mo of compressed data)
-* A web server: Apache2 (recommanded), nginx, lighttpd (not tested on others)
-* PHP 5.2.1+ (PHP 5.3.7+ recommanded)
+* A web server: Apache2 (recommended), nginx, lighttpd (not tested on others)
+* PHP 5.2.1+ (PHP 5.3.7+ recommended)
 	* Required extensions: [PDO_MySQL](http://php.net/pdo-mysql) or [PDO_SQLite](http://php.net/pdo-sqlite), [cURL](http://php.net/curl), [GMP](http://php.net/gmp) (for API access on platforms < 64 bits), [IDN](http://php.net/intl.idn) (for Internationalized Domain Names)
-	* Recommanded extensions : [JSON](http://php.net/json), [mbstring](http://php.net/mbstring), [zlib](http://php.net/zlib), [Zip](http://php.net/zip)
-* MySQL 5.0.3+ (recommanded) or SQLite 3.7.4+
-* A recent browser like Firefox 4+, Chrome, Opera, Safari, Internet Explorer 9+
+	* Recommended extensions: [JSON](http://php.net/json), [mbstring](http://php.net/mbstring), [zlib](http://php.net/zlib), [Zip](http://php.net/zip)
+* MySQL 5.0.3+ (recommended) or SQLite 3.7.4+
+* A recent browser like Firefox, Chrome, Opera, Safari. [Internet Explorer currently not supported, but support will come back](https://github.com/FreshRSS/FreshRSS/issues/772).
 	* Works on mobile
 
 ![FreshRSS screenshot](http://marienfressinaud.fr/data/images/freshrss/freshrss_default-design.png)
@@ -45,7 +43,7 @@ The best way is to open issues on GitHub
 2. Dump the application on your server (expose only the `./p/` folder)
 3. Add write access on `./data/` folder to the webserver user
 4. Access FreshRSS with your browser and follow the installation process
-5. Every thing should be working :) If you encounter any problem, feel free to contact me.
+5. Everything should be working :) If you encounter any problem, feel free to contact me.
 6. Advanced configuration settings can be seen in [config.php](./data/config.default.php).
 
 # Access control
@@ -59,18 +57,18 @@ It is needed for the multi-user mode to limit access to FreshRSS. You can:
 # Automatic feed update
 * You can add a Cron job to launch the update script.
 Check the Cron documentation related to your distribution ([Debian/Ubuntu](https://help.ubuntu.com/community/CronHowto), [Red Hat/Fedora](https://fedoraproject.org/wiki/Administration_Guide_Draft/Cron), [Slackware](http://docs.slackware.com/fr:slackbook:process_control?#cron), [Gentoo](https://wiki.gentoo.org/wiki/Cron), [Arch Linux](https://wiki.archlinux.org/index.php/Cron)…).
-It’s a good idea to use the web server user .
+It’s a good idea to use the Web server user.
 For example, if you want to run the script every hour:
 
 ```
-7 * * * * php /chemin/vers/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1
+7 * * * * php /your-path/FreshRSS/app/actualize_script.php > /tmp/FreshRSS.log 2>&1
 ```
 
 # Advices
 * For a better security, expose only the `./p/` folder on the web.
 	* Be aware that the `./data/` folder contains all personal data, so it is a bad idea to expose it.
 * The `./constants.php` file defines access to application folder. If you want to customize your installation, every thing happens here.
-* If you encounter any problem, logs are accessibles from the interface or manually in `./data/log/*.log` files.
+* If you encounter any problem, logs are accessible from the interface or manually in `./data/log/*.log` files.
 
 # Backup
 * You need to keep `./data/config.php`, `./data/*_user.php` and `./data/persona/` files

+ 24 - 12
app/Controllers/feedController.php

@@ -268,7 +268,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
 	 * If id and url are not specified, all the feeds are actualized. But if force is
 	 * false, process stops at 10 feeds to avoid time execution problem.
 	 */
-	public function actualizeAction($simplePie = null) {
+	public function actualizeAction($simplePiePush = null) {
 		@set_time_limit(300);
 
 		$feedDAO = FreshRSS_Factory::createFeedDao();
@@ -295,10 +295,16 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
 		// Calculate date of oldest entries we accept in DB.
 		$nb_month_old = max(FreshRSS_Context::$user_conf->old_entries, 1);
 		$date_min = time() - (3600 * 24 * 30 * $nb_month_old);
+		$pshbMinAge = time() - (3600 * 24);	//TODO: Make a configuration.
 
 		$updated_feeds = 0;
 		$is_read = FreshRSS_Context::$user_conf->mark_when['reception'] ? 1 : 0;
 		foreach ($feeds as $feed) {
+			$pubSubHubbubEnabled = $feed->pubSubHubbubEnabled();
+			if ((!$simplePiePush) && (!$id) && (!$force) && $pubSubHubbubEnabled && ($feed->lastUpdate() > $pshbMinAge)) {
+				continue;	//When PubSubHubbub is used, do not pull refresh so often
+			}
+
 			if (!$feed->lock()) {
 				Minz_Log::notice('Feed already being actualized: ' . $feed->url());
 				continue;
@@ -306,8 +312,8 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
 
 			$url = $feed->url();	//For detection of HTTP 301
 			try {
-				if ($simplePie) {
-					$feed->loadEntries($simplePie);	//Used by PubSubHubbub
+				if ($simplePiePush) {
+					$feed->loadEntries($simplePiePush);	//Used by PubSubHubbub
 				} else {
 					$feed->load(false);
 				}
@@ -374,6 +380,14 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
 							continue;
 						}
 
+						if ($pubSubHubbubEnabled && !$simplePiePush) {	//We use push, but have discovered an article by pull!
+							$text = 'An article was discovered by pull although we use PubSubHubbub!: Feed ' . $url . ' GUID ' . $entry->guid();
+							file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" . $text . "\n", FILE_APPEND);
+							Minz_Log::warning($text);
+							$pubSubHubbubEnabled = false;
+							$feed->pubSubHubbubEnabled(false);	//To force the renewal of our lease
+						}
+
 						if (!$entryDAO->hasTransaction()) {
 							$entryDAO->beginTransaction();
 						}
@@ -423,15 +437,13 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
 				$feedDAO->updateFeed($feed->id(), array('url' => $feed->url()));
 			}
 
-			if ($simplePie === null) {
-				$feed->faviconPrepare();
-				if (in_array($feed->url(), array('http://push-pub.appspot.com/feed'))) {	//TODO: Remove white-list after testing
-					Minz_Log::debug('PubSubHubbub match ' . $feed->url());
-					if ($feed->pubSubHubbubPrepare()) {
-						Minz_Log::notice('PubSubHubbub subscribe ' . $feed->url());
-						if (!$feed->pubSubHubbubSubscribe(true)) {	//Subscribe
-							Minz_Log::warning('Error while PubSubHubbub subscribing to ' . $feed->url());
-						}
+			$feed->faviconPrepare();
+			if (in_array($feed->url(), array('http://push-pub.appspot.com/feed'))) {	//TODO: Remove white-list after testing
+				Minz_Log::debug('PubSubHubbub match ' . $feed->url());
+				if ($feed->pubSubHubbubPrepare()) {
+					Minz_Log::notice('PubSubHubbub subscribe ' . $feed->url());
+					if (!$feed->pubSubHubbubSubscribe(true)) {	//Subscribe
+						Minz_Log::warning('Error while PubSubHubbub subscribing to ' . $feed->url());
 					}
 				}
 			}

+ 50 - 9
app/Models/Feed.php

@@ -104,6 +104,16 @@ class FreshRSS_Feed extends Minz_Model {
 	public function ttl() {
 		return $this->ttl;
 	}
+	// public function ttlExpire() {
+		// $ttl = $this->ttl;
+		// if ($ttl == -2) {	//Default
+			// $ttl = FreshRSS_Context::$user_conf->ttl_default;
+		// }
+		// if ($ttl == -1) {	//Never
+			// $ttl = 64000000;	//~2 years. Good enough for PubSubHubbub logic
+		// }
+		// return $this->lastUpdate + $ttl;
+	// }
 	public function nbEntries() {
 		if ($this->nbEntries < 0) {
 			$feedDAO = FreshRSS_Factory::createFeedDao();
@@ -349,18 +359,42 @@ class FreshRSS_Feed extends Minz_Model {
 
 	//<PubSubHubbub>
 
+	function pubSubHubbubEnabled($keep = true) {
+		$url = $this->selfUrl ? $this->selfUrl : $this->url;
+		$hubFilename = PSHB_PATH . '/feeds/' . base64url_encode($url) . '/!hub.json';
+		if ($hubFile = @file_get_contents($hubFilename)) {
+			$hubJson = json_decode($hubFile, true);
+			if (!$keep) {
+				$hubJson['lease_end'] = time() - 60;
+				file_put_contents($hubFilename, json_encode($hubJson));
+				file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t"
+					. 'Force expire lease for ' . $url . "\n", FILE_APPEND);
+			} elseif ($hubJson && (empty($hubJson['lease_end']) || $hubJson['lease_end'] > time())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
 	function pubSubHubbubPrepare() {
 		$key = '';
 		if (FreshRSS_Context::$system_conf->base_url && $this->hubUrl && $this->selfUrl) {
 			$path = PSHB_PATH . '/feeds/' . base64url_encode($this->selfUrl);
-			if ($hubFile = @file_get_contents($path . '/!hub.json')) {
+			$hubFilename = $path . '/!hub.json';
+			if ($hubFile = @file_get_contents($hubFilename)) {
 				$hubJson = json_decode($hubFile, true);
 				if (!$hubJson || empty($hubJson['key']) || !ctype_xdigit($hubJson['key'])) {
-					Minz_Log::warning('Invalid JSON for PubSubHubbub: ' . $this->url);
+					$text = 'Invalid JSON for PubSubHubbub: ' . $this->url;
+					Minz_Log::warning($text);
+					file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" . $text . "\n", FILE_APPEND);
 					return false;
 				}
-				if (empty($hubJson['lease_end']) || $hubJson['lease_end'] <= time()) {
-					Minz_Log::warning('PubSubHubbub lease expired: ' . $this->url);
+				if (empty($hubJson['lease_end']) || ($hubJson['lease_end'] <= (time() + (3600 * 24)))) {	//TODO: Make a better policy
+					$text = 'PubSubHubbub lease ends at '
+						. date('c', empty($hubJson['lease_end']) ? time() : $hubJson['lease_end'])
+						. ' and needs renewal: ' . $this->url;
+					Minz_Log::warning($text);
+					file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" . $text . "\n", FILE_APPEND);
 					$key = $hubJson['key'];	//To renew our lease
 				}
 			} else {
@@ -370,12 +404,12 @@ class FreshRSS_Feed extends Minz_Model {
 					'hub' => $this->hubUrl,
 					'key' => $key,
 				);
-				file_put_contents($path . '/!hub.json', json_encode($hubJson));
+				file_put_contents($hubFilename, json_encode($hubJson));
 				@mkdir(PSHB_PATH . '/keys/');
 				file_put_contents(PSHB_PATH . '/keys/' . $key . '.txt', base64url_encode($this->selfUrl));
-				Minz_Log::debug('PubSubHubbub prepared for ' . $this->url);
-				file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" .
-					'PubSubHubbub prepared for ' . $this->url . "\n", FILE_APPEND);
+				$text = 'PubSubHubbub prepared for ' . $this->url;
+				Minz_Log::debug($text);
+				file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" . $text . "\n", FILE_APPEND);
 			}
 			$currentUser = Minz_Session::param('currentUser');
 			if (ctype_alnum($currentUser) && !file_exists($path . '/' . $currentUser . '.txt')) {
@@ -388,7 +422,8 @@ class FreshRSS_Feed extends Minz_Model {
 	//Parameter true to subscribe, false to unsubscribe.
 	function pubSubHubbubSubscribe($state) {
 		if (FreshRSS_Context::$system_conf->base_url && $this->hubUrl && $this->selfUrl) {
-			$hubFile = @file_get_contents(PSHB_PATH . '/feeds/' . base64url_encode($this->selfUrl) . '/!hub.json');
+			$hubFilename = PSHB_PATH . '/feeds/' . base64url_encode($this->selfUrl) . '/!hub.json';
+			$hubFile = @file_get_contents($hubFilename);
 			if ($hubFile === false) {
 				Minz_Log::warning('JSON not found for PubSubHubbub: ' . $this->url);
 				return false;
@@ -421,6 +456,12 @@ class FreshRSS_Feed extends Minz_Model {
 			file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" .
 				'PubSubHubbub ' . ($state ? 'subscribe' : 'unsubscribe') . ' to ' . $this->selfUrl .
 				' with callback ' . $callbackUrl . ': ' . $info['http_code'] . ' ' . $response . "\n", FILE_APPEND);
+
+			if (!$state) {	//unsubscribe
+				$hubJson['lease_end'] = time() - 60;
+				file_put_contents($hubFilename, json_encode($hubJson));
+			}
+
 			return substr($info['http_code'], 0, 1) == '2';
 		}
 		return false;

+ 1 - 0
app/i18n/cz/conf.php

@@ -84,6 +84,7 @@ return array(
 		'articles_per_page' => 'Počet článků na stranu',
 		'auto_load_more' => 'Načítat další články dole na stránce',
 		'auto_remove_article' => 'Po přečtení články schovat',
+		'mark_updated_article_unread' => 'Označte aktualizované položky jako nepřečtené',
 		'confirm_enabled' => 'Vyžadovat potvrzení pro akci “označit vše jako přečtené”',
 		'display_articles_unfolded' => 'Ve výchozím stavu zobrazovat články otevřené',
 		'display_categories_unfolded' => 'Ve výchozím stavu zobrazovat kategorie zavřené',

+ 1 - 0
app/i18n/cz/sub.php

@@ -37,6 +37,7 @@ return array(
 		'url' => 'URL kanálu',
 		'validator' => 'Zkontrolovat platnost kanálu',
 		'website' => 'URL webové stránky',
+		'pubsubhubbub' => 'Okamžité oznámení s PubSubHubbub',
 	),
 	'import_export' => array(
 		'export' => 'Export',

+ 1 - 0
app/i18n/de/sub.php

@@ -37,6 +37,7 @@ return array(
 		'url' => 'Feed-URL',
 		'validator' => 'Überprüfen Sie die Gültigkeit des Feeds',
 		'website' => 'Webseiten-URL',
+		'pubsubhubbub' => 'Sofortige Benachrichtigung mit PubSubHubbub',
 	),
 	'import_export' => array(
 		'export' => 'Exportieren',

+ 1 - 0
app/i18n/en/sub.php

@@ -37,6 +37,7 @@ return array(
 		'url' => 'Feed URL',
 		'validator' => 'Check the validity of the feed',
 		'website' => 'Website URL',
+		'pubsubhubbub' => 'Instant notification with PubSubHubbub',
 	),
 	'import_export' => array(
 		'export' => 'Export',

+ 1 - 0
app/i18n/fr/sub.php

@@ -37,6 +37,7 @@ return array(
 		'url' => 'URL du flux',
 		'validator' => 'Vérifier la valididé du flux',
 		'website' => 'URL du site',
+		'pubsubhubbub' => 'Notification instantanée par PubSubHubbub',
 	),
 	'import_export' => array(
 		'export' => 'Exporter',

+ 8 - 0
app/views/helpers/feed/update.phtml

@@ -126,6 +126,14 @@
 				?></select>
 			</div>
 		</div>
+		<div class="form-group">
+			<label class="group-name" for="pubsubhubbub"><?php echo _t('sub.feed.pubsubhubbub'); ?></label>
+			<div class="group-controls">
+				<label class="checkbox" for="pubsubhubbub">
+					<input type="checkbox" name="pubsubhubbub" id="pubsubhubbub" disabled="disabled" value="1"<?php echo $this->feed->pubSubHubbubEnabled() ? ' checked="checked"' : ''; ?> />
+				</label>
+			</div>
+		</div>
 		<div class="form-group form-actions">
 			<div class="group-controls">
 				<button class="btn btn-important"><?php echo _t('gen.action.submit'); ?></button>

+ 1 - 1
data/users/_/config.default.php

@@ -25,7 +25,7 @@ return array (
 
 	# In the case an article has changed (e.g. updated content):
 	#	Set to `true` to mark it unread, or `false` to leave it as-is.
-	'mark_updated_article_unread' => false,
+	'mark_updated_article_unread' => false, //TODO: -1 => ignore, 0 => update, 1 => update and mark as unread
 
 	'sort_order' => 'DESC',
 	'anon_access' => false,

+ 5 - 3
p/api/pshb.php

@@ -57,8 +57,10 @@ if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] === 'subscribe') {
 	$leaseSeconds = empty($_REQUEST['hub_lease_seconds']) ? 0 : intval($_REQUEST['hub_lease_seconds']);
 	if ($leaseSeconds > 60) {
 		$hubJson['lease_end'] = time() + $leaseSeconds;
-		file_put_contents('./!hub.json', json_encode($hubJson));
+	} else {
+		unset($hubJson['lease_end']);
 	}
+	file_put_contents('./!hub.json', json_encode($hubJson));
 	exit(isset($_REQUEST['hub_challenge']) ? $_REQUEST['hub_challenge'] : '');
 }
 
@@ -84,7 +86,7 @@ $self = isset($links[0]) ? $links[0] : null;
 
 if ($self !== base64url_decode($canonical64)) {
 	//header('HTTP/1.1 422 Unprocessable Entity');
-	logMe('Warning: Self URL ' . $self . ' does not match registered canonical URL!: ' . base64url_decode($canonical64));
+	logMe('Warning: Self URL [' . $self . '] does not match registered canonical URL!: ' . base64url_decode($canonical64));
 	//die('Self URL does not match registered canonical URL!');
 	$self = base64url_decode($canonical64);
 }
@@ -120,5 +122,5 @@ if ($nb === 0) {
 	die('Nobody is subscribed to this feed anymore after all!');
 }
 
-logMe($self . ' done: ' . $nb);
+logMe('PubSubHubbub ' . $self . ' done: ' . $nb);
 exit('Done: ' . $nb . "\n");