summaryrefslogtreecommitdiff
path: root/packages/backend/src/models
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-06-11 19:31:03 +0900
committerGitHub <noreply@github.com>2022-06-11 19:31:03 +0900
commit182a1bf653ecfbcf76e4530b3077c6252b0d4827 (patch)
tree45d1472747d4cac017e96616f844292f5785ccdd /packages/backend/src/models
parent12.110.1 (diff)
parent12.111.0 (diff)
downloadmisskey-182a1bf653ecfbcf76e4530b3077c6252b0d4827.tar.gz
misskey-182a1bf653ecfbcf76e4530b3077c6252b0d4827.tar.bz2
misskey-182a1bf653ecfbcf76e4530b3077c6252b0d4827.zip
Merge pull request #8783 from misskey-dev/develop
Release: 12.111.0
Diffstat (limited to 'packages/backend/src/models')
-rw-r--r--packages/backend/src/models/entities/access-token.ts6
-rw-r--r--packages/backend/src/models/entities/auth-session.ts2
-rw-r--r--packages/backend/src/models/entities/clip.ts2
-rw-r--r--packages/backend/src/models/entities/drive-file.ts1
-rw-r--r--packages/backend/src/models/entities/emoji.ts1
-rw-r--r--packages/backend/src/models/entities/instance.ts20
-rw-r--r--packages/backend/src/models/entities/meta.ts4
-rw-r--r--packages/backend/src/models/entities/muting.ts1
-rw-r--r--packages/backend/src/models/entities/note.ts6
-rw-r--r--packages/backend/src/models/entities/user-profile.ts1
-rw-r--r--packages/backend/src/models/entities/user.ts2
-rw-r--r--packages/backend/src/models/repositories/drive-file.ts47
-rw-r--r--packages/backend/src/models/repositories/note.ts36
-rw-r--r--packages/backend/src/models/repositories/page.ts6
-rw-r--r--packages/backend/src/models/repositories/user.ts91
15 files changed, 134 insertions, 92 deletions
diff --git a/packages/backend/src/models/entities/access-token.ts b/packages/backend/src/models/entities/access-token.ts
index 69cdc49cec..c6e2141a46 100644
--- a/packages/backend/src/models/entities/access-token.ts
+++ b/packages/backend/src/models/entities/access-token.ts
@@ -15,7 +15,6 @@ export class AccessToken {
@Column('timestamp with time zone', {
nullable: true,
- default: null,
})
public lastUsedAt: Date | null;
@@ -29,7 +28,6 @@ export class AccessToken {
@Column('varchar', {
length: 128,
nullable: true,
- default: null,
})
public session: string | null;
@@ -52,7 +50,6 @@ export class AccessToken {
@Column({
...id(),
nullable: true,
- default: null,
})
public appId: App['id'] | null;
@@ -65,21 +62,18 @@ export class AccessToken {
@Column('varchar', {
length: 128,
nullable: true,
- default: null,
})
public name: string | null;
@Column('varchar', {
length: 512,
nullable: true,
- default: null,
})
public description: string | null;
@Column('varchar', {
length: 512,
nullable: true,
- default: null,
})
public iconUrl: string | null;
diff --git a/packages/backend/src/models/entities/auth-session.ts b/packages/backend/src/models/entities/auth-session.ts
index b825856201..295d1b486c 100644
--- a/packages/backend/src/models/entities/auth-session.ts
+++ b/packages/backend/src/models/entities/auth-session.ts
@@ -23,7 +23,7 @@ export class AuthSession {
...id(),
nullable: true,
})
- public userId: User['id'];
+ public userId: User['id'] | null;
@ManyToOne(type => User, {
onDelete: 'CASCADE',
diff --git a/packages/backend/src/models/entities/clip.ts b/packages/backend/src/models/entities/clip.ts
index da6b3c7a7f..1386684c32 100644
--- a/packages/backend/src/models/entities/clip.ts
+++ b/packages/backend/src/models/entities/clip.ts
@@ -37,7 +37,7 @@ export class Clip {
public isPublic: boolean;
@Column('varchar', {
- length: 2048, nullable: true, default: null,
+ length: 2048, nullable: true,
comment: 'The description of the Clip.',
})
public description: string | null;
diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts
index 3d375f0e35..a636d1d519 100644
--- a/packages/backend/src/models/entities/drive-file.ts
+++ b/packages/backend/src/models/entities/drive-file.ts
@@ -79,7 +79,6 @@ export class DriveFile {
})
public properties: { width?: number; height?: number; orientation?: number; avgColor?: string };
- @Index()
@Column('boolean')
public storedInternal: boolean;
diff --git a/packages/backend/src/models/entities/emoji.ts b/packages/backend/src/models/entities/emoji.ts
index b72ca72331..7332dd1857 100644
--- a/packages/backend/src/models/entities/emoji.ts
+++ b/packages/backend/src/models/entities/emoji.ts
@@ -36,6 +36,7 @@ export class Emoji {
@Column('varchar', {
length: 512,
+ default: '',
})
public publicUrl: string;
diff --git a/packages/backend/src/models/entities/instance.ts b/packages/backend/src/models/entities/instance.ts
index bb24d6b30f..7ea9234384 100644
--- a/packages/backend/src/models/entities/instance.ts
+++ b/packages/backend/src/models/entities/instance.ts
@@ -107,53 +107,53 @@ export class Instance {
public isSuspended: boolean;
@Column('varchar', {
- length: 64, nullable: true, default: null,
+ length: 64, nullable: true,
comment: 'The software of the Instance.',
})
public softwareName: string | null;
@Column('varchar', {
- length: 64, nullable: true, default: null,
+ length: 64, nullable: true,
})
public softwareVersion: string | null;
@Column('boolean', {
- nullable: true, default: null,
+ nullable: true,
})
public openRegistrations: boolean | null;
@Column('varchar', {
- length: 256, nullable: true, default: null,
+ length: 256, nullable: true,
})
public name: string | null;
@Column('varchar', {
- length: 4096, nullable: true, default: null,
+ length: 4096, nullable: true,
})
public description: string | null;
@Column('varchar', {
- length: 128, nullable: true, default: null,
+ length: 128, nullable: true,
})
public maintainerName: string | null;
@Column('varchar', {
- length: 256, nullable: true, default: null,
+ length: 256, nullable: true,
})
public maintainerEmail: string | null;
@Column('varchar', {
- length: 256, nullable: true, default: null,
+ length: 256, nullable: true,
})
public iconUrl: string | null;
@Column('varchar', {
- length: 256, nullable: true, default: null,
+ length: 256, nullable: true,
})
public faviconUrl: string | null;
@Column('varchar', {
- length: 64, nullable: true, default: null,
+ length: 64, nullable: true,
})
public themeColor: string | null;
diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts
index 4d58b5f04f..80b5228bcd 100644
--- a/packages/backend/src/models/entities/meta.ts
+++ b/packages/backend/src/models/entities/meta.ts
@@ -78,7 +78,7 @@ export class Meta {
public blockedHosts: string[];
@Column('varchar', {
- length: 512, array: true, default: '{"/featured", "/channels", "/explore", "/pages", "/about-misskey"}',
+ length: 512, array: true, default: '{/featured,/channels,/explore,/pages,/about-misskey}',
})
public pinnedPages: string[];
@@ -346,14 +346,12 @@ export class Meta {
@Column('varchar', {
length: 8192,
- default: null,
nullable: true,
})
public defaultLightTheme: string | null;
@Column('varchar', {
length: 8192,
- default: null,
nullable: true,
})
public defaultDarkTheme: string | null;
diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts
index b3a7e7a671..8f9e69063a 100644
--- a/packages/backend/src/models/entities/muting.ts
+++ b/packages/backend/src/models/entities/muting.ts
@@ -17,7 +17,6 @@ export class Muting {
@Index()
@Column('timestamp with time zone', {
nullable: true,
- default: null,
})
public expiresAt: Date | null;
diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts
index da49d53b69..0ffeb85f69 100644
--- a/packages/backend/src/models/entities/note.ts
+++ b/packages/backend/src/models/entities/note.ts
@@ -53,8 +53,8 @@ export class Note {
})
public threadId: string | null;
- @Column('varchar', {
- length: 8192, nullable: true,
+ @Column('text', {
+ nullable: true,
})
public text: string | null;
@@ -179,7 +179,7 @@ export class Note {
@Index()
@Column({
...id(),
- nullable: true, default: null,
+ nullable: true,
comment: 'The ID of source channel.',
})
public channelId: Channel['id'] | null;
diff --git a/packages/backend/src/models/entities/user-profile.ts b/packages/backend/src/models/entities/user-profile.ts
index f95cb144c5..1778742ea2 100644
--- a/packages/backend/src/models/entities/user-profile.ts
+++ b/packages/backend/src/models/entities/user-profile.ts
@@ -192,6 +192,7 @@ export class UserProfile {
@Column('jsonb', {
default: [],
+ comment: 'List of instances muted by the user.',
})
public mutedInstances: string[];
diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts
index 29d9a0c2ca..df92fb8259 100644
--- a/packages/backend/src/models/entities/user.ts
+++ b/packages/backend/src/models/entities/user.ts
@@ -207,7 +207,7 @@ export class User {
@Column('boolean', {
default: false,
- comment: 'Whether to show users replying to other users in the timeline',
+ comment: 'Whether to show users replying to other users in the timeline.',
})
public showTimelineReplies: boolean;
diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts
index 69dc1721c2..0d589d4f11 100644
--- a/packages/backend/src/models/repositories/drive-file.ts
+++ b/packages/backend/src/models/repositories/drive-file.ts
@@ -1,6 +1,5 @@
import { db } from '@/db/postgre.js';
import { DriveFile } from '@/models/entities/drive-file.js';
-import { Users, DriveFolders } from '../index.js';
import { User } from '@/models/entities/user.js';
import { toPuny } from '@/misc/convert-host.js';
import { awaitAll, Promiseable } from '@/prelude/await-all.js';
@@ -9,6 +8,7 @@ import config from '@/config/index.js';
import { query, appendQuery } from '@/prelude/url.js';
import { Meta } from '@/models/entities/meta.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
+import { Users, DriveFolders } from '../index.js';
type PackOptions = {
detail?: boolean,
@@ -29,6 +29,8 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
getPublicProperties(file: DriveFile): DriveFile['properties'] {
if (file.properties.orientation != null) {
+ // TODO
+ //const properties = structuredClone(file.properties);
const properties = JSON.parse(JSON.stringify(file.properties));
if (file.properties.orientation >= 5) {
[properties.width, properties.height] = [properties.height, properties.width];
@@ -111,7 +113,40 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
async pack(
src: DriveFile['id'] | DriveFile,
- options?: PackOptions
+ options?: PackOptions,
+ ): Promise<Packed<'DriveFile'>> {
+ const opts = Object.assign({
+ detail: false,
+ self: false,
+ }, options);
+
+ const file = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src });
+
+ return await awaitAll<Packed<'DriveFile'>>({
+ id: file.id,
+ createdAt: file.createdAt.toISOString(),
+ name: file.name,
+ type: file.type,
+ md5: file.md5,
+ size: file.size,
+ isSensitive: file.isSensitive,
+ blurhash: file.blurhash,
+ properties: opts.self ? file.properties : this.getPublicProperties(file),
+ url: opts.self ? file.url : this.getPublicUrl(file, false),
+ thumbnailUrl: this.getPublicUrl(file, true),
+ comment: file.comment,
+ folderId: file.folderId,
+ folder: opts.detail && file.folderId ? DriveFolders.pack(file.folderId, {
+ detail: true,
+ }) : null,
+ userId: opts.withUser ? file.userId : null,
+ user: (opts.withUser && file.userId) ? Users.pack(file.userId) : null,
+ });
+ },
+
+ async packNullable(
+ src: DriveFile['id'] | DriveFile,
+ options?: PackOptions,
): Promise<Packed<'DriveFile'> | null> {
const opts = Object.assign({
detail: false,
@@ -145,9 +180,9 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
async packMany(
files: (DriveFile['id'] | DriveFile)[],
- options?: PackOptions
- ) {
- const items = await Promise.all(files.map(f => this.pack(f, options)));
- return items.filter(x => x != null);
+ options?: PackOptions,
+ ): Promise<Packed<'DriveFile'>[]> {
+ const items = await Promise.all(files.map(f => this.packNullable(f, options)));
+ return items.filter((x): x is Packed<'DriveFile'> => x != null);
},
});
diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts
index cf5fcb1787..3fefab0319 100644
--- a/packages/backend/src/models/repositories/note.ts
+++ b/packages/backend/src/models/repositories/note.ts
@@ -136,6 +136,7 @@ async function populateMyReaction(note: Note, meId: User['id'], _hint_?: {
export const NoteRepository = db.getRepository(Note).extend({
async isVisibleForMe(note: Note, meId: User['id'] | null): Promise<boolean> {
+ // This code must always be synchronized with the checks in generateVisibilityQuery.
// visibility が specified かつ自分が指定されていなかったら非表示
if (note.visibility === 'specified') {
if (meId == null) {
@@ -144,13 +145,7 @@ export const NoteRepository = db.getRepository(Note).extend({
return true;
} else {
// 指定されているかどうか
- const specified = note.visibleUserIds.some((id: any) => meId === id);
-
- if (specified) {
- return true;
- } else {
- return false;
- }
+ return note.visibleUserIds.some((id: any) => meId === id);
}
}
@@ -168,16 +163,25 @@ export const NoteRepository = db.getRepository(Note).extend({
return true;
} else {
// フォロワーかどうか
- const following = await Followings.findOneBy({
- followeeId: note.userId,
- followerId: meId,
- });
+ const [following, user] = await Promise.all([
+ Followings.count({
+ where: {
+ followeeId: note.userId,
+ followerId: meId,
+ },
+ take: 1,
+ }),
+ Users.findOneByOrFail({ id: meId }),
+ ]);
- if (following == null) {
- return false;
- } else {
- return true;
- }
+ /* If we know the following, everyhting is fine.
+
+ But if we do not know the following, it might be that both the
+ author of the note and the author of the like are remote users,
+ in which case we can never know the following. Instead we have
+ to assume that the users are following each other.
+ */
+ return following > 0 || (note.userHost != null && user.host != null);
}
}
diff --git a/packages/backend/src/models/repositories/page.ts b/packages/backend/src/models/repositories/page.ts
index 1bffb23fa2..092b26b396 100644
--- a/packages/backend/src/models/repositories/page.ts
+++ b/packages/backend/src/models/repositories/page.ts
@@ -1,10 +1,10 @@
import { db } from '@/db/postgre.js';
import { Page } from '@/models/entities/page.js';
import { Packed } from '@/misc/schema.js';
-import { Users, DriveFiles, PageLikes } from '../index.js';
import { awaitAll } from '@/prelude/await-all.js';
import { DriveFile } from '@/models/entities/drive-file.js';
import { User } from '@/models/entities/user.js';
+import { Users, DriveFiles, PageLikes } from '../index.js';
export const PageRepository = db.getRepository(Page).extend({
async pack(
@@ -14,7 +14,7 @@ export const PageRepository = db.getRepository(Page).extend({
const meId = me ? me.id : null;
const page = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src });
- const attachedFiles: Promise<DriveFile | undefined>[] = [];
+ const attachedFiles: Promise<DriveFile | null>[] = [];
const collectFile = (xs: any[]) => {
for (const x of xs) {
if (x.type === 'image') {
@@ -73,7 +73,7 @@ export const PageRepository = db.getRepository(Page).extend({
script: page.script,
eyeCatchingImageId: page.eyeCatchingImageId,
eyeCatchingImage: page.eyeCatchingImageId ? await DriveFiles.pack(page.eyeCatchingImageId) : null,
- attachedFiles: DriveFiles.packMany(await Promise.all(attachedFiles)),
+ attachedFiles: DriveFiles.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null)),
likedCount: page.likedCount,
isLiked: meId ? await PageLikes.findOneBy({ pageId: page.id, userId: meId }).then(x => x != null) : undefined,
});
diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts
index 541fbaf003..8a4e48efdd 100644
--- a/packages/backend/src/models/repositories/user.ts
+++ b/packages/backend/src/models/repositories/user.ts
@@ -61,47 +61,58 @@ export const UserRepository = db.getRepository(User).extend({
//#endregion
async getRelation(me: User['id'], target: User['id']) {
- const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([
- Followings.findOneBy({
- followerId: me,
- followeeId: target,
- }),
- Followings.findOneBy({
- followerId: target,
- followeeId: me,
- }),
- FollowRequests.findOneBy({
- followerId: me,
- followeeId: target,
- }),
- FollowRequests.findOneBy({
- followerId: target,
- followeeId: me,
- }),
- Blockings.findOneBy({
- blockerId: me,
- blockeeId: target,
- }),
- Blockings.findOneBy({
- blockerId: target,
- blockeeId: me,
- }),
- Mutings.findOneBy({
- muterId: me,
- muteeId: target,
- }),
- ]);
-
- return {
+ return awaitAll({
id: target,
- isFollowing: following1 != null,
- hasPendingFollowRequestFromYou: followReq1 != null,
- hasPendingFollowRequestToYou: followReq2 != null,
- isFollowed: following2 != null,
- isBlocking: toBlocking != null,
- isBlocked: fromBlocked != null,
- isMuted: mute != null,
- };
+ isFollowing: Followings.count({
+ where: {
+ followerId: me,
+ followeeId: target,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ isFollowed: Followings.count({
+ where: {
+ followerId: target,
+ followeeId: me,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ hasPendingFollowRequestFromYou: FollowRequests.count({
+ where: {
+ followerId: me,
+ followeeId: target,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ hasPendingFollowRequestToYou: FollowRequests.count({
+ where: {
+ followerId: target,
+ followeeId: me,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ isBlocking: Blockings.count({
+ where: {
+ blockerId: me,
+ blockeeId: target,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ isBlocked: Blockings.count({
+ where: {
+ blockerId: target,
+ blockeeId: me,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ isMuted: Mutings.count({
+ where: {
+ muterId: me,
+ muteeId: target,
+ },
+ take: 1,
+ }).then(n => n > 0),
+ });
},
async getHasUnreadMessagingMessage(userId: User['id']): Promise<boolean> {