// sticker.js // Copyright (C) 2022 DTP Technologies, LLC // License: Apache-2.0 'use strict'; const slug = require('slug'); const mongoose = require('mongoose'); const Sticker = mongoose.model('Sticker'); const User = mongoose.model('User'); const { SiteService, SiteError, SiteAsync } = require('../../lib/site-lib'); const MAX_CHANNEL_STICKERS = 50; const MAX_USER_STICKERS = 10; class StickerService extends SiteService { constructor (dtp) { super(dtp, module.exports); } async start ( ) { await super.start(); const { user: userService } = this.dtp.services; this.populateSticker = [ { path: 'owner', select: userService.USER_SELECT, }, ]; this.queue = this.getJobQueue('media', this.dtp.config.jobQueues.media); this.stickerTemplate = this.loadViewTemplate('sticker/components/sticker-standalone.pug'); } async createSticker (ownerType, owner, file, stickerDefinition) { const { minio: minioService } = this.dtp.services; const NOW = new Date(); this.log.debug('received sticker', { file, stickerDefinition }); // this is faster than Model.countDocuments() const currentStickers = await Sticker.find({ owner: owner._id }).select('_id').lean(); switch (ownerType) { case 'ChatRoom': if (currentStickers.length >= MAX_CHANNEL_STICKERS) { throw new SiteError(508, `You have ${MAX_CHANNEL_STICKERS} stickers. Please remove a sticker before adding a new one.`); } break; case 'User': if (currentStickers.length >= MAX_USER_STICKERS) { throw new SiteError(508, `You have ${MAX_USER_STICKERS} stickers. Please remove a sticker before adding a new one one.`); } break; } const sticker = new Sticker(); sticker.created = NOW; sticker.status = 'processing'; sticker.ownerType = ownerType; sticker.owner = owner._id; sticker.slug = slug(stickerDefinition.slug.toLowerCase().trim()); const bucket = process.env.MINIO_VIDEO_BUCKET; const key = `/stickers/${sticker._id.toString().slice(0, 3)}/${sticker._id}`; sticker.original = { bucket, key, type: file.mimetype, size: file.size, }; await minioService.uploadFile({ bucket, key, filePath: file.path, metadata: { 'Content-Type': file.mimetype, 'Content-Length': file.size, }, }); await sticker.save(); await this.queue.add('sticker-ingest', { stickerId: sticker._id }); return sticker.toObject(); } async getForChannel (channel) { const stickers = await Sticker .find({ status: 'live', ownerType: 'Channel', owner: channel._id }) .sort({ created: -1 }) .populate(this.populateSticker) .lean(); return stickers; } async getForUser (user) { const stickers = await Sticker .find({ status: 'live', ownerType: 'User', owner: user._id }) .sort({ created: -1 }) .populate(this.populateSticker) .lean(); return stickers; } async getStickers (pagination) { const stickers = await Sticker .find() .sort({ created: -1 }) .skip(pagination.skip) .limit(pagination.cpp) .populate(this.populateSticker) .lean(); return stickers; } async getBySlug (slug) { const sticker = await Sticker .findOne({ slug }) .populate(this.populateSticker) .lean(); return sticker; } async getById (stickerId, includeOriginal = false) { let query = Sticker.findOne({ _id: stickerId }); if (includeOriginal) { query = query.select('+original'); } const sticker = await query .populate(this.populateSticker) .lean(); return sticker; } async setStatus (sticker, status) { await Sticker.updateOne({ _id: sticker._id }, { $set: { status } }); } async resolveStickerSlugs (slugs) { const stickers = [ ]; await SiteAsync.each(slugs, async (slug) => { const sticker = await Sticker.findOne({ slug: slug }); if (!sticker) { return; } stickers.push(sticker); }); return stickers; } async removeSticker (sticker) { const stickerId = sticker._id; this.log.info('creating sticker delete job', { stickerId }); await this.queue.add('sticker-delete', { stickerId }); } async render (sticker, stickerOptions) { return this.stickerTemplate({ sticker, stickerOptions }); } async addFavorite (user, stickerId) { stickerId = mongoose.Types.ObjectId(stickerId); const sticker = await Sticker.findById(stickerId); if (!sticker) { throw new SiteError(404, 'Sticker not found'); } await User.updateOne( { _id: user._id }, { $addToSet: { favoriteStickers: sticker._id }, }, ); } async removeFavorite (user, stickerId) { stickerId = mongoose.Types.ObjectId(stickerId); await User.updateOne( { _id: user._id }, { $pull: { favoriteStickers: stickerId }, }, ); } async getFavorites (user) { const stickers = await Sticker .populate(user.favoriteStickers, this.populateSticker); return stickers; } } module.exports = { slug: 'sticker', name: 'sticker', create: (dtp) => { return new StickerService(dtp); }, };