diff options
Diffstat (limited to 'src/models')
| -rw-r--r-- | src/models/entities/gallery-like.ts | 33 | ||||
| -rw-r--r-- | src/models/entities/gallery-post.ts | 79 | ||||
| -rw-r--r-- | src/models/index.ts | 4 | ||||
| -rw-r--r-- | src/models/repositories/gallery-like.ts | 25 | ||||
| -rw-r--r-- | src/models/repositories/gallery-post.ts | 113 |
5 files changed, 254 insertions, 0 deletions
diff --git a/src/models/entities/gallery-like.ts b/src/models/entities/gallery-like.ts new file mode 100644 index 0000000000..7d084a2275 --- /dev/null +++ b/src/models/entities/gallery-like.ts @@ -0,0 +1,33 @@ +import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; +import { User } from './user'; +import { id } from '../id'; +import { GalleryPost } from './gallery-post'; + +@Entity() +@Index(['userId', 'postId'], { unique: true }) +export class GalleryLike { + @PrimaryColumn(id()) + public id: string; + + @Column('timestamp with time zone') + public createdAt: Date; + + @Index() + @Column(id()) + public userId: User['id']; + + @ManyToOne(type => User, { + onDelete: 'CASCADE' + }) + @JoinColumn() + public user: User | null; + + @Column(id()) + public postId: GalleryPost['id']; + + @ManyToOne(type => GalleryPost, { + onDelete: 'CASCADE' + }) + @JoinColumn() + public post: GalleryPost | null; +} diff --git a/src/models/entities/gallery-post.ts b/src/models/entities/gallery-post.ts new file mode 100644 index 0000000000..f59cd671f3 --- /dev/null +++ b/src/models/entities/gallery-post.ts @@ -0,0 +1,79 @@ +import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; +import { User } from './user'; +import { id } from '../id'; +import { DriveFile } from './drive-file'; + +@Entity() +export class GalleryPost { + @PrimaryColumn(id()) + public id: string; + + @Index() + @Column('timestamp with time zone', { + comment: 'The created date of the GalleryPost.' + }) + public createdAt: Date; + + @Index() + @Column('timestamp with time zone', { + comment: 'The updated date of the GalleryPost.' + }) + public updatedAt: Date; + + @Column('varchar', { + length: 256, + }) + public title: string; + + @Column('varchar', { + length: 2048, nullable: true + }) + public description: string | null; + + @Index() + @Column({ + ...id(), + comment: 'The ID of author.' + }) + public userId: User['id']; + + @ManyToOne(type => User, { + onDelete: 'CASCADE' + }) + @JoinColumn() + public user: User | null; + + @Index() + @Column({ + ...id(), + array: true, default: '{}' + }) + public fileIds: DriveFile['id'][]; + + @Index() + @Column('boolean', { + default: false, + comment: 'Whether the post is sensitive.' + }) + public isSensitive: boolean; + + @Index() + @Column('integer', { + default: 0 + }) + public likedCount: number; + + @Index() + @Column('varchar', { + length: 128, array: true, default: '{}' + }) + public tags: string[]; + + constructor(data: Partial<GalleryPost>) { + if (data == null) return; + + for (const [k, v] of Object.entries(data)) { + (this as any)[k] = v; + } + } +} diff --git a/src/models/index.ts b/src/models/index.ts index 213570a9c4..9d08e49858 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -43,6 +43,8 @@ import { UserSecurityKey } from './entities/user-security-key'; import { HashtagRepository } from './repositories/hashtag'; import { PageRepository } from './repositories/page'; import { PageLikeRepository } from './repositories/page-like'; +import { GalleryPostRepository } from './repositories/gallery-post'; +import { GalleryLikeRepository } from './repositories/gallery-like'; import { ModerationLogRepository } from './repositories/moderation-logs'; import { UsedUsername } from './entities/used-username'; import { ClipRepository } from './repositories/clip'; @@ -105,6 +107,8 @@ export const ReversiMatchings = getCustomRepository(ReversiMatchingRepository); export const Logs = getRepository(Log); export const Pages = getCustomRepository(PageRepository); export const PageLikes = getCustomRepository(PageLikeRepository); +export const GalleryPosts = getCustomRepository(GalleryPostRepository); +export const GalleryLikes = getCustomRepository(GalleryLikeRepository); export const ModerationLogs = getCustomRepository(ModerationLogRepository); export const Clips = getCustomRepository(ClipRepository); export const ClipNotes = getRepository(ClipNote); diff --git a/src/models/repositories/gallery-like.ts b/src/models/repositories/gallery-like.ts new file mode 100644 index 0000000000..e01c17cff5 --- /dev/null +++ b/src/models/repositories/gallery-like.ts @@ -0,0 +1,25 @@ +import { EntityRepository, Repository } from 'typeorm'; +import { GalleryLike } from '../entities/gallery-like'; +import { GalleryPosts } from '..'; + +@EntityRepository(GalleryLike) +export class GalleryLikeRepository extends Repository<GalleryLike> { + public async pack( + src: GalleryLike['id'] | GalleryLike, + me?: any + ) { + const like = typeof src === 'object' ? src : await this.findOneOrFail(src); + + return { + id: like.id, + post: await GalleryPosts.pack(like.post || like.postId, me), + }; + } + + public packMany( + likes: any[], + me: any + ) { + return Promise.all(likes.map(x => this.pack(x, me))); + } +} diff --git a/src/models/repositories/gallery-post.ts b/src/models/repositories/gallery-post.ts new file mode 100644 index 0000000000..f1d6fe6326 --- /dev/null +++ b/src/models/repositories/gallery-post.ts @@ -0,0 +1,113 @@ +import { EntityRepository, Repository } from 'typeorm'; +import { GalleryPost } from '../entities/gallery-post'; +import { SchemaType } from '../../misc/schema'; +import { Users, DriveFiles, GalleryLikes } from '..'; +import { awaitAll } from '../../prelude/await-all'; +import { User } from '../entities/user'; + +export type PackedGalleryPost = SchemaType<typeof packedGalleryPostSchema>; + +@EntityRepository(GalleryPost) +export class GalleryPostRepository extends Repository<GalleryPost> { + public async pack( + src: GalleryPost['id'] | GalleryPost, + me?: { id: User['id'] } | null | undefined, + ): Promise<PackedGalleryPost> { + const meId = me ? me.id : null; + const post = typeof src === 'object' ? src : await this.findOneOrFail(src); + + return await awaitAll({ + id: post.id, + createdAt: post.createdAt.toISOString(), + updatedAt: post.updatedAt.toISOString(), + userId: post.userId, + user: Users.pack(post.user || post.userId, me), + title: post.title, + description: post.description, + fileIds: post.fileIds, + files: DriveFiles.packMany(post.fileIds), + tags: post.tags.length > 0 ? post.tags : undefined, + isSensitive: post.isSensitive, + likedCount: post.likedCount, + isLiked: meId ? await GalleryLikes.findOne({ postId: post.id, userId: meId }).then(x => x != null) : undefined, + }); + } + + public packMany( + posts: GalleryPost[], + me?: { id: User['id'] } | null | undefined, + ) { + return Promise.all(posts.map(x => this.pack(x, me))); + } +} + +export const packedGalleryPostSchema = { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + createdAt: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'date-time', + }, + updatedAt: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'date-time', + }, + title: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + description: { + type: 'string' as const, + optional: false as const, nullable: true as const, + }, + userId: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + }, + user: { + type: 'object' as const, + ref: 'User', + optional: false as const, nullable: false as const, + }, + fileIds: { + type: 'array' as const, + optional: true as const, nullable: false as const, + items: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id' + } + }, + files: { + type: 'array' as const, + optional: true as const, nullable: false as const, + items: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'DriveFile' + } + }, + tags: { + type: 'array' as const, + optional: true as const, nullable: false as const, + items: { + type: 'string' as const, + optional: false as const, nullable: false as const, + } + }, + isSensitive: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + } +}; |