forked from kaverti/website
244 lines
5.2 KiB
JavaScript
244 lines
5.2 KiB
JavaScript
let express = require('express')
|
|
let router = express.Router()
|
|
const auth = require('../lib/auth')
|
|
|
|
let { Sequelize, Log, userWall, Thread, User, Category } = require('../models')
|
|
|
|
const Errors = require('../lib/errors')
|
|
const now = new Date()
|
|
const lastWeek = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - 6)
|
|
|
|
function processLogsForLineChart (logs) {
|
|
let normalizedDateLogs = logs.map(log => {
|
|
let date = new Date(log.createdAt)
|
|
date.setHours(0, 0, 0)
|
|
return { createdAt: date }
|
|
})
|
|
|
|
let pageViewsObj = normalizedDateLogs.reduce((obj, log) => {
|
|
if(!obj[log.createdAt]) {
|
|
obj[log.createdAt] = { date: log.createdAt, pageViews: 1 }
|
|
} else {
|
|
obj[log.createdAt].pageViews++
|
|
}
|
|
|
|
return obj
|
|
}, {})
|
|
|
|
for(let i = 0; i < 7; i++) {
|
|
let date = new Date(lastWeek)
|
|
date.setUTCDate(date.getUTCDate() + i)
|
|
|
|
if(!pageViewsObj[date]) {
|
|
pageViewsObj[date] = {
|
|
date,
|
|
pageViews: 0
|
|
}
|
|
}
|
|
}
|
|
|
|
let pageViewsArr = Object.keys(pageViewsObj).map(date => {
|
|
return pageViewsObj[date]
|
|
})
|
|
|
|
let pageViewsSorted = pageViewsArr.sort((a, b) => {
|
|
if(a.date < b.date) {
|
|
return -1
|
|
} else if(a.date > b.date) {
|
|
return 1
|
|
} else {
|
|
return 0
|
|
}
|
|
})
|
|
|
|
return pageViewsSorted
|
|
}
|
|
|
|
router.post('/', auth, async(req, res, next) => {
|
|
try {
|
|
let thread, user
|
|
if(req.body.route === 'thread') {
|
|
thread = await Thread.findByPk(req.body.resourceId)
|
|
|
|
if(!thread) throw Errors.sequelizeValidation(Sequelize, {
|
|
error: 'thread does not exist',
|
|
value: req.body.resourceId
|
|
})
|
|
} else if(
|
|
req.body.route === 'userPosts' ||
|
|
req.body.route === 'userThreads' ||
|
|
req.body.route === 'userMarketplace' ||
|
|
req.body.route === 'userWall'
|
|
) {
|
|
user = await User.findByPk(req.body.resourceId)
|
|
|
|
if(!user) throw Errors.sequelizeValidation(Sequelize, {
|
|
error: 'User does not exist, or feature isn\'t implemented.',
|
|
value: req.body.resourceId
|
|
})
|
|
} else if(
|
|
(req.body.route === 'settingsGeneral' ||
|
|
req.body.route === 'settingsAccount') &&
|
|
!req.userData.loggedIn
|
|
) {
|
|
throw Errors.requestNotAuthorized
|
|
}
|
|
|
|
let log = await Log.create({
|
|
route: req.body.route
|
|
})
|
|
|
|
if(thread) await log.setThread(thread)
|
|
if(user) await log.setUser(user)
|
|
if(req.userData.username) {
|
|
let sessionUser = await User.findOne({
|
|
where: { username: req.userData.username }
|
|
})
|
|
await log.setSessionUser(sessionUser)
|
|
}
|
|
|
|
res.json(log.toJSON())
|
|
|
|
} catch (e) { next(e) }
|
|
})
|
|
|
|
router.all('*', auth, async(req, res, next) => {
|
|
let user = await User.findOne({ where: {
|
|
username: req.userData.username
|
|
}})
|
|
if(!user) throw Errors.requestNotAuthorized
|
|
if(req.userData.admin && user.admin) {
|
|
next()
|
|
} else {
|
|
res.status(401)
|
|
res.json({
|
|
errors: [Errors.sessionAdminProtection]
|
|
})
|
|
}
|
|
})
|
|
|
|
router.get('/top-threads', auth, async(req, res, next) => {
|
|
try {
|
|
let logs = await Log.findAll({
|
|
where: {
|
|
createdAt: {
|
|
$gt: new Date(Date.now() - 1000*60*60*24)
|
|
},
|
|
route: 'thread'
|
|
},
|
|
include: [Thread]
|
|
})
|
|
|
|
//Sum each log for a thread
|
|
let pageViewsObj = logs.reduce((obj, log) => {
|
|
//E.g. if thread deleted
|
|
if(!log.Thread) return obj;
|
|
|
|
if(!obj[log.Thread.id]) {
|
|
obj[log.Thread.id] = { Thread: log.Thread, pageViews: 1 }
|
|
} else {
|
|
obj[log.Thread.id].pageViews++
|
|
}
|
|
|
|
return obj
|
|
}, {})
|
|
|
|
//Transform to array
|
|
let pageViewsArr = Object.keys(pageViewsObj).map(id => {
|
|
return pageViewsObj[id]
|
|
})
|
|
|
|
//Sort by number of page views descending
|
|
let sortedPageViewsArr = pageViewsArr.sort((a, b) => {
|
|
if(a.pageViews < b.pageViews) {
|
|
return 1
|
|
} else if (a.pageViews > b.pageViews) {
|
|
return -1
|
|
} else {
|
|
return 0
|
|
}
|
|
})
|
|
|
|
//Return top 3
|
|
res.json(sortedPageViewsArr.slice(0, 4))
|
|
|
|
} catch (e) { next(e) }
|
|
})
|
|
|
|
router.get('/page-views', auth, async(req, res, next) => {
|
|
try {
|
|
let logs = await Log.findAll({
|
|
where: {
|
|
createdAt: {
|
|
$gt: lastWeek
|
|
}
|
|
},
|
|
order: [['createdAt', 'ASC']]
|
|
})
|
|
|
|
res.json(processLogsForLineChart(logs))
|
|
} catch (e) { next(e) }
|
|
})
|
|
|
|
router.get('/new-users', auth, async(req, res, next) => {
|
|
try {
|
|
let users = await User.findAll({
|
|
where: {
|
|
createdAt: {
|
|
$gt: lastWeek
|
|
}
|
|
},
|
|
order: [['createdAt', 'ASC']]
|
|
})
|
|
|
|
res.json(processLogsForLineChart(users))
|
|
} catch (e) { next(e) }
|
|
})
|
|
|
|
router.get('/categories', auth, async(req, res, next) => {
|
|
try {
|
|
let categories = await Category.findAll()
|
|
let categoryThreadCount = []
|
|
|
|
await Promise.all(categories.map(async category => {
|
|
let count = await Thread.count({ where: { CategoryId: category.id } })
|
|
categoryThreadCount.push({
|
|
value: count,
|
|
label: category.name,
|
|
color: category.color
|
|
})
|
|
}))
|
|
|
|
res.json(categoryThreadCount)
|
|
} catch (e) { next(e) }
|
|
})
|
|
|
|
router.get('/new-thread', auth, async(req, res, next) => {
|
|
try {
|
|
let now = Date.now()
|
|
|
|
let threadsTodayCount = await Thread.count({
|
|
where: {
|
|
createdAt: {
|
|
$gt: new Date(now - 1000*60*60*24)
|
|
}
|
|
}
|
|
})
|
|
let threadsYesterdayCount = await Thread.count({
|
|
where: {
|
|
createdAt: {
|
|
$lt: new Date(now - 1000*60*60*24),
|
|
$gt: new Date(now - 1000*60*60*24*2)
|
|
}
|
|
}
|
|
})
|
|
|
|
res.json({
|
|
count: threadsTodayCount,
|
|
change: threadsTodayCount - threadsYesterdayCount
|
|
})
|
|
} catch (e) { next(e) }
|
|
})
|
|
|
|
module.exports = router
|