2015-03-17 21:09:54 -07:00
var async = require ( 'async' ) ,
2015-03-28 17:38:11 +09:00
User = require ( '../models/User' ) ,
Challenge = require ( './../models/Challenge' ) ,
Story = require ( './../models/Story' ) ,
2015-04-08 17:18:51 -07:00
FieldGuide = require ( './../models/FieldGuide' ) ,
2015-03-30 20:08:29 -07:00
Nonprofit = require ( './../models/Nonprofit' ) ,
2015-03-28 17:38:11 +09:00
Comment = require ( './../models/Comment' ) ,
resources = require ( './resources.json' ) ,
secrets = require ( './../config/secrets' ) ,
2015-03-30 20:08:29 -07:00
nonprofits = require ( '../seed_data/nonprofits.json' ) ,
2015-04-08 17:18:51 -07:00
fieldGuides = require ( '../seed_data/field-guides.json' ) ,
2015-03-28 17:38:11 +09:00
moment = require ( 'moment' ) ,
2015-04-29 08:00:57 -04:00
Twit = require ( 'twit' ) ,
2015-03-28 17:38:11 +09:00
https = require ( 'https' ) ,
debug = require ( 'debug' ) ( 'freecc:cntr:resources' ) ,
cheerio = require ( 'cheerio' ) ,
request = require ( 'request' ) ,
2015-05-16 00:39:43 -04:00
R = require ( 'ramda' ) ,
2015-05-18 22:03:27 -04:00
_ = require ( 'lodash' ) ,
fs = require ( 'fs' ) ;
2014-12-10 20:44:33 -08:00
2015-04-24 13:13:50 -04:00
/ * *
* Cached values
* /
2015-05-20 22:45:19 -04:00
var allFieldGuideIds , allFieldGuideNames , allNonprofitNames ,
2015-05-19 22:31:01 -04:00
allBonfireIndexesAndNames , challengeMap , challengeMapWithIds ,
2015-05-20 13:07:41 -04:00
challengeMapWithNames , allChallengeIds , allChallenges ;
2015-04-24 13:13:50 -04:00
2014-11-10 10:29:16 -08:00
/ * *
* GET /
* Resources .
* /
2014-12-26 00:05:00 -08:00
2015-03-21 16:34:06 +09:00
Array . zip = function ( left , right , combinerFunction ) {
var counter ,
results = [ ] ;
for ( counter = 0 ; counter < Math . min ( left . length , right . length ) ; counter ++ ) {
2015-03-28 17:38:11 +09:00
results . push ( combinerFunction ( left [ counter ] , right [ counter ] ) ) ;
2015-03-21 16:34:06 +09:00
}
return results ;
} ;
2015-05-19 22:31:01 -04:00
( function ( ) {
if ( ! challengeMap ) {
var localChallengeMap = { } ;
var files = fs . readdirSync ( _ _dirname + '/../seed_data/challenges' ) ;
var keyCounter = 0 ;
files = files . map ( function ( file ) {
return require ( _ _dirname +
'/../seed_data/challenges/' + file ) ;
} ) ;
files = files . sort ( function ( a , b ) {
return a . order - b . order ;
} ) ;
files . forEach ( function ( file ) {
localChallengeMap [ keyCounter ++ ] = file ;
} ) ;
challengeMap = _ . cloneDeep ( localChallengeMap ) ;
}
} ) ( ) ;
2015-05-18 21:20:32 -04:00
2014-12-23 08:48:28 -08:00
module . exports = {
2015-05-18 21:20:32 -04:00
2015-05-16 00:39:43 -04:00
getChallengeMapWithIds : function ( ) {
2015-05-20 13:07:41 -04:00
if ( ! challengeMapWithIds ) {
2015-05-19 22:31:01 -04:00
challengeMapWithIds = { } ;
Object . keys ( challengeMap ) . forEach ( function ( key ) {
var onlyIds = challengeMap [ key ] . challenges . map ( function ( elem ) {
return elem . _id ;
2015-05-16 00:39:43 -04:00
} ) ;
challengeMapWithIds [ key ] = onlyIds ;
} ) ;
2015-05-19 22:31:01 -04:00
}
2015-05-20 13:07:41 -04:00
return challengeMapWithIds ;
2015-05-16 00:39:43 -04:00
} ,
2015-05-19 22:31:01 -04:00
allChallengeIds : function ( ) {
2015-05-20 13:07:41 -04:00
if ( ! allChallengeIds ) {
2015-05-19 22:31:01 -04:00
allChallengeIds = [ ] ;
2015-05-20 13:07:41 -04:00
Object . keys ( this . getChallengeMapWithIds ( ) ) . forEach ( function ( key ) {
2015-05-20 00:38:25 -04:00
allChallengeIds . push ( challengeMapWithIds [ key ] ) ;
2015-05-16 00:39:43 -04:00
} ) ;
2015-05-19 22:31:01 -04:00
allChallengeIds = R . flatten ( allChallengeIds ) ;
}
return allChallengeIds ;
2015-05-16 00:39:43 -04:00
} ,
2015-05-20 13:07:41 -04:00
allChallenges : function ( ) {
if ( ! allChallenges ) {
allChallenges = [ ] ;
Object . keys ( this . getChallengeMapWithNames ( ) ) . forEach ( function ( key ) {
allChallenges . push ( challengeMap [ key ] . challenges ) ;
} ) ;
allChallenges = R . flatten ( allChallenges ) ;
}
return allChallenges ;
} ,
2015-05-19 22:31:01 -04:00
getChallengeMapWithNames : function ( ) {
2015-05-20 13:07:41 -04:00
if ( ! challengeMapWithNames ) {
2015-05-19 22:31:01 -04:00
challengeMapWithNames = { } ;
Object . keys ( challengeMap ) .
forEach ( function ( key ) {
var onlyNames = challengeMap [ key ] . challenges . map ( function ( elem ) {
return elem . name ;
} ) ;
challengeMapWithNames [ key ] = onlyNames ;
} ) ;
}
2015-05-20 13:07:41 -04:00
return challengeMapWithNames ;
2015-05-19 22:31:01 -04:00
} ,
2015-05-16 00:39:43 -04:00
2015-03-28 17:38:11 +09:00
sitemap : function sitemap ( req , res , next ) {
var appUrl = 'http://www.freecodecamp.com' ;
var now = moment ( new Date ( ) ) . format ( 'YYYY-MM-DD' ) ;
2015-04-24 13:13:50 -04:00
async . parallel ( {
2015-04-24 18:57:55 -04:00
users : function ( callback ) {
User . aggregate ( )
. group ( { _id : 1 , usernames : { $addToSet : '$profile.username' } } )
. match ( { 'profile.username' : { $ne : '' } } )
. exec ( function ( err , users ) {
if ( err ) {
debug ( 'User err: ' , err ) ;
callback ( err ) ;
} else {
callback ( null , users [ 0 ] . usernames ) ;
}
} ) ;
} ,
2015-04-24 13:13:50 -04:00
challenges : function ( callback ) {
2015-05-20 22:45:19 -04:00
Challenge . aggregate ( )
2015-04-24 18:57:55 -04:00
. group ( { _id : 1 , names : { $addToSet : '$name' } } )
. exec ( function ( err , challenges ) {
if ( err ) {
2015-05-20 22:45:19 -04:00
debug ( 'Challenge err: ' , err ) ;
2015-04-24 18:57:55 -04:00
callback ( err ) ;
} else {
callback ( null , challenges [ 0 ] . names ) ;
}
} ) ;
2015-04-24 13:13:50 -04:00
} ,
stories : function ( callback ) {
2015-04-24 18:57:55 -04:00
Story . aggregate ( )
. group ( { _id : 1 , links : { $addToSet : '$link' } } )
. exec ( function ( err , stories ) {
2015-04-24 13:13:50 -04:00
if ( err ) {
debug ( 'Story err: ' , err ) ;
callback ( err ) ;
} else {
2015-04-24 18:57:55 -04:00
callback ( null , stories [ 0 ] . links ) ;
2015-04-24 13:13:50 -04:00
}
} ) ;
} ,
nonprofits : function ( callback ) {
2015-04-24 18:57:55 -04:00
Nonprofit . aggregate ( )
. group ( { _id : 1 , names : { $addToSet : '$name' } } )
. exec ( function ( err , nonprofits ) {
2015-03-06 00:13:58 -08:00
if ( err ) {
2015-03-28 17:38:11 +09:00
debug ( 'User err: ' , err ) ;
2015-04-24 13:13:50 -04:00
callback ( err ) ;
} else {
2015-04-24 18:57:55 -04:00
callback ( null , nonprofits [ 0 ] . names ) ;
2015-03-06 00:13:58 -08:00
}
2015-03-28 17:38:11 +09:00
} ) ;
2015-04-24 13:13:50 -04:00
} ,
fieldGuides : function ( callback ) {
2015-04-24 18:57:55 -04:00
FieldGuide . aggregate ( )
. group ( { _id : 1 , names : { $addToSet : '$name' } } )
. exec ( function ( err , fieldGuides ) {
2015-04-24 13:13:50 -04:00
if ( err ) {
debug ( 'User err: ' , err ) ;
callback ( err ) ;
} else {
2015-04-24 18:57:55 -04:00
callback ( null , fieldGuides [ 0 ] . names ) ;
2015-04-24 13:13:50 -04:00
}
} ) ;
}
} , function ( err , results ) {
if ( err ) {
return next ( err ) ;
} else {
setTimeout ( function ( ) {
res . header ( 'Content-Type' , 'application/xml' ) ;
res . render ( 'resources/sitemap' , {
appUrl : appUrl ,
now : now ,
2015-04-24 18:57:55 -04:00
users : results . users ,
2015-04-24 13:13:50 -04:00
challenges : results . challenges ,
stories : results . stories ,
nonprofits : results . nonprofits ,
fieldGuides : results . fieldGuides
} ) ;
} , 0 ) ;
}
}
) ;
2015-03-28 17:38:11 +09:00
} ,
chat : function chat ( req , res ) {
2015-04-05 00:16:23 -07:00
if ( req . user && req . user . progressTimestamps . length > 5 ) {
2015-04-17 01:39:55 -04:00
res . redirect ( 'http://freecode.slack.com' ) ;
2015-04-05 00:16:23 -07:00
} else {
res . render ( 'resources/chat' , {
2015-04-07 00:11:31 -07:00
title : "Watch us code live on Twitch.tv"
2015-04-05 00:16:23 -07:00
} ) ;
}
2015-03-28 17:38:11 +09:00
} ,
2015-05-15 18:43:07 -07:00
catPhotoSubmit : function catPhotoSubmit ( req , res ) {
2015-05-15 23:34:20 -07:00
res . send ( 'Success! You have submitted your cat photo. Return to your website by typing any letter into your code editor.' )
2015-05-15 18:43:07 -07:00
} ,
2015-04-27 16:17:29 -07:00
nonprofits : function nonprofits ( req , res ) {
res . render ( 'resources/nonprofits' , {
title : 'A guide to our Nonprofit Projects'
} ) ;
} ,
nonprofitsForm : function nonprofitsForm ( req , res ) {
res . render ( 'resources/nonprofits-form' , {
title : 'A guide to our Nonprofit Projects'
} ) ;
} ,
agileProjectManagers : function agileProjectManagers ( req , res ) {
res . render ( 'resources/pmi-acp-agile-project-managers' , {
title : 'Get Agile Project Management Experience for the PMI-ACP'
} ) ;
} ,
agileProjectManagersForm : function agileProjectManagersForm ( req , res ) {
res . render ( 'resources/pmi-acp-agile-project-managers-form' , {
title : 'Get Agile Project Management Experience for the PMI-ACP'
} ) ;
} ,
2015-04-07 00:11:31 -07:00
twitch : function twitch ( req , res ) {
res . render ( 'resources/twitch' , {
title : "Enter Free Code Camp's Chat Rooms"
} ) ;
} ,
2015-04-30 23:41:40 -07:00
unsubscribe : function unsubscribe ( req , res ) {
User . findOne ( { email : req . params . email } , function ( err , user ) {
if ( user ) {
if ( err ) {
return next ( err ) ;
}
user . sendMonthlyEmail = false ;
user . save ( function ( ) {
if ( err ) {
return next ( err ) ;
}
res . redirect ( '/unsubscribed' ) ;
} ) ;
} else {
res . redirect ( '/unsubscribed' ) ;
}
} ) ;
} ,
unsubscribed : function unsubscribed ( req , res ) {
res . render ( 'resources/unsubscribed' , {
title : "You have been unsubscribed"
} ) ;
} ,
2015-03-28 17:38:11 +09:00
githubCalls : function ( req , res ) {
var githubHeaders = { headers : { 'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1521.3 Safari/537.36' } , port : 80 } ;
request ( 'https://api.github.com/repos/freecodecamp/freecodecamp/pulls?client_id=' + secrets . github . clientID + '&client_secret=' + secrets . github . clientSecret , githubHeaders , function ( err , status1 , pulls ) {
pulls = pulls ? Object . keys ( JSON . parse ( pulls ) ) . length : "Can't connect to github" ;
request ( 'https://api.github.com/repos/freecodecamp/freecodecamp/issues?client_id=' + secrets . github . clientID + '&client_secret=' + secrets . github . clientSecret , githubHeaders , function ( err , status2 , issues ) {
issues = ( ( pulls === parseInt ( pulls ) ) && issues ) ? Object . keys ( JSON . parse ( issues ) ) . length - pulls : "Can't connect to GitHub" ;
res . send ( { "issues" : issues , "pulls" : pulls } ) ;
} ) ;
} ) ;
} ,
2015-03-29 19:19:19 +09:00
trelloCalls : function ( req , res , next ) {
request ( 'https://trello.com/1/boards/BA3xVpz9/cards?key=' + secrets . trello . key , function ( err , status , trello ) {
if ( err ) { return next ( err ) ; }
trello = ( status && status . statusCode === 200 ) ? ( JSON . parse ( trello ) ) : "Can't connect to to Trello" ;
res . end ( JSON . stringify ( trello ) ) ;
} ) ;
} ,
2015-03-30 15:15:07 -07:00
2015-03-29 19:19:19 +09:00
bloggerCalls : function ( req , res , next ) {
request ( 'https://www.googleapis.com/blogger/v3/blogs/2421288658305323950/posts?key=' + secrets . blogger . key , function ( err , status , blog ) {
if ( err ) { return next ( err ) ; }
blog = ( status && status . statusCode === 200 ) ? JSON . parse ( blog ) : "Can't connect to Blogger" ;
res . end ( JSON . stringify ( blog ) ) ;
} ) ;
} ,
2015-03-28 17:38:11 +09:00
about : function ( req , res , next ) {
if ( req . user ) {
if ( ! req . user . profile . picture || req . user . profile . picture === "https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-180x180.png" ) {
req . user . profile . picture = "https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png" ;
req . user . save ( ) ;
}
}
2015-03-29 19:19:19 +09:00
var date1 = new Date ( "10/15/2014" ) ;
2015-03-28 17:38:11 +09:00
var date2 = new Date ( ) ;
2015-03-29 14:44:49 -07:00
2015-03-28 17:38:11 +09:00
var timeDiff = Math . abs ( date2 . getTime ( ) - date1 . getTime ( ) ) ;
var daysRunning = Math . ceil ( timeDiff / ( 1000 * 3600 * 24 ) ) ;
var announcements = resources . announcements ;
function numberWithCommas ( x ) {
return x . toString ( ) . replace ( /\B(?=(\d{3})+(?!\d))/g , "," ) ;
}
User . count ( { } , function ( err , c3 ) {
if ( err ) {
debug ( 'User err: ' , err ) ;
return next ( err ) ;
}
2015-04-24 13:13:50 -04:00
2015-04-24 15:53:22 -04:00
res . render ( 'resources/learn-to-code' , {
title : 'About Free Code Camp' ,
daysRunning : daysRunning ,
c3 : numberWithCommas ( c3 ) ,
announcements : announcements
2015-03-28 17:38:11 +09:00
} ) ;
} ) ;
} ,
randomPhrase : function ( ) {
2015-04-24 13:13:50 -04:00
return resources . phrases [ Math . floor (
Math . random ( ) * resources . phrases . length ) ] ;
2015-03-28 17:38:11 +09:00
} ,
randomVerb : function ( ) {
2015-04-24 13:13:50 -04:00
return resources . verbs [ Math . floor (
Math . random ( ) * resources . verbs . length ) ] ;
2015-03-28 17:38:11 +09:00
} ,
randomCompliment : function ( ) {
2015-04-24 13:13:50 -04:00
return resources . compliments [ Math . floor (
Math . random ( ) * resources . compliments . length ) ] ;
2015-03-28 17:38:11 +09:00
} ,
2015-04-08 17:18:51 -07:00
allFieldGuideIds : function ( ) {
2015-04-24 13:13:50 -04:00
if ( allFieldGuideIds ) {
return allFieldGuideIds ;
} else {
allFieldGuideIds = fieldGuides .
map ( function ( elem ) {
2015-04-25 12:28:14 -04:00
return elem . _id ;
2015-04-24 13:13:50 -04:00
} ) ;
return allFieldGuideIds ;
}
2015-04-05 16:44:07 -07:00
} ,
2015-04-08 17:18:51 -07:00
allFieldGuideNames : function ( ) {
2015-04-24 13:13:50 -04:00
if ( allFieldGuideNames ) {
return allFieldGuideNames ;
} else {
allFieldGuideNames = fieldGuides .
map ( function ( elem ) {
return {
name : elem . name
} ;
} ) ;
return allFieldGuideNames ;
}
2015-03-30 20:08:29 -07:00
} ,
allNonprofitNames : function ( ) {
2015-04-24 13:13:50 -04:00
if ( allNonprofitNames ) {
return allNonprofitNames ;
} else {
allNonprofitNames = nonprofits .
map ( function ( elem ) {
return {
name : elem . name
} ;
} ) ;
return allNonprofitNames ;
}
2015-03-30 15:15:07 -07:00
} ,
2015-03-28 17:38:11 +09:00
whichEnvironment : function ( ) {
return process . env . NODE _ENV ;
} ,
2015-03-30 15:15:07 -07:00
2015-03-28 17:38:11 +09:00
getURLTitle : function ( url , callback ) {
( function ( ) {
var result = { title : '' , image : '' , url : '' , description : '' } ;
request ( url , function ( error , response , body ) {
if ( ! error && response . statusCode === 200 ) {
var $ = cheerio . load ( body ) ;
var metaDescription = $ ( "meta[name='description']" ) ;
var metaImage = $ ( "meta[property='og:image']" ) ;
var urlImage = metaImage . attr ( 'content' ) ? metaImage . attr ( 'content' ) : '' ;
2015-04-24 13:13:50 -04:00
var metaTitle = $ ( 'title' ) ;
2015-03-28 17:38:11 +09:00
var description = metaDescription . attr ( 'content' ) ? metaDescription . attr ( 'content' ) : '' ;
2015-04-30 14:55:00 -07:00
result . title = metaTitle . text ( ) . length < 90 ? metaTitle . text ( ) : metaTitle . text ( ) . slice ( 0 , 87 ) + "..." ;
2015-03-28 17:38:11 +09:00
result . image = urlImage ;
result . description = description ;
callback ( null , result ) ;
} else {
callback ( 'failed' ) ;
}
} ) ;
} ) ( ) ;
} ,
2015-03-30 15:15:07 -07:00
2015-03-28 17:38:11 +09:00
updateUserStoryPictures : function ( userId , picture , username , cb ) {
var counter = 0 ,
foundStories ,
foundComments ;
Story . find ( { 'author.userId' : userId } , function ( err , stories ) {
if ( err ) {
return cb ( err ) ;
}
foundStories = stories ;
counter ++ ;
saveStoriesAndComments ( ) ;
} ) ;
Comment . find ( { 'author.userId' : userId } , function ( err , comments ) {
if ( err ) {
return cb ( err ) ;
}
foundComments = comments ;
counter ++ ;
saveStoriesAndComments ( ) ;
} ) ;
function saveStoriesAndComments ( ) {
if ( counter !== 2 ) {
return ;
}
var tasks = [ ] ;
R . forEach ( function ( comment ) {
comment . author . picture = picture ;
comment . author . username = username ;
comment . markModified ( 'author' ) ;
tasks . push ( function ( cb ) {
comment . save ( cb ) ;
2015-02-22 18:23:50 +09:00
} ) ;
2015-03-28 17:38:11 +09:00
} , foundComments ) ;
R . forEach ( function ( story ) {
story . author . picture = picture ;
story . author . username = username ;
story . markModified ( 'author' ) ;
tasks . push ( function ( cb ) {
story . save ( cb ) ;
2015-03-08 16:50:51 +09:00
} ) ;
2015-03-28 17:38:11 +09:00
} , foundStories ) ;
async . parallel ( tasks , function ( err ) {
2015-04-24 13:13:50 -04:00
if ( err ) {
return cb ( err ) ;
}
2015-03-28 17:38:11 +09:00
cb ( ) ;
} ) ;
2015-03-08 16:50:51 +09:00
}
2015-04-29 08:00:57 -04:00
} ,
codepenResources : {
twitter : function ( req , res ) {
// sends out random tweets about javascript
var T = new Twit ( {
consumer _key : secrets . twitter . consumerKey ,
consumer _secret : secrets . twitter . consumerSecret ,
access _token : secrets . twitter . token ,
access _token _secret : secrets . twitter . tokenSecret
} ) ;
2015-04-29 20:07:38 -04:00
if ( req . params . screenName ) {
screenName = req . params . screenName ;
} else {
screenName = 'freecodecamp' ;
}
T . get ( 'statuses/user_timeline' , { screen _name : screenName , count : 10 } , function ( err , data , response ) {
2015-04-29 08:00:57 -04:00
return res . json ( data ) ;
} ) ;
} ,
twitterFCCStream : function ( ) {
// sends out a tweet stream from FCC's account
} ,
twitch : function ( ) {
// exports information from the twitch account
} ,
slack : function ( ) {
}
2015-03-28 17:38:11 +09:00
}
2015-03-08 16:50:51 +09:00
} ;