You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
5.5 KiB
215 lines
5.5 KiB
// 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 removeForUser (user) {
|
|
await Sticker
|
|
.find({ ownerType: user.type, owner: user._id })
|
|
.populate(this.populateSticker)
|
|
.cursor()
|
|
.eachAsync(async (sticker) => {
|
|
await this.removeSticker(sticker);
|
|
});
|
|
}
|
|
|
|
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',
|
|
className: 'StickerService',
|
|
create: (dtp) => { return new StickerService(dtp); },
|
|
};
|