diff --git a/app/controllers/api/v1/System.controller.js b/app/controllers/api/v1/System.controller.js index 699f448..0bc5658 100644 --- a/app/controllers/api/v1/System.controller.js +++ b/app/controllers/api/v1/System.controller.js @@ -64,6 +64,7 @@ class ReflectController extends Controller { }) await announcement.save() + await announcement.log_populate() return res.api(await announcement.to_api()) } diff --git a/app/jobs/PopulateAnnouncement.job.js b/app/jobs/PopulateAnnouncement.job.js new file mode 100644 index 0000000..a9c4426 --- /dev/null +++ b/app/jobs/PopulateAnnouncement.job.js @@ -0,0 +1,29 @@ +const { Job } = require('flitter-jobs') + +class PopulateAnnouncementJob extends Job { + static get services() { + return [...super.services, 'models', 'output'] + } + + async execute(job) { + const { data } = job + const { announcement_id } = data + + try { + const Announcement = this.models.get('system:Announcement') + const announcement = await Announcement.findById(announcement_id) + + if ( !announcement ) { + this.output.error(`Unable to find announcement with ID: ${announcement_id}`) + throw new Error('Unable to find announcement with that ID.') + } + + await announcement.populate() + this.output.success('Populated announcements.') + } catch (e) { + this.output.error(e) + } + } +} + +module.exports = exports = PopulateAnnouncementJob diff --git a/app/models/system/Announcement.model.js b/app/models/system/Announcement.model.js index abceb38..e738ac2 100644 --- a/app/models/system/Announcement.model.js +++ b/app/models/system/Announcement.model.js @@ -1,6 +1,10 @@ const { Model } = require('flitter-orm') class AnnouncementModel extends Model { + static get services() { + return [...super.services, 'models', 'jobs', 'configs'] + } + static get schema() { return { title: String, @@ -21,6 +25,73 @@ class AnnouncementModel extends Model { type: this.type, } } + + async groups() { + const Group = this.models.get('auth:Group') + return await Group.find({ _id: { $in: this.group_ids.map(x => this.constructor.to_object_id(x)) } }) + } + + async users() { + const User = this.models.get('auth:User') + return await User.find({ _id: { $in: this.user_ids.map(x => this.constructor.to_object_id(x)) } }) + } + + async all_users() { + const users = await this.users() + const groups = await this.groups() + + const all_users = users + const all_user_ids = users.map(x => x.id) + for ( const group of groups ) { + const group_users = await group.users() + for ( const user of group_users ) { + if ( !all_user_ids.includes(user.id) ) { + all_user_ids.push(user.id) + all_users.push(user) + } + } + } + + return all_users + } + + async log_populate() { + await this.jobs.queue('notifications').add('PopulateAnnouncement', { + announcement_id: this.id, + }) + } + + async populate() { + if ( this.type === 'email' ) { + await this.populate_emails() + } else if ( this.type === 'banner' ) { + await this.populate_banners() + } + } + + async populate_emails() { + const users = await this.all_users() + for ( const user of users ) { + await this.jobs.queue('mailer').add('EMail', { + to: user.email, + subject: 'Announcement | ' + this.configs.get('app.name'), + email_params: { + header_text: this.title, + body_paragraphs: [ + this.message, + ], + }, + }) + } + } + + async populate_banners() { + const users = await this.all_users() + const Message = this.models.get('Message') + for ( const user of users ) { + await Message.create(user, `${this.title} - ${this.message}`) + } + } } module.exports = exports = AnnouncementModel