Merge pull request #21 from fatchan/combinedquery

combine update action queries
merge-requests/208/head
Tom 5 years ago committed by GitHub
commit 262ef1afd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 163
      controllers/forms.js
  2. 83
      db/posts.js
  3. 7
      gulp/res/css/style.css
  4. 48
      gulp/res/img/locked.svg
  5. 4
      gulp/res/img/saged.svg
  6. 240
      gulp/res/img/sticky.svg
  7. 1
      helpers/actionchecker.js
  8. 7
      models/forms/ban-poster.js
  9. 2
      models/forms/delete-post.js
  10. 22
      models/forms/deletepostsfiles.js
  11. 21
      models/forms/dismiss-report.js
  12. 23
      models/forms/dismissglobalreport.js
  13. 19
      models/forms/globalreportpost.js
  14. 23
      models/forms/lockposts.js
  15. 20
      models/forms/make-post.js
  16. 14
      models/forms/report-post.js
  17. 23
      models/forms/sageposts.js
  18. 33
      models/forms/spoiler-post.js
  19. 23
      models/forms/stickyposts.js
  20. 2
      server.js
  21. 3
      views/includes/actionfooter.pug
  22. 7
      views/mixins/post.pug

@ -6,6 +6,7 @@ const express = require('express')
, Posts = require(__dirname+'/../db/posts.js')
, Trips = require(__dirname+'/../db/trips.js')
, Bans = require(__dirname+'/../db/bans.js')
, Mongo = require(__dirname+'/../db/db.js')
, banPoster = require(__dirname+'/../models/forms/ban-poster.js')
, removeBans = require(__dirname+'/../models/forms/removebans.js')
, makePost = require(__dirname+'/../models/forms/make-post.js')
@ -13,6 +14,9 @@ const express = require('express')
, deleteBanners = require(__dirname+'/../models/forms/deletebanners.js')
, deletePosts = require(__dirname+'/../models/forms/delete-post.js')
, spoilerPosts = require(__dirname+'/../models/forms/spoiler-post.js')
, stickyPosts = require(__dirname+'/../models/forms/stickyposts.js')
, sagePosts = require(__dirname+'/../models/forms/sageposts.js')
, lockPosts = require(__dirname+'/../models/forms/lockposts.js')
, deletePostsFiles = require(__dirname+'/../models/forms/deletepostsfiles.js')
, reportPosts = require(__dirname+'/../models/forms/report-post.js')
, globalReportPosts = require(__dirname+'/../models/forms/globalreportpost.js')
@ -25,9 +29,7 @@ const express = require('express')
, checkPerms = require(__dirname+'/../helpers/hasperms.js')
, numberConverter = require(__dirname+'/../helpers/number-converter.js')
, banCheck = require(__dirname+'/../helpers/bancheck.js')
, actionChecker = require(__dirname+'/../helpers/actionchecker.js')
, actions = ['report', 'global_report', 'spoiler', 'delete', 'delete_file', 'dismiss', 'global_dismiss', 'ban', 'global_ban']
, authActions = ['dismiss', 'global_dismiss', 'ban', 'global_ban'];
, actionChecker = require(__dirname+'/../helpers/actionchecker.js');
// login to account
router.post('/login', (req, res, next) => {
@ -331,14 +333,20 @@ router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, a
})
}
let passwordPosts = posts;
//get the ids
const postMongoIds = posts.map(post => Mongo.ObjectId(post._id));
let passwordPostMongoIds = [];
let passwordPosts = [];
if (!hasPerms && anyPasswords) {
//if any actions require passwords, filter to ones with correct password
//just to avoid multiple filters and mapping, do it all here
passwordPosts = posts.filter(post => {
return post.password != null
&& post.password.length > 0
&& post.password == req.body.password
});
if (post.password != null
&& post.password.length > 0
&& post.password == req.body.password) {
passwordPostMongoIds.push(Mongo.ObjectId(post._id))
return true;
}
});
if (passwordPosts.length === 0) {
return res.status(403).render('message', {
'title': 'Forbidden',
@ -346,40 +354,116 @@ router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, a
'redirect': `/${req.params.board}`
});
}
} else {
passwordPosts = posts;
passwordPostMongoIds = postMongoIds;
}
const messages = [];
const combinedQuery = {};
const passwordCombinedQuery = {};
try {
if (hasPerms) {
// if getting global banned, board ban doesnt matter
if (req.body.global_ban) {
messages.push((await banPoster(req, res, next, null, posts)));
const { message } = await banPoster(req, res, next, null, posts);
messages.push(message);
} else if (req.body.ban) {
messages.push((await banPoster(req, res, next, req.params.board, posts)));
const { message } = await banPoster(req, res, next, req.params.board, posts);
messages.push(message);
}
}
if (req.body.delete) {
messages.push((await deletePosts(req, res, next, passwordPosts)));
const { message } = await deletePosts(req, res, next, passwordPosts);
messages.push(message);
} else {
// if it was getting deleted, we cant do any of these
if (req.body.delete_file) {
messages.push((await deletePostsFiles(req, res, next, passwordPosts)));
const { message, action, query } = await deletePostsFiles(passwordPosts);
if (action) {
passwordCombinedQuery[action] = { ...passwordCombinedQuery[action], ...query}
}
messages.push(message);
} else if (req.body.spoiler) {
messages.push((await spoilerPosts(req, res, next, passwordPosts)));
const { message, action, query } = spoilerPosts(passwordPosts);
if (action) {
passwordCombinedQuery[action] = { ...passwordCombinedQuery[action], ...query}
}
messages.push(message);
}
if (hasPerms) {
//lock, sticky, sage
if (req.body.sage) {
const { message, action, query } = sagePosts(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
if (req.body.lock) {
const { message, action, query } = lockPosts(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
if (req.body.sticky) {
const { message, action, query } = stickyPosts(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
}
// cannot report and dismiss at same time
if (req.body.report) {
messages.push((await reportPosts(req, res, next)));
const { message, action, query } = reportPosts(req, posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
} else if (hasPerms && req.body.dismiss) {
messages.push((await dismissReports(req, res, next)));
const { message, action, query } = dismissReports(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
// cannot report and dismiss at same time
if (req.body.global_report) {
messages.push((await globalReportPosts(req, res, next, posts)));
const { message, action, query } = globalReportPosts(req, posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
} else if (hasPerms && req.body.global_dismiss) {
messages.push((await dismissGlobalReports(req, res, next, posts)));
const { message, action, query } = dismissGlobalReports(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
}
const dbPromises = []
if (Object.keys(combinedQuery).length > 0) {
dbPromises.push(
Posts.db.updateMany({
'_id': {
'$in': postMongoIds
}
}, combinedQuery)
)
}
if (Object.keys(passwordCombinedQuery).length > 0) {
dbPromises.push(
Posts.db.updateMany({
'_id': {
'$in': passwordPostMongoIds
}
}, passwordCombinedQuery)
)
}
await Promise.all(dbPromises);
} catch (err) {
return next(err);
}
@ -460,7 +544,7 @@ router.post('/global/actions', checkPermsMiddleware, numberConverter, async(req,
return res.status(400).render('message', {
'title': 'Bad request',
'errors': errors,
'redirect': `/${req.params.board}`
'redirect': '/globalmanage'
})
}
@ -474,39 +558,48 @@ router.post('/global/actions', checkPermsMiddleware, numberConverter, async(req,
})
}
//get the ids
const postMongoIds = posts.map(post => Mongo.ObjectId(post._id));
const messages = [];
const combinedQuery = {};
try {
//ban before delete
if (req.body.global_ban) {
messages.push((await banPoster(req, res, next, null, posts)));
const { message } = await banPoster(req, res, next, null, posts);
messages.push(message);
}
// if its getting deleted, we cant do anythign else
if (req.body.delete) {
messages.push((await deletePosts(req, res, next, posts)));
} else{
const { message } = await deletePosts(req, res, next, posts);
messages.push(message);
} else {
// if it was getting deleted, we cant do any of these
if (req.body.delete_file) {
messages.push((await deletePostsFiles(req, res, next, posts)));
} else if (req.body.spoiler) {
// if it was getting deleted, we cant spoiler
messages.push((await spoilerPosts(req, res, next, posts)));
const { message, action, query } = await deletePostsFiles(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
if (req.body.global_dismiss) {
messages.push((await dismissGlobalReports(req, res, next, posts)));
const { message, action, query } = dismissGlobalReports(posts);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
}
}
await Posts.db.updateMany({
'_id': {
'$in': postMongoIds
}
}, combinedQuery)
} catch (err) {
if (err.status) {
// return out special error
return res.status(err.status).render('message', err.message);
}
//some other error, use regular error handler
return next(err);
}
return res.render('message', {
'title': 'Success',
'messages': messages,
'redirect': `/${req.params.board}`
'redirect': '/globalmanage'
});
});

@ -23,7 +23,8 @@ module.exports = {
'globalreports': 0,
}
}).sort({
'bumped': -1
'sticky': -1,
'bumped': -1,
}).skip(10*(page-1)).limit(10).toArray();
// add last 5 posts in reverse order to preview
@ -198,7 +199,7 @@ module.exports = {
}).toArray();
},
insertOne: async (board, data) => {
insertOne: async (board, data, thread) => {
if (data.thread !== null) {
//if not a thread, update reply and image count on op document;
@ -213,7 +214,7 @@ module.exports = {
}
}
// bump thread if name not sage
if (data.email !== 'sage') {
if (data.email !== 'sage' && !thread.saged) {
query['$set'] = {
'bumped': Date.now()
}
@ -233,31 +234,6 @@ module.exports = {
},
reportMany: (board, ids, report) => {
return db.updateMany({
'postId': {
'$in': ids
},
'board': board
}, {
'$push': {
'reports': report
}
});
},
globalReportMany: (ids, report) => {
return db.updateMany({
'_id': {
'$in': ids
},
}, {
'$push': {
'globalreports': report
}
});
},
getReports: (board) => {
return db.find({
'reports.0': {
@ -274,19 +250,6 @@ module.exports = {
}).toArray();
},
dismissReports: (board, ids) => {
return db.updateMany({
'postId': {
'$in': ids
},
'board': board
}, {
'$set': {
'reports': []
}
});
},
getGlobalReports: () => {
return db.find({
'globalreports.0': {
@ -302,34 +265,10 @@ module.exports = {
}).toArray();
},
dismissGlobalReports: (ids) => {
return db.updateMany({
'_id': {
'$in': ids
},
}, {
'$set': {
'globalreports': []
}
});
},
deleteOne: (board, options) => {
return db.deleteOne(options);
},
deleteFilesMany: (ids) => {
return db.updateMany({
'_id': {
'$in': ids
}
}, {
'$set': {
'files': []
}
});
},
deleteMany: (ids) => {
return db.deleteMany({
@ -340,20 +279,6 @@ module.exports = {
},
spoilerMany: (ids) => {
return db.updateMany({
'_id': {
'$in': ids
}
}, {
'$set': {
'spoiler': true
}
});
},
deleteAll: (board) => {
return db.deleteMany({
'board': board

@ -148,7 +148,7 @@ span {
margin: 10px 0;
}
.post-container, .pages {
.post-container, .pages, .toggle-label {
background: #D6DAF0;
border-color: #B7C5D9;
border-width: 0 1px 1px 0;
@ -170,7 +170,7 @@ span {
}
.actions label {
margin: 2px 0;
padding: 2px 0;
}
.toggle-label:hover {
@ -178,11 +178,8 @@ span {
}
.toggle-label {
background: #D6DAF0;
padding: 10px;
border-radius: 3px;
text-align: center;
border: 1px solid lightgray;
max-width: 100%;
box-sizing: border-box;
display: flex;

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 24 24"
enable-background="new 0 0 24 24"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="Locked_icon_red.svg"><metadata
id="metadata11"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs9" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="888"
inkscape:window-height="480"
id="namedview7"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="Layer_1" /><g
transform="matrix(1 0 0 -1 0 1638)"
id="g3"><path
d="M15,1630c0,0,0,3-2.5,3s-2.5-3-2.5-3v-1h5V1630z M17,1630v-1h2v-10H9c-1.7,0-3,1.3-3,3v7h2v1c0,0,0,5,4.5,5 C17,1635,17,1630,17,1630z"
id="path5"
style="fill:#d11d13;fill-opacity:1" /></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="164" height="156" version="1.0">
<path d="M36,0v70h-36l82,86l82-86h-36V0z" fill="#f00"/>
</svg>

After

Width:  |  Height:  |  Size: 200 B

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="500mm"
height="500mm"
viewBox="0 0 1771.6535 1771.6535"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="TJ-Openclipart-68-office-stationery-tack-pin-12-5-16 - final.svg"
inkscape:export-filename="C:\Users\tejasollie\Desktop\TJ-OpenClipArt 30-1-16\68-Office Stationery\TJ-Openclipart-68-office-stationery-tack-pin-12-5-16.png"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300"
enable-background="new">
<defs
id="defs4">
<filter
inkscape:label="Silk Carpet"
inkscape:menu="Textures"
inkscape:menu-tooltip="Silk carpet texture, horizontal stripes"
style="color-interpolation-filters:sRGB;"
id="filter4271"
height="1.3"
width="1.3"
y="-0.15"
x="-0.15">
<feTurbulence
baseFrequency="0.1"
seed="50"
numOctaves="5"
result="result1"
type="fractalNoise"
id="feTurbulence4273" />
<feGaussianBlur
stdDeviation="4"
result="result7"
id="feGaussianBlur4275" />
<feDisplacementMap
result="result5"
in="SourceGraphic"
scale="20"
xChannelSelector="G"
in2="result7"
id="feDisplacementMap4277" />
<feComposite
result="result2"
operator="in"
in2="result1"
in="result5"
id="feComposite4279" />
<feGaussianBlur
stdDeviation="1"
result="result6"
id="feGaussianBlur4281" />
<feSpecularLighting
surfaceScale="-3"
result="result4"
specularConstant="3.5"
specularExponent="35"
in="result6"
id="feSpecularLighting4283">
<feDistantLight
elevation="45"
azimuth="225"
id="feDistantLight4285" />
</feSpecularLighting>
<feComposite
k1="1.7"
k3="0.7"
in2="result2"
in="result4"
operator="arithmetic"
result="result91"
id="feComposite4287" />
<feBlend
result="fbSourceGraphic"
mode="multiply"
in2="result91"
id="feBlend4289" />
<feComposite
in2="fbSourceGraphic"
in="fbSourceGraphic"
result="result2"
operator="arithmetic"
id="feComposite4291" />
<feComposite
in="result2"
result="result4"
operator="arithmetic"
k2="2"
k3="2"
in2="fbSourceGraphic"
id="feComposite4293" />
<feBlend
mode="screen"
in="result4"
in2="result4"
id="feBlend4295"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix4329" />
<feTurbulence
id="feTurbulence4331"
type="turbulence"
numOctaves="2"
baseFrequency="0.01 0.11"
seed="10"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix4333"
result="result5"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1.3 0 " />
<feComposite
id="feComposite4335"
in2="result5"
in="fbSourceGraphic"
operator="out" />
<feMorphology
id="feMorphology4337"
operator="dilate"
radius="1.3"
result="result3" />
<feTurbulence
id="feTurbulence4339"
numOctaves="3"
baseFrequency="0.08 0.05"
type="fractalNoise"
seed="7"
result="result6" />
<feGaussianBlur
id="feGaussianBlur4341"
stdDeviation="0.5"
result="result7" />
<feDisplacementMap
id="feDisplacementMap4343"
in2="result7"
in="result3"
xChannelSelector="R"
yChannelSelector="G"
scale="3"
result="result4" />
<feComposite
id="feComposite4345"
in2="result4"
in="result4"
k1="1"
result="result2"
operator="arithmetic"
k2="1" />
<feBlend
id="feBlend4347"
in2="result4"
mode="normal"
in="result2" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Lighting"
id="filter4412">
<feComponentTransfer
in="blur"
result="component"
id="feComponentTransfer4414">
<feFuncR
type="gamma"
amplitude="5.05"
exponent="0.989583"
offset="0"
id="feFuncR4416" />
<feFuncG
type="gamma"
amplitude="5.05"
exponent="0.989583"
offset="0"
id="feFuncG4418" />
<feFuncB
type="gamma"
amplitude="5.05"
exponent="0.989583"
offset="0"
id="feFuncB4420" />
</feComponentTransfer>
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.16000001"
inkscape:cx="-325.83103"
inkscape:cy="994.39246"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1366"
inkscape:window-height="664"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 1">
<g
id="g4196"
transform="translate(987.49901,199.60027)">
<path
style="fill:#a90000"
d="m -118.26364,1449.3513 -16.44054,-79.5748 0.0165,-326.7161 c 0.0132,-261.42674 -0.0586,-326.81796 -0.35949,-327.22608 -0.3531,-0.47892 -10.93529,-0.51456 -173.24975,-0.58383 l -172.87364,-0.0738 114.26506,-167.33019 c 62.84575,-92.03161 114.34581,-167.63159 114.44457,-167.99996 0.30018,-1.11993 0.21519,-271.90836 -0.0856,-272.69946 -0.19725,-0.51879 -1.76235,-1.54023 -5.625,-3.67104 C -312.0261,73.767659 -353.35868,38.711589 -377.47396,2.2900386 -401.64799,-34.220171 -409.69236,-72.203351 -401.63119,-111.7731 c 2.74683,-13.48332 8.31609,-29.65984 14.35287,-41.6895 l 1.51089,-3.0108 285.03348,0.0752 285.03343,0.0752 1.3325,3 c 14.0781,31.69662 18.7044,63.007054 13.7194,92.849974 -6.9133,41.38594 -31.4562,80.09425 -73.9246,116.59146 -18.7857,16.1444 -43.738501,33.2019 -69.502701,47.511376 -4.6874,2.60334 -6.7025,3.87993 -6.821,4.32105 -0.2269,0.84507 -0.216,271.04718 0.011,271.8939 0.099,0.36732 51.598901,75.9673 114.445401,167.99996 l 114.2664,167.33208 -172.8745,0.0738 c -162.315191,0.0693 -172.897451,0.10491 -173.250551,0.58383 -0.30093,0.40812 -0.37278,65.79934 -0.35949,327.22617 l 0.0165,326.7161 -16.44054,79.5748 c -9.04227,43.7661 -16.507999,79.5747 -16.590499,79.5747 -0.0825,0 -7.54824,-35.8086 -16.59051,-79.5747 z"
id="path4198"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

@ -3,6 +3,7 @@
const actions = [
{name:'lock', global:false, auth:true, passwords:false},
{name:'sticky', global:false, auth:true, passwords:false},
{name:'sage', global:false, auth:true, passwords:false},
{name:'report', global:false, auth:false, passwords:false},
{name:'global_report', global:false, auth:false, passwords:false},
{name:'spoiler', global:true, auth:false, passwords:true},

@ -1,9 +1,6 @@
'use strict';
const uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js')
, hasPerms = require(__dirname+'/../../helpers/hasperms.js')
, Bans = require(__dirname+'/../../db/bans.js')
, Posts = require(__dirname+'/../../db/posts.js');
const Bans = require(__dirname+'/../../db/bans.js')
module.exports = async (req, res, next, board, posts) => {
@ -21,6 +18,6 @@ module.exports = async (req, res, next, board, posts) => {
const bannedIps = await Bans.insertMany(bans).then(result => result.insertedCount);
return `Banned ${bannedIps} ips`;
return { message:`Banned ${bannedIps} ips` };
}

@ -49,6 +49,6 @@ module.exports = async (req, res, next, posts) => {
}));
//hooray!
return `Deleted ${boardThreads.length} threads and ${deletedPosts-boardThreads.length} posts`
return { message:`Deleted ${boardThreads.length} threads and ${deletedPosts-boardThreads.length} posts` };
}

@ -5,11 +5,8 @@ const path = require('path')
, fs = require('fs')
, unlink = util.promisify(fs.unlink)
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js')
, hasPerms = require(__dirname+'/../../helpers/hasperms.js')
, Mongo = require(__dirname+'/../../db/db.js')
, Posts = require(__dirname+'/../../db/posts.js');
module.exports = async (req, res, next, posts) => {
module.exports = async (posts) => {
//get filenames from all the posts
let fileNames = [];
@ -26,11 +23,18 @@ module.exports = async (req, res, next, posts) => {
])
}));
//delete posts from DB
const postMongoIds = posts.map(post => Mongo.ObjectId(post._id))
const deletedFilesPosts = await Posts.deleteFilesMany(postMongoIds).then(result => result.deletedCount);
if (fileNames.length === 0) {
return {
message: 'No files to delete'
}
}
//hooray!
return `Deleted ${fileNames.length} files across ${deletedFilesPosts} posts`
return {
message:`Deleted ${fileNames.length} file(s) across ${posts.length} post(s)`,
action:'$set',
query: {
'files': []
}
};
}

@ -1,12 +1,23 @@
'use strict';
const Posts = require(__dirname+'/../../db/posts.js')
, hasPerms = require(__dirname+'/../../helpers/hasperms.js');
module.exports = (posts) => {
module.exports = async (req, res, next) => {
const filteredposts = posts.filter(post => {
return post.reports.length > 0
})
const dismissedReports = await Posts.dismissReports(req.params.board, req.body.checkedposts).then(result => result.modifiedCount);
if (filteredposts.length === 0) {
return {
message: 'No report(s) to dismiss'
}
}
return `Dismissed ${dismissedReports} reports successfully`;
return {
message: 'Dismissed reports',
action: '$set',
query: {
'reports': []
}
};
}

@ -1,14 +1,23 @@
'use strict';
const Mongo = require(__dirname+'/../../db/db.js')
, Posts = require(__dirname+'/../../db/posts.js')
, hasPerms = require(__dirname+'/../../helpers/hasperms.js');
module.exports = (posts) => {
module.exports = async (req, res, next, posts) => {
const filteredposts = posts.filter(post => {
return post.globalreports.length > 0
})
const postMongoIds = posts.map(post => Mongo.ObjectId(post._id))
const dismissedCount = await Posts.dismissGlobalReports(postMongoIds).then(result => result.modifiedCount);
if (filteredposts.length === 0) {
return {
message: 'No global report(s) to dismiss'
}
}
return `Dismissed ${dismissedCount} reports successfully`;
return {
message: 'Dismissed global report(s)',
action: '$set',
query: {
'globalreports': []
}
};
}

@ -1,9 +1,8 @@
'use strict';
const Mongo = require(__dirname+'/../../db/db.js')
, Posts = require(__dirname+'/../../db/posts.js');
const Posts = require(__dirname+'/../../db/posts.js');
module.exports = async (req, res, next, posts) => {
module.exports = (req, posts) => {
const ip = req.headers['x-real-ip'] || req.connection.remoteAddress;
const report = {
@ -12,12 +11,12 @@ module.exports = async (req, res, next, posts) => {
'ip': ip
}
const ids = posts.map(p => Mongo.ObjectId(p._id))
//push the report to all checked posts
const reportedPosts = await Posts.globalReportMany(ids, report).then(result => result.modifiedCount);
//hooray!
return `Global reported ${reportedPosts} posts successfully`
return {
message: `Global reported ${posts.length} post(s)`,
action: '$push',
query: {
'globalreports': report
}
};
}

@ -0,0 +1,23 @@
'use strict';
module.exports = (posts) => {
const filteredposts = posts.filter(post => {
return !post.locked
})
if (filteredposts.length === 0) {
return {
message: 'Post(s) already locked',
};
}
return {
message: `Locked ${filteredposts.length} post(s)`,
action: '$set',
query: {
'locked': true
}
};
}

@ -19,7 +19,7 @@ const uuidv4 = require('uuid/v4')
}
}
, nameRegex = /^(?<name>[^\s#]+)?(?:##(?<tripcode>[^ ]{1}[^\s#]+))?(?:## (?<capcode>[^\s#]+))?$/
, hasPerms = require(__dirname+'/../../helpers/hasperms.js')
, permsCheck = require(__dirname+'/../../helpers/hasperms.js')
, fileUpload = require(__dirname+'/../../helpers/files/file-upload.js')
, fileCheckMimeType = require(__dirname+'/../../helpers/files/file-check-mime-types.js')
, imageThumbnail = require(__dirname+'/../../helpers/files/image-thumbnail.js')
@ -33,8 +33,9 @@ module.exports = async (req, res, next, numFiles) => {
// check if this is responding to an existing thread
let redirect = `/${req.params.board}`
let salt = '';
let thread;
let hasPerms = permsCheck(req, res);
if (req.body.thread) {
let thread;
try {
thread = await Posts.getPost(req.params.board, req.body.thread, true);
} catch (err) {
@ -47,6 +48,13 @@ module.exports = async (req, res, next, numFiles) => {
'redirect': redirect
});
}
if (thread.locked && !hasPerms) {
return res.status(400).render('message', {
'title': 'Bad request',
'message': 'Thread Locked',
'redirect': redirect
});
}
salt = thread.salt;
redirect += `/thread/${req.body.thread}`
}
@ -151,7 +159,7 @@ module.exports = async (req, res, next, numFiles) => {
tripcode = `!!${(await getTripCode(groups.tripcode))}`;
}
//capcode
if (groups.capcode && hasPerms(req, res)) {
if (groups.capcode && hasPerms) {
// TODO: add proper code for different capcodes
capcode = groups.capcode;
}
@ -185,13 +193,17 @@ module.exports = async (req, res, next, numFiles) => {
'files': files,
'reports': [],
'globalreports': [],
'sticky': false,
'locked': false,
'saged': false,
'cyclic': false,
'replyposts': 0,
'replyimages': 0,
};
let postId;
try {
postId = await Posts.insertOne(req.params.board, data);
postId = await Posts.insertOne(req.params.board, data, thread);
} catch (err) {
return next(err);
}

@ -2,7 +2,7 @@
const Posts = require(__dirname+'/../../db/posts.js');
module.exports = async (req, res, next) => {
module.exports = (req, posts) => {
const ip = req.headers['x-real-ip'] || req.connection.remoteAddress;
const report = {
@ -11,10 +11,12 @@ module.exports = async (req, res, next) => {
'ip': ip
}
//push the report to all checked posts
const reportedCount = await Posts.reportMany(req.params.board, req.body.checkedposts, report).then(result => result.modifiedCount);
//hooray!
return `Reported ${reportedCount} posts successfully`
return {
message: `Reported ${posts.length} post(s)`,
action: '$push',
query: {
'reports': report
}
};
}

@ -0,0 +1,23 @@
'use strict';
module.exports = (posts) => {
const filteredposts = posts.filter(post => {
return !post.saged
})
if (filteredposts.length === 0) {
return {
message: 'Post(s) already saged',
};
}
return {
message: `Saged ${filteredposts.length} post(s)`,
action: '$set',
query: {
'saged': true
}
};
}

@ -1,29 +1,24 @@
'use strict';
const path = require('path')
, util = require('util')
, fs = require('fs')
, unlink = util.promisify(fs.unlink)
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js')
, hasPerms = require(__dirname+'/../../helpers/hasperms.js')
, Mongo = require(__dirname+'/../../db/db.js')
, Posts = require(__dirname+'/../../db/posts.js');
module.exports = async (req, res, next, posts) => {
module.exports = (posts) => {
// filter to ones not spoilered
posts = posts.filter(post => {
const filteredPosts = posts.filter(post => {
return !post.spoiler
});
if (posts.length === 0) {
return 'Posts already spoilered';
}
// spoiler posts
const postMongoIds = posts.map(post => Mongo.ObjectId(post._id));
const spoileredPosts = await Posts.spoilerMany(postMongoIds).then(result => result.modifiedCount);
if (filteredPosts.length === 0) {
return {
message:'Post(s) already spoilered'
};
}
//hooray!
return `Spoilered ${spoileredPosts} posts`
return {
message: `Spoilered ${filteredPosts.length} post(s)`,
action: '$set',
query: {
'spoiler': true
}
};
}

@ -0,0 +1,23 @@
'use strict';
module.exports = (posts) => {
const filteredposts = posts.filter(post => {
return !post.sticky
})
if (filteredposts.length === 0) {
return {
message: 'Post(s) already stickied',
};
}
return {
message: `Stickied ${filteredposts.length} post(s)`,
action: '$set',
query: {
'sticky': true
}
};
}

@ -53,7 +53,7 @@ const express = require('express')
// use pug view engine
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views/pages'));
//app.enable('view cache');
app.enable('view cache');
// routes
app.use('/forms', require(__dirname+'/controllers/forms.js'))

@ -30,6 +30,9 @@ label.toggle-label Toggle Post Actions
label
input.post-check(type='checkbox', name='lock' value=1)
| Lock
label
input.post-check(type='checkbox', name='sage' value=1)
| Sage
label
input.post-check(type='checkbox', name='ban' value=1)
| Ban Poster

@ -21,6 +21,13 @@ mixin post(post, truncate, manage=false, globalmanage=false)
span #{post.date.toLocaleString()}
span.user-id(style=`background: #${post.userId}`) #{post.userId}
span: a(href=postURL) ##{post.postId}
if !post.thread
if post.sticky
img(src='/img/sticky.svg' height='14')
if post.saged
img(src='/img/saged.svg' height='12')
if post.locked
img(src='/img/locked.svg' height='16')
.post-data
if post.files.length > 0
.post-files

Loading…
Cancel
Save