@@ -1,6 +1,6 @@
|
||||
import { keyBy } from 'lodash'
|
||||
|
||||
import { Body, Get, Post, Query } from '@nestjs/common'
|
||||
import { Body, Delete, Get, Param, Post, Query } from '@nestjs/common'
|
||||
|
||||
import { ApiController } from '~/common/decorators/api-controller.decorator'
|
||||
import { Auth } from '~/common/decorators/auth.decorator'
|
||||
@@ -8,7 +8,13 @@ import { HTTPDecorators } from '~/common/decorators/http.decorator'
|
||||
import { IpLocation, IpRecord } from '~/common/decorators/ip.decorator'
|
||||
import { PagerDto } from '~/shared/dto/pager.dto'
|
||||
|
||||
import { Activity } from './activity.constant'
|
||||
import { ActivityService } from './activity.service'
|
||||
import {
|
||||
ActivityDeleteDto,
|
||||
ActivityQueryDto,
|
||||
ActivityTypeParamsDto,
|
||||
} from './dtos/activity.dto'
|
||||
import { LikeBodyDto } from './dtos/like.dto'
|
||||
import { GetPresenceQueryDto, UpdatePresenceDto } from './dtos/presence.dto'
|
||||
|
||||
@@ -39,11 +45,16 @@ export class ActivityController {
|
||||
|
||||
@Get('/')
|
||||
@Auth()
|
||||
async activities(@Query() pager: PagerDto) {
|
||||
const { page, size } = pager
|
||||
async activities(@Query() pager: ActivityQueryDto) {
|
||||
const { page, size, type } = pager
|
||||
|
||||
// TODO currently only support like activities, so hard code here
|
||||
return this.service.getLikeActivities(page, size)
|
||||
switch (type) {
|
||||
case Activity.Like:
|
||||
return this.service.getLikeActivities(page, size)
|
||||
|
||||
case Activity.ReadDuration:
|
||||
return this.service.getReadDurationActivities(page, size)
|
||||
}
|
||||
}
|
||||
|
||||
@Post('/presence/update')
|
||||
@@ -68,4 +79,22 @@ export class ActivityController {
|
||||
return keyBy(list, 'identity')
|
||||
})
|
||||
}
|
||||
|
||||
@Delete('/:type')
|
||||
@Auth()
|
||||
async deletePresence(
|
||||
@Param() params: ActivityTypeParamsDto,
|
||||
@Body() Body: ActivityDeleteDto,
|
||||
) {
|
||||
return this.service.deleteActivityByType(
|
||||
params.type,
|
||||
Body.before ? new Date(Body.before) : new Date(),
|
||||
)
|
||||
}
|
||||
|
||||
@Auth()
|
||||
@Delete('/all')
|
||||
async deleteAllPresence() {
|
||||
return this.service.deleteAll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { transformDataToPaginate } from '~/transformers/paginate.transformer'
|
||||
|
||||
import { Activity } from './activity.constant'
|
||||
import { ActivityModel } from './activity.model'
|
||||
import { isValidRoomName } from './activity.util'
|
||||
import { extractArticleIdFromRoomName, isValidRoomName } from './activity.util'
|
||||
|
||||
declare module '~/utils/socket.util' {
|
||||
interface SocketMetadata {
|
||||
@@ -187,6 +187,39 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
|
||||
return transformedPager
|
||||
}
|
||||
|
||||
async getReadDurationActivities(page = 1, size = 10) {
|
||||
const activities = await this.model.paginate(
|
||||
{
|
||||
type: Activity.ReadDuration,
|
||||
},
|
||||
{
|
||||
page,
|
||||
limit: size,
|
||||
sort: {
|
||||
created: -1,
|
||||
},
|
||||
},
|
||||
)
|
||||
const data = transformDataToPaginate(activities)
|
||||
|
||||
const articleIds = [] as string[]
|
||||
for (let i = 0; i < data.data.length; i++) {
|
||||
const item = data.data[i]
|
||||
const roomName = item.payload.roomName
|
||||
if (!roomName) continue
|
||||
const refId = extractArticleIdFromRoomName(roomName)
|
||||
articleIds.push(refId)
|
||||
data.data[i] = data.data[i].toObject()
|
||||
;(data.data[i] as any).refId = refId
|
||||
}
|
||||
|
||||
const documentMap = await this.databaseService.findGlobalByIds(articleIds)
|
||||
return {
|
||||
...data,
|
||||
objects: documentMap,
|
||||
}
|
||||
}
|
||||
|
||||
async likeAndEmit(type: ActivityLikeSupportType, id: string, ip: string) {
|
||||
try {
|
||||
const res = await this.countingService.updateLikeCountWithIp(type, id, ip)
|
||||
@@ -297,4 +330,17 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
|
||||
(x) => x.identity,
|
||||
)
|
||||
}
|
||||
|
||||
async deleteActivityByType(type: Activity, beforeDate: Date) {
|
||||
return this.model.deleteMany({
|
||||
type,
|
||||
created: {
|
||||
$lt: beforeDate,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async deleteAll() {
|
||||
return this.model.deleteMany({})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,7 @@ export const isValidRoomName = (roomName: string) => {
|
||||
|
||||
export const getArticleIdFromRoomName = (roomName: string) =>
|
||||
roomName.slice(prefix.length)
|
||||
|
||||
export const extractArticleIdFromRoomName = (roomName: string) => {
|
||||
return roomName.slice(prefix.length)
|
||||
}
|
||||
|
||||
28
apps/core/src/modules/activity/dtos/activity.dto.ts
Normal file
28
apps/core/src/modules/activity/dtos/activity.dto.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Transform } from 'class-transformer'
|
||||
import { IsEnum, IsNumber, IsOptional } from 'class-validator'
|
||||
|
||||
import { PagerDto } from '~/shared/dto/pager.dto'
|
||||
|
||||
import { Activity } from '../activity.constant'
|
||||
|
||||
const TransformEnum = () =>
|
||||
Transform(({ value }) => (typeof value === 'undefined' ? value : +value))
|
||||
|
||||
export class ActivityTypeParamsDto {
|
||||
@IsEnum(Activity)
|
||||
@TransformEnum()
|
||||
type: Activity
|
||||
}
|
||||
|
||||
export class ActivityDeleteDto {
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
before?: number
|
||||
}
|
||||
|
||||
export class ActivityQueryDto extends PagerDto {
|
||||
@IsEnum(Activity)
|
||||
@IsOptional()
|
||||
@TransformEnum()
|
||||
type: Activity
|
||||
}
|
||||
@@ -128,6 +128,48 @@ export class DatabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
public async findGlobalByIds(ids: string[]): Promise<{
|
||||
posts: PostModel[]
|
||||
notes: NoteModel[]
|
||||
pages: PageModel[]
|
||||
recentlies: RecentlyModel[]
|
||||
}>
|
||||
public async findGlobalByIds(ids: string[]) {
|
||||
const doc = await Promise.all([
|
||||
this.postModel
|
||||
.find({
|
||||
_id: { $in: ids },
|
||||
})
|
||||
.populate('category')
|
||||
.lean(),
|
||||
this.noteModel
|
||||
.find({
|
||||
_id: { $in: ids },
|
||||
})
|
||||
.lean({ autopopulate: true })
|
||||
.select('+password'),
|
||||
this.pageModel
|
||||
.find({
|
||||
_id: { $in: ids },
|
||||
})
|
||||
.lean(),
|
||||
this.recentlyModel
|
||||
.find({
|
||||
_id: { $in: ids },
|
||||
})
|
||||
.lean(),
|
||||
])
|
||||
|
||||
const result = doc.reduce((acc, list, index) => {
|
||||
return {
|
||||
...acc,
|
||||
[(['posts', 'notes', 'pages', 'recentlies'] as const)[index]]: list,
|
||||
}
|
||||
}, {})
|
||||
|
||||
return result as any
|
||||
}
|
||||
|
||||
public get db() {
|
||||
return this.connection.db
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user