2019-04-03 00:25:12 +02:00
const crypto = require ( 'crypto' )
const moment = require ( 'moment' )
const { Op } = require ( 'sequelize' )
const lodash = require ( 'lodash' )
2019-06-06 23:54:32 +02:00
const { event : Event , comment : Comment , tag : Tag , place : Place , notification : Notification } = require ( '../models' )
2019-05-30 12:04:14 +02:00
const Sequelize = require ( 'sequelize' )
2019-07-08 01:53:37 +02:00
const notifier = require ( '../../notifier' )
2019-04-03 00:25:12 +02:00
const eventController = {
async addComment ( req , res ) {
// comment could be added to an event or to another comment
let event = await Event . findOne ( { where : { activitypub _id : { [ Op . eq ] : req . body . id } } } )
if ( ! event ) {
const comment = await Comment . findOne ( { where : { activitypub _id : { [ Op . eq ] : req . body . id } } , include : Event } )
event = comment . event
}
const comment = new Comment ( req . body )
event . addComment ( comment )
res . json ( comment )
} ,
async getMeta ( req , res ) {
2019-05-30 12:04:14 +02:00
const places = await Place . findAll ( {
2019-05-30 12:12:51 +02:00
order : [ [ Sequelize . literal ( 'weigth' ) , 'DESC' ] ] ,
2019-05-30 12:04:14 +02:00
attributes : {
2019-06-26 14:44:21 +02:00
include : [ [ Sequelize . fn ( 'count' , Sequelize . col ( 'events.placeId' ) ) , 'weigth' ] ] ,
2019-05-30 12:12:51 +02:00
exclude : [ 'weigth' , 'createdAt' , 'updatedAt' ]
2019-05-30 12:04:14 +02:00
} ,
2019-05-30 12:12:51 +02:00
include : [ { model : Event , attributes : [ ] } ] ,
group : [ 'place.id' ]
2019-05-30 12:04:14 +02:00
} )
const tags = await Tag . findAll ( {
2019-06-07 17:02:33 +02:00
order : [ [ 'weigth' , 'DESC' ] ] ,
2019-05-30 12:04:14 +02:00
attributes : {
exclude : [ 'createdAt' , 'updatedAt' ]
2019-06-26 14:44:21 +02:00
} ,
2019-05-30 12:12:51 +02:00
} )
2019-05-30 12:04:14 +02:00
2019-04-03 00:25:12 +02:00
res . json ( { tags , places } )
} ,
async getNotifications ( event ) {
function match ( event , filters ) {
// matches if no filter specified
if ( ! filters ) return true
// check for visibility
if ( typeof filters . is _visible !== 'undefined' && filters . is _visible !== event . is _visible ) return false
if ( ! filters . tags && ! filters . places ) return true
if ( ! filters . tags . length && ! filters . places . length ) return true
if ( filters . tags . length ) {
const m = lodash . intersection ( event . tags . map ( t => t . tag ) , filters . tags )
if ( m . length > 0 ) return true
}
if ( filters . places . length ) {
if ( filters . places . find ( p => p === event . place . name ) ) {
return true
}
}
}
const notifications = await Notification . findAll ( )
// get notification that matches with selected event
return notifications . filter ( notification => match ( event , notification . filters ) )
} ,
async updateTag ( req , res ) {
const tag = await Tag . findByPk ( req . body . tag )
if ( tag ) {
res . json ( await tag . update ( req . body ) )
} else {
res . sendStatus ( 404 )
}
} ,
async updatePlace ( req , res ) {
const place = await Place . findByPk ( req . body . id )
await place . update ( req . body )
res . json ( place )
} ,
2019-06-14 23:26:13 +02:00
// TODO retrieve next/prev event also
// select id, start_datetime, title from events where start_datetime > (select start_datetime from events where id=89) order by start_datetime limit 20;
2019-04-03 00:25:12 +02:00
async get ( req , res ) {
2019-07-04 01:09:35 +02:00
const is _admin = req . user && req . user . is _admin
2019-04-03 00:25:12 +02:00
const id = req . params . event _id
2019-06-26 14:44:21 +02:00
let event = await Event . findByPk ( id , {
plain : true ,
attributes : { exclude : [ 'createdAt' , 'updatedAt' ] } ,
2019-06-14 23:26:13 +02:00
include : [
2019-06-26 14:44:21 +02:00
{ model : Tag , attributes : [ 'tag' , 'weigth' ] , through : { attributes : [ ] } } ,
{ model : Place , attributes : [ 'name' , 'address' ] } ,
Comment
2019-06-07 17:02:33 +02:00
] ,
2019-06-26 14:44:21 +02:00
order : [ [ Comment , 'id' , 'DESC' ] ]
2019-05-30 12:04:14 +02:00
} )
2019-06-25 01:05:38 +02:00
2019-07-04 01:02:45 +02:00
if ( event && ( event . is _visible || is _admin ) ) {
2019-06-12 22:26:28 +02:00
res . json ( event )
} else {
res . sendStatus ( 404 )
}
2019-04-03 00:25:12 +02:00
} ,
async confirm ( req , res ) {
2019-07-04 01:20:32 +02:00
console . error ( 'confirm event' )
2019-07-04 00:29:50 +02:00
const id = Number ( req . params . event _id )
2019-04-03 00:25:12 +02:00
const event = await Event . findByPk ( id )
2019-07-04 01:02:45 +02:00
if ( ! event ) return res . sendStatus ( 404 )
2019-04-03 00:25:12 +02:00
try {
2019-07-04 01:02:45 +02:00
event . is _visible = true
await event . save ( )
2019-07-08 01:53:37 +02:00
2019-04-03 00:25:12 +02:00
res . sendStatus ( 200 )
2019-07-08 01:53:37 +02:00
// send notification
notifier . notifyEvent ( event . id )
2019-04-03 00:25:12 +02:00
} catch ( e ) {
res . sendStatus ( 404 )
}
} ,
async unconfirm ( req , res ) {
2019-07-04 00:29:50 +02:00
const id = Number ( req . params . event _id )
2019-04-03 00:25:12 +02:00
const event = await Event . findByPk ( id )
2019-07-04 01:02:45 +02:00
if ( ! event ) return sendStatus ( 404 )
2019-04-03 00:25:12 +02:00
try {
2019-07-04 01:02:45 +02:00
event . is _visible = false
await event . save ( )
2019-04-03 00:25:12 +02:00
res . sendStatus ( 200 )
} catch ( e ) {
res . sendStatus ( 404 )
}
} ,
async getUnconfirmed ( req , res ) {
const events = await Event . findAll ( {
where : {
is _visible : false
} ,
order : [ [ 'start_datetime' , 'ASC' ] ] ,
include : [ Tag , Place ]
} )
res . json ( events )
} ,
async addNotification ( req , res ) {
try {
const notification = {
filters : { is _visible : true } ,
email : req . body . email ,
type : 'mail' ,
remove _code : crypto . randomBytes ( 16 ) . toString ( 'hex' )
}
await Notification . create ( notification )
res . sendStatus ( 200 )
} catch ( e ) {
res . sendStatus ( 404 )
}
} ,
async delNotification ( req , res ) {
const remove _code = req . params . code
try {
const notification = await Notification . findOne ( { where : { remove _code : { [ Op . eq ] : remove _code } } } )
await notification . destroy ( )
} catch ( e ) {
return res . sendStatus ( 404 )
}
res . sendStatus ( 200 )
} ,
async getAll ( req , res ) {
// this is due how v-calendar shows dates
2019-07-11 23:31:37 +02:00
const start = moment ( )
. year ( req . params . year )
. month ( req . params . month )
. startOf ( 'month' )
. startOf ( 'isoWeek' )
let end = moment ( )
. year ( req . params . year )
. month ( req . params . month )
. endOf ( 'month' )
2019-04-03 00:25:12 +02:00
const shownDays = end . diff ( start , 'days' )
2019-06-26 14:44:21 +02:00
if ( shownDays <= 35 ) end = end . add ( 1 , 'week' )
end = end . endOf ( 'isoWeek' )
2019-07-11 23:31:37 +02:00
let events = await Event . findAll ( {
2019-04-29 00:27:29 +02:00
where : {
2019-07-13 01:02:11 +02:00
// return only confirmed events
2019-04-29 00:27:29 +02:00
is _visible : true ,
2019-07-13 01:02:11 +02:00
[ Op . or ] : [
// return all recurrent events
{ recurrent : { [ Op . ne ] : null } } ,
// and events in specified range
{ start _datetime : { [ Op . between ] : [ start . unix ( ) , end . unix ( ) ] } }
2019-04-29 00:27:29 +02:00
]
} ,
2019-07-13 01:02:11 +02:00
attributes : { exclude : [ 'createdAt' , 'updatedAt' , 'placeId' ] } ,
order : [ [ Tag , 'weigth' , 'DESC' ] ] ,
2019-04-29 00:27:29 +02:00
include : [
2019-07-13 01:02:11 +02:00
{ model : Tag , required : false } ,
2019-05-30 12:12:51 +02:00
{ model : Place , required : false , attributes : [ 'id' , 'name' , 'address' ] }
2019-04-29 00:27:29 +02:00
]
2019-04-03 00:25:12 +02:00
} )
2019-07-11 23:31:37 +02:00
2019-07-13 01:02:11 +02:00
events = events . map ( e => e . get ( ) ) . map ( e => {
2019-07-11 23:31:37 +02:00
e . start _datetime = e . start _datetime * 1000
e . end _datetime = e . end _datetime * 1000
e . tags = e . tags . map ( t => t . tag )
return e
} )
2019-07-13 01:02:11 +02:00
// build singular events from a recurrent pattern
function createEventsFromRecurrent ( e , dueTo = null , maxEvents = 8 ) {
2019-07-11 23:31:37 +02:00
const events = [ ]
2019-07-13 01:02:11 +02:00
const recurrent = JSON . parse ( e . recurrent )
if ( ! recurrent . frequency ) return false
const cursor = moment ( start )
2019-07-11 23:31:37 +02:00
const start _date = moment ( e . start _datetime )
2019-07-13 01:02:11 +02:00
const frequency = recurrent . frequency
const days = [ start _date . day ( ) ]
2019-07-14 01:44:28 +02:00
const type = recurrent . type
2019-07-11 23:31:37 +02:00
// EACH WEEK
if ( frequency === '1w' ) {
while ( true ) {
const found = days . indexOf ( cursor . day ( ) )
2019-07-13 01:02:11 +02:00
if ( found !== - 1 ) break
2019-07-11 23:31:37 +02:00
cursor . add ( 1 , 'day' )
}
2019-07-13 01:02:11 +02:00
cursor . set ( 'hour' , start _date . hour ( ) ) . set ( 'minute' , start _date . minutes ( ) )
2019-07-11 23:31:37 +02:00
while ( true ) {
if ( ( dueTo && cursor . isAfter ( dueTo ) ) || events . length > maxEvents ) break
2019-07-13 01:02:11 +02:00
e . start _datetime = cursor . unix ( ) * 1000
events . push ( Object . assign ( { } , e ) )
cursor . add ( 1 , 'week' )
2019-07-11 23:31:37 +02:00
}
}
// EACH TWO WEEKS
2019-07-14 01:44:28 +02:00
if ( frequency === '2w' ) {
while ( true ) {
const found = days . indexOf ( cursor . day ( ) )
if ( found !== - 1 ) break
cursor . add ( 1 , 'day' )
}
cursor . set ( 'hour' , start _date . hour ( ) ) . set ( 'minute' , start _date . minutes ( ) )
while ( true ) {
if ( ( dueTo && cursor . isAfter ( dueTo ) ) || events . length > maxEvents ) break
e . start _datetime = cursor . unix ( ) * 1000
events . push ( Object . assign ( { } , e ) )
cursor . add ( 1 , 'week' )
}
}
2019-07-11 23:31:37 +02:00
return events
}
2019-07-13 01:02:11 +02:00
let allEvents = events . filter ( e => ! e . recurrent )
events . filter ( e => e . recurrent ) . forEach ( e => {
const events = createEventsFromRecurrent ( e , end )
if ( events )
allEvents = allEvents . concat ( events )
} )
2019-07-11 23:31:37 +02:00
2019-07-13 01:02:11 +02:00
// allEvents.sort((a,b) => a.start_datetime-b.start_datetime)
res . json ( allEvents . sort ( ( a , b ) => a . start _datetime - b . start _datetime ) )
2019-04-03 00:25:12 +02:00
}
}
module . exports = eventController