Commit 7bb1eb7d authored by yPhil's avatar yPhil
Browse files

Slowly recovering

- The whole favicon Promise was broken
- Now saving tabs only when the last feed is loaded
- Console messages regarding favicons
parent 37344d6c
Pipeline #420824 failed with stage
in 47 seconds
......@@ -16,8 +16,6 @@ PTL.feed = {
onerror: "this.onerror=null;this.src='/static/images/rss.gif';"
})
.on("error", function(error) {
// console.error('Fav1: %s (%s)', error, url);
// $(this).attr('src', '/static/images/rss.gif');
$(this).parent().parent().children('div.dataStore').data('iconhash', '');
PTL.tab.saveTabs();
});
......@@ -90,11 +88,11 @@ PTL.feed = {
.attr('class', 'feed-control translate icon-refresh feedRefresh')
.data('title', 'Refresh this feed', url)
.attr('title', PTL.tr('Refresh this feed', url))
.click(async function() {
.click(function() {
// var plop = $(this).parent().parent().parent().next('div.feedBody').find('li').lengh;
$('.selected').removeClass('selected');
$('.icon-checked').toggleClass('icon-checked icon-checkbox');
await PTL.feed.populate($(this), progress);
PTL.feed.populate($(this), progress).then().catch(e => {console.log('whoap: %s (%s)', e);});
});
const $feedControls = $('<div>')
......@@ -473,7 +471,6 @@ PTL.feed = {
fetchIcon: function(feedHost) {
return new Promise((resolve, reject) => {
$.get("/favicon", {
url: decodeURI(feedHost),
dataType: "json"
......@@ -505,7 +502,7 @@ PTL.feed = {
});
},
populate: async function($button, progress, newLimit) {
populate: async function($button, progress) {
const $dataStore = $button.parent().parent(),
$refreshButton = $dataStore.find('i.feedRefresh.icon-refresh').addClass('spin'),
......@@ -542,23 +539,21 @@ PTL.feed = {
.addClass('folded');
}
// if (feedIconHash) {
// $favIcon.attr('src', '/favicons/' + feedIconHash + '.favicon');
// } else {
// await PTL.feed.fetchIcon(feedHost).then((iconhash) => {
// if (iconhash) {
// $favIcon.attr('src', '/favicons/' + iconhash + '.favicon');
// $dataStore.data('iconhash', iconhash);
// PTL.tab.saveTabs();
// }
// }).catch((error) => {
// console.log('Fav: %s (%s)', JSON.stringify(error), feedUrl);
// $favIcon.addClass('icon-rss');
// });
// }
if (feedIconHash) {
$favIcon.attr('src', '/favicons/' + feedIconHash + '.favicon');
} else {
PTL.feed.fetchIcon(feedHost)
.then(hash => {
// PTL.util.say(PTL.tr('New icon in cache') + ' (' + hash + '.favicon / ' + feedHost + ')', 'success');
$favIcon.attr('src', '/favicons/' + hash + '.favicon');
$dataStore.data('iconhash', hash);
PTL.tab.saveTabs();
})
.catch(e => {
PTL.util.say(PTL.tr('Error fetching icon') + ' (' + feedHost + ')' , 'warning');
});
}
if ($dataStore.data('status') == 'on') {
......@@ -613,6 +608,8 @@ PTL.feed = {
}
if (progress) progress.increment();
return true;
}
......
......@@ -86,9 +86,11 @@ PTL.i18n.translations = {
"How many new items should this feed display at a time?" : { fr: "Combien de nouveaux articles dans ce flux ?", ja: "フィードは一度にいくつ表示する必要がありますか?", es: "¿Cuántos elementos nuevos debería mostrar el feed a la vez?" },
"Tabs and feeds saved" : { fr: "Onglets et flux enregistrés" , ja: "タブとソースが保存されました", es: "Pestañas y fuentes guardadas" },
"New icon in cache" : { fr: "Nouvelle icône dans le cache" , ja: "キャッシュの新しいアイコン", es: "Nuevo icono en caché" },
"Tabs and feeds saved" : { fr: "Onglets et flux enregistrés" , ja: "タブとソースが保存されました", es: "Pestañas y fuentes guardadas" },
"Error fetching icon" : { fr: "Erreur au téléchargement de l'icône" , ja: "アイコンのフェッチエラー", es: "Error al buscar icono" },
"Theme" : { fr: "Thème" , ja: "テーマ", es: "Tema" },
"Language" : { fr: "Langue" , ja: "言語", es: "Idioma" },
......
......@@ -453,6 +453,8 @@ PTL.util = {
value: 1,
complete: function() {
$progressLabel.addClass('on');
PTL.tab.saveTabs();
console.log('SAVED: %s (%s)');
}
});
......
const fetch = require('node-fetch'),
iconv = require('iconv-lite'),
FeedParser = require('feedparser');
const fetch = require('node-fetch'),
iconv = require('iconv-lite'),
FeedParser = require('feedparser');
exports.getFeed = getFeed;
......@@ -29,14 +29,14 @@ function getParams(str) {
return params;
}
function formatError (error) {
function formatError(error) {
let message = (error.message) ? error.message : 'Can\'t read this feed';
let type = (error.type) ? error.type : 'Unknown type';
let status = (error.status && Number.isInteger(error.status)) ? error.status : 400;
return { type: type, status: status, message: message };
return { type: type, status: status, message: message };
}
function getFeed(feedUrl, lastItem, callback) {
......@@ -46,10 +46,9 @@ function getFeed(feedUrl, lastItem, callback) {
'accept': 'text/html,application/xhtml+xml',
redirect: 'follow'
}).then(function(res) {
if (res.status != 200) {
reject();
callback(formatError({type:'Network error', status:res.status, message:'Bad server response'}));
callback(formatError({ type: 'Network error', status: res.status, message: 'Bad server response' }));
}
var feedparser = new FeedParser();
......@@ -59,59 +58,51 @@ function getFeed(feedUrl, lastItem, callback) {
responseStream = maybeTranslate(responseStream, charset);
responseStream.pipe(feedparser);
return new Promise((resolve, reject) => {
feedparser.on('error', function(error) {
feedparser.on('error', function(error) {
reject();
callback(formatError(error));
}).on('readable', function() {
try {
var item = this.read();
if (item !== null) {
feedItems.push(item);
}
}
catch (error) {
reject();
callback(formatError(error));
}
}).on('end', function() {
callback(formatError(error));
}).on('readable', function() {
if (feedItems.length === 0) {
reject();
callback(formatError({type:'Empty feed', status:300, message:'Feed OK, but empty'}));
try {
var item = this.read();
if (item !== null) {
feedItems.push(item);
}
resolve();
}
catch (error) {
callback(formatError(error));
}
var newLastItem;
var totalNewItems;
var i = 0;
}).on('end', function() {
feedItems.forEach(countItems);
if (feedItems.length === 0) {
callback(formatError({ type: 'Empty feed', status: 300, message: 'Feed OK, but empty' }));
}
function countItems(item) {
i++;
if (newLastItem == undefined) newLastItem = item.link;
if (item.link == lastItem) totalNewItems = i - 1;
}
var newLastItem;
var totalNewItems;
var i = 0;
feedItems.forEach(countItems);
if (totalNewItems == undefined) totalNewItems = i;
function countItems(item) {
i++;
if (newLastItem == undefined) newLastItem = item.link;
if (item.link == lastItem) totalNewItems = i - 1;
}
const meta = this.meta;
return callback(null, feedItems, meta.title || feedUrl, meta.link || feedUrl, newLastItem, totalNewItems);
if (totalNewItems == undefined) totalNewItems = i;
});
const meta = this.meta;
return callback(null, feedItems, meta.title || feedUrl, meta.link || feedUrl, newLastItem, totalNewItems);
});
}).catch((error) => {
// callback(formatError(error));
callback(formatError({type:'Network problem', status:300, message: error.message || 'Network problem'}));
callback(formatError({ type: 'Network problem', status: 300, message: error.message || 'Network problem' }));
});
......
......@@ -17,45 +17,41 @@ console.error('### (re)START ## Version (%s)', pjson.version);
router.use(sanitize);
const downloadFile = (async (url, path) => {
const res = await fetch(url);
const fileStream = fs.createWriteStream(path);
await new Promise((resolve, reject) => {
res.body.pipe(fileStream);
res.body.on("error", reject);
fileStream.on("finish", resolve);
});
});
router.get('/favicon', function(req, res) {
favrat(req.query.url, function(err, url) {
favrat(req.query.url, function(error, url) {
if (err) console.error('######### err: %s (%s)', err);
if (url) {
if (error) {
console.erroror('######### error: %s (%s)', error);
res.status(500).send(error);
} else if (url) {
console.error('######### url: %s (%s)',url);
if (!url.startsWith('http') || !url.startsWith('//')) url = 'http://' + url.substring(url.indexOf("/") + 1);
// if (!url.startsWith('http') || !url.startsWith('//')) url = 'http://' + url.substring(url.indexOf("/") + 1);
const hash = crypto.createHash('md5').update(url).digest('hex'),
fileName = hash + '.favicon',
filePath = path.join(pjson.FAVICONS_CACHE_DIR, fileName);
// res.send(hash);
fetch(url)
.then(
res =>
new Promise((resolve, reject) => {
const dest = fs.createWriteStream(filePath, {'Content-Type': 'image/x-icon'});
res.body.pipe(dest);
res.body.on("end", () => {
resolve({fileName, url});
});
dest.on("error", () => {
reject('No favicon found');
res.status(500).send(false);
});
})
).catch(error => {
res.status(500).send(error);
});
downloadFile(url, filePath);
} else {
res.status(500).send(false);
res.send(hash);
// } else {
// res.status(500).send(false);
}
});
});
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment