correct recent sorting, no more class for Posts and fix 404 loop

merge-requests/208/head
fatchan 5 years ago
parent 8ffdedee8a
commit e97692408e
  1. 58
      controllers/api.js
  2. 62
      controllers/frontend.js
  3. 13
      models/index.js
  4. 78
      models/posts.js
  5. 25
      server.js
  6. 20
      views/pages/thread.pug

@ -2,11 +2,7 @@
const express = require('express')
, router = express.Router()
, { check, validationResult } = require('express-validator/check')
, utils = require('../utils.js')
, util = require('util')
, fs = require('fs')
, mkdir = util.promisify(fs.mkdir)
, Posts = require(__dirname+'/../models/posts.js');
/*
@ -22,23 +18,17 @@ roughly:
*/
// make new post
router.post('/api/board/:board', async (req, res, next) => {
router.post('/api/board/:board', Posts.checkBoard, async (req, res, next) => {
});
// delete a post
router.delete('/api/board/:board/post/:id', async (req, res, next) => {
router.delete('/api/board/:board/post/:id', Posts.checkBoard, async (req, res, next) => {
});
// get recent threads and preview posts
router.get('/api/board/:board/recent/:page', async (req, res, next) => {
//make sure the board exists
const boards = await Posts.checkBoard(req.params.board)
if (boards.length <= 0) {
return next();
}
router.get('/api/board/:board/recent/:page', Posts.checkBoard, async (req, res, next) => {
//get the recently bumped thread & preview posts
let threads;
@ -57,13 +47,7 @@ router.get('/api/board/:board/recent/:page', async (req, res, next) => {
});
// get a thread
router.get('/api/board/:board/thread/:thread', async (req, res, next) => {
//make sure the board exists
const boards = await Posts.checkBoard(req.params.board)
if (boards.length <= 0) {
return next();
}
router.get('/api/board/:board/thread/:thread', Posts.checkBoard, async (req, res, next) => {
//get the recently bumped thread & preview posts
let thread;
@ -82,13 +66,7 @@ router.get('/api/board/:board/thread/:thread', async (req, res, next) => {
});
// get array of threads (catalog)
router.get('/api/board/:board/catalog', async (req, res, next) => {
//make sure the board exists
const boards = await Posts.checkBoard(req.params.board)
if (boards.length <= 0) {
return next();
}
router.get('/api/board/:board/catalog', Posts.checkBoard, async (req, res, next) => {
//get the recently bumped thread & preview posts
let data;
@ -106,32 +84,6 @@ router.get('/api/board/:board/catalog', async (req, res, next) => {
});
// board page web frontend
router.get('/:board/:page?', async (req, res, next) => {
//make sure the board exists
const boards = await Posts.checkBoard(req.params.board)
if (boards.length <= 0) {
return next();
}
//get the recently bumped thread & preview posts
let threads;
try {
threads = await Posts.getRecent(req.params.board, req.params.page);
} catch (err) {
return next(err);
}
//render the page
res.render('board', {
csrf: req.csrfToken(),
board: req.params.board,
threads: threads || []
});
});
/*
(async () => {
await Posts.deleteAll('b');

@ -0,0 +1,62 @@
'use strict';
const express = require('express')
, router = express.Router()
, utils = require('../utils.js')
, Posts = require(__dirname+'/../models/posts.js');
/*
roughly:
- GET /api/board/:board/catalog -> all threads (catalog)
- GET /api/board/:board/recent/:page? -> recent posts per page (board homepage)
- GET /api/board/:board/thread/:thread -> get all posts in a thread
- POST /api/board/:board -> make a new thread
- POST /api/board/:board/thread/:thread -> make a new post in a thread
- DELETE /api/board/:board/post/:id -> delete a post
*/
// board page/recents
router.get('/:board/:page?', Posts.checkBoard, async (req, res, next) => {
//get the recently bumped thread & preview posts
let threads;
try {
threads = await Posts.getRecent(req.params.board, req.params.page);
} catch (err) {
return next(err);
}
//render the page
res.render('board', {
csrf: req.csrfToken(),
board: req.params.board,
threads: threads || []
});
});
// thread view page
router.get('/:board/thread/:thread', Posts.checkBoard, async (req, res, next) => {
//get the recently bumped thread & preview posts
let thread;
try {
thread = await Posts.getThread(req.params.board, req.params.thread);
} catch (err) {
return next(err);
}
//render the page
res.render('thread', {
csrf: req.csrfToken(),
board: req.params.board,
threads: [thread] || []
});
});
module.exports = router;

@ -1,13 +0,0 @@
'use strict';
const fs = require('fs')
, models = {};
fs.readdirSync(__dirname).forEach(file => {
if (file === 'index.js') {
return;
}
const name = file.substring(0,file.length-3);
const model = require(__dirname+'/'+file);
module.exports[name] = model;
});

@ -1,18 +1,15 @@
'use strict';
const Mongo = require(__dirname+'/../helpers/db.js')
, db = Mongo.client.db('chan-boards');
module.exports = new class Posts {
constructor() {
this._db = Mongo.client.db('chan-boards');
}
module.exports = {
//TODO: IMPLEMENT PAGINATION
async getRecent(board, page) {
getRecent: async (board, page) => {
// get all thread posts (posts with null thread id)
const threads = await this._db.collection(board).find({
const threads = await db.collection(board).find({
'thread': null
}).sort({
'bumped': -1
@ -20,25 +17,26 @@ module.exports = new class Posts {
// add posts to all threads in parallel
await Promise.all(threads.map(async thread => {
thread.replies = await this._db.collection(board).find({
const replies = await db.collection(board).find({
'thread': thread._id
}).sort({
'_id': 1
'_id': -1
}).limit(3).toArray();
thread.replies = replies.reverse();
}));
return threads;
}
},
async getThread(board, id) {
getThread: async (board, id) => {
// get thread post and potential replies concurrently
const data = await Promise.all([
this._db.collection(board).findOne({
db.collection(board).findOne({
'_id': Mongo.ObjectId(id)
}),
this._db.collection(board).find({
db.collection(board).find({
'thread': Mongo.ObjectId(id)
}).sort({
'_id': 1
@ -53,31 +51,31 @@ module.exports = new class Posts {
return thread;
}
},
async getCatalog(board) {
getCatalog: async (board) => {
// get all threads for catalog
return this._db.collection(board).find({
return db.collection(board).find({
'thread': null
}).toArray();
}
},
async getPost(board, id) {
getPost: async (board, id) => {
// get a post
return this._db.collection(board).findOne({
return db.collection(board).findOne({
'_id': Mongo.ObjectId(id)
});
}
},
async insertOne(board, data) {
insertOne: async (board, data) => {
// bump thread if name not sage
if (data.thread !== null && data.author !== 'sage') {
await this._db.collection(board).updateOne({
await db.collection(board).updateOne({
'_id': data.thread
}, {
$set: {
@ -86,24 +84,30 @@ module.exports = new class Posts {
})
}
return this._db.collection(board).insertOne(data);
return db.collection(board).insertOne(data);
},
}
deleteOne: async (board, options) => {
return db.collection(board).deleteOne(options);
},
async deleteOne(board, options) {
return this._db.collection(board).deleteOne(options);
}
deleteMany: async (board, options) => {
return db.collection(board).deleteMany(options);
},
async deleteMany(board, options) {
return this._db.collection(board).deleteMany(options);
}
deleteAll: async (board) => {
return db.collection(board).deleteMany({});
},
async deleteAll(board) {
return this._db.collection(board).deleteMany({});
}
checkBoard: async (req, res, next) => {
const boards = await db.listCollections({ 'name': req.params.board }, { 'nameOnly': true }).toArray();
if (!boards || boards.length == 0) {
return res.status(404).render('404')
}
next();
async checkBoard(name) {
return this._db.listCollections({ 'name': name }, { 'nameOnly': true }).toArray();
}
},
}()
}

@ -56,35 +56,24 @@ const express = require('express')
app.use('/img', express.static(__dirname + '/static/img'));
// routes
const posts = require(__dirname+'/controllers/posts.js');
// const modRoutes = require(__dirname+'/controllers/mod.js')()
app.use('/', posts)
// app.use('/', mod)
app.use('/api', require(__dirname+'/controllers/api.js'))
app.use('/', require(__dirname+'/controllers/frontend.js'))
//generic error page
app.get('/error', (req, res) => {
res.status(500).render('error', {
user: req.session.user
})
})
//wildcard after all other routes -- how we handle 404s
// after other routes 404
app.get('*', (req, res) => {
res.status(404).render('404', {
user: req.session.user
})
res.status(404).render('404')
})
//catch any unhandled errors
// catch any unhandled errors
app.use((err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN') {
return res.status(403).send('Invalid CSRF token')
}
console.error(err.stack)
return res.redirect('/error')
return res.status(500).render('error')
})
//listen
// listen
app.listen(configs.port, () => {
console.log(`Listening on port ${configs.port}`);
});

@ -0,0 +1,20 @@
extends ../layout.pug
block head
title /#{board}/
block content
for thread in threads
h1 OP:
div #{thread._id}
div #{thread.author}
div #{thread.date}
div #{thread.content}
h1 Replies:
for post in thread.replies
div #{post._id}
div #{post.author}
div #{post.date}
div #{post.content}
br
hr
Loading…
Cancel
Save