200 lines
6.1 KiB
TypeScript
Executable File
200 lines
6.1 KiB
TypeScript
Executable File
import { Injectable } from '@nestjs/common';
|
||
import { BaseService } from '../base/base.service';
|
||
import { UserProfile, db, ObjectType, Prisma, VisitType } from '@nice/common';
|
||
import EventBus from '@server/utils/event-bus';
|
||
@Injectable()
|
||
export class VisitService extends BaseService<Prisma.VisitDelegate> {
|
||
constructor() {
|
||
super(db, ObjectType.VISIT);
|
||
}
|
||
async create(args: Prisma.VisitCreateArgs, staff?: UserProfile) {
|
||
const { postId, messageId } = args.data;
|
||
const clientIp = (args.data.meta as any)?.ip;
|
||
const visitorId = args.data.visitorId || staff?.id;
|
||
let result;
|
||
const existingVisit = await db.visit.findFirst({
|
||
where: {
|
||
type: args.data.type,
|
||
OR: [
|
||
{
|
||
AND: [
|
||
{ OR: [{ postId }, { messageId }] },
|
||
{ visitorId: visitorId || null },
|
||
],
|
||
},
|
||
{
|
||
AND: [
|
||
{ OR: [{ postId }, { messageId }] },
|
||
{ visitorId: null },
|
||
{ meta: { path: ['ip'], equals: clientIp } },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
});
|
||
if (!existingVisit) {
|
||
result = await super.create(args);
|
||
} else if (args.data.type === VisitType.READED) {
|
||
result = await super.update({
|
||
where: { id: existingVisit.id },
|
||
data: {
|
||
...args.data,
|
||
views: existingVisit.views + 1,
|
||
},
|
||
});
|
||
} else if (args.data.type === VisitType.LIKE) {
|
||
if (!visitorId && existingVisit) {
|
||
const thirtyMinutesAgo = new Date(Date.now() - 30 * 60 * 1000);
|
||
if (existingVisit.updatedAt < thirtyMinutesAgo) {
|
||
// 如果上次更新时间超过30分钟,增加view计数
|
||
result = await super.update({
|
||
where: { id: existingVisit.id },
|
||
data: {
|
||
...args.data,
|
||
views: existingVisit.views + 1,
|
||
},
|
||
});
|
||
}
|
||
}
|
||
}
|
||
if (postId) {
|
||
if (visitorId) {
|
||
EventBus.emit('updatePostState', {
|
||
id: postId,
|
||
});
|
||
}
|
||
if (args.data.type === VisitType.READED) {
|
||
EventBus.emit('updateVisitCount', {
|
||
objectType: ObjectType.POST,
|
||
id: postId,
|
||
visitType: VisitType.READED,
|
||
});
|
||
}
|
||
if (args.data.type === VisitType.LIKE) {
|
||
EventBus.emit('updateVisitCount', {
|
||
objectType: ObjectType.POST,
|
||
id: postId,
|
||
visitType: VisitType.LIKE,
|
||
});
|
||
}
|
||
if (args.data.type === VisitType.HATE) {
|
||
EventBus.emit('updateVisitCount', {
|
||
objectType: ObjectType.POST,
|
||
id: postId,
|
||
visitType: VisitType.HATE,
|
||
});
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
async createMany(args: Prisma.VisitCreateManyArgs, staff?: UserProfile) {
|
||
const data = Array.isArray(args.data) ? args.data : [args.data];
|
||
const updatePromises: any[] = [];
|
||
const createData: Prisma.VisitCreateManyInput[] = [];
|
||
await Promise.all(
|
||
data.map(async (item) => {
|
||
if (staff && !item.visitorId) item.visitorId = staff.id;
|
||
const { postId, messageId, visitorId } = item;
|
||
const existingVisit = await db.visit.findFirst({
|
||
where: {
|
||
visitorId,
|
||
OR: [{ postId }, { messageId }],
|
||
},
|
||
});
|
||
|
||
if (existingVisit) {
|
||
updatePromises.push(
|
||
super.update({
|
||
where: { id: existingVisit.id },
|
||
data: {
|
||
...item,
|
||
views: existingVisit.views + 1,
|
||
},
|
||
}),
|
||
);
|
||
} else {
|
||
createData.push(item);
|
||
}
|
||
}),
|
||
);
|
||
// Execute all updates in parallel
|
||
await Promise.all(updatePromises);
|
||
// Create new visits for those not existing
|
||
if (createData.length > 0) {
|
||
return super.createMany({
|
||
...args,
|
||
data: createData,
|
||
});
|
||
}
|
||
|
||
return { count: updatePromises.length }; // Return the number of updates if no new creates
|
||
}
|
||
async deleteMany(args: Prisma.VisitDeleteManyArgs, staff?: UserProfile) {
|
||
// const where = Array.isArray(args.where) ? args.where : [args.where];
|
||
// const updatePromises: any[] = [];
|
||
// const createData: Prisma.VisitCreateManyInput[] = [];
|
||
// super
|
||
// await Promise.all(
|
||
// data.map(async (item) => {
|
||
// if (staff && !item.visitorId) item.visitorId = staff.id;
|
||
// const { postId, messageId, visitorId } = item;
|
||
// const existingVisit = await db.visit.findFirst({
|
||
// where: {
|
||
// visitorId,
|
||
// OR: [{ postId }, { messageId }],
|
||
// },
|
||
// });
|
||
|
||
// if (existingVisit) {
|
||
// updatePromises.push(
|
||
// super.update({
|
||
// where: { id: existingVisit.id },
|
||
// data: {
|
||
// ...item,
|
||
// views: existingVisit.views + 1,
|
||
// },
|
||
// }),
|
||
// );
|
||
// } else {
|
||
// createData.push(item);
|
||
// }
|
||
// }),
|
||
// );
|
||
// // Execute all updates in parallel
|
||
// await Promise.all(updatePromises);
|
||
// // Create new visits for those not existing
|
||
// if (createData.length > 0) {
|
||
// return super.createMany({
|
||
// ...args,
|
||
// data: createData,
|
||
// });
|
||
// }
|
||
// return { count: updatePromises.length }; // Return the number of updates if no new creates
|
||
const superDetele = super.deleteMany(args, staff);
|
||
if (args?.where?.postId) {
|
||
if (args.where.type === VisitType.READED) {
|
||
EventBus.emit('updateVisitCount', {
|
||
objectType: ObjectType.POST,
|
||
id: args?.where?.postId as string,
|
||
visitType: VisitType.READED,
|
||
});
|
||
}
|
||
if (args.where.type === VisitType.LIKE) {
|
||
EventBus.emit('updateVisitCount', {
|
||
objectType: ObjectType.POST,
|
||
id: args?.where?.postId as string,
|
||
visitType: VisitType.LIKE,
|
||
});
|
||
}
|
||
if (args.where.type === VisitType.HATE) {
|
||
EventBus.emit('updateVisitCount', {
|
||
objectType: ObjectType.POST,
|
||
id: args?.where?.postId as string,
|
||
visitType: VisitType.HATE,
|
||
});
|
||
}
|
||
}
|
||
return superDetele;
|
||
}
|
||
}
|