|
@@ -14,8 +14,14 @@ import {
|
|
|
Resolver,
|
|
|
UseMiddleware,
|
|
|
} from 'type-graphql'
|
|
|
-import { ReportVideoInfo } from '../entities/ReportVideoInfo'
|
|
|
-import { ReportedVideoModel, saveReportedVideo } from '../models/ReportedContent'
|
|
|
+import { ChannelReportInfo, VideoReportInfo } from '../entities/EntityReportsInfo'
|
|
|
+import { MaxLength } from 'class-validator'
|
|
|
+import {
|
|
|
+ ReportedChannelModel,
|
|
|
+ ReportedVideoModel,
|
|
|
+ saveReportedChannel,
|
|
|
+ saveReportedVideo,
|
|
|
+} from '../models/ReportedContent'
|
|
|
import { OrionContext } from '../types'
|
|
|
|
|
|
const ONE_HOUR = 60 * 60 * 1000
|
|
@@ -43,6 +49,17 @@ class ReportVideoArgs {
|
|
|
videoId: string
|
|
|
|
|
|
@Field()
|
|
|
+ @MaxLength(400, { message: 'Rationale cannot be longer than 400 characters' })
|
|
|
+ rationale: string
|
|
|
+}
|
|
|
+
|
|
|
+@ArgsType()
|
|
|
+class ReportChannelArgs {
|
|
|
+ @Field(() => ID)
|
|
|
+ channelId: string
|
|
|
+
|
|
|
+ @Field()
|
|
|
+ @MaxLength(400, { message: 'Rationale cannot be longer than 400 characters' })
|
|
|
rationale: string
|
|
|
}
|
|
|
|
|
@@ -50,14 +67,16 @@ enum VideoReportOrderByInput {
|
|
|
createdAt_ASC = 'createdAt_ASC',
|
|
|
createdAt_DESC = 'createdAt_DESC',
|
|
|
}
|
|
|
-
|
|
|
registerEnumType(VideoReportOrderByInput, { name: 'VideoReportOrderByInput' })
|
|
|
|
|
|
-@InputType()
|
|
|
-class VideoReportWhereInput {
|
|
|
- @Field(() => ID, { nullable: true })
|
|
|
- videoId?: string
|
|
|
+enum ChannelReportOrderByInput {
|
|
|
+ createdAt_ASC = 'createdAt_ASC',
|
|
|
+ createdAt_DESC = 'createdAt_DESC',
|
|
|
+}
|
|
|
+registerEnumType(ChannelReportOrderByInput, { name: 'ChannelReportOrderByInput' })
|
|
|
|
|
|
+@InputType()
|
|
|
+class ReportsWhereInput {
|
|
|
@Field(() => Date, { nullable: true })
|
|
|
createdAt_lt?: Date
|
|
|
|
|
@@ -69,31 +88,57 @@ class VideoReportWhereInput {
|
|
|
}
|
|
|
|
|
|
@ArgsType()
|
|
|
-class VideoReportsArgs {
|
|
|
- @Field(() => VideoReportWhereInput, { nullable: true })
|
|
|
- where: VideoReportWhereInput
|
|
|
+class ReportsArgs {
|
|
|
+ @Field(() => Int, { nullable: true, defaultValue: 30 })
|
|
|
+ limit: number
|
|
|
+
|
|
|
+ @Field(() => Int, { nullable: true })
|
|
|
+ skip: number
|
|
|
+}
|
|
|
+
|
|
|
+@InputType()
|
|
|
+class VideoReportsWhereInput extends ReportsWhereInput {
|
|
|
+ @Field(() => ID, { nullable: true })
|
|
|
+ videoId?: string
|
|
|
+}
|
|
|
+@ArgsType()
|
|
|
+class VideoReportsArgs extends ReportsArgs {
|
|
|
+ @Field(() => VideoReportsWhereInput, { nullable: true })
|
|
|
+ where: VideoReportsWhereInput
|
|
|
|
|
|
@Field(() => VideoReportOrderByInput, {
|
|
|
nullable: true,
|
|
|
defaultValue: VideoReportOrderByInput.createdAt_DESC,
|
|
|
})
|
|
|
orderBy: VideoReportOrderByInput
|
|
|
+}
|
|
|
|
|
|
- @Field(() => Int, { nullable: true, defaultValue: 30 })
|
|
|
- limit: number
|
|
|
+@InputType()
|
|
|
+class ChannelReportsWhereInput extends ReportsWhereInput {
|
|
|
+ @Field(() => ID, { nullable: true })
|
|
|
+ channelId?: string
|
|
|
+}
|
|
|
|
|
|
- @Field(() => Int, { nullable: true })
|
|
|
- skip: number
|
|
|
+@ArgsType()
|
|
|
+class ChannelReportsArgs extends ReportsArgs {
|
|
|
+ @Field(() => ChannelReportsWhereInput, { nullable: true })
|
|
|
+ where: ChannelReportsWhereInput
|
|
|
+
|
|
|
+ @Field(() => ChannelReportOrderByInput, {
|
|
|
+ nullable: true,
|
|
|
+ defaultValue: ChannelReportOrderByInput.createdAt_DESC,
|
|
|
+ })
|
|
|
+ orderBy: ChannelReportOrderByInput
|
|
|
}
|
|
|
|
|
|
@Resolver()
|
|
|
export class ReportsInfosResolver {
|
|
|
- @Mutation(() => ReportVideoInfo, { description: 'Report a video' })
|
|
|
+ @Mutation(() => VideoReportInfo, { description: 'Report a video' })
|
|
|
@UseMiddleware(rateLimit(MAX_REPORTS_PER_HOUR))
|
|
|
async reportVideo(
|
|
|
@Args() { videoId, rationale }: ReportVideoArgs,
|
|
|
@Ctx() ctx: OrionContext
|
|
|
- ): Promise<ReportVideoInfo> {
|
|
|
+ ): Promise<VideoReportInfo> {
|
|
|
const createdAt = new Date()
|
|
|
const reportedVideo = await saveReportedVideo({
|
|
|
rationale,
|
|
@@ -111,12 +156,35 @@ export class ReportsInfosResolver {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @Query(() => [ReportVideoInfo])
|
|
|
+ @Mutation(() => ChannelReportInfo, { description: 'Report a channel' })
|
|
|
+ @UseMiddleware(rateLimit(MAX_REPORTS_PER_HOUR))
|
|
|
+ async reportChannel(
|
|
|
+ @Args() { channelId, rationale }: ReportChannelArgs,
|
|
|
+ @Ctx() ctx: OrionContext
|
|
|
+ ): Promise<ChannelReportInfo> {
|
|
|
+ const createdAt = new Date()
|
|
|
+ const reportedVideo = await saveReportedChannel({
|
|
|
+ rationale,
|
|
|
+ channelId,
|
|
|
+ reporterIp: ctx.remoteHost || '',
|
|
|
+ timestamp: createdAt,
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ rationale,
|
|
|
+ channelId,
|
|
|
+ createdAt,
|
|
|
+ id: reportedVideo.id,
|
|
|
+ reporterIp: ctx.remoteHost || '',
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Query(() => [VideoReportInfo])
|
|
|
@Authorized()
|
|
|
async reportedVideos(
|
|
|
@Args() { orderBy, where, limit, skip }: VideoReportsArgs,
|
|
|
@Ctx() ctx: OrionContext
|
|
|
- ): Promise<ReportVideoInfo[]> {
|
|
|
+ ): Promise<VideoReportInfo[]> {
|
|
|
const reportedVideosDocument = await ReportedVideoModel.find({
|
|
|
...(where?.videoId ? { videoId: where?.videoId } : {}),
|
|
|
...(where?.createdAt_gt ? { timestamp: { $gte: where.createdAt_gt } } : {}),
|
|
@@ -137,4 +205,30 @@ export class ReportsInfosResolver {
|
|
|
})) || []
|
|
|
)
|
|
|
}
|
|
|
+ @Query(() => [ChannelReportInfo])
|
|
|
+ @Authorized()
|
|
|
+ async reportedChannels(
|
|
|
+ @Args() { orderBy, where, limit, skip }: ChannelReportsArgs,
|
|
|
+ @Ctx() ctx: OrionContext
|
|
|
+ ): Promise<ChannelReportInfo[]> {
|
|
|
+ const reportedChannelsDocument = await ReportedChannelModel.find({
|
|
|
+ ...(where?.channelId ? { channelId: where?.channelId } : {}),
|
|
|
+ ...(where?.createdAt_gt ? { timestamp: { $gte: where.createdAt_gt } } : {}),
|
|
|
+ ...(where?.createdAt_lt ? { timestamp: { $lte: where.createdAt_lt } } : {}),
|
|
|
+ ...(where?.reporterIp ? { reporterIp: where?.reporterIp } : {}),
|
|
|
+ })
|
|
|
+ .skip(skip)
|
|
|
+ .limit(limit)
|
|
|
+ .sort({ timestamp: orderBy.split('_').at(-1) })
|
|
|
+
|
|
|
+ return (
|
|
|
+ reportedChannelsDocument.map((reportedChannel) => ({
|
|
|
+ rationale: reportedChannel.rationale,
|
|
|
+ channelId: reportedChannel.channelId,
|
|
|
+ createdAt: reportedChannel.timestamp,
|
|
|
+ id: reportedChannel.id,
|
|
|
+ reporterIp: ctx.remoteHost || '',
|
|
|
+ })) || []
|
|
|
+ )
|
|
|
+ }
|
|
|
}
|