christmas/routes/wishlist/index.js

298 lines
11 KiB
JavaScript
Raw Normal View History

2020-12-01 15:14:57 -08:00
const createDOMPurify = require('dompurify')
2020-11-08 13:54:08 -08:00
const express = require('express')
2020-12-01 15:14:57 -08:00
const getProductName = require('get-product-name')
const { JSDOM } = require('jsdom')
const marked = require('marked')
2020-11-01 19:24:40 -08:00
const u64 = require('u64')
2018-11-20 11:19:58 -08:00
2020-12-01 15:14:57 -08:00
const config = require('../../config')
const publicRoute = require('../../middlewares/publicRoute')
const verifyAuth = require('../../middlewares/verifyAuth')
const window = new JSDOM('').window
const DOMPurify = createDOMPurify(window)
2018-11-20 11:19:58 -08:00
const totals = wishlist => {
2020-11-08 13:54:08 -08:00
let unpledged = 0
let pledged = 0
2018-11-20 11:19:58 -08:00
wishlist.forEach(wishItem => {
2020-11-08 13:54:08 -08:00
if (wishItem.pledgedBy) pledged += 1
else unpledged += 1
})
return { unpledged, pledged }
}
2018-11-20 11:19:58 -08:00
const ValidURL = (string) => { // Ty SO
try {
2019-11-13 09:34:32 -08:00
const url = new URL(string)
2020-12-01 19:09:25 -08:00
if (global._CC.config.wishlist.smile) {
2019-11-13 09:34:32 -08:00
if (url.hostname === 'www.amazon.com') url.hostname = 'smile.amazon.com'
}
2020-11-08 13:54:08 -08:00
if (url) return url
2018-11-20 11:19:58 -08:00
} catch (_) {
2020-11-08 13:54:08 -08:00
return false
2018-11-20 11:19:58 -08:00
}
}
module.exports = (db) => {
2020-11-08 13:54:08 -08:00
const router = express.Router()
2018-11-20 11:19:58 -08:00
2020-11-08 14:23:51 -08:00
router.get('/', publicRoute(), async (req, res) => {
2018-11-20 11:19:58 -08:00
const docs = await db.allDocs({ include_docs: true })
2020-12-01 19:09:25 -08:00
if (global._CC.config.wishlist.singleList) {
2020-11-08 13:54:08 -08:00
for (const row of docs.rows) {
2019-11-18 10:57:47 -08:00
if (row.doc.admin) return res.redirect(`/wishlist/${row.doc._id}`)
}
}
2021-12-03 08:13:43 -08:00
res.render('wishlists', { title: _CC.lang('WISHLISTS_TITLE'), users: docs.rows, totals })
2020-11-08 13:54:08 -08:00
})
2018-11-20 11:19:58 -08:00
2020-11-08 14:23:51 -08:00
router.get('/:user', publicRoute(), async (req, res) => {
2018-11-20 11:19:58 -08:00
try {
2020-11-08 13:54:08 -08:00
const dbUser = await db.get(req.params.user)
2020-12-01 19:09:25 -08:00
if (global._CC.config.wishlist.singleList) {
2019-11-18 10:57:47 -08:00
if (!dbUser.admin) {
const docs = await db.allDocs({ include_docs: true })
2020-11-08 13:54:08 -08:00
for (const row of docs.rows) {
2019-11-18 10:57:47 -08:00
if (row.doc.admin) return res.redirect(`/wishlist/${row.doc._id}`)
}
}
}
2020-11-08 13:54:08 -08:00
const firstCanSee = dbUser.wishlist.findIndex(element => (element.addedBy === req.params.user))
const wishlistReverse = [...dbUser.wishlist].reverse()
const lastCanSeeValue = wishlistReverse.find(element => (element.addedBy === req.params.user))
const lastCanSee = dbUser.wishlist.indexOf(lastCanSeeValue)
2020-12-01 15:14:57 -08:00
for (const item of dbUser.wishlist) {
2020-12-01 19:09:25 -08:00
if (global._CC.config.wishlist.note.markdown) item.note = DOMPurify.sanitize(marked(item.note))
2020-12-01 15:14:57 -08:00
}
2018-11-23 07:12:28 -08:00
res.render('wishlist', {
2021-12-03 08:13:43 -08:00
title: _CC.lang('WISHLIST_TITLE', dbUser._id),
name: dbUser._id,
wishlist: [
...dbUser.wishlist.filter(item => item.addedBy === req.params.user),
...dbUser.wishlist.filter(item => item.addedBy !== req.params.user)
],
firstCanSee,
2018-11-23 07:12:28 -08:00
lastCanSee
2020-11-08 13:54:08 -08:00
})
2018-11-20 11:19:58 -08:00
} catch (error) {
2020-11-08 13:54:08 -08:00
req.flash('error', error)
return res.redirect('/wishlist')
2018-11-20 11:19:58 -08:00
}
2020-11-08 13:54:08 -08:00
})
2018-11-20 11:19:58 -08:00
router.post('/:user', verifyAuth(), async (req, res) => {
2020-11-01 19:24:40 -08:00
if (!req.body.itemUrlOrName) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_URL_REQUIRED'))
2020-11-01 19:24:40 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
}
2020-11-08 13:54:08 -08:00
const potentialUrl = req.body.itemUrlOrName.split(' ').pop()
const url = ValidURL(potentialUrl)
const item = {}
let productData
2018-11-20 11:19:58 -08:00
try {
2020-11-08 13:54:08 -08:00
if (url) productData = await getProductName(url, config.proxyServer)
} catch (err) {
2020-11-08 13:54:08 -08:00
req.flash('error', err.toString())
}
2020-11-08 13:54:08 -08:00
item.name = (productData ? productData.name : '')
2020-11-02 20:28:05 -08:00
item.price = productData?.price
item.image = productData?.image
2020-11-08 13:54:08 -08:00
item.addedBy = req.user._id
item.pledgedBy = (req.user._id === req.params.user ? undefined : req.user._id)
item.note = req.body.note
if (url) item.url = url
if (!url) item.name = req.body.itemUrlOrName
2020-11-08 13:54:08 -08:00
item.id = u64.encode(new Date().getTime().toString())
const doc = await db.get(req.params.user)
doc.wishlist.push(item)
2020-11-01 19:24:40 -08:00
try {
2020-11-08 13:54:08 -08:00
await db.put(doc)
2020-11-01 19:24:40 -08:00
} catch {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_CONFLICT'))
2020-11-01 19:24:40 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
}
2018-11-30 13:44:06 -08:00
req.flash(
'success',
(
req.user._id === req.params.user
2020-11-08 13:54:08 -08:00
? 'Added item to wishlist'
: `Pleged item for ${req.params.user}`
2018-11-30 13:44:06 -08:00
)
2020-11-08 13:54:08 -08:00
)
res.redirect(`/wishlist/${req.params.user}`)
})
2018-11-20 11:19:58 -08:00
router.post('/:user/pledge/:itemId', verifyAuth(), async (req, res) => {
2020-11-08 13:54:08 -08:00
const docs = await db.allDocs({ include_docs: true })
2018-11-20 11:19:58 -08:00
for (let i = 0; i < docs.rows.length; i++) {
for (let j = 0; j < docs.rows[i].doc.wishlist.length; j++) {
if (docs.rows[i].doc.wishlist[j].id === req.params.itemId) {
if (docs.rows[i].doc.wishlist[j].pledgedBy !== undefined) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_PLEDGE_DUPLICATE'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-20 11:19:58 -08:00
}
2020-11-08 13:54:08 -08:00
docs.rows[i].doc.wishlist[j].pledgedBy = req.user._id
await db.put(docs.rows[i].doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('WISHLIST_PLEDGE_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-20 11:19:58 -08:00
}
}
}
2020-11-08 13:54:08 -08:00
})
2018-11-20 11:19:58 -08:00
router.post('/:user/unpledge/:itemId', verifyAuth(), async (req, res) => {
2020-11-08 13:54:08 -08:00
const docs = await db.allDocs({ include_docs: true })
2018-11-20 11:19:58 -08:00
for (let i = 0; i < docs.rows.length; i++) {
for (let j = 0; j < docs.rows[i].doc.wishlist.length; j++) {
if (docs.rows[i].doc.wishlist[j].id === req.params.itemId) {
if (docs.rows[i].doc.wishlist[j].pledgedBy !== req.user._id) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_UNPLEDGE_GUARD'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-20 11:19:58 -08:00
}
2020-11-08 13:54:08 -08:00
docs.rows[i].doc.wishlist[j].pledgedBy = undefined
if (docs.rows[i].doc.wishlist[j].addedBy === req.user._id) docs.rows[i].doc.wishlist.splice(j, 1)
await db.put(docs.rows[i].doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('WISHLIST_UNPLEDGE_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-20 11:19:58 -08:00
}
}
}
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_UNPLEDGE_MISSING'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
})
2018-11-20 11:19:58 -08:00
router.post('/:user/remove/:itemId', verifyAuth(), async (req, res) => {
if (req.user._id !== req.params.user) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_REMOVE_GUARD'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-20 11:19:58 -08:00
}
2020-11-08 13:54:08 -08:00
const doc = await db.get(req.user._id)
2018-11-20 11:19:58 -08:00
for (let i = 0; i < doc.wishlist.length; i++) {
if (doc.wishlist[i].id === req.params.itemId) {
2020-11-08 13:54:08 -08:00
doc.wishlist.splice(i, 1)
await db.put(doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('WISHLIST_REMOVE_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-20 11:19:58 -08:00
}
}
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_REMOVE_MISSING'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
})
2018-11-20 11:19:58 -08:00
2018-11-23 06:03:16 -08:00
router.post('/:user/move/:direction/:itemId', verifyAuth(), async (req, res) => {
if (req.user._id !== req.params.user) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_MOVE_GUARD'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-23 06:03:16 -08:00
}
2020-11-08 13:54:08 -08:00
const doc = await db.get(req.user._id)
2021-01-02 14:17:20 -08:00
let wishlist = doc.wishlist
if (req.params.direction === 'top') {
const item = wishlist.find(item => item.id === req.params.itemId)
wishlist = wishlist.filter(item => item.id !== req.params.itemId)
wishlist.unshift(item)
} else {
if (req.params.direction === 'up') wishlist.reverse()
let moveFromIndex
wishlist.forEach(wish => {
if (wish.id === req.params.itemId) moveFromIndex = wishlist.indexOf(wish)
})
const moveToIndex = wishlist.findIndex(wish => (wishlist.indexOf(wish) > moveFromIndex && wish.addedBy === req.user._id))
if (moveToIndex < 0 || moveToIndex > wishlist.length) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_MOVE_INVALID'))
2021-01-02 14:17:20 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
}
[wishlist[moveFromIndex], wishlist[moveToIndex]] = [wishlist[moveToIndex], wishlist[moveFromIndex]]
if (req.params.direction === 'up') wishlist.reverse()
2018-11-23 07:12:28 -08:00
}
2021-01-02 14:17:20 -08:00
2020-11-08 13:54:08 -08:00
doc.wishlist = wishlist
await db.put(doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('WISHLIST_MOVE_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
})
2018-11-30 13:44:06 -08:00
router.get('/:user/note/:id', verifyAuth(), async (req, res) => {
2020-11-08 13:54:08 -08:00
const doc = await db.get(req.params.user)
const item = doc.wishlist.find(item => item.id === req.params.id)
2020-11-08 13:54:08 -08:00
res.render('note', { item })
})
2018-11-30 13:44:06 -08:00
router.post('/:user/note/:id', verifyAuth(), async (req, res) => {
2020-11-08 13:54:08 -08:00
const doc = await db.get(req.params.user)
const wishlist = doc.wishlist
for (let i = 0; i < wishlist.length; i++) {
const wishlistItem = wishlist[i]
if (wishlistItem.id !== req.params.id) continue
2018-11-30 13:44:06 -08:00
if (req.user._id !== req.params.user && req.user._id !== wishlistItem.addedBy) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('NOTE_GUARD'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-30 13:44:06 -08:00
}
2020-11-01 19:01:30 -08:00
for (const type of [
2020-11-02 14:43:57 -08:00
'name', 'note', 'url', 'price', 'image'
2020-11-01 19:01:30 -08:00
]) {
2020-11-08 13:54:08 -08:00
if (!Object.prototype.hasOwnProperty.call(req.body, type)) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('NOTE_MISSING_PROP', type))
2020-11-01 19:01:30 -08:00
return res.redirect(`/wishlist/${req.params.user}/note/${req.params.id}`)
}
wishlistItem[type] = req.body[type]
}
2020-11-08 13:54:08 -08:00
wishlist[i] = wishlistItem
2018-11-30 13:44:06 -08:00
}
2020-11-08 13:54:08 -08:00
doc.wishlist = wishlist
await db.put(doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('NOTE_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
})
2020-11-07 12:54:53 -08:00
router.post('/:user/refresh/:id', verifyAuth(), async (req, res) => {
2020-11-08 13:54:08 -08:00
const doc = await db.get(req.params.user)
const wishlist = doc.wishlist
for (let i = 0; i < wishlist.length; i++) {
const wishlistItem = wishlist[i]
if (wishlistItem.id !== req.params.id) continue
2020-11-07 12:54:53 -08:00
if (req.user._id !== req.params.user && req.user._id !== wishlistItem.addedBy) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_REFRESH_GUARD'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2020-11-07 12:54:53 -08:00
}
if (!wishlistItem.url) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('WISHLIST_REFRESH_NO_URL'))
2020-11-07 12:54:53 -08:00
return res.redirect(`/wishlist/${req.params.user}/note/${req.params.id}`)
}
const productData = await getProductName(wishlistItem.url)
2020-11-08 13:54:08 -08:00
for (const field of ['name', 'price', 'image']) {
2020-11-07 12:54:53 -08:00
if (productData[field]) wishlistItem[field] = productData[field]
}
2020-11-08 13:54:08 -08:00
wishlist[i] = wishlistItem
2020-11-07 12:54:53 -08:00
}
2020-11-08 13:54:08 -08:00
doc.wishlist = wishlist
await db.put(doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('WISHLIST_REFRESH_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}/note/${req.params.id}`)
})
2018-11-30 13:44:06 -08:00
router.post('/:user/note/remove/:id', verifyAuth(), async (req, res) => {
2020-11-08 13:54:08 -08:00
const doc = await db.get(req.params.user)
const wishlist = doc.wishlist
for (let i = 0; i < wishlist.length; i++) {
const wishlistItem = wishlist[i]
if (wishlistItem.id !== req.params.id) continue
2018-11-30 13:44:06 -08:00
if (req.user._id !== req.params.user && req.user._id !== wishlistItem.addedBy) {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('NOTE_REMOVE_GUARD'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-30 13:44:06 -08:00
}
if (wishlistItem.note) {
2020-11-08 13:54:08 -08:00
wishlistItem.note = undefined
wishlist[i] = wishlistItem
2018-11-30 13:44:06 -08:00
} else {
2021-12-03 08:13:43 -08:00
req.flash('error', _CC.lang('NOTE_REMOVE_MISSING'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
}
2018-11-30 13:44:06 -08:00
}
2020-11-08 13:54:08 -08:00
doc.wishlist = wishlist
await db.put(doc)
2021-12-03 08:13:43 -08:00
req.flash('success', _CC.lang('NOTE_REMOVE_SUCCESS'))
2020-11-08 13:54:08 -08:00
return res.redirect(`/wishlist/${req.params.user}`)
2018-11-30 13:44:06 -08:00
})
2020-11-08 13:54:08 -08:00
return router
}