mirror of
https://framagit.org/les/gancio.git
synced 2025-01-31 16:42:22 +01:00
tag / place / event filtering, refactoring, cleaning
This commit is contained in:
parent
4d39fc41c5
commit
e03b9c4499
7 changed files with 164 additions and 84 deletions
|
@ -8,7 +8,7 @@ const linkifyHtml = require('linkify-html')
|
|||
const Sequelize = require('sequelize')
|
||||
const dayjs = require('dayjs')
|
||||
const helpers = require('../../helpers')
|
||||
|
||||
const Col = helpers.col
|
||||
const Event = require('../models/event')
|
||||
const Resource = require('../models/resource')
|
||||
const Tag = require('../models/tag')
|
||||
|
@ -17,6 +17,7 @@ const Notification = require('../models/notification')
|
|||
const APUser = require('../models/ap_user')
|
||||
|
||||
const exportController = require('./export')
|
||||
const tagController = require('./tag')
|
||||
|
||||
const log = require('../../log')
|
||||
|
||||
|
@ -29,8 +30,8 @@ const eventController = {
|
|||
order: [[Sequelize.col('w'), 'DESC']],
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{ name: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%' )},
|
||||
{ address: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('address')), 'LIKE', '%' + search + '%')},
|
||||
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%' ),
|
||||
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('address')), 'LIKE', '%' + search + '%')
|
||||
]
|
||||
},
|
||||
attributes: [['name', 'label'], 'address', 'id', [Sequelize.cast(Sequelize.fn('COUNT', Sequelize.col('events.placeId')),'INTEGER'), 'w']],
|
||||
|
@ -91,7 +92,7 @@ const eventController = {
|
|||
[
|
||||
{ title: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('title')), 'LIKE', '%' + search + '%') },
|
||||
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%'),
|
||||
Sequelize.fn('EXISTS', Sequelize.literal('SELECT 1 FROM event_tags WHERE "event_tags"."eventId"="event".id AND "tagTag" = ?'))
|
||||
Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=${Col('event.id')} AND LOWER(${Col('tagTag')}) = ?`))
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ const eventController = {
|
|||
include: [
|
||||
{
|
||||
model: Tag,
|
||||
order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
||||
// order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
||||
attributes: ['tag'],
|
||||
through: { attributes: [] }
|
||||
},
|
||||
|
@ -247,7 +248,6 @@ const eventController = {
|
|||
order: [['start_datetime', 'DESC'], ['id', 'DESC']]
|
||||
})
|
||||
|
||||
// TODO: also check if event is mine
|
||||
if (event && (event.is_visible || is_admin)) {
|
||||
event = event.get()
|
||||
event.next = next && (next.slug || next.id)
|
||||
|
@ -278,7 +278,7 @@ const eventController = {
|
|||
return res.sendStatus(404)
|
||||
}
|
||||
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
||||
log.warn(`Someone unallowed is trying to confirm -> "${event.title} `)
|
||||
log.warn(`Someone not allowed is trying to confirm -> "${event.title} `)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
|
@ -304,6 +304,7 @@ const eventController = {
|
|||
const event = await Event.findByPk(id)
|
||||
if (!event) { return req.sendStatus(404) }
|
||||
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
||||
log.warn(`Someone not allowed is trying to unconfirm -> "${event.title} `)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
|
@ -317,7 +318,7 @@ const eventController = {
|
|||
},
|
||||
|
||||
/** get all unconfirmed events */
|
||||
async getUnconfirmed (req, res) {
|
||||
async getUnconfirmed (_req, res) {
|
||||
try {
|
||||
const events = await Event.findAll({
|
||||
where: {
|
||||
|
@ -391,7 +392,7 @@ const eventController = {
|
|||
if (body.place_id) {
|
||||
place = await Place.findByPk(body.place_id)
|
||||
} else {
|
||||
place = await Place.findOne({ where: { name: body.place_name.trim() }})
|
||||
place = await Place.findOne({ where: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), Op.eq, body.place_name.trim().toLocaleLowerCase() )})
|
||||
if (!place) {
|
||||
if (!body.place_address || !body.place_name) {
|
||||
return res.status(400).send(`place_id or place_name and place_address required`)
|
||||
|
@ -427,6 +428,7 @@ const eventController = {
|
|||
height: req.file.height,
|
||||
width: req.file.width,
|
||||
name: body.image_name || body.title || '',
|
||||
size: req.file.size || 0,
|
||||
focalpoint: [parseFloat(focalpoint[0]), parseFloat(focalpoint[1])]
|
||||
}]
|
||||
} else {
|
||||
|
@ -438,11 +440,10 @@ const eventController = {
|
|||
await event.setPlace(place)
|
||||
|
||||
// create/assign tags
|
||||
let tags = []
|
||||
if (body.tags) {
|
||||
body.tags = body.tags.map(t => t.trim())
|
||||
await Tag.bulkCreate(body.tags.map(t => ({ tag: t })), { ignoreDuplicates: true })
|
||||
const tags = await Tag.findAll({ where: { tag: { [Op.in]: body.tags } } })
|
||||
await event.addTags(tags)
|
||||
tags = await tagController._findOrCreate(body.tags)
|
||||
await event.setTags(tags)
|
||||
}
|
||||
|
||||
// associate user to event and reverse
|
||||
|
@ -452,7 +453,7 @@ const eventController = {
|
|||
}
|
||||
|
||||
event = event.get()
|
||||
event.tags = body.tags
|
||||
event.tags = tags.map(t => t.tag)
|
||||
event.place = place
|
||||
// return created event to the client
|
||||
res.json(event)
|
||||
|
@ -520,6 +521,7 @@ const eventController = {
|
|||
height: req.file.height,
|
||||
width: req.file.width,
|
||||
name: body.image_name || body.title || '',
|
||||
size: req.file.size || 0,
|
||||
focalpoint: [parseFloat(focalpoint[0].slice(0, 6)), parseFloat(focalpoint[1].slice(0, 6))]
|
||||
}]
|
||||
} else if (!body.image) {
|
||||
|
@ -584,58 +586,85 @@ const eventController = {
|
|||
}
|
||||
},
|
||||
|
||||
async _select ({ start, end, tags, places, show_recurrent, max }) {
|
||||
/**
|
||||
* Method to search for events with pagination and filtering
|
||||
* @returns
|
||||
*/
|
||||
async _select ({
|
||||
start = dayjs().unix(),
|
||||
end,
|
||||
tags,
|
||||
places,
|
||||
show_recurrent,
|
||||
limit,
|
||||
page,
|
||||
older }) {
|
||||
|
||||
const where = {
|
||||
// do not include parent recurrent event
|
||||
// do not include _parent_ recurrent event
|
||||
recurrent: null,
|
||||
|
||||
// confirmed event only
|
||||
is_visible: true,
|
||||
|
||||
[Op.or]: {
|
||||
start_datetime: { [Op.gte]: start },
|
||||
end_datetime: { [Op.gte]: start }
|
||||
start_datetime: { [older ? Op.lte : Op.gte]: start },
|
||||
end_datetime: { [older ? Op.lte : Op.gte]: start }
|
||||
}
|
||||
}
|
||||
|
||||
// include recurrent events?
|
||||
if (!show_recurrent) {
|
||||
where.parentId = null
|
||||
}
|
||||
|
||||
if (end) {
|
||||
where.start_datetime = { [Op.lte]: end }
|
||||
where.start_datetime = { [older ? Op.gte : Op.lte]: end }
|
||||
}
|
||||
|
||||
// normalize tags
|
||||
if (tags) {
|
||||
tags = tags.split(',').map(t => t.trim().toLocaleLowerCase())
|
||||
}
|
||||
|
||||
const replacements = []
|
||||
if (tags && places) {
|
||||
where[Op.or] = {
|
||||
placeId: places ? places.split(',') : [],
|
||||
}
|
||||
where[Op.and] = [
|
||||
{ placeId: places ? places.split(',') : []},
|
||||
Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=event.id AND LOWER(${Col('tagTag')}) in (?)`))
|
||||
]
|
||||
replacements.push(tags)
|
||||
} else if (tags) {
|
||||
where[Op.and] = Sequelize.fn('EXISTS', Sequelize.literal('SELECT 1 FROM event_tags WHERE "event_tags"."eventId"="event".id AND "tagTag" in (?)'))
|
||||
where[Op.and] = Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=event.id AND LOWER(${Col('tagTag')}) in (?)`))
|
||||
replacements.push(tags)
|
||||
} else if (places) {
|
||||
where.placeId = places.split(',')
|
||||
}
|
||||
|
||||
let pagination = {}
|
||||
if (limit) {
|
||||
pagination = {
|
||||
limit,
|
||||
offset: limit * page,
|
||||
}
|
||||
}
|
||||
|
||||
const events = await Event.findAll({
|
||||
where,
|
||||
attributes: {
|
||||
exclude: ['likes', 'boost', 'userId', 'is_visible', 'createdAt', 'updatedAt', 'description', 'resources']
|
||||
exclude: ['likes', 'boost', 'userId', 'is_visible', 'createdAt', 'description', 'resources', 'recurrent', 'placeId', 'parentId']
|
||||
},
|
||||
order: ['start_datetime'],
|
||||
order: [['start_datetime', older ? 'DESC' : 'ASC' ]],
|
||||
include: [
|
||||
{ model: Resource, required: false, attributes: ['id'] },
|
||||
{
|
||||
model: Tag,
|
||||
order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
||||
// order: [Sequelize.literal('(SELECT COUNT(tagTag) FROM event_tags WHERE tagTag = tag) DESC')],
|
||||
attributes: ['tag'],
|
||||
through: { attributes: [] }
|
||||
},
|
||||
{ model: Place, required: true, attributes: ['id', 'name', 'address'] }
|
||||
],
|
||||
limit: max,
|
||||
...pagination,
|
||||
replacements
|
||||
}).catch(e => {
|
||||
log.error('[EVENT]', e)
|
||||
|
@ -658,13 +687,15 @@ const eventController = {
|
|||
const end = req.query.end
|
||||
const tags = req.query.tags
|
||||
const places = req.query.places
|
||||
const max = req.query.max
|
||||
const limit = req.query.max
|
||||
const page = req.query.page = 0
|
||||
const older = req.query.older || false
|
||||
|
||||
const show_recurrent = settings.allow_recurrent_event &&
|
||||
typeof req.query.show_recurrent !== 'undefined' ? req.query.show_recurrent === 'true' : settings.recurrent_event_visible
|
||||
|
||||
res.json(await eventController._select({
|
||||
start, end, places, tags, show_recurrent, max
|
||||
start, end, places, tags, show_recurrent, limit, page, older
|
||||
}))
|
||||
},
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ const ics = require('ics')
|
|||
const exportController = {
|
||||
|
||||
async export (req, res) {
|
||||
const type = req.params.type
|
||||
const format = req.params.format
|
||||
const tags = req.query.tags
|
||||
const places = req.query.places
|
||||
const show_recurrent = !!req.query.show_recurrent
|
||||
|
@ -43,7 +43,7 @@ const exportController = {
|
|||
attributes: { exclude: ['is_visible', 'recurrent', 'createdAt', 'likes', 'boost', 'userId', 'placeId'] },
|
||||
where: {
|
||||
is_visible: true,
|
||||
recurrent: { [Op.eq]: null },
|
||||
recurrent: null,
|
||||
start_datetime: { [Op.gte]: yesterday },
|
||||
...where
|
||||
},
|
||||
|
@ -58,7 +58,7 @@ const exportController = {
|
|||
{ model: Place, attributes: ['name', 'id', 'address'] }]
|
||||
})
|
||||
|
||||
switch (type) {
|
||||
switch (format) {
|
||||
case 'rss':
|
||||
case 'feed':
|
||||
return exportController.feed(req, res, events.slice(0, 20))
|
||||
|
@ -69,10 +69,10 @@ const exportController = {
|
|||
}
|
||||
},
|
||||
|
||||
feed (_req, res, events) {
|
||||
feed (_req, res, events, title = res.locals.settings.title, link = `${res.locals.settings.baseurl}/feed/rss`) {
|
||||
const settings = res.locals.settings
|
||||
res.type('application/rss+xml; charset=UTF-8')
|
||||
res.render('feed/rss.pug', { events, settings, moment })
|
||||
res.render('feed/rss.pug', { events, settings, moment, title, link })
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,22 +1,36 @@
|
|||
const dayjs = require('dayjs')
|
||||
const Place = require('../models/place')
|
||||
const Event = require('../models/event')
|
||||
const eventController = require('./event')
|
||||
const exportController = require('./export')
|
||||
|
||||
const log = require('../../log')
|
||||
const { Op, where, col, fn, cast } = require('sequelize')
|
||||
|
||||
module.exports = {
|
||||
|
||||
async getEvents (req, res) {
|
||||
const name = req.params.placeName
|
||||
const place = await Place.findOne({ where: { name }})
|
||||
const placeName = req.params.placeName
|
||||
const place = await Place.findOne({ where: { name: placeName }})
|
||||
if (!place) {
|
||||
log.warn(`Place ${name} not found`)
|
||||
log.warn(`Place ${placeName} not found`)
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
const start = dayjs().unix()
|
||||
const events = await eventController._select({ start, places: `${place.id}`, show_recurrent: true})
|
||||
|
||||
return res.json({ events, place })
|
||||
const format = req.params.format || 'json'
|
||||
log.debug(`Events for place: ${placeName}`)
|
||||
const events = await eventController._select({ places: String(place.id), show_recurrent: true })
|
||||
|
||||
switch (format) {
|
||||
case 'rss':
|
||||
return exportController.feed(req, res, events,
|
||||
`${res.locals.settings.title} - Place @${place.name}`,
|
||||
`${res.locals.settings.baseurl}/feed/rss/place/${place.name}`)
|
||||
case 'ics':
|
||||
return exportController.ics(req, res, events)
|
||||
default:
|
||||
return res.json({ events, place })
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
@ -36,7 +50,7 @@ module.exports = {
|
|||
return res.json(places)
|
||||
},
|
||||
|
||||
async get (req, res) {
|
||||
async search (req, res) {
|
||||
const search = req.query.search.toLocaleLowerCase()
|
||||
const places = await Place.findAll({
|
||||
order: [[cast(fn('COUNT', col('events.placeId')),'INTEGER'), 'DESC']],
|
||||
|
@ -49,7 +63,9 @@ module.exports = {
|
|||
attributes: ['name', 'address', 'id'],
|
||||
include: [{ model: Event, where: { is_visible: true }, required: true, attributes: [] }],
|
||||
group: ['place.id'],
|
||||
raw: true
|
||||
raw: true,
|
||||
limit: 10,
|
||||
subQuery: false
|
||||
})
|
||||
|
||||
// TOFIX: don't know why limit does not work
|
||||
|
|
|
@ -1,31 +1,37 @@
|
|||
const Tag = require('../models/tag')
|
||||
const Event = require('../models/event')
|
||||
|
||||
const { where, fn, col, Op } = require('sequelize')
|
||||
const exportController = require('./export')
|
||||
const eventController = require('./event')
|
||||
|
||||
module.exports = {
|
||||
// async getEvents (req, res) {
|
||||
// const name = req.params.placeName
|
||||
// const place = await Place.findOne({ where: { name }})
|
||||
// if (!place) {
|
||||
// log.warn(`Place ${name} not found`)
|
||||
// return res.sendStatus(404)
|
||||
// }
|
||||
// const start = dayjs().unix()
|
||||
// const events = await eventController._select({ start, places: `${place.id}`, show_recurrent: true})
|
||||
|
||||
// return res.json({ events, place })
|
||||
// },
|
||||
async _findOrCreate (tags) {
|
||||
// trim tags
|
||||
const trimmedTags = tags.map(t => t.trim())
|
||||
const lowercaseTags = trimmedTags.map(t => t.toLocaleLowerCase())
|
||||
|
||||
// /feed/rss/tag/tagname
|
||||
// /feed/ics/tag/tagname
|
||||
// /feed/json/tag/tagname
|
||||
// search for already existing tags (tag is the same as TaG)
|
||||
const existingTags = await Tag.findAll({ where: { [Op.and]: where(fn('LOWER', col('tag')), { [Op.in]: lowercaseTags }) } })
|
||||
const lowercaseExistingTags = existingTags.map(t => t.tag.toLocaleLowerCase())
|
||||
const remainingTags = trimmedTags.filter(t => ! lowercaseExistingTags.includes(t.toLocaleLowerCase()))
|
||||
|
||||
// create remaining tags (cannot use updateOnDuplicate or manage conflicts)
|
||||
return [].concat(
|
||||
existingTags,
|
||||
await Tag.bulkCreate(remainingTags.map(t => ({ tag: t })))
|
||||
)
|
||||
},
|
||||
|
||||
// /feed/rss/tag/:tagname
|
||||
// /feed/ics/tag/:tagname
|
||||
// /feed/json/tag/:tagname
|
||||
// tag/:tag
|
||||
async getEvents (req, res) {
|
||||
const eventController = require('./event')
|
||||
const format = req.params.format || 'json'
|
||||
const tags = req.params.tag
|
||||
const events = await eventController._select({ tags, show_recurrent: true })
|
||||
|
||||
const events = await eventController._select({ tags: tags.toLocaleLowerCase(), show_recurrent: true })
|
||||
switch (format) {
|
||||
case 'rss':
|
||||
return exportController.feed(req, res, events,
|
||||
|
|
|
@ -33,7 +33,7 @@ if (config.status !== 'READY') {
|
|||
const resourceController = require('./controller/resource')
|
||||
const oauthController = require('./controller/oauth')
|
||||
const announceController = require('./controller/announce')
|
||||
const cohortController = require('./controller/cohort')
|
||||
const collectionController = require('./controller/collection')
|
||||
const helpers = require('../helpers')
|
||||
const storage = require('./storage')
|
||||
const upload = multer({ storage })
|
||||
|
@ -58,8 +58,8 @@ if (config.status !== 'READY') {
|
|||
}
|
||||
```
|
||||
*/
|
||||
api.get('/ping', (req, res) => res.sendStatus(200))
|
||||
api.get('/user', isAuth, (req, res) => res.json(res.locals.user))
|
||||
api.get('/ping', (_req, res) => res.sendStatus(200))
|
||||
api.get('/user', isAuth, (_req, res) => res.json(res.locals.user))
|
||||
|
||||
|
||||
api.post('/user/recover', userController.forgotPassword)
|
||||
|
@ -88,9 +88,11 @@ if (config.status !== 'READY') {
|
|||
* @param {integer} [start] - start timestamp (default: now)
|
||||
* @param {integer} [end] - end timestamp (optional)
|
||||
* @param {array} [tags] - List of tags
|
||||
* @param {array} [places] - List of places
|
||||
* @param {integer} [max] - Max events
|
||||
* @param {array} [places] - List of places id
|
||||
* @param {integer} [max] - Limit events
|
||||
* @param {boolean} [show_recurrent] - Show also recurrent events (default: as choosen in admin settings)
|
||||
* @param {integer} [page] - Pagination
|
||||
* @param {boolean} [older] - select <= start instead of >=
|
||||
* @example ***Example***
|
||||
* [https://demo.gancio.org/api/events](https://demo.gancio.org/api/events)
|
||||
* [usage example](https://framagit.org/les/gancio/-/blob/master/webcomponents/src/GancioEvents.svelte#L18-42)
|
||||
|
@ -131,9 +133,6 @@ if (config.status !== 'READY') {
|
|||
// get tags/places
|
||||
api.get('/event/meta', eventController.searchMeta)
|
||||
|
||||
// get unconfirmed events
|
||||
api.get('/event/unconfirmed', isAdmin, eventController.getUnconfirmed)
|
||||
|
||||
// add event notification TODO
|
||||
api.post('/event/notification', eventController.addNotification)
|
||||
api.delete('/event/notification/:code', eventController.delNotification)
|
||||
|
@ -142,7 +141,10 @@ if (config.status !== 'READY') {
|
|||
api.post('/settings/logo', isAdmin, multer({ dest: config.upload_path }).single('logo'), settingsController.setLogo)
|
||||
api.post('/settings/smtp', isAdmin, settingsController.testSMTP)
|
||||
|
||||
// confirm event
|
||||
// get unconfirmed events
|
||||
api.get('/event/unconfirmed', isAdmin, eventController.getUnconfirmed)
|
||||
|
||||
// [un]confirm event
|
||||
api.put('/event/confirm/:event_id', isAuth, eventController.confirm)
|
||||
api.put('/event/unconfirm/:event_id', isAuth, eventController.unconfirm)
|
||||
|
||||
|
@ -153,12 +155,13 @@ if (config.status !== 'READY') {
|
|||
api.get('/export/:type', cors, exportController.export)
|
||||
|
||||
|
||||
api.get('/place/:placeName/events', cors, placeController.getEvents)
|
||||
api.get('/place/all', isAdmin, placeController.getAll)
|
||||
api.get('/place', cors, placeController.get)
|
||||
api.get('/place/:placeName', cors, placeController.getEvents)
|
||||
api.get('/place', cors, placeController.search)
|
||||
api.put('/place', isAdmin, placeController.updatePlace)
|
||||
|
||||
api.get('/tag', cors, tagController.get)
|
||||
api.get('/tag', cors, tagController.search)
|
||||
api.get('/tag/:tag', cors, tagController.getEvents)
|
||||
|
||||
// - FEDIVERSE INSTANCES, MODERATION, RESOURCES
|
||||
api.get('/instances', isAdmin, instanceController.getAll)
|
||||
|
@ -175,14 +178,14 @@ if (config.status !== 'READY') {
|
|||
api.put('/announcements/:announce_id', isAdmin, announceController.update)
|
||||
api.delete('/announcements/:announce_id', isAdmin, announceController.remove)
|
||||
|
||||
// - COHORT
|
||||
api.get('/cohorts/:name', cohortController.getEvents)
|
||||
api.get('/cohorts', cohortController.getAll)
|
||||
api.post('/cohorts', isAdmin, cohortController.add)
|
||||
api.delete('/cohort/:id', isAdmin, cohortController.remove)
|
||||
api.get('/filter/:cohort_id', isAdmin, cohortController.getFilters)
|
||||
api.post('/filter', isAdmin, cohortController.addFilter)
|
||||
api.delete('/filter/:id', isAdmin, cohortController.removeFilter)
|
||||
// - COLLECTIONS
|
||||
api.get('/collections/:name', cors, collectionController.getEvents)
|
||||
api.get('/collections', collectionController.getAll)
|
||||
api.post('/collections', isAdmin, collectionController.add)
|
||||
api.delete('/collection/:id', isAdmin, collectionController.remove)
|
||||
api.get('/filter/:collection_id', isAdmin, collectionController.getFilters)
|
||||
api.post('/filter', isAdmin, collectionController.addFilter)
|
||||
api.delete('/filter/:id', isAdmin, collectionController.removeFilter)
|
||||
|
||||
// OAUTH
|
||||
api.get('/clients', isAuth, oauthController.getClients)
|
||||
|
|
|
@ -116,6 +116,14 @@ module.exports = {
|
|||
next()
|
||||
},
|
||||
|
||||
col (field) {
|
||||
if (config.db.dialect === 'postgres') {
|
||||
return '"' + field.split('.').join('"."') + '"'
|
||||
} else {
|
||||
return field
|
||||
}
|
||||
},
|
||||
|
||||
async getImageFromURL (url) {
|
||||
log.debug(`getImageFromURL ${url}`)
|
||||
if(!/^https?:\/\//.test(url)) {
|
||||
|
@ -233,5 +241,13 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
next()
|
||||
},
|
||||
|
||||
async feedRedirect (req, res, next) {
|
||||
const accepted = req.accepts('html', 'application/rss+xml', 'text/calendar')
|
||||
if (['application/rss+xml', 'text/calendar'].includes(accepted) && /^\/(tag|place|collection)\/.*/.test(req.path)) {
|
||||
return res.redirect((accepted === 'application/rss+xml' ? '/feed/rss' : '/feed/ics') + req.path)
|
||||
}
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,17 @@ if (config.status === 'READY') {
|
|||
const federation = require('./federation')
|
||||
const webfinger = require('./federation/webfinger')
|
||||
const exportController = require('./api/controller/export')
|
||||
const tagController = require('./api/controller/tag')
|
||||
const placeController = require('./api/controller/place')
|
||||
const collectionController = require('./api/controller/collection')
|
||||
|
||||
// rss / ics feed
|
||||
app.use(helpers.feedRedirect)
|
||||
app.get('/feed/:format/tag/:tag', cors(), tagController.getEvents)
|
||||
app.get('/feed/:format/place/:placeName', cors(), placeController.getEvents)
|
||||
app.get('/feed/:format/collection/:name', cors(), collectionController.getEvents)
|
||||
app.get('/feed/:format', cors(), exportController.export)
|
||||
|
||||
// rss/ics/atom feed
|
||||
app.get('/feed/:type', cors(), exportController.export)
|
||||
|
||||
app.use('/event/:slug', helpers.APRedirect)
|
||||
|
||||
|
@ -59,7 +67,7 @@ app.use('/api', api)
|
|||
|
||||
// // Handle 500
|
||||
app.use((error, _req, res, _next) => {
|
||||
log.error('[ERROR]', error)
|
||||
log.error('[ERROR]' + error)
|
||||
return res.status(500).send('500: Internal Server Error')
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue