src/modules/comment/comment.model.ts
Properties |
Accessors |
Optional email |
Type : string | null
|
Decorators :
@IsEmail()
|
Defined in src/modules/comment/comment.model.ts:65
|
name |
Type : string
|
Decorators :
@MaxLength(20)
|
Defined in src/modules/comment/comment.model.ts:58
|
Optional site |
Type : string | null
|
Decorators :
@IsUrl({require_protocol: true})
|
Defined in src/modules/comment/comment.model.ts:71
|
email_hash |
getemail_hash()
|
Defined in src/modules/comment/comment.model.ts:73
|
import { AutoIncrementID } from '@typegoose/auto-increment'
import { prop, plugin, modelOptions, Severity } from '@typegoose/typegoose'
import { Type } from 'class-transformer'
import {
IsString,
MinLength,
MaxLength,
IsDefined,
IsIn,
IsIP,
IsUrl,
IsEmail,
IsInt,
IsOptional,
IsNotEmpty,
IsArray,
IsObject,
ValidateNested,
ArrayUnique
} from 'class-validator'
import { GENERAL_AUTO_INCREMENT_ID_CONFIG } from '@app/constants/increment.constant'
import { mongoosePaginate } from '@app/utils/paginate'
import { getProviderByTypegooseClass } from '@app/transformers/model.transformer'
import { decodeMD5 } from '@app/transformers/codec.transformer'
import { ROOT_COMMENT_PID, CommentState } from '@app/constants/biz.constant'
import { IPLocation } from '@app/processors/helper/helper.service.ip'
import { KeyValueModel } from '@app/models/key-value.model'
export const COMMENT_STATES = [
CommentState.Auditing,
CommentState.Published,
CommentState.Deleted,
CommentState.Spam
] as const
export const COMMENT_GUEST_QUERY_FILTER = Object.freeze({
state: CommentState.Published
})
@modelOptions({
schemaOptions: {
versionKey: false,
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
})
export class Author {
@MaxLength(20)
@IsString()
@IsNotEmpty()
@prop({ required: true, validate: /\S+/ })
name: string
// MARK: can't get Disqus user's email
@IsEmail()
@IsString()
@IsOptional()
@prop({ type: String, default: null })
email?: string | null
@IsUrl({ require_protocol: true })
@IsString()
@IsOptional()
@prop({ type: String, default: null })
site?: string | null
public get email_hash() {
const email = this.email?.trim().toLowerCase()
return email ? decodeMD5(email) : null
}
}
export class CommentBase {
@IsInt()
@IsNotEmpty({ message: 'post ID?' })
@prop({ required: true, index: true })
post_id: number
// parent comment ID
@IsInt()
@prop({ default: ROOT_COMMENT_PID, index: true })
pid: number
@MinLength(3) // sync with Disqus
@MaxLength(3000)
@IsString()
@IsNotEmpty({ message: 'comment content?' })
@prop({ required: true, validate: /\S+/ })
content: string
// user agent
@IsString()
@prop({ type: String, default: null })
agent?: string | null
@Type(() => Author)
@ValidateNested()
@IsObject()
@IsNotEmpty()
@IsDefined({ message: 'comment author?' })
@prop({ required: true, _id: false })
author: Author
}
@plugin(mongoosePaginate)
@plugin(AutoIncrementID, GENERAL_AUTO_INCREMENT_ID_CONFIG)
@modelOptions({
// https://typegoose.github.io/typegoose/docs/api/decorators/model-options/#allowmixed
options: { allowMixed: Severity.ALLOW },
schemaOptions: {
versionKey: false,
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at'
}
}
})
export class Comment extends CommentBase {
@prop({ unique: true })
id?: number
// state
@IsIn(COMMENT_STATES)
@IsInt()
@prop({ enum: CommentState, default: CommentState.Published, index: true })
state: CommentState
// likes
@IsInt()
@prop({ default: 0, index: true })
likes: number
@IsInt()
@prop({ default: 0, index: true })
dislikes: number
// IP address
@IsIP()
@IsOptional()
@prop({ type: String, default: null })
ip: string | null
// IP location
@prop({ type: Object, default: null })
ip_location: Partial<IPLocation> | null
@prop({ default: Date.now, immutable: true })
created_at?: Date
@prop({ default: Date.now })
updated_at?: Date
@ArrayUnique()
@IsArray()
@prop({ _id: false, default: [], type: () => [KeyValueModel] })
extends: KeyValueModel[]
}
export const CommentProvider = getProviderByTypegooseClass(Comment)