Fix sitemap
Add 24 hour cache Add jobs to sitemap Possible warning about to many eventemitter listeners
This commit is contained in:
@ -1,24 +1,15 @@
|
|||||||
var Rx = require('rx'),
|
import request from 'request';
|
||||||
async = require('async'),
|
import constantStrings from '../utils/constantStrings.json';
|
||||||
moment = require('moment'),
|
import labs from '../resources/labs.json';
|
||||||
request = require('request'),
|
import testimonials from '../resources/testimonials.json';
|
||||||
debug = require('debug')('fcc:cntr:resources'),
|
import secrets from '../../config/secrets';
|
||||||
constantStrings = require('../utils/constantStrings.json'),
|
|
||||||
labs = require('../resources/labs.json'),
|
|
||||||
testimonials = require('../resources/testimonials.json'),
|
|
||||||
secrets = require('../../config/secrets');
|
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
var router = app.loopback.Router();
|
const router = app.loopback.Router();
|
||||||
var User = app.models.User;
|
const User = app.models.User;
|
||||||
var Challenge = app.models.Challenge;
|
|
||||||
var Story = app.models.Story;
|
|
||||||
var Nonprofit = app.models.Nonprofit;
|
|
||||||
|
|
||||||
router.get('/api/github', githubCalls);
|
router.get('/api/github', githubCalls);
|
||||||
router.get('/api/blogger', bloggerCalls);
|
router.get('/api/blogger', bloggerCalls);
|
||||||
router.get('/api/trello', trelloCalls);
|
router.get('/api/trello', trelloCalls);
|
||||||
router.get('/sitemap.xml', sitemap);
|
|
||||||
router.get('/chat', chat);
|
router.get('/chat', chat);
|
||||||
router.get('/coding-bootcamp-cost-calculator', bootcampCalculator);
|
router.get('/coding-bootcamp-cost-calculator', bootcampCalculator);
|
||||||
router.get('/twitch', twitch);
|
router.get('/twitch', twitch);
|
||||||
@ -43,7 +34,6 @@ module.exports = function(app) {
|
|||||||
router.get('/how-nonprofit-projects-work', howNonprofitProjectsWork);
|
router.get('/how-nonprofit-projects-work', howNonprofitProjectsWork);
|
||||||
router.get('/code-of-conduct', codeOfConduct);
|
router.get('/code-of-conduct', codeOfConduct);
|
||||||
router.get('/academic-honesty', academicHonesty);
|
router.get('/academic-honesty', academicHonesty);
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
'/the-fastest-web-page-on-the-internet',
|
'/the-fastest-web-page-on-the-internet',
|
||||||
theFastestWebPageOnTheInternet
|
theFastestWebPageOnTheInternet
|
||||||
@ -51,118 +41,6 @@ module.exports = function(app) {
|
|||||||
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
function sitemap(req, res, next) {
|
|
||||||
var appUrl = 'http://www.freecodecamp.com';
|
|
||||||
var now = moment(new Date()).format('YYYY-MM-DD');
|
|
||||||
|
|
||||||
// TODO(berks): refactor async to rx
|
|
||||||
async.parallel({
|
|
||||||
users: function(callback) {
|
|
||||||
User.find(
|
|
||||||
{
|
|
||||||
where: { username: { nlike: '' } },
|
|
||||||
fields: { username: true }
|
|
||||||
},
|
|
||||||
function(err, users) {
|
|
||||||
if (err) {
|
|
||||||
debug('User err: ', err);
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
Rx.Observable.from(users, null, null, Rx.Scheduler.default)
|
|
||||||
.map(function(user) {
|
|
||||||
return user.username;
|
|
||||||
})
|
|
||||||
.toArray()
|
|
||||||
.subscribe(
|
|
||||||
function(usernames) {
|
|
||||||
callback(null, usernames);
|
|
||||||
},
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
challenges: function(callback) {
|
|
||||||
Challenge.find(
|
|
||||||
{ fields: { name: true } },
|
|
||||||
function(err, challenges) {
|
|
||||||
if (err) {
|
|
||||||
debug('Challenge err: ', err);
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
Rx.Observable.from(challenges, null, null, Rx.Scheduler.default)
|
|
||||||
.map(function(challenge) {
|
|
||||||
return challenge.name;
|
|
||||||
})
|
|
||||||
.toArray()
|
|
||||||
.subscribe(
|
|
||||||
callback.bind(callback, null),
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
stories: function(callback) {
|
|
||||||
Story.find(
|
|
||||||
{ field: { link: true } },
|
|
||||||
function(err, stories) {
|
|
||||||
if (err) {
|
|
||||||
debug('Story err: ', err);
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
Rx.Observable.from(stories, null, null, Rx.Scheduler.default)
|
|
||||||
.map(function(story) {
|
|
||||||
return story.link;
|
|
||||||
})
|
|
||||||
.toArray()
|
|
||||||
.subscribe(
|
|
||||||
callback.bind(callback, null),
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
nonprofits: function(callback) {
|
|
||||||
Nonprofit.find(
|
|
||||||
{ field: { name: true } },
|
|
||||||
function(err, nonprofits) {
|
|
||||||
if (err) {
|
|
||||||
debug('User err: ', err);
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
Rx.Observable.from(nonprofits, null, null, Rx.Scheduler.default)
|
|
||||||
.map(function(nonprofit) {
|
|
||||||
return nonprofit.name;
|
|
||||||
})
|
|
||||||
.toArray()
|
|
||||||
.subscribe(
|
|
||||||
callback.bind(callback, null),
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, function(err, results) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
return process.nextTick(function() {
|
|
||||||
res.header('Content-Type', 'application/xml');
|
|
||||||
res.render('resources/sitemap', {
|
|
||||||
appUrl: appUrl,
|
|
||||||
now: now,
|
|
||||||
users: results.users,
|
|
||||||
challenges: results.challenges,
|
|
||||||
stories: results.stories,
|
|
||||||
nonprofits: results.nonprofits
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function chat(req, res) {
|
function chat(req, res) {
|
||||||
res.redirect('https://gitter.im/FreeCodeCamp/FreeCodeCamp');
|
res.redirect('https://gitter.im/FreeCodeCamp/FreeCodeCamp');
|
||||||
}
|
}
|
||||||
|
64
server/boot/sitemap.js
Normal file
64
server/boot/sitemap.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
import { Scheduler, Observable } from 'rx';
|
||||||
|
import { timeCache, observeQuery } from '../utils/rx';
|
||||||
|
import { dasherize } from '../utils';
|
||||||
|
|
||||||
|
const cacheTimeout = [ 24, 'hours' ];
|
||||||
|
const appUrl = 'https://www.freecodecamp.com';
|
||||||
|
|
||||||
|
// getCachedObservable(
|
||||||
|
// app: ExpressApp,
|
||||||
|
// modelName: String,
|
||||||
|
// nameProp: String,
|
||||||
|
// map: (nameProp: String) => String
|
||||||
|
// ) => Observable[models]
|
||||||
|
function getCachedObservable(app, modelName, nameProp, map) {
|
||||||
|
return observeQuery(
|
||||||
|
app.models[modelName],
|
||||||
|
'find',
|
||||||
|
{ fields: { [nameProp]: true } }
|
||||||
|
)
|
||||||
|
.flatMap(models => {
|
||||||
|
return Observable.from(models, null, null, Scheduler.default);
|
||||||
|
})
|
||||||
|
.filter(model => !!model[nameProp])
|
||||||
|
.map(model => model[nameProp])
|
||||||
|
.map(map ? map : (x) => x)
|
||||||
|
.toArray()
|
||||||
|
::timeCache(cacheTimeout[0], cacheTimeout[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function sitemapRouter(app) {
|
||||||
|
const router = app.loopback.Router();
|
||||||
|
const challenges$ = getCachedObservable(app, 'Challenge', 'dashedName');
|
||||||
|
const stories$ = getCachedObservable(app, 'Story', 'storyLink', dasherize);
|
||||||
|
const jobs$ = getCachedObservable(app, 'Job', 'id');
|
||||||
|
function sitemap(req, res, next) {
|
||||||
|
const now = moment(new Date()).format('YYYY-MM-DD');
|
||||||
|
return Observable.combineLatest(
|
||||||
|
challenges$,
|
||||||
|
stories$,
|
||||||
|
jobs$,
|
||||||
|
(
|
||||||
|
challenges,
|
||||||
|
stories,
|
||||||
|
jobs
|
||||||
|
) => ({ challenges, stories, jobs })
|
||||||
|
)
|
||||||
|
.subscribe(
|
||||||
|
({ challenges, stories, jobs }) => {
|
||||||
|
res.header('Content-Type', 'application/xml');
|
||||||
|
res.render('resources/sitemap', {
|
||||||
|
appUrl,
|
||||||
|
now,
|
||||||
|
challenges,
|
||||||
|
stories,
|
||||||
|
jobs
|
||||||
|
});
|
||||||
|
},
|
||||||
|
next
|
||||||
|
);
|
||||||
|
}
|
||||||
|
router.get('/sitemap.xml', sitemap);
|
||||||
|
app.use(router);
|
||||||
|
}
|
@ -25,15 +25,20 @@ export function saveInstance(instance) {
|
|||||||
// alias saveInstance
|
// alias saveInstance
|
||||||
export const saveUser = saveInstance;
|
export const saveUser = saveInstance;
|
||||||
|
|
||||||
export function observeQuery(Model, method, query) {
|
// observeQuery(Model: Object, methodName: String, query: Any) => Observable
|
||||||
return Rx.Observable.fromNodeCallback(Model[method], Model)(query);
|
export function observeQuery(Model, methodName, query) {
|
||||||
|
return Rx.Observable.fromNodeCallback(Model[methodName], Model)(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// observeMethod(
|
||||||
|
// context: Object, methodName: String
|
||||||
|
// ) => (query: Any) => Observable
|
||||||
export function observeMethod(context, methodName) {
|
export function observeMethod(context, methodName) {
|
||||||
return Rx.Observable.fromNodeCallback(context[methodName], context);
|
return Rx.Observable.fromNodeCallback(context[methodName], context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeChache(amount: Number, unit: String) => Observable
|
// must be bound to an observable instance
|
||||||
|
// timeCache(amount: Number, unit: String) => Observable
|
||||||
export function timeCache(time, unit) {
|
export function timeCache(time, unit) {
|
||||||
const source = this;
|
const source = this;
|
||||||
let cache;
|
let cache;
|
||||||
|
@ -49,24 +49,23 @@ urlset(xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
|
|||||||
lastmod= now
|
lastmod= now
|
||||||
priority= 0.9
|
priority= 0.9
|
||||||
|
|
||||||
//- User
|
|
||||||
each user in users
|
|
||||||
url
|
|
||||||
loc #{appUrl}/#{user}
|
|
||||||
lastmod= now
|
|
||||||
changefreq weekly
|
|
||||||
priority= 0.5
|
|
||||||
|
|
||||||
each challenge in challenges
|
each challenge in challenges
|
||||||
url
|
url
|
||||||
loc #{appUrl}/challenges/#{challenge.replace(/\s/g, '-')}
|
loc #{appUrl}/challenges/#{challenge}
|
||||||
lastmod= now
|
lastmod= now
|
||||||
changefreq weekly
|
changefreq weekly
|
||||||
priority= 0.9
|
priority= 0.9
|
||||||
|
|
||||||
each story in stories
|
each story in stories
|
||||||
url
|
url
|
||||||
loc #{appUrl}/news/#{story.replace(/\s/g, '-')}
|
loc #{appUrl}/news/#{story}
|
||||||
lastmod= now
|
lastmod= now
|
||||||
changefreq weekly
|
changefreq monthly
|
||||||
|
priority= 0.5
|
||||||
|
|
||||||
|
each job in jobs
|
||||||
|
url
|
||||||
|
loc #{appUrl}/jobs/#{job}
|
||||||
|
lastmod= now
|
||||||
|
changefreq monthly
|
||||||
priority= 0.5
|
priority= 0.5
|
||||||
|
Reference in New Issue
Block a user