chore(server): Move api-server in to it's own DIR
This commit is contained in:
committed by
mrugesh mohapatra
parent
9fba6bce4c
commit
46a217d0a5
86
api-server/server/rss/index.js
Normal file
86
api-server/server/rss/index.js
Normal file
@ -0,0 +1,86 @@
|
||||
import _ from 'lodash';
|
||||
import compareDesc from 'date-fns/compare_desc';
|
||||
import debug from 'debug';
|
||||
|
||||
import { getMediumFeed } from './medium';
|
||||
import { getLybsynFeed } from './lybsyn';
|
||||
|
||||
const log = debug('fcc:rss:news-feed');
|
||||
|
||||
const fiveMinutes = 1000 * 60 * 5;
|
||||
|
||||
class NewsFeed {
|
||||
constructor() {
|
||||
|
||||
this.state = {
|
||||
readyState: false,
|
||||
mediumFeed: [],
|
||||
lybsynFeed: [],
|
||||
combinedFeed: []
|
||||
};
|
||||
this.refreshFeeds();
|
||||
|
||||
setInterval(this.refreshFeeds, fiveMinutes);
|
||||
}
|
||||
|
||||
setState = stateUpdater => {
|
||||
const newState = stateUpdater(this.state);
|
||||
this.state = _.merge({}, this.state, newState);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshFeeds = () => {
|
||||
const currentFeed = this.state.combinedFeed.slice(0);
|
||||
log('grabbing feeds');
|
||||
return Promise.all([
|
||||
getMediumFeed(),
|
||||
getLybsynFeed()
|
||||
]).then(
|
||||
([mediumFeed, lybsynFeed]) => this.setState(
|
||||
state => ({
|
||||
...state,
|
||||
mediumFeed,
|
||||
lybsynFeed
|
||||
})
|
||||
))
|
||||
.then(() => {
|
||||
log('crossing the streams');
|
||||
const { mediumFeed, lybsynFeed} = this.state;
|
||||
const combinedFeed = [ ...mediumFeed, ...lybsynFeed ].sort((a, b) => {
|
||||
return compareDesc(a.isoDate, b.isoDate);
|
||||
});
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
combinedFeed,
|
||||
readyState: true
|
||||
}));
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
combinedFeed: currentFeed
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
getFeed = () => new Promise((resolve) => {
|
||||
let notReadyCount = 0;
|
||||
|
||||
function waitForReady() {
|
||||
log('notReadyCount', notReadyCount);
|
||||
notReadyCount++;
|
||||
return this.state.readyState || notReadyCount === 5 ?
|
||||
resolve(this.state.combinedFeed) :
|
||||
setTimeout(waitForReady, 100);
|
||||
}
|
||||
log('are we ready?', this.state.readyState);
|
||||
return this.state.readyState ?
|
||||
resolve(this.state.combinedFeed) :
|
||||
setTimeout(waitForReady, 100);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export default NewsFeed;
|
47
api-server/server/rss/lybsyn.js
Normal file
47
api-server/server/rss/lybsyn.js
Normal file
@ -0,0 +1,47 @@
|
||||
import http from 'http';
|
||||
import _ from 'lodash';
|
||||
|
||||
const lybsynFeed = 'http://freecodecamp.libsyn.com/render-type/json';
|
||||
|
||||
export function getLybsynFeed() {
|
||||
return new Promise((resolve, reject) => {
|
||||
http.get(lybsynFeed, res => {
|
||||
let raw = '';
|
||||
|
||||
res.on('data', chunk => {
|
||||
raw += chunk;
|
||||
});
|
||||
|
||||
res.on('error', err => reject(err));
|
||||
|
||||
res.on('end', () => {
|
||||
let feed = [];
|
||||
|
||||
try {
|
||||
feed = JSON.parse(raw);
|
||||
} catch (err) {
|
||||
return reject(err);
|
||||
}
|
||||
const items = feed.map(
|
||||
item => _.pick(item, [
|
||||
'full_item_url',
|
||||
'item_title',
|
||||
'release_date',
|
||||
'item_body_short'
|
||||
])
|
||||
)
|
||||
/* eslint-disable camelcase */
|
||||
.map(({ full_item_url, item_title, release_date, item_body_short}) => ({
|
||||
title: item_title,
|
||||
extract: item_body_short,
|
||||
isoDate: new Date(release_date).toISOString(),
|
||||
link: full_item_url
|
||||
}));
|
||||
/* eslint-enable camelcase */
|
||||
return resolve(items);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
39
api-server/server/rss/medium.js
Normal file
39
api-server/server/rss/medium.js
Normal file
@ -0,0 +1,39 @@
|
||||
import Parser from 'rss-parser';
|
||||
import _ from 'lodash';
|
||||
|
||||
const parser = new Parser();
|
||||
|
||||
const mediumFeed = 'https://medium.freecodecamp.org/feed';
|
||||
|
||||
function getExtract(str) {
|
||||
return str.slice(0, str.indexOf('</p>') + 4);
|
||||
}
|
||||
|
||||
|
||||
function addResponsiveClass(str) {
|
||||
return str.replace(/\<img/g, '<img class="img-responsive"');
|
||||
}
|
||||
|
||||
export function getMediumFeed() {
|
||||
return new Promise((resolve, reject) => {
|
||||
parser.parseURL(mediumFeed, (err, feed) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
const items = feed.items
|
||||
.map(
|
||||
item => _.pick(item, ['title', 'link', 'isoDate', 'content:encoded'])
|
||||
)
|
||||
.map(
|
||||
(item) => ({
|
||||
...item,
|
||||
extract: getExtract(item['content:encoded'])
|
||||
})
|
||||
)
|
||||
.map(item => _.omit(item, ['content:encoded']))
|
||||
.map(item => ({ ...item, extract: addResponsiveClass(item.extract)}));
|
||||
resolve(items);
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user