/**
* API controller for feed support.
* @module controllers/feeds
* @license MIT
* @author Kai KRETSCHMANN <kai@kretschmann.consulting>
*/
const PackagesService = require('../service/PackagesService');
const log4js = require('log4js');
const logger = log4js.getLogger();
logger.level = process.env.LOGLEVEL || /* istanbul ignore next */ 'warn'; // LCOV_EXCL_LINE
const Feed = require('feed').Feed;
const maxFeedItems = 25;
const maxFeedAge = 30;
const sortItemFeed = 'tsupdated';
const sortDirectionFeed = 'down';
const API_BASE_URL = 'https://api.binarytransparency.net/v1/';
const WEB_URL = 'https://bintra.directory/';
const MY_NAME = 'Kai KRETSCHMANN';
const MY_EMAIL = 'kai@kretschmann.consulting';
const MY_WEB_URL = 'https://kai.kretschmann.consulting';
/**
* generate common meta data object..
* @function getInitialFeed
* @private
*/
function getInitialFeed () {
const myfeed = new Feed({
title: 'Binary Transparency Directory',
description: 'Feed for hash code monitoring',
id: WEB_URL,
link: WEB_URL,
language: 'en', // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
image: WEB_URL + 'image.png',
favicon: WEB_URL + 'favicon.ico',
copyright: 'All rights reserved 2021, ' + MY_NAME,
updated: new Date(),
generator: 'Feed for bintra', // optional, default = 'Feed for Node.js'
feedLinks: {
json: API_BASE_URL + 'feed.json',
rss: API_BASE_URL + 'feed.rss',
atom: API_BASE_URL + 'feed.atom'
},
author: {
name: MY_NAME,
email: MY_EMAIL,
link: MY_WEB_URL
}
});
myfeed.addCategory('Technology');
myfeed.addContributor({
name: MY_NAME,
email: MY_EMAIL,
link: MY_WEB_URL
});
return myfeed;
}
/**
* Show single entry data.
* @function createContent
* @private
*/
function createContent (entry) {
return `Archive ${entry.name}, version ${entry.version} for ${entry.arch}, ${entry.family} with hash ${entry.hash}`;
}
/**
* Reply on error.
* @function replyWithError
* @private
*/
function replyWithError (res, payload) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
return res.end('error ' + payload);
}
/**
* Show feed data in wanted format.
* @function feedRss
* @private
*/
function feedRss (res) {
const rssfeed = getInitialFeed();
PackagesService.listPackages(0, maxFeedItems, sortItemFeed, sortDirectionFeed, maxFeedAge)
.then(function (items) {
items.forEach(function (entry) {
const myid = entry._id;
rssfeed.addItem({
title: entry.name,
id: API_BASE_URL + 'package/' + myid,
link: WEB_URL + 'details/?id=' + myid,
description: entry.name,
date: entry.tsupdated || new Date(),
content: createContent(entry)
});
});
res.writeHead(200, {
'Content-Type': 'application/rss+xml'
});
return res.end(rssfeed.rss2());
})
.catch(function (payload) {
return replyWithError(res, payload); // LCOV_EXCL_LINE
});
}
/**
* Show feed data in wanted format.
* @function feedAtom
* @private
*/
function feedAtom (res) {
const atomfeed = getInitialFeed();
PackagesService.listPackages(0, maxFeedItems, sortItemFeed, sortDirectionFeed, maxFeedAge)
.then(function (items) {
items.forEach(function (entry) {
const myid = entry._id;
atomfeed.addItem({
title: entry.name,
link: API_BASE_URL + 'package/' + myid,
description: entry.name,
date: entry.tsupdated || new Date(),
content: createContent(entry)
});
});
res.writeHead(200, {
'Content-Type': 'application/rss+xml'
});
return res.end(atomfeed.atom1());
})
.catch(function (payload) {
return replyWithError(res, payload); // LCOV_EXCL_LINE
});
}
/**
* Show feed data in wanted format.
* @function feedJson
* @private
*/
function feedJson (res) {
const jsonfeed = getInitialFeed();
PackagesService.listPackages(0, maxFeedItems, sortItemFeed, sortDirectionFeed, maxFeedAge)
.then(function (items) {
items.forEach(function (entry) {
const myid = entry._id;
jsonfeed.addItem({
title: entry.name,
id: entry._id,
link: API_BASE_URL + 'package/' + myid,
description: entry.name,
date: entry.tsupdated || new Date(),
content: createContent(entry)
});
});
res.writeHead(200, {
'Content-Type': 'application/json'
});
return res.end(jsonfeed.json1());
})
.catch(function (payload) {
return replyWithError(res, payload); // LCOV_EXCL_LINE
});
}
/**
* Show feed data in wanted format.
* @function bintraFeed
* @public
*/
module.exports.bintraFeed = function bintraFeed (_req, res, _next, type) {
switch (type) {
case 'rss':
feedRss(res);
break;
case 'atom':
feedAtom(res);
break;
case 'json':
feedJson(res);
break;
default:
logger.error('Wrong type ' + type);
replyWithError(res, 'Wrong type');
break;
}
};