refactor: migrate to typeorm 3.0 (#8443)
* wip * wip * wip * Update following.ts * wip * wip * wip * Update resolve-user.ts * maxQueryExecutionTime * wip * wip
This commit is contained in:
		
							parent
							
								
									41c87074e6
								
							
						
					
					
						commit
						1c67c26bd8
					
				
					 325 changed files with 1314 additions and 1494 deletions
				
			
		|  | @ -198,11 +198,13 @@ MongoDBの時とは違い、findOneでレコードを取得する時に対象レ | ||||||
| MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください | MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください | ||||||
| 
 | 
 | ||||||
| ### Migration作成方法 | ### Migration作成方法 | ||||||
| ``` | packages/backendで: | ||||||
| npx ts-node ./node_modules/typeorm/cli.js migration:generate -n 変更の名前 -o | ```sh | ||||||
|  | npx typeorm migration:generate -d ormconfig.js -o <migration name> | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| 作成されたスクリプトは不必要な変更を含むため除去してください。 | - 生成後、ファイルをmigration下に移してください | ||||||
|  | - 作成されたスクリプトは不必要な変更を含むため除去してください | ||||||
| 
 | 
 | ||||||
| ### コネクションには`markRaw`せよ | ### コネクションには`markRaw`せよ | ||||||
| **Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。 | **Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。 | ||||||
|  |  | ||||||
|  | @ -13,8 +13,7 @@ | ||||||
| 		"start": "cd packages/backend && node --experimental-json-modules ./built/index.js", | 		"start": "cd packages/backend && node --experimental-json-modules ./built/index.js", | ||||||
| 		"start:test": "cd packages/backend && cross-env NODE_ENV=test node --experimental-json-modules ./built/index.js", | 		"start:test": "cd packages/backend && cross-env NODE_ENV=test node --experimental-json-modules ./built/index.js", | ||||||
| 		"init": "npm run migrate", | 		"init": "npm run migrate", | ||||||
| 		"ormconfig": "node ./packages/backend/ormconfig.js", | 		"migrate": "cd packages/backend && npx typeorm migration:run -d ormconfig.js", | ||||||
| 		"migrate": "cd packages/backend && npx typeorm migration:run", |  | ||||||
| 		"migrateandstart": "npm run migrate && npm run start", | 		"migrateandstart": "npm run migrate && npm run start", | ||||||
| 		"gulp": "gulp build", | 		"gulp": "gulp build", | ||||||
| 		"watch": "npm run dev", | 		"watch": "npm run dev", | ||||||
|  |  | ||||||
|  | @ -1,7 +1,8 @@ | ||||||
|  | import { DataSource } from 'typeorm'; | ||||||
| import config from './built/config/index.js'; | import config from './built/config/index.js'; | ||||||
| import { entities } from './built/db/postgre.js'; | import { entities } from './built/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| export default { | export default new DataSource({ | ||||||
| 	type: 'postgres', | 	type: 'postgres', | ||||||
| 	host: config.db.host, | 	host: config.db.host, | ||||||
| 	port: config.db.port, | 	port: config.db.port, | ||||||
|  | @ -11,7 +12,4 @@ export default { | ||||||
| 	extra: config.db.extra, | 	extra: config.db.extra, | ||||||
| 	entities: entities, | 	entities: entities, | ||||||
| 	migrations: ['migration/*.js'], | 	migrations: ['migration/*.js'], | ||||||
| 	cli: { | }); | ||||||
| 		migrationsDir: 'migration' |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ | ||||||
| 	"private": true, | 	"private": true, | ||||||
| 	"type": "module", | 	"type": "module", | ||||||
| 	"scripts": { | 	"scripts": { | ||||||
| 		"init": "npm run migrate", |  | ||||||
| 		"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", | 		"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", | ||||||
| 		"watch": "node watch.mjs", | 		"watch": "node watch.mjs", | ||||||
| 		"lint": "eslint --quiet src/**/*.ts", | 		"lint": "eslint --quiet src/**/*.ts", | ||||||
|  | @ -163,7 +162,7 @@ | ||||||
| 		"tsc-alias": "1.4.1", | 		"tsc-alias": "1.4.1", | ||||||
| 		"tsconfig-paths": "3.14.0", | 		"tsconfig-paths": "3.14.0", | ||||||
| 		"twemoji-parser": "14.0.0", | 		"twemoji-parser": "14.0.0", | ||||||
| 		"typeorm": "0.2.45", | 		"typeorm": "0.3.3", | ||||||
| 		"typescript": "4.6.3", | 		"typescript": "4.6.3", | ||||||
| 		"ulid": "2.3.0", | 		"ulid": "2.3.0", | ||||||
| 		"unzipper": "0.10.11", | 		"unzipper": "0.10.11", | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ import chalk from 'chalk'; | ||||||
| import chalkTemplate from 'chalk-template'; | import chalkTemplate from 'chalk-template'; | ||||||
| import * as portscanner from 'portscanner'; | import * as portscanner from 'portscanner'; | ||||||
| import semver from 'semver'; | import semver from 'semver'; | ||||||
| import { getConnection } from 'typeorm'; |  | ||||||
| 
 | 
 | ||||||
| import Logger from '@/services/logger.js'; | import Logger from '@/services/logger.js'; | ||||||
| import loadConfig from '@/config/load.js'; | import loadConfig from '@/config/load.js'; | ||||||
|  | @ -15,7 +14,7 @@ import { Config } from '@/config/types.js'; | ||||||
| import { lessThan } from '@/prelude/array.js'; | import { lessThan } from '@/prelude/array.js'; | ||||||
| import { envOption } from '../env.js'; | import { envOption } from '../env.js'; | ||||||
| import { showMachineInfo } from '@/misc/show-machine-info.js'; | import { showMachineInfo } from '@/misc/show-machine-info.js'; | ||||||
| import { initDb } from '../db/postgre.js'; | import { db, initDb } from '../db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| const _filename = fileURLToPath(import.meta.url); | const _filename = fileURLToPath(import.meta.url); | ||||||
| const _dirname = dirname(_filename); | const _dirname = dirname(_filename); | ||||||
|  | @ -144,7 +143,7 @@ async function connectDb(): Promise<void> { | ||||||
| 	try { | 	try { | ||||||
| 		dbLogger.info('Connecting...'); | 		dbLogger.info('Connecting...'); | ||||||
| 		await initDb(); | 		await initDb(); | ||||||
| 		const v = await getConnection().query('SHOW server_version').then(x => x[0].server_version); | 		const v = await db.query('SHOW server_version').then(x => x[0].server_version); | ||||||
| 		dbLogger.succ(`Connected: v${v}`); | 		dbLogger.succ(`Connected: v${v}`); | ||||||
| 	} catch (e) { | 	} catch (e) { | ||||||
| 		dbLogger.error('Cannot connect', null, true); | 		dbLogger.error('Cannot connect', null, true); | ||||||
|  |  | ||||||
|  | @ -2,9 +2,10 @@ | ||||||
| import pg from 'pg'; | import pg from 'pg'; | ||||||
| pg.types.setTypeParser(20, Number); | pg.types.setTypeParser(20, Number); | ||||||
| 
 | 
 | ||||||
| import { createConnection, Logger, getConnection } from 'typeorm'; | import { Logger, DataSource } from 'typeorm'; | ||||||
| import * as highlight from 'cli-highlight'; | import * as highlight from 'cli-highlight'; | ||||||
| import config from '@/config/index.js'; | import config from '@/config/index.js'; | ||||||
|  | import { envOption } from '../env.js'; | ||||||
| 
 | 
 | ||||||
| import { dbLogger } from './logger.js'; | import { dbLogger } from './logger.js'; | ||||||
| 
 | 
 | ||||||
|  | @ -61,7 +62,6 @@ import { Antenna } from '@/models/entities/antenna.js'; | ||||||
| import { AntennaNote } from '@/models/entities/antenna-note.js'; | import { AntennaNote } from '@/models/entities/antenna-note.js'; | ||||||
| import { PromoNote } from '@/models/entities/promo-note.js'; | import { PromoNote } from '@/models/entities/promo-note.js'; | ||||||
| import { PromoRead } from '@/models/entities/promo-read.js'; | import { PromoRead } from '@/models/entities/promo-read.js'; | ||||||
| import { envOption } from '../env.js'; |  | ||||||
| import { Relay } from '@/models/entities/relay.js'; | import { Relay } from '@/models/entities/relay.js'; | ||||||
| import { MutedNote } from '@/models/entities/muted-note.js'; | import { MutedNote } from '@/models/entities/muted-note.js'; | ||||||
| import { Channel } from '@/models/entities/channel.js'; | import { Channel } from '@/models/entities/channel.js'; | ||||||
|  | @ -74,7 +74,7 @@ import { UserPending } from '@/models/entities/user-pending.js'; | ||||||
| 
 | 
 | ||||||
| import { entities as charts } from '@/services/chart/entities.js'; | import { entities as charts } from '@/services/chart/entities.js'; | ||||||
| 
 | 
 | ||||||
| const sqlLogger = dbLogger.createSubLogger('sql', 'white', false); | const sqlLogger = dbLogger.createSubLogger('sql', 'gray', false); | ||||||
| 
 | 
 | ||||||
| class MyCustomLogger implements Logger { | class MyCustomLogger implements Logger { | ||||||
| 	private highlight(sql: string) { | 	private highlight(sql: string) { | ||||||
|  | @ -84,9 +84,7 @@ class MyCustomLogger implements Logger { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public logQuery(query: string, parameters?: any[]) { | 	public logQuery(query: string, parameters?: any[]) { | ||||||
| 		if (envOption.verbose) { | 		sqlLogger.info(this.highlight(query).substring(0, 100)); | ||||||
| 			sqlLogger.info(this.highlight(query).substring(0, 100)); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public logQueryError(error: string, query: string, parameters?: any[]) { | 	public logQueryError(error: string, query: string, parameters?: any[]) { | ||||||
|  | @ -176,55 +174,51 @@ export const entities = [ | ||||||
| 	...charts, | 	...charts, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| export function initDb(justBorrow = false, sync = false, forceRecreate = false) { | const log = process.env.NODE_ENV !== 'production'; | ||||||
| 	if (!forceRecreate) { |  | ||||||
| 		try { |  | ||||||
| 			const conn = getConnection(); |  | ||||||
| 			return Promise.resolve(conn); |  | ||||||
| 		} catch (e) {} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	const log = process.env.NODE_ENV !== 'production'; | export const db = new DataSource({ | ||||||
| 
 | 	type: 'postgres', | ||||||
| 	return createConnection({ | 	host: config.db.host, | ||||||
| 		type: 'postgres', | 	port: config.db.port, | ||||||
| 		host: config.db.host, | 	username: config.db.user, | ||||||
| 		port: config.db.port, | 	password: config.db.pass, | ||||||
| 		username: config.db.user, | 	database: config.db.db, | ||||||
| 		password: config.db.pass, | 	extra: { | ||||||
| 		database: config.db.db, | 		statement_timeout: 1000 * 10, | ||||||
| 		extra: { | 		...config.db.extra, | ||||||
| 			statement_timeout: 1000 * 10, | 	}, | ||||||
| 			...config.db.extra, | 	synchronize: process.env.NODE_ENV === 'test', | ||||||
|  | 	dropSchema: process.env.NODE_ENV === 'test', | ||||||
|  | 	cache: !config.db.disableCache ? { | ||||||
|  | 		type: 'redis', | ||||||
|  | 		options: { | ||||||
|  | 			host: config.redis.host, | ||||||
|  | 			port: config.redis.port, | ||||||
|  | 			password: config.redis.pass, | ||||||
|  | 			prefix: `${config.redis.prefix}:query:`, | ||||||
|  | 			db: config.redis.db || 0, | ||||||
| 		}, | 		}, | ||||||
| 		synchronize: process.env.NODE_ENV === 'test' || sync, | 	} : false, | ||||||
| 		dropSchema: process.env.NODE_ENV === 'test' && !justBorrow, | 	logging: log, | ||||||
| 		cache: !config.db.disableCache ? { | 	logger: log ? new MyCustomLogger() : undefined, | ||||||
| 			type: 'redis', | 	maxQueryExecutionTime: 300, | ||||||
| 			options: { | 	entities: entities, | ||||||
| 				host: config.redis.host, | 	migrations: ['../../migration/*.js'], | ||||||
| 				port: config.redis.port, | }); | ||||||
| 				password: config.redis.pass, | 
 | ||||||
| 				prefix: `${config.redis.prefix}:query:`, | export async function initDb() { | ||||||
| 				db: config.redis.db || 0, | 	await db.connect(); | ||||||
| 			}, |  | ||||||
| 		} : false, |  | ||||||
| 		logging: log, |  | ||||||
| 		logger: log ? new MyCustomLogger() : undefined, |  | ||||||
| 		entities: entities, |  | ||||||
| 	}); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function resetDb() { | export async function resetDb() { | ||||||
| 	const reset = async () => { | 	const reset = async () => { | ||||||
| 		const conn = await getConnection(); | 		const tables = await db.query(`SELECT relname AS "table"
 | ||||||
| 		const tables = await conn.query(`SELECT relname AS "table"
 |  | ||||||
| 		FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) | 		FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) | ||||||
| 		WHERE nspname NOT IN ('pg_catalog', 'information_schema') | 		WHERE nspname NOT IN ('pg_catalog', 'information_schema') | ||||||
| 			AND C.relkind = 'r' | 			AND C.relkind = 'r' | ||||||
| 			AND nspname !~ '^pg_toast';`);
 | 			AND nspname !~ '^pg_toast';`);
 | ||||||
| 		for (const table of tables) { | 		for (const table of tables) { | ||||||
| 			await conn.query(`DELETE FROM "${table.table}" CASCADE`); | 			await db.query(`DELETE FROM "${table.table}" CASCADE`); | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ export async function checkHitAntenna(antenna: Antenna, note: (Note | Packed<'No | ||||||
| 	if (note.visibility === 'specified') return false; | 	if (note.visibility === 'specified') return false; | ||||||
| 
 | 
 | ||||||
| 	// アンテナ作成者がノート作成者にブロックされていたらスキップ
 | 	// アンテナ作成者がノート作成者にブロックされていたらスキップ
 | ||||||
| 	const blockings = await blockingCache.fetch(noteUser.id, () => Blockings.find({ blockerId: noteUser.id }).then(res => res.map(x => x.blockeeId))); | 	const blockings = await blockingCache.fetch(noteUser.id, () => Blockings.findBy({ blockerId: noteUser.id }).then(res => res.map(x => x.blockeeId))); | ||||||
| 	if (blockings.some(blocking => blocking === antenna.userId)) return false; | 	if (blockings.some(blocking => blocking === antenna.userId)) return false; | ||||||
| 
 | 
 | ||||||
| 	if (note.visibility === 'followers') { | 	if (note.visibility === 'followers') { | ||||||
|  | @ -32,15 +32,15 @@ export async function checkHitAntenna(antenna: Antenna, note: (Note | Packed<'No | ||||||
| 		if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) return false; | 		if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) return false; | ||||||
| 		if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false; | 		if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false; | ||||||
| 	} else if (antenna.src === 'list') { | 	} else if (antenna.src === 'list') { | ||||||
| 		const listUsers = (await UserListJoinings.find({ | 		const listUsers = (await UserListJoinings.findBy({ | ||||||
| 			userListId: antenna.userListId!, | 			userListId: antenna.userListId!, | ||||||
| 		})).map(x => x.userId); | 		})).map(x => x.userId); | ||||||
| 
 | 
 | ||||||
| 		if (!listUsers.includes(note.userId)) return false; | 		if (!listUsers.includes(note.userId)) return false; | ||||||
| 	} else if (antenna.src === 'group') { | 	} else if (antenna.src === 'group') { | ||||||
| 		const joining = await UserGroupJoinings.findOneOrFail(antenna.userGroupJoiningId!); | 		const joining = await UserGroupJoinings.findOneByOrFail({ id: antenna.userGroupJoiningId! }); | ||||||
| 
 | 
 | ||||||
| 		const groupUsers = (await UserGroupJoinings.find({ | 		const groupUsers = (await UserGroupJoinings.findBy({ | ||||||
| 			userGroupId: joining.userGroupId, | 			userGroupId: joining.userGroupId, | ||||||
| 		})).map(x => x.userId); | 		})).map(x => x.userId); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| import { Meta } from '@/models/entities/meta.js'; | import { Meta } from '@/models/entities/meta.js'; | ||||||
| import { getConnection } from 'typeorm'; |  | ||||||
| 
 | 
 | ||||||
| let cache: Meta; | let cache: Meta; | ||||||
| 
 | 
 | ||||||
| export async function fetchMeta(noCache = false): Promise<Meta> { | export async function fetchMeta(noCache = false): Promise<Meta> { | ||||||
| 	if (!noCache && cache) return cache; | 	if (!noCache && cache) return cache; | ||||||
| 
 | 
 | ||||||
| 	return await getConnection().transaction(async transactionalEntityManager => { | 	return await db.transaction(async transactionalEntityManager => { | ||||||
| 		// 過去のバグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する
 | 		// 過去のバグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する
 | ||||||
| 		const meta = await transactionalEntityManager.findOne(Meta, { | 		const meta = await transactionalEntityManager.findOne(Meta, { | ||||||
| 			order: { | 			order: { | ||||||
|  |  | ||||||
|  | @ -5,5 +5,5 @@ import { Users } from '@/models/index.js'; | ||||||
| export async function fetchProxyAccount(): Promise<ILocalUser | null> { | export async function fetchProxyAccount(): Promise<ILocalUser | null> { | ||||||
| 	const meta = await fetchMeta(); | 	const meta = await fetchMeta(); | ||||||
| 	if (meta.proxyAccountId == null) return null; | 	if (meta.proxyAccountId == null) return null; | ||||||
| 	return await Users.findOneOrFail(meta.proxyAccountId) as ILocalUser; | 	return await Users.findOneByOrFail({ id: meta.proxyAccountId }) as ILocalUser; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,5 +6,5 @@ import { Cache } from './cache.js'; | ||||||
| const cache = new Cache<UserKeypair>(Infinity); | const cache = new Cache<UserKeypair>(Infinity); | ||||||
| 
 | 
 | ||||||
| export async function getUserKeypair(userId: User['id']): Promise<UserKeypair> { | export async function getUserKeypair(userId: User['id']): Promise<UserKeypair> { | ||||||
| 	return await cache.fetch(userId, () => UserKeypairs.findOneOrFail(userId)); | 	return await cache.fetch(userId, () => UserKeypairs.findOneByOrFail({ userId: userId })); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { In } from 'typeorm'; | import { In, IsNull } from 'typeorm'; | ||||||
| import { Emojis } from '@/models/index.js'; | import { Emojis } from '@/models/index.js'; | ||||||
| import { Emoji } from '@/models/entities/emoji.js'; | import { Emoji } from '@/models/entities/emoji.js'; | ||||||
| import { Note } from '@/models/entities/note.js'; | import { Note } from '@/models/entities/note.js'; | ||||||
|  | @ -52,9 +52,9 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu | ||||||
| 	const { name, host } = parseEmojiStr(emojiName, noteUserHost); | 	const { name, host } = parseEmojiStr(emojiName, noteUserHost); | ||||||
| 	if (name == null) return null; | 	if (name == null) return null; | ||||||
| 
 | 
 | ||||||
| 	const queryOrNull = async () => (await Emojis.findOne({ | 	const queryOrNull = async () => (await Emojis.findOneBy({ | ||||||
| 		name, | 		name, | ||||||
| 		host, | 		host: host ?? IsNull(), | ||||||
| 	})) || null; | 	})) || null; | ||||||
| 
 | 
 | ||||||
| 	const emoji = await cache.fetch(`${name} ${host}`, queryOrNull); | 	const emoji = await cache.fetch(`${name} ${host}`, queryOrNull); | ||||||
|  | @ -112,7 +112,7 @@ export async function prefetchEmojis(emojis: { name: string; host: string | null | ||||||
| 	for (const host of hosts) { | 	for (const host of hosts) { | ||||||
| 		emojisQuery.push({ | 		emojisQuery.push({ | ||||||
| 			name: In(notCachedEmojis.filter(e => e.host === host).map(e => e.name)), | 			name: In(notCachedEmojis.filter(e => e.host === host).map(e => e.name)), | ||||||
| 			host: host, | 			host: host ?? IsNull(), | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 	const _emojis = emojisQuery.length > 0 ? await Emojis.find({ | 	const _emojis = emojisQuery.length > 0 ? await Emojis.find({ | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ import { emojiRegex } from './emoji-regex.js'; | ||||||
| import { fetchMeta } from './fetch-meta.js'; | import { fetchMeta } from './fetch-meta.js'; | ||||||
| import { Emojis } from '@/models/index.js'; | import { Emojis } from '@/models/index.js'; | ||||||
| import { toPunyNullable } from './convert-host.js'; | import { toPunyNullable } from './convert-host.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const legacies: Record<string, string> = { | const legacies: Record<string, string> = { | ||||||
| 	'like':     '👍', | 	'like':     '👍', | ||||||
|  | @ -74,8 +75,8 @@ export async function toDbReaction(reaction?: string | null, reacterHost?: strin | ||||||
| 	const custom = reaction.match(/^:([\w+-]+)(?:@\.)?:$/); | 	const custom = reaction.match(/^:([\w+-]+)(?:@\.)?:$/); | ||||||
| 	if (custom) { | 	if (custom) { | ||||||
| 		const name = custom[1]; | 		const name = custom[1]; | ||||||
| 		const emoji = await Emojis.findOne({ | 		const emoji = await Emojis.findOneBy({ | ||||||
| 			host: reacterHost || null, | 			host: reacterHost ?? IsNull(), | ||||||
| 			name, | 			name, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| import { getRepository, getCustomRepository } from 'typeorm'; | import { } from 'typeorm'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
|  | 
 | ||||||
| import { Announcement } from './entities/announcement.js'; | import { Announcement } from './entities/announcement.js'; | ||||||
| import { AnnouncementRead } from './entities/announcement-read.js'; | import { AnnouncementRead } from './entities/announcement-read.js'; | ||||||
| import { Instance } from './entities/instance.js'; | import { Instance } from './entities/instance.js'; | ||||||
|  | @ -63,65 +65,65 @@ import { PasswordResetRequest } from './entities/password-reset-request.js'; | ||||||
| import { UserPending } from './entities/user-pending.js'; | import { UserPending } from './entities/user-pending.js'; | ||||||
| import { InstanceRepository } from './repositories/instance.js'; | import { InstanceRepository } from './repositories/instance.js'; | ||||||
| 
 | 
 | ||||||
| export const Announcements = getRepository(Announcement); | export const Announcements = db.getRepository(Announcement); | ||||||
| export const AnnouncementReads = getRepository(AnnouncementRead); | export const AnnouncementReads = db.getRepository(AnnouncementRead); | ||||||
| export const Apps = getCustomRepository(AppRepository); | export const Apps = (AppRepository); | ||||||
| export const Notes = getCustomRepository(NoteRepository); | export const Notes = (NoteRepository); | ||||||
| export const NoteFavorites = getCustomRepository(NoteFavoriteRepository); | export const NoteFavorites = (NoteFavoriteRepository); | ||||||
| export const NoteWatchings = getRepository(NoteWatching); | export const NoteWatchings = db.getRepository(NoteWatching); | ||||||
| export const NoteThreadMutings = getRepository(NoteThreadMuting); | export const NoteThreadMutings = db.getRepository(NoteThreadMuting); | ||||||
| export const NoteReactions = getCustomRepository(NoteReactionRepository); | export const NoteReactions = (NoteReactionRepository); | ||||||
| export const NoteUnreads = getRepository(NoteUnread); | export const NoteUnreads = db.getRepository(NoteUnread); | ||||||
| export const Polls = getRepository(Poll); | export const Polls = db.getRepository(Poll); | ||||||
| export const PollVotes = getRepository(PollVote); | export const PollVotes = db.getRepository(PollVote); | ||||||
| export const Users = getCustomRepository(UserRepository); | export const Users = (UserRepository); | ||||||
| export const UserProfiles = getRepository(UserProfile); | export const UserProfiles = db.getRepository(UserProfile); | ||||||
| export const UserKeypairs = getRepository(UserKeypair); | export const UserKeypairs = db.getRepository(UserKeypair); | ||||||
| export const UserPendings = getRepository(UserPending); | export const UserPendings = db.getRepository(UserPending); | ||||||
| export const AttestationChallenges = getRepository(AttestationChallenge); | export const AttestationChallenges = db.getRepository(AttestationChallenge); | ||||||
| export const UserSecurityKeys = getRepository(UserSecurityKey); | export const UserSecurityKeys = db.getRepository(UserSecurityKey); | ||||||
| export const UserPublickeys = getRepository(UserPublickey); | export const UserPublickeys = db.getRepository(UserPublickey); | ||||||
| export const UserLists = getCustomRepository(UserListRepository); | export const UserLists = (UserListRepository); | ||||||
| export const UserListJoinings = getRepository(UserListJoining); | export const UserListJoinings = db.getRepository(UserListJoining); | ||||||
| export const UserGroups = getCustomRepository(UserGroupRepository); | export const UserGroups = (UserGroupRepository); | ||||||
| export const UserGroupJoinings = getRepository(UserGroupJoining); | export const UserGroupJoinings = db.getRepository(UserGroupJoining); | ||||||
| export const UserGroupInvitations = getCustomRepository(UserGroupInvitationRepository); | export const UserGroupInvitations = (UserGroupInvitationRepository); | ||||||
| export const UserNotePinings = getRepository(UserNotePining); | export const UserNotePinings = db.getRepository(UserNotePining); | ||||||
| export const UsedUsernames = getRepository(UsedUsername); | export const UsedUsernames = db.getRepository(UsedUsername); | ||||||
| export const Followings = getCustomRepository(FollowingRepository); | export const Followings = (FollowingRepository); | ||||||
| export const FollowRequests = getCustomRepository(FollowRequestRepository); | export const FollowRequests = (FollowRequestRepository); | ||||||
| export const Instances = getCustomRepository(InstanceRepository); | export const Instances = (InstanceRepository); | ||||||
| export const Emojis = getCustomRepository(EmojiRepository); | export const Emojis = (EmojiRepository); | ||||||
| export const DriveFiles = getCustomRepository(DriveFileRepository); | export const DriveFiles = (DriveFileRepository); | ||||||
| export const DriveFolders = getCustomRepository(DriveFolderRepository); | export const DriveFolders = (DriveFolderRepository); | ||||||
| export const Notifications = getCustomRepository(NotificationRepository); | export const Notifications = (NotificationRepository); | ||||||
| export const Metas = getRepository(Meta); | export const Metas = db.getRepository(Meta); | ||||||
| export const Mutings = getCustomRepository(MutingRepository); | export const Mutings = (MutingRepository); | ||||||
| export const Blockings = getCustomRepository(BlockingRepository); | export const Blockings = (BlockingRepository); | ||||||
| export const SwSubscriptions = getRepository(SwSubscription); | export const SwSubscriptions = db.getRepository(SwSubscription); | ||||||
| export const Hashtags = getCustomRepository(HashtagRepository); | export const Hashtags = (HashtagRepository); | ||||||
| export const AbuseUserReports = getCustomRepository(AbuseUserReportRepository); | export const AbuseUserReports = (AbuseUserReportRepository); | ||||||
| export const RegistrationTickets = getRepository(RegistrationTicket); | export const RegistrationTickets = db.getRepository(RegistrationTicket); | ||||||
| export const AuthSessions = getCustomRepository(AuthSessionRepository); | export const AuthSessions = (AuthSessionRepository); | ||||||
| export const AccessTokens = getRepository(AccessToken); | export const AccessTokens = db.getRepository(AccessToken); | ||||||
| export const Signins = getCustomRepository(SigninRepository); | export const Signins = (SigninRepository); | ||||||
| export const MessagingMessages = getCustomRepository(MessagingMessageRepository); | export const MessagingMessages = (MessagingMessageRepository); | ||||||
| export const Pages = getCustomRepository(PageRepository); | export const Pages = (PageRepository); | ||||||
| export const PageLikes = getCustomRepository(PageLikeRepository); | export const PageLikes = (PageLikeRepository); | ||||||
| export const GalleryPosts = getCustomRepository(GalleryPostRepository); | export const GalleryPosts = (GalleryPostRepository); | ||||||
| export const GalleryLikes = getCustomRepository(GalleryLikeRepository); | export const GalleryLikes = (GalleryLikeRepository); | ||||||
| export const ModerationLogs = getCustomRepository(ModerationLogRepository); | export const ModerationLogs = (ModerationLogRepository); | ||||||
| export const Clips = getCustomRepository(ClipRepository); | export const Clips = (ClipRepository); | ||||||
| export const ClipNotes = getRepository(ClipNote); | export const ClipNotes = db.getRepository(ClipNote); | ||||||
| export const Antennas = getCustomRepository(AntennaRepository); | export const Antennas = (AntennaRepository); | ||||||
| export const AntennaNotes = getRepository(AntennaNote); | export const AntennaNotes = db.getRepository(AntennaNote); | ||||||
| export const PromoNotes = getRepository(PromoNote); | export const PromoNotes = db.getRepository(PromoNote); | ||||||
| export const PromoReads = getRepository(PromoRead); | export const PromoReads = db.getRepository(PromoRead); | ||||||
| export const Relays = getCustomRepository(RelayRepository); | export const Relays = (RelayRepository); | ||||||
| export const MutedNotes = getRepository(MutedNote); | export const MutedNotes = db.getRepository(MutedNote); | ||||||
| export const Channels = getCustomRepository(ChannelRepository); | export const Channels = (ChannelRepository); | ||||||
| export const ChannelFollowings = getRepository(ChannelFollowing); | export const ChannelFollowings = db.getRepository(ChannelFollowing); | ||||||
| export const ChannelNotePinings = getRepository(ChannelNotePining); | export const ChannelNotePinings = db.getRepository(ChannelNotePining); | ||||||
| export const RegistryItems = getRepository(RegistryItem); | export const RegistryItems = db.getRepository(RegistryItem); | ||||||
| export const Ads = getRepository(Ad); | export const Ads = db.getRepository(Ad); | ||||||
| export const PasswordResetRequests = getRepository(PasswordResetRequest); | export const PasswordResetRequests = db.getRepository(PasswordResetRequest); | ||||||
|  |  | ||||||
|  | @ -1,14 +1,13 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { AbuseUserReport } from '@/models/entities/abuse-user-report.js'; | import { AbuseUserReport } from '@/models/entities/abuse-user-report.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(AbuseUserReport) | export const AbuseUserReportRepository = db.getRepository(AbuseUserReport).extend({ | ||||||
| export class AbuseUserReportRepository extends Repository<AbuseUserReport> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: AbuseUserReport['id'] | AbuseUserReport, | 		src: AbuseUserReport['id'] | AbuseUserReport, | ||||||
| 	) { | 	) { | ||||||
| 		const report = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const report = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: report.id, | 			id: report.id, | ||||||
|  | @ -29,11 +28,11 @@ export class AbuseUserReportRepository extends Repository<AbuseUserReport> { | ||||||
| 			}) : null, | 			}) : null, | ||||||
| 			forwarded: report.forwarded, | 			forwarded: report.forwarded, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		reports: any[], | 		reports: any[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(reports.map(x => this.pack(x))); | 		return Promise.all(reports.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,17 +1,16 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Antenna } from '@/models/entities/antenna.js'; | import { Antenna } from '@/models/entities/antenna.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { AntennaNotes, UserGroupJoinings } from '../index.js'; | import { AntennaNotes, UserGroupJoinings } from '../index.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Antenna) | export const AntennaRepository = db.getRepository(Antenna).extend({ | ||||||
| export class AntennaRepository extends Repository<Antenna> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Antenna['id'] | Antenna, | 		src: Antenna['id'] | Antenna, | ||||||
| 	): Promise<Packed<'Antenna'>> { | 	): Promise<Packed<'Antenna'>> { | ||||||
| 		const antenna = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const antenna = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		const hasUnreadNote = (await AntennaNotes.findOne({ antennaId: antenna.id, read: false })) != null; | 		const hasUnreadNote = (await AntennaNotes.findOneBy({ antennaId: antenna.id, read: false })) != null; | ||||||
| 		const userGroupJoining = antenna.userGroupJoiningId ? await UserGroupJoinings.findOne(antenna.userGroupJoiningId) : null; | 		const userGroupJoining = antenna.userGroupJoiningId ? await UserGroupJoinings.findOneBy({ id: antenna.userGroupJoiningId }) : null; | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: antenna.id, | 			id: antenna.id, | ||||||
|  | @ -29,5 +28,5 @@ export class AntennaRepository extends Repository<Antenna> { | ||||||
| 			withFile: antenna.withFile, | 			withFile: antenna.withFile, | ||||||
| 			hasUnreadNote, | 			hasUnreadNote, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,12 +1,11 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { App } from '@/models/entities/app.js'; | import { App } from '@/models/entities/app.js'; | ||||||
| import { AccessTokens } from '../index.js'; | import { AccessTokens } from '../index.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { User } from '../entities/user.js'; | import { User } from '../entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(App) | export const AppRepository = db.getRepository(App).extend({ | ||||||
| export class AppRepository extends Repository<App> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: App['id'] | App, | 		src: App['id'] | App, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -21,7 +20,7 @@ export class AppRepository extends Repository<App> { | ||||||
| 			includeProfileImageIds: false, | 			includeProfileImageIds: false, | ||||||
| 		}, options); | 		}, options); | ||||||
| 
 | 
 | ||||||
| 		const app = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const app = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: app.id, | 			id: app.id, | ||||||
|  | @ -30,11 +29,11 @@ export class AppRepository extends Repository<App> { | ||||||
| 			permission: app.permission, | 			permission: app.permission, | ||||||
| 			...(opts.includeSecret ? { secret: app.secret } : {}), | 			...(opts.includeSecret ? { secret: app.secret } : {}), | ||||||
| 			...(me ? { | 			...(me ? { | ||||||
| 				isAuthorized: await AccessTokens.count({ | 				isAuthorized: await AccessTokens.countBy({ | ||||||
| 					appId: app.id, | 					appId: app.id, | ||||||
| 					userId: me.id, | 					userId: me.id, | ||||||
| 				}).then(count => count > 0), | 				}).then(count => count > 0), | ||||||
| 			} : {}), | 			} : {}), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,21 +1,20 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Apps } from '../index.js'; | import { Apps } from '../index.js'; | ||||||
| import { AuthSession } from '@/models/entities/auth-session.js'; | import { AuthSession } from '@/models/entities/auth-session.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(AuthSession) | export const AuthSessionRepository = db.getRepository(AuthSession).extend({ | ||||||
| export class AuthSessionRepository extends Repository<AuthSession> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: AuthSession['id'] | AuthSession, | 		src: AuthSession['id'] | AuthSession, | ||||||
| 		me?: { id: User['id'] } | null | undefined | 		me?: { id: User['id'] } | null | undefined | ||||||
| 	) { | 	) { | ||||||
| 		const session = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const session = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: session.id, | 			id: session.id, | ||||||
| 			app: Apps.pack(session.appId, me), | 			app: Apps.pack(session.appId, me), | ||||||
| 			token: session.token, | 			token: session.token, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,17 +1,16 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { Blocking } from '@/models/entities/blocking.js'; | import { Blocking } from '@/models/entities/blocking.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Blocking) | export const BlockingRepository = db.getRepository(Blocking).extend({ | ||||||
| export class BlockingRepository extends Repository<Blocking> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Blocking['id'] | Blocking, | 		src: Blocking['id'] | Blocking, | ||||||
| 		me?: { id: User['id'] } | null | undefined | 		me?: { id: User['id'] } | null | undefined | ||||||
| 	): Promise<Packed<'Blocking'>> { | 	): Promise<Packed<'Blocking'>> { | ||||||
| 		const blocking = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const blocking = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: blocking.id, | 			id: blocking.id, | ||||||
|  | @ -21,12 +20,12 @@ export class BlockingRepository extends Repository<Blocking> { | ||||||
| 				detail: true, | 				detail: true, | ||||||
| 			}), | 			}), | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		blockings: any[], | 		blockings: any[], | ||||||
| 		me: { id: User['id'] } | 		me: { id: User['id'] } | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(blockings.map(x => this.pack(x, me))); | 		return Promise.all(blockings.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,23 +1,22 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Channel } from '@/models/entities/channel.js'; | import { Channel } from '@/models/entities/channel.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { DriveFiles, ChannelFollowings, NoteUnreads } from '../index.js'; | import { DriveFiles, ChannelFollowings, NoteUnreads } from '../index.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Channel) | export const ChannelRepository = db.getRepository(Channel).extend({ | ||||||
| export class ChannelRepository extends Repository<Channel> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Channel['id'] | Channel, | 		src: Channel['id'] | Channel, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 	): Promise<Packed<'Channel'>> { | 	): Promise<Packed<'Channel'>> { | ||||||
| 		const channel = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const channel = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 		const meId = me ? me.id : null; | 		const meId = me ? me.id : null; | ||||||
| 
 | 
 | ||||||
| 		const banner = channel.bannerId ? await DriveFiles.findOne(channel.bannerId) : null; | 		const banner = channel.bannerId ? await DriveFiles.findOneBy({ id: channel.bannerId }) : null; | ||||||
| 
 | 
 | ||||||
| 		const hasUnreadNote = meId ? (await NoteUnreads.findOne({ noteChannelId: channel.id, userId: meId })) != null : undefined; | 		const hasUnreadNote = meId ? (await NoteUnreads.findOneBy({ noteChannelId: channel.id, userId: meId })) != null : undefined; | ||||||
| 
 | 
 | ||||||
| 		const following = meId ? await ChannelFollowings.findOne({ | 		const following = meId ? await ChannelFollowings.findOneBy({ | ||||||
| 			followerId: meId, | 			followerId: meId, | ||||||
| 			followeeId: channel.id, | 			followeeId: channel.id, | ||||||
| 		}) : null; | 		}) : null; | ||||||
|  | @ -38,5 +37,5 @@ export class ChannelRepository extends Repository<Channel> { | ||||||
| 				hasUnreadNote, | 				hasUnreadNote, | ||||||
| 			} : {}), | 			} : {}), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,15 +1,14 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Clip } from '@/models/entities/clip.js'; | import { Clip } from '@/models/entities/clip.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Clip) | export const ClipRepository = db.getRepository(Clip).extend({ | ||||||
| export class ClipRepository extends Repository<Clip> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Clip['id'] | Clip, | 		src: Clip['id'] | Clip, | ||||||
| 	): Promise<Packed<'Clip'>> { | 	): Promise<Packed<'Clip'>> { | ||||||
| 		const clip = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const clip = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: clip.id, | 			id: clip.id, | ||||||
|  | @ -20,12 +19,12 @@ export class ClipRepository extends Repository<Clip> { | ||||||
| 			description: clip.description, | 			description: clip.description, | ||||||
| 			isPublic: clip.isPublic, | 			isPublic: clip.isPublic, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		clips: Clip[], | 		clips: Clip[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(clips.map(x => this.pack(x))); | 		return Promise.all(clips.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { DriveFile } from '@/models/entities/drive-file.js'; | import { DriveFile } from '@/models/entities/drive-file.js'; | ||||||
| import { Users, DriveFolders } from '../index.js'; | import { Users, DriveFolders } from '../index.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
|  | @ -16,9 +16,8 @@ type PackOptions = { | ||||||
| 	withUser?: boolean, | 	withUser?: boolean, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(DriveFile) | export const DriveFileRepository = db.getRepository(DriveFile).extend({ | ||||||
| export class DriveFileRepository extends Repository<DriveFile> { | 	validateFileName(name: string): boolean { | ||||||
| 	public validateFileName(name: string): boolean { |  | ||||||
| 		return ( | 		return ( | ||||||
| 			(name.trim().length > 0) && | 			(name.trim().length > 0) && | ||||||
| 			(name.length <= 200) && | 			(name.length <= 200) && | ||||||
|  | @ -26,9 +25,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			(name.indexOf('/') === -1) && | 			(name.indexOf('/') === -1) && | ||||||
| 			(name.indexOf('..') === -1) | 			(name.indexOf('..') === -1) | ||||||
| 		); | 		); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public getPublicProperties(file: DriveFile): DriveFile['properties'] { | 	getPublicProperties(file: DriveFile): DriveFile['properties'] { | ||||||
| 		if (file.properties.orientation != null) { | 		if (file.properties.orientation != null) { | ||||||
| 			const properties = JSON.parse(JSON.stringify(file.properties)); | 			const properties = JSON.parse(JSON.stringify(file.properties)); | ||||||
| 			if (file.properties.orientation >= 5) { | 			if (file.properties.orientation >= 5) { | ||||||
|  | @ -39,9 +38,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return file.properties; | 		return file.properties; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public getPublicUrl(file: DriveFile, thumbnail = false): string | null { | 	getPublicUrl(file: DriveFile, thumbnail = false): string | null { | ||||||
| 		// リモートかつメディアプロキシ
 | 		// リモートかつメディアプロキシ
 | ||||||
| 		if (file.uri != null && file.userHost != null && config.mediaProxy != null) { | 		if (file.uri != null && file.userHost != null && config.mediaProxy != null) { | ||||||
| 			return appendQuery(config.mediaProxy, query({ | 			return appendQuery(config.mediaProxy, query({ | ||||||
|  | @ -62,9 +61,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 		const isImage = file.type && ['image/png', 'image/apng', 'image/gif', 'image/jpeg', 'image/webp', 'image/svg+xml'].includes(file.type); | 		const isImage = file.type && ['image/png', 'image/apng', 'image/gif', 'image/jpeg', 'image/webp', 'image/svg+xml'].includes(file.type); | ||||||
| 
 | 
 | ||||||
| 		return thumbnail ? (file.thumbnailUrl || (isImage ? (file.webpublicUrl || file.url) : null)) : (file.webpublicUrl || file.url); | 		return thumbnail ? (file.thumbnailUrl || (isImage ? (file.webpublicUrl || file.url) : null)) : (file.webpublicUrl || file.url); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async calcDriveUsageOf(user: User['id'] | { id: User['id'] }): Promise<number> { | 	async calcDriveUsageOf(user: User['id'] | { id: User['id'] }): Promise<number> { | ||||||
| 		const id = typeof user === 'object' ? user.id : user; | 		const id = typeof user === 'object' ? user.id : user; | ||||||
| 
 | 
 | ||||||
| 		const { sum } = await this | 		const { sum } = await this | ||||||
|  | @ -75,9 +74,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			.getRawOne(); | 			.getRawOne(); | ||||||
| 
 | 
 | ||||||
| 		return parseInt(sum, 10) || 0; | 		return parseInt(sum, 10) || 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async calcDriveUsageOfHost(host: string): Promise<number> { | 	async calcDriveUsageOfHost(host: string): Promise<number> { | ||||||
| 		const { sum } = await this | 		const { sum } = await this | ||||||
| 			.createQueryBuilder('file') | 			.createQueryBuilder('file') | ||||||
| 			.where('file.userHost = :host', { host: toPuny(host) }) | 			.where('file.userHost = :host', { host: toPuny(host) }) | ||||||
|  | @ -86,9 +85,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			.getRawOne(); | 			.getRawOne(); | ||||||
| 
 | 
 | ||||||
| 		return parseInt(sum, 10) || 0; | 		return parseInt(sum, 10) || 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async calcDriveUsageOfLocal(): Promise<number> { | 	async calcDriveUsageOfLocal(): Promise<number> { | ||||||
| 		const { sum } = await this | 		const { sum } = await this | ||||||
| 			.createQueryBuilder('file') | 			.createQueryBuilder('file') | ||||||
| 			.where('file.userHost IS NULL') | 			.where('file.userHost IS NULL') | ||||||
|  | @ -97,9 +96,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			.getRawOne(); | 			.getRawOne(); | ||||||
| 
 | 
 | ||||||
| 		return parseInt(sum, 10) || 0; | 		return parseInt(sum, 10) || 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async calcDriveUsageOfRemote(): Promise<number> { | 	async calcDriveUsageOfRemote(): Promise<number> { | ||||||
| 		const { sum } = await this | 		const { sum } = await this | ||||||
| 			.createQueryBuilder('file') | 			.createQueryBuilder('file') | ||||||
| 			.where('file.userHost IS NOT NULL') | 			.where('file.userHost IS NOT NULL') | ||||||
|  | @ -108,11 +107,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			.getRawOne(); | 			.getRawOne(); | ||||||
| 
 | 
 | ||||||
| 		return parseInt(sum, 10) || 0; | 		return parseInt(sum, 10) || 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async pack(src: DriveFile['id'], options?: PackOptions): Promise<Packed<'DriveFile'> | null>; | 	async pack( | ||||||
| 	public async pack(src: DriveFile, options?: PackOptions): Promise<Packed<'DriveFile'>>; |  | ||||||
| 	public async pack( |  | ||||||
| 		src: DriveFile['id'] | DriveFile, | 		src: DriveFile['id'] | DriveFile, | ||||||
| 		options?: PackOptions | 		options?: PackOptions | ||||||
| 	): Promise<Packed<'DriveFile'> | null> { | 	): Promise<Packed<'DriveFile'> | null> { | ||||||
|  | @ -121,11 +118,9 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			self: false, | 			self: false, | ||||||
| 		}, options); | 		}, options); | ||||||
| 
 | 
 | ||||||
| 		const file = typeof src === 'object' ? src : await this.findOne(src); | 		const file = typeof src === 'object' ? src : await this.findOneBy({ id: src }); | ||||||
| 		if (file == null) return null; | 		if (file == null) return null; | ||||||
| 
 | 
 | ||||||
| 		const meta = await fetchMeta(); |  | ||||||
| 
 |  | ||||||
| 		return await awaitAll<Packed<'DriveFile'>>({ | 		return await awaitAll<Packed<'DriveFile'>>({ | ||||||
| 			id: file.id, | 			id: file.id, | ||||||
| 			createdAt: file.createdAt.toISOString(), | 			createdAt: file.createdAt.toISOString(), | ||||||
|  | @ -146,13 +141,13 @@ export class DriveFileRepository extends Repository<DriveFile> { | ||||||
| 			userId: opts.withUser ? file.userId : null, | 			userId: opts.withUser ? file.userId : null, | ||||||
| 			user: (opts.withUser && file.userId) ? Users.pack(file.userId) : null, | 			user: (opts.withUser && file.userId) ? Users.pack(file.userId) : null, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async packMany( | 	async packMany( | ||||||
| 		files: (DriveFile['id'] | DriveFile)[], | 		files: (DriveFile['id'] | DriveFile)[], | ||||||
| 		options?: PackOptions | 		options?: PackOptions | ||||||
| 	) { | 	) { | ||||||
| 		const items = await Promise.all(files.map(f => this.pack(f, options))); | 		const items = await Promise.all(files.map(f => this.pack(f, options))); | ||||||
| 		return items.filter(x => x != null); | 		return items.filter(x => x != null); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,12 +1,11 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { DriveFolders, DriveFiles } from '../index.js'; | import { DriveFolders, DriveFiles } from '../index.js'; | ||||||
| import { DriveFolder } from '@/models/entities/drive-folder.js'; | import { DriveFolder } from '@/models/entities/drive-folder.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(DriveFolder) | export const DriveFolderRepository = db.getRepository(DriveFolder).extend({ | ||||||
| export class DriveFolderRepository extends Repository<DriveFolder> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: DriveFolder['id'] | DriveFolder, | 		src: DriveFolder['id'] | DriveFolder, | ||||||
| 		options?: { | 		options?: { | ||||||
| 			detail: boolean | 			detail: boolean | ||||||
|  | @ -16,7 +15,7 @@ export class DriveFolderRepository extends Repository<DriveFolder> { | ||||||
| 			detail: false, | 			detail: false, | ||||||
| 		}, options); | 		}, options); | ||||||
| 
 | 
 | ||||||
| 		const folder = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const folder = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: folder.id, | 			id: folder.id, | ||||||
|  | @ -25,10 +24,10 @@ export class DriveFolderRepository extends Repository<DriveFolder> { | ||||||
| 			parentId: folder.parentId, | 			parentId: folder.parentId, | ||||||
| 
 | 
 | ||||||
| 			...(opts.detail ? { | 			...(opts.detail ? { | ||||||
| 				foldersCount: DriveFolders.count({ | 				foldersCount: DriveFolders.countBy({ | ||||||
| 					parentId: folder.id, | 					parentId: folder.id, | ||||||
| 				}), | 				}), | ||||||
| 				filesCount: DriveFiles.count({ | 				filesCount: DriveFiles.countBy({ | ||||||
| 					folderId: folder.id, | 					folderId: folder.id, | ||||||
| 				}), | 				}), | ||||||
| 
 | 
 | ||||||
|  | @ -39,5 +38,5 @@ export class DriveFolderRepository extends Repository<DriveFolder> { | ||||||
| 				} : {}), | 				} : {}), | ||||||
| 			} : {}), | 			} : {}), | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,13 +1,12 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Emoji } from '@/models/entities/emoji.js'; | import { Emoji } from '@/models/entities/emoji.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Emoji) | export const EmojiRepository = db.getRepository(Emoji).extend({ | ||||||
| export class EmojiRepository extends Repository<Emoji> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Emoji['id'] | Emoji, | 		src: Emoji['id'] | Emoji, | ||||||
| 	): Promise<Packed<'Emoji'>> { | 	): Promise<Packed<'Emoji'>> { | ||||||
| 		const emoji = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const emoji = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: emoji.id, | 			id: emoji.id, | ||||||
|  | @ -18,11 +17,11 @@ export class EmojiRepository extends Repository<Emoji> { | ||||||
| 			// || emoji.originalUrl してるのは後方互換性のため
 | 			// || emoji.originalUrl してるのは後方互換性のため
 | ||||||
| 			url: emoji.publicUrl || emoji.originalUrl, | 			url: emoji.publicUrl || emoji.originalUrl, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		emojis: any[], | 		emojis: any[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(emojis.map(x => this.pack(x))); | 		return Promise.all(emojis.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,20 +1,19 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { FollowRequest } from '@/models/entities/follow-request.js'; | import { FollowRequest } from '@/models/entities/follow-request.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(FollowRequest) | export const FollowRequestRepository = db.getRepository(FollowRequest).extend({ | ||||||
| export class FollowRequestRepository extends Repository<FollowRequest> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: FollowRequest['id'] | FollowRequest, | 		src: FollowRequest['id'] | FollowRequest, | ||||||
| 		me?: { id: User['id'] } | null | undefined | 		me?: { id: User['id'] } | null | undefined | ||||||
| 	) { | 	) { | ||||||
| 		const request = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const request = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: request.id, | 			id: request.id, | ||||||
| 			follower: await Users.pack(request.followerId, me), | 			follower: await Users.pack(request.followerId, me), | ||||||
| 			followee: await Users.pack(request.followeeId, me), | 			followee: await Users.pack(request.followeeId, me), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { Following } from '@/models/entities/following.js'; | import { Following } from '@/models/entities/following.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
|  | @ -29,25 +29,24 @@ type RemoteFolloweeFollowing = Following & { | ||||||
| 	followeeSharedInbox: string; | 	followeeSharedInbox: string; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Following) | export const FollowingRepository = db.getRepository(Following).extend({ | ||||||
| export class FollowingRepository extends Repository<Following> { | 	isLocalFollower(following: Following): following is LocalFollowerFollowing { | ||||||
| 	public isLocalFollower(following: Following): following is LocalFollowerFollowing { |  | ||||||
| 		return following.followerHost == null; | 		return following.followerHost == null; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public isRemoteFollower(following: Following): following is RemoteFollowerFollowing { | 	isRemoteFollower(following: Following): following is RemoteFollowerFollowing { | ||||||
| 		return following.followerHost != null; | 		return following.followerHost != null; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public isLocalFollowee(following: Following): following is LocalFolloweeFollowing { | 	isLocalFollowee(following: Following): following is LocalFolloweeFollowing { | ||||||
| 		return following.followeeHost == null; | 		return following.followeeHost == null; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public isRemoteFollowee(following: Following): following is RemoteFolloweeFollowing { | 	isRemoteFollowee(following: Following): following is RemoteFolloweeFollowing { | ||||||
| 		return following.followeeHost != null; | 		return following.followeeHost != null; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async pack( | 	async pack( | ||||||
| 		src: Following['id'] | Following, | 		src: Following['id'] | Following, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		opts?: { | 		opts?: { | ||||||
|  | @ -55,7 +54,7 @@ export class FollowingRepository extends Repository<Following> { | ||||||
| 			populateFollower?: boolean; | 			populateFollower?: boolean; | ||||||
| 		} | 		} | ||||||
| 	): Promise<Packed<'Following'>> { | 	): Promise<Packed<'Following'>> { | ||||||
| 		const following = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const following = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		if (opts == null) opts = {}; | 		if (opts == null) opts = {}; | ||||||
| 
 | 
 | ||||||
|  | @ -71,9 +70,9 @@ export class FollowingRepository extends Repository<Following> { | ||||||
| 				detail: true, | 				detail: true, | ||||||
| 			}) : undefined, | 			}) : undefined, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		followings: any[], | 		followings: any[], | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		opts?: { | 		opts?: { | ||||||
|  | @ -82,5 +81,5 @@ export class FollowingRepository extends Repository<Following> { | ||||||
| 		} | 		} | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(followings.map(x => this.pack(x, me, opts))); | 		return Promise.all(followings.map(x => this.pack(x, me, opts))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,25 +1,24 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { GalleryLike } from '@/models/entities/gallery-like.js'; | import { GalleryLike } from '@/models/entities/gallery-like.js'; | ||||||
| import { GalleryPosts } from '../index.js'; | import { GalleryPosts } from '../index.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(GalleryLike) | export const GalleryLikeRepository = db.getRepository(GalleryLike).extend({ | ||||||
| export class GalleryLikeRepository extends Repository<GalleryLike> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: GalleryLike['id'] | GalleryLike, | 		src: GalleryLike['id'] | GalleryLike, | ||||||
| 		me?: any | 		me?: any | ||||||
| 	) { | 	) { | ||||||
| 		const like = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const like = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: like.id, | 			id: like.id, | ||||||
| 			post: await GalleryPosts.pack(like.post || like.postId, me), | 			post: await GalleryPosts.pack(like.post || like.postId, me), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		likes: any[], | 		likes: any[], | ||||||
| 		me: any | 		me: any | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(likes.map(x => this.pack(x, me))); | 		return Promise.all(likes.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,18 +1,17 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { GalleryPost } from '@/models/entities/gallery-post.js'; | import { GalleryPost } from '@/models/entities/gallery-post.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { Users, DriveFiles, GalleryLikes } from '../index.js'; | import { Users, DriveFiles, GalleryLikes } from '../index.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(GalleryPost) | export const GalleryPostRepository = db.getRepository(GalleryPost).extend({ | ||||||
| export class GalleryPostRepository extends Repository<GalleryPost> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: GalleryPost['id'] | GalleryPost, | 		src: GalleryPost['id'] | GalleryPost, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 	): Promise<Packed<'GalleryPost'>> { | 	): Promise<Packed<'GalleryPost'>> { | ||||||
| 		const meId = me ? me.id : null; | 		const meId = me ? me.id : null; | ||||||
| 		const post = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const post = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: post.id, | 			id: post.id, | ||||||
|  | @ -27,14 +26,14 @@ export class GalleryPostRepository extends Repository<GalleryPost> { | ||||||
| 			tags: post.tags.length > 0 ? post.tags : undefined, | 			tags: post.tags.length > 0 ? post.tags : undefined, | ||||||
| 			isSensitive: post.isSensitive, | 			isSensitive: post.isSensitive, | ||||||
| 			likedCount: post.likedCount, | 			likedCount: post.likedCount, | ||||||
| 			isLiked: meId ? await GalleryLikes.findOne({ postId: post.id, userId: meId }).then(x => x != null) : undefined, | 			isLiked: meId ? await GalleryLikes.findOneBy({ postId: post.id, userId: meId }).then(x => x != null) : undefined, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		posts: GalleryPost[], | 		posts: GalleryPost[], | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(posts.map(x => this.pack(x, me))); | 		return Promise.all(posts.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,10 +1,9 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Hashtag } from '@/models/entities/hashtag.js'; | import { Hashtag } from '@/models/entities/hashtag.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Hashtag) | export const HashtagRepository = db.getRepository(Hashtag).extend({ | ||||||
| export class HashtagRepository extends Repository<Hashtag> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Hashtag, | 		src: Hashtag, | ||||||
| 	): Promise<Packed<'Hashtag'>> { | 	): Promise<Packed<'Hashtag'>> { | ||||||
| 		return { | 		return { | ||||||
|  | @ -16,11 +15,11 @@ export class HashtagRepository extends Repository<Hashtag> { | ||||||
| 			attachedLocalUsersCount: src.attachedLocalUsersCount, | 			attachedLocalUsersCount: src.attachedLocalUsersCount, | ||||||
| 			attachedRemoteUsersCount: src.attachedRemoteUsersCount, | 			attachedRemoteUsersCount: src.attachedRemoteUsersCount, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		hashtags: Hashtag[], | 		hashtags: Hashtag[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(hashtags.map(x => this.pack(x))); | 		return Promise.all(hashtags.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,10 +1,9 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Instance } from '@/models/entities/instance.js'; | import { Instance } from '@/models/entities/instance.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Instance) | export const InstanceRepository = db.getRepository(Instance).extend({ | ||||||
| export class InstanceRepository extends Repository<Instance> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		instance: Instance, | 		instance: Instance, | ||||||
| 	): Promise<Packed<'FederationInstance'>> { | 	): Promise<Packed<'FederationInstance'>> { | ||||||
| 		return { | 		return { | ||||||
|  | @ -29,11 +28,11 @@ export class InstanceRepository extends Repository<Instance> { | ||||||
| 			iconUrl: instance.iconUrl, | 			iconUrl: instance.iconUrl, | ||||||
| 			infoUpdatedAt: instance.infoUpdatedAt ? instance.infoUpdatedAt.toISOString() : null, | 			infoUpdatedAt: instance.infoUpdatedAt ? instance.infoUpdatedAt.toISOString() : null, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		instances: Instance[], | 		instances: Instance[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(instances.map(x => this.pack(x))); | 		return Promise.all(instances.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,12 +1,11 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { MessagingMessage } from '@/models/entities/messaging-message.js'; | import { MessagingMessage } from '@/models/entities/messaging-message.js'; | ||||||
| import { Users, DriveFiles, UserGroups } from '../index.js'; | import { Users, DriveFiles, UserGroups } from '../index.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(MessagingMessage) | export const MessagingMessageRepository = db.getRepository(MessagingMessage).extend({ | ||||||
| export class MessagingMessageRepository extends Repository<MessagingMessage> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: MessagingMessage['id'] | MessagingMessage, | 		src: MessagingMessage['id'] | MessagingMessage, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -19,7 +18,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> { | ||||||
| 			populateGroup: true, | 			populateGroup: true, | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		const message = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const message = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: message.id, | 			id: message.id, | ||||||
|  | @ -36,5 +35,5 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> { | ||||||
| 			isRead: message.isRead, | 			isRead: message.isRead, | ||||||
| 			reads: message.reads, | 			reads: message.reads, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,14 +1,13 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { ModerationLog } from '@/models/entities/moderation-log.js'; | import { ModerationLog } from '@/models/entities/moderation-log.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(ModerationLog) | export const ModerationLogRepository = db.getRepository(ModerationLog).extend({ | ||||||
| export class ModerationLogRepository extends Repository<ModerationLog> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: ModerationLog['id'] | ModerationLog, | 		src: ModerationLog['id'] | ModerationLog, | ||||||
| 	) { | 	) { | ||||||
| 		const log = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const log = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: log.id, | 			id: log.id, | ||||||
|  | @ -20,11 +19,11 @@ export class ModerationLogRepository extends Repository<ModerationLog> { | ||||||
| 				detail: true, | 				detail: true, | ||||||
| 			}), | 			}), | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		reports: any[], | 		reports: any[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(reports.map(x => this.pack(x))); | 		return Promise.all(reports.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,17 +1,16 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Users } from '../index.js'; | import { Users } from '../index.js'; | ||||||
| import { Muting } from '@/models/entities/muting.js'; | import { Muting } from '@/models/entities/muting.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Muting) | export const MutingRepository = db.getRepository(Muting).extend({ | ||||||
| export class MutingRepository extends Repository<Muting> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Muting['id'] | Muting, | 		src: Muting['id'] | Muting, | ||||||
| 		me?: { id: User['id'] } | null | undefined | 		me?: { id: User['id'] } | null | undefined | ||||||
| 	): Promise<Packed<'Muting'>> { | 	): Promise<Packed<'Muting'>> { | ||||||
| 		const muting = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const muting = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: muting.id, | 			id: muting.id, | ||||||
|  | @ -22,12 +21,12 @@ export class MutingRepository extends Repository<Muting> { | ||||||
| 				detail: true, | 				detail: true, | ||||||
| 			}), | 			}), | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		mutings: any[], | 		mutings: any[], | ||||||
| 		me: { id: User['id'] } | 		me: { id: User['id'] } | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(mutings.map(x => this.pack(x, me))); | 		return Promise.all(mutings.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,15 +1,14 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { NoteFavorite } from '@/models/entities/note-favorite.js'; | import { NoteFavorite } from '@/models/entities/note-favorite.js'; | ||||||
| import { Notes } from '../index.js'; | import { Notes } from '../index.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(NoteFavorite) | export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({ | ||||||
| export class NoteFavoriteRepository extends Repository<NoteFavorite> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: NoteFavorite['id'] | NoteFavorite, | 		src: NoteFavorite['id'] | NoteFavorite, | ||||||
| 		me?: { id: User['id'] } | null | undefined | 		me?: { id: User['id'] } | null | undefined | ||||||
| 	) { | 	) { | ||||||
| 		const favorite = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const favorite = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: favorite.id, | 			id: favorite.id, | ||||||
|  | @ -17,12 +16,12 @@ export class NoteFavoriteRepository extends Repository<NoteFavorite> { | ||||||
| 			noteId: favorite.noteId, | 			noteId: favorite.noteId, | ||||||
| 			note: await Notes.pack(favorite.note || favorite.noteId, me), | 			note: await Notes.pack(favorite.note || favorite.noteId, me), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		favorites: any[], | 		favorites: any[], | ||||||
| 		me: { id: User['id'] } | 		me: { id: User['id'] } | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(favorites.map(x => this.pack(x, me))); | 		return Promise.all(favorites.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,13 +1,12 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { NoteReaction } from '@/models/entities/note-reaction.js'; | import { NoteReaction } from '@/models/entities/note-reaction.js'; | ||||||
| import { Notes, Users } from '../index.js'; | import { Notes, Users } from '../index.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { convertLegacyReaction } from '@/misc/reaction-lib.js'; | import { convertLegacyReaction } from '@/misc/reaction-lib.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(NoteReaction) | export const NoteReactionRepository = db.getRepository(NoteReaction).extend({ | ||||||
| export class NoteReactionRepository extends Repository<NoteReaction> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: NoteReaction['id'] | NoteReaction, | 		src: NoteReaction['id'] | NoteReaction, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -18,7 +17,7 @@ export class NoteReactionRepository extends Repository<NoteReaction> { | ||||||
| 			withNote: false, | 			withNote: false, | ||||||
| 		}, options); | 		}, options); | ||||||
| 
 | 
 | ||||||
| 		const reaction = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const reaction = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: reaction.id, | 			id: reaction.id, | ||||||
|  | @ -29,5 +28,5 @@ export class NoteReactionRepository extends Repository<NoteReaction> { | ||||||
| 				note: await Notes.pack(reaction.note ?? reaction.noteId, me), | 				note: await Notes.pack(reaction.note ?? reaction.noteId, me), | ||||||
| 			} : {}), | 			} : {}), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { EntityRepository, Repository, In } from 'typeorm'; | import { In } from 'typeorm'; | ||||||
| import * as mfm from 'mfm-js'; | import * as mfm from 'mfm-js'; | ||||||
| import { Note } from '@/models/entities/note.js'; | import { Note } from '@/models/entities/note.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
|  | @ -9,10 +9,70 @@ import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib.js'; | import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib.js'; | ||||||
| import { NoteReaction } from '@/models/entities/note-reaction.js'; | import { NoteReaction } from '@/models/entities/note-reaction.js'; | ||||||
| import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/populate-emojis.js'; | import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/populate-emojis.js'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Note) | async function hideNote(packedNote: Packed<'Note'>, meId: User['id'] | null) { | ||||||
| export class NoteRepository extends Repository<Note> { | 	// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
 | ||||||
| 	public async isVisibleForMe(note: Note, meId: User['id'] | null): Promise<boolean> { | 	let hide = false; | ||||||
|  | 
 | ||||||
|  | 	// visibility が specified かつ自分が指定されていなかったら非表示
 | ||||||
|  | 	if (packedNote.visibility === 'specified') { | ||||||
|  | 		if (meId == null) { | ||||||
|  | 			hide = true; | ||||||
|  | 		} else if (meId === packedNote.userId) { | ||||||
|  | 			hide = false; | ||||||
|  | 		} else { | ||||||
|  | 			// 指定されているかどうか
 | ||||||
|  | 			const specified = packedNote.visibleUserIds!.some((id: any) => meId === id); | ||||||
|  | 
 | ||||||
|  | 			if (specified) { | ||||||
|  | 				hide = false; | ||||||
|  | 			} else { | ||||||
|  | 				hide = true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
 | ||||||
|  | 	if (packedNote.visibility === 'followers') { | ||||||
|  | 		if (meId == null) { | ||||||
|  | 			hide = true; | ||||||
|  | 		} else if (meId === packedNote.userId) { | ||||||
|  | 			hide = false; | ||||||
|  | 		} else if (packedNote.reply && (meId === packedNote.reply.userId)) { | ||||||
|  | 			// 自分の投稿に対するリプライ
 | ||||||
|  | 			hide = false; | ||||||
|  | 		} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) { | ||||||
|  | 			// 自分へのメンション
 | ||||||
|  | 			hide = false; | ||||||
|  | 		} else { | ||||||
|  | 			// フォロワーかどうか
 | ||||||
|  | 			const following = await Followings.findOneBy({ | ||||||
|  | 				followeeId: packedNote.userId, | ||||||
|  | 				followerId: meId, | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			if (following == null) { | ||||||
|  | 				hide = true; | ||||||
|  | 			} else { | ||||||
|  | 				hide = false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (hide) { | ||||||
|  | 		packedNote.visibleUserIds = undefined; | ||||||
|  | 		packedNote.fileIds = []; | ||||||
|  | 		packedNote.files = []; | ||||||
|  | 		packedNote.text = null; | ||||||
|  | 		packedNote.poll = undefined; | ||||||
|  | 		packedNote.cw = null; | ||||||
|  | 		packedNote.isHidden = true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const NoteRepository = db.getRepository(Note).extend({ | ||||||
|  | 	async isVisibleForMe(note: Note, meId: User['id'] | null): Promise<boolean> { | ||||||
| 		// visibility が specified かつ自分が指定されていなかったら非表示
 | 		// visibility が specified かつ自分が指定されていなかったら非表示
 | ||||||
| 		if (note.visibility === 'specified') { | 		if (note.visibility === 'specified') { | ||||||
| 			if (meId == null) { | 			if (meId == null) { | ||||||
|  | @ -45,7 +105,7 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 				return true; | 				return true; | ||||||
| 			} else { | 			} else { | ||||||
| 				// フォロワーかどうか
 | 				// フォロワーかどうか
 | ||||||
| 				const following = await Followings.findOne({ | 				const following = await Followings.findOneBy({ | ||||||
| 					followeeId: note.userId, | 					followeeId: note.userId, | ||||||
| 					followerId: meId, | 					followerId: meId, | ||||||
| 				}); | 				}); | ||||||
|  | @ -59,69 +119,9 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	private async hideNote(packedNote: Packed<'Note'>, meId: User['id'] | null) { | 	async pack( | ||||||
| 		// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
 |  | ||||||
| 		let hide = false; |  | ||||||
| 
 |  | ||||||
| 		// visibility が specified かつ自分が指定されていなかったら非表示
 |  | ||||||
| 		if (packedNote.visibility === 'specified') { |  | ||||||
| 			if (meId == null) { |  | ||||||
| 				hide = true; |  | ||||||
| 			} else if (meId === packedNote.userId) { |  | ||||||
| 				hide = false; |  | ||||||
| 			} else { |  | ||||||
| 				// 指定されているかどうか
 |  | ||||||
| 				const specified = packedNote.visibleUserIds!.some((id: any) => meId === id); |  | ||||||
| 
 |  | ||||||
| 				if (specified) { |  | ||||||
| 					hide = false; |  | ||||||
| 				} else { |  | ||||||
| 					hide = true; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
 |  | ||||||
| 		if (packedNote.visibility === 'followers') { |  | ||||||
| 			if (meId == null) { |  | ||||||
| 				hide = true; |  | ||||||
| 			} else if (meId === packedNote.userId) { |  | ||||||
| 				hide = false; |  | ||||||
| 			} else if (packedNote.reply && (meId === packedNote.reply.userId)) { |  | ||||||
| 				// 自分の投稿に対するリプライ
 |  | ||||||
| 				hide = false; |  | ||||||
| 			} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) { |  | ||||||
| 				// 自分へのメンション
 |  | ||||||
| 				hide = false; |  | ||||||
| 			} else { |  | ||||||
| 				// フォロワーかどうか
 |  | ||||||
| 				const following = await Followings.findOne({ |  | ||||||
| 					followeeId: packedNote.userId, |  | ||||||
| 					followerId: meId, |  | ||||||
| 				}); |  | ||||||
| 
 |  | ||||||
| 				if (following == null) { |  | ||||||
| 					hide = true; |  | ||||||
| 				} else { |  | ||||||
| 					hide = false; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (hide) { |  | ||||||
| 			packedNote.visibleUserIds = undefined; |  | ||||||
| 			packedNote.fileIds = []; |  | ||||||
| 			packedNote.files = []; |  | ||||||
| 			packedNote.text = null; |  | ||||||
| 			packedNote.poll = undefined; |  | ||||||
| 			packedNote.cw = null; |  | ||||||
| 			packedNote.isHidden = true; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public async pack( |  | ||||||
| 		src: Note['id'] | Note, | 		src: Note['id'] | Note, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -138,11 +138,11 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 		}, options); | 		}, options); | ||||||
| 
 | 
 | ||||||
| 		const meId = me ? me.id : null; | 		const meId = me ? me.id : null; | ||||||
| 		const note = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const note = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 		const host = note.userHost; | 		const host = note.userHost; | ||||||
| 
 | 
 | ||||||
| 		async function populatePoll() { | 		async function populatePoll() { | ||||||
| 			const poll = await Polls.findOneOrFail(note.id); | 			const poll = await Polls.findOneByOrFail({ noteId: note.id }); | ||||||
| 			const choices = poll.choices.map(c => ({ | 			const choices = poll.choices.map(c => ({ | ||||||
| 				text: c, | 				text: c, | ||||||
| 				votes: poll.votes[poll.choices.indexOf(c)], | 				votes: poll.votes[poll.choices.indexOf(c)], | ||||||
|  | @ -150,7 +150,7 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 			})); | 			})); | ||||||
| 
 | 
 | ||||||
| 			if (poll.multiple) { | 			if (poll.multiple) { | ||||||
| 				const votes = await PollVotes.find({ | 				const votes = await PollVotes.findBy({ | ||||||
| 					userId: meId!, | 					userId: meId!, | ||||||
| 					noteId: note.id, | 					noteId: note.id, | ||||||
| 				}); | 				}); | ||||||
|  | @ -160,7 +160,7 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 					choices[myChoice].isVoted = true; | 					choices[myChoice].isVoted = true; | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				const vote = await PollVotes.findOne({ | 				const vote = await PollVotes.findOneBy({ | ||||||
| 					userId: meId!, | 					userId: meId!, | ||||||
| 					noteId: note.id, | 					noteId: note.id, | ||||||
| 				}); | 				}); | ||||||
|  | @ -188,7 +188,7 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 				// 実装上抜けがあるだけかもしれないので、「ヒントに含まれてなかったら(=undefinedなら)return」のようにはしない
 | 				// 実装上抜けがあるだけかもしれないので、「ヒントに含まれてなかったら(=undefinedなら)return」のようにはしない
 | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			const reaction = await NoteReactions.findOne({ | 			const reaction = await NoteReactions.findOneBy({ | ||||||
| 				userId: meId!, | 				userId: meId!, | ||||||
| 				noteId: note.id, | 				noteId: note.id, | ||||||
| 			}); | 			}); | ||||||
|  | @ -209,7 +209,7 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 		const channel = note.channelId | 		const channel = note.channelId | ||||||
| 			? note.channel | 			? note.channel | ||||||
| 				? note.channel | 				? note.channel | ||||||
| 				: await Channels.findOne(note.channelId) | 				: await Channels.findOneBy({ id: note.channelId }) | ||||||
| 			: null; | 			: null; | ||||||
| 
 | 
 | ||||||
| 		const reactionEmojiNames = Object.keys(note.reactions).filter(x => x?.startsWith(':')).map(x => decodeReaction(x).reaction).map(x => x.replace(/:/g, '')); | 		const reactionEmojiNames = Object.keys(note.reactions).filter(x => x?.startsWith(':')).map(x => decodeReaction(x).reaction).map(x => x.replace(/:/g, '')); | ||||||
|  | @ -275,13 +275,13 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!opts.skipHide) { | 		if (!opts.skipHide) { | ||||||
| 			await this.hideNote(packed, meId); | 			await hideNote(packed, meId); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return packed; | 		return packed; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async packMany( | 	async packMany( | ||||||
| 		notes: Note[], | 		notes: Note[], | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -296,7 +296,7 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 		if (meId) { | 		if (meId) { | ||||||
| 			const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!); | 			const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!); | ||||||
| 			const targets = [...notes.map(n => n.id), ...renoteIds]; | 			const targets = [...notes.map(n => n.id), ...renoteIds]; | ||||||
| 			const myReactions = await NoteReactions.find({ | 			const myReactions = await NoteReactions.findBy({ | ||||||
| 				userId: meId, | 				userId: meId, | ||||||
| 				noteId: In(targets), | 				noteId: In(targets), | ||||||
| 			}); | 			}); | ||||||
|  | @ -314,5 +314,5 @@ export class NoteRepository extends Repository<Note> { | ||||||
| 				myReactions: myReactionsMap, | 				myReactions: myReactionsMap, | ||||||
| 			}, | 			}, | ||||||
| 		}))); | 		}))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { EntityRepository, In, Repository } from 'typeorm'; | import { In, Repository } from 'typeorm'; | ||||||
| import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '../index.js'; | import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '../index.js'; | ||||||
| import { Notification } from '@/models/entities/notification.js'; | import { Notification } from '@/models/entities/notification.js'; | ||||||
| import { awaitAll } from '@/prelude/await-all.js'; | import { awaitAll } from '@/prelude/await-all.js'; | ||||||
|  | @ -8,10 +8,10 @@ import { NoteReaction } from '@/models/entities/note-reaction.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis.js'; | import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis.js'; | ||||||
| import { notificationTypes } from '@/types.js'; | import { notificationTypes } from '@/types.js'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Notification) | export const NotificationRepository = db.getRepository(Notification).extend({ | ||||||
| export class NotificationRepository extends Repository<Notification> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Notification['id'] | Notification, | 		src: Notification['id'] | Notification, | ||||||
| 		options: { | 		options: { | ||||||
| 			_hintForEachNotes_?: { | 			_hintForEachNotes_?: { | ||||||
|  | @ -19,8 +19,8 @@ export class NotificationRepository extends Repository<Notification> { | ||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
| 	): Promise<Packed<'Notification'>> { | 	): Promise<Packed<'Notification'>> { | ||||||
| 		const notification = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const notification = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 		const token = notification.appAccessTokenId ? await AccessTokens.findOneOrFail(notification.appAccessTokenId) : null; | 		const token = notification.appAccessTokenId ? await AccessTokens.findOneByOrFail({ id: notification.appAccessTokenId }) : null; | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll({ | 		return await awaitAll({ | ||||||
| 			id: notification.id, | 			id: notification.id, | ||||||
|  | @ -82,9 +82,9 @@ export class NotificationRepository extends Repository<Notification> { | ||||||
| 				icon: notification.customIcon || token?.iconUrl, | 				icon: notification.customIcon || token?.iconUrl, | ||||||
| 			} : {}), | 			} : {}), | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async packMany( | 	async packMany( | ||||||
| 		notifications: Notification[], | 		notifications: Notification[], | ||||||
| 		meId: User['id'] | 		meId: User['id'] | ||||||
| 	) { | 	) { | ||||||
|  | @ -95,7 +95,7 @@ export class NotificationRepository extends Repository<Notification> { | ||||||
| 		const myReactionsMap = new Map<Note['id'], NoteReaction | null>(); | 		const myReactionsMap = new Map<Note['id'], NoteReaction | null>(); | ||||||
| 		const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!); | 		const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!); | ||||||
| 		const targets = [...noteIds, ...renoteIds]; | 		const targets = [...noteIds, ...renoteIds]; | ||||||
| 		const myReactions = await NoteReactions.find({ | 		const myReactions = await NoteReactions.findBy({ | ||||||
| 			userId: meId, | 			userId: meId, | ||||||
| 			noteId: In(targets), | 			noteId: In(targets), | ||||||
| 		}); | 		}); | ||||||
|  | @ -111,5 +111,5 @@ export class NotificationRepository extends Repository<Notification> { | ||||||
| 				myReactions: myReactionsMap, | 				myReactions: myReactionsMap, | ||||||
| 			}, | 			}, | ||||||
| 		}))); | 		}))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,26 +1,25 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { PageLike } from '@/models/entities/page-like.js'; | import { PageLike } from '@/models/entities/page-like.js'; | ||||||
| import { Pages } from '../index.js'; | import { Pages } from '../index.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(PageLike) | export const PageLikeRepository = db.getRepository(PageLike).extend({ | ||||||
| export class PageLikeRepository extends Repository<PageLike> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: PageLike['id'] | PageLike, | 		src: PageLike['id'] | PageLike, | ||||||
| 		me?: { id: User['id'] } | null | undefined | 		me?: { id: User['id'] } | null | undefined | ||||||
| 	) { | 	) { | ||||||
| 		const like = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const like = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: like.id, | 			id: like.id, | ||||||
| 			page: await Pages.pack(like.page || like.pageId, me), | 			page: await Pages.pack(like.page || like.pageId, me), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		likes: any[], | 		likes: any[], | ||||||
| 		me: { id: User['id'] } | 		me: { id: User['id'] } | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(likes.map(x => this.pack(x, me))); | 		return Promise.all(likes.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Page } from '@/models/entities/page.js'; | import { Page } from '@/models/entities/page.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| import { Users, DriveFiles, PageLikes } from '../index.js'; | import { Users, DriveFiles, PageLikes } from '../index.js'; | ||||||
|  | @ -6,20 +6,19 @@ import { awaitAll } from '@/prelude/await-all.js'; | ||||||
| import { DriveFile } from '@/models/entities/drive-file.js'; | import { DriveFile } from '@/models/entities/drive-file.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Page) | export const PageRepository = db.getRepository(Page).extend({ | ||||||
| export class PageRepository extends Repository<Page> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Page['id'] | Page, | 		src: Page['id'] | Page, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 	): Promise<Packed<'Page'>> { | 	): Promise<Packed<'Page'>> { | ||||||
| 		const meId = me ? me.id : null; | 		const meId = me ? me.id : null; | ||||||
| 		const page = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const page = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		const attachedFiles: Promise<DriveFile | undefined>[] = []; | 		const attachedFiles: Promise<DriveFile | undefined>[] = []; | ||||||
| 		const collectFile = (xs: any[]) => { | 		const collectFile = (xs: any[]) => { | ||||||
| 			for (const x of xs) { | 			for (const x of xs) { | ||||||
| 				if (x.type === 'image') { | 				if (x.type === 'image') { | ||||||
| 					attachedFiles.push(DriveFiles.findOne({ | 					attachedFiles.push(DriveFiles.findOneBy({ | ||||||
| 						id: x.fileId, | 						id: x.fileId, | ||||||
| 						userId: page.userId, | 						userId: page.userId, | ||||||
| 					})); | 					})); | ||||||
|  | @ -76,14 +75,14 @@ export class PageRepository extends Repository<Page> { | ||||||
| 			eyeCatchingImage: page.eyeCatchingImageId ? await DriveFiles.pack(page.eyeCatchingImageId) : null, | 			eyeCatchingImage: page.eyeCatchingImageId ? await DriveFiles.pack(page.eyeCatchingImageId) : null, | ||||||
| 			attachedFiles: DriveFiles.packMany(await Promise.all(attachedFiles)), | 			attachedFiles: DriveFiles.packMany(await Promise.all(attachedFiles)), | ||||||
| 			likedCount: page.likedCount, | 			likedCount: page.likedCount, | ||||||
| 			isLiked: meId ? await PageLikes.findOne({ pageId: page.id, userId: meId }).then(x => x != null) : undefined, | 			isLiked: meId ? await PageLikes.findOneBy({ pageId: page.id, userId: meId }).then(x => x != null) : undefined, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		pages: Page[], | 		pages: Page[], | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(pages.map(x => this.pack(x, me))); | 		return Promise.all(pages.map(x => this.pack(x, me))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Relay } from '@/models/entities/relay.js'; | import { Relay } from '@/models/entities/relay.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Relay) | export const RelayRepository = db.getRepository(Relay).extend({ | ||||||
| export class RelayRepository extends Repository<Relay> { | }); | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,11 +1,10 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { Signin } from '@/models/entities/signin.js'; | import { Signin } from '@/models/entities/signin.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(Signin) | export const SigninRepository = db.getRepository(Signin).extend({ | ||||||
| export class SigninRepository extends Repository<Signin> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: Signin, | 		src: Signin, | ||||||
| 	) { | 	) { | ||||||
| 		return src; | 		return src; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,23 +1,22 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { UserGroupInvitation } from '@/models/entities/user-group-invitation.js'; | import { UserGroupInvitation } from '@/models/entities/user-group-invitation.js'; | ||||||
| import { UserGroups } from '../index.js'; | import { UserGroups } from '../index.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(UserGroupInvitation) | export const UserGroupInvitationRepository = db.getRepository(UserGroupInvitation).extend({ | ||||||
| export class UserGroupInvitationRepository extends Repository<UserGroupInvitation> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: UserGroupInvitation['id'] | UserGroupInvitation, | 		src: UserGroupInvitation['id'] | UserGroupInvitation, | ||||||
| 	) { | 	) { | ||||||
| 		const invitation = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const invitation = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			id: invitation.id, | 			id: invitation.id, | ||||||
| 			group: await UserGroups.pack(invitation.userGroup || invitation.userGroupId), | 			group: await UserGroups.pack(invitation.userGroup || invitation.userGroupId), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany( | 	packMany( | ||||||
| 		invitations: any[], | 		invitations: any[], | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(invitations.map(x => this.pack(x))); | 		return Promise.all(invitations.map(x => this.pack(x))); | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,16 +1,15 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { UserGroup } from '@/models/entities/user-group.js'; | import { UserGroup } from '@/models/entities/user-group.js'; | ||||||
| import { UserGroupJoinings } from '../index.js'; | import { UserGroupJoinings } from '../index.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(UserGroup) | export const UserGroupRepository = db.getRepository(UserGroup).extend({ | ||||||
| export class UserGroupRepository extends Repository<UserGroup> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: UserGroup['id'] | UserGroup, | 		src: UserGroup['id'] | UserGroup, | ||||||
| 	): Promise<Packed<'UserGroup'>> { | 	): Promise<Packed<'UserGroup'>> { | ||||||
| 		const userGroup = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const userGroup = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		const users = await UserGroupJoinings.find({ | 		const users = await UserGroupJoinings.findBy({ | ||||||
| 			userGroupId: userGroup.id, | 			userGroupId: userGroup.id, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  | @ -21,5 +20,5 @@ export class UserGroupRepository extends Repository<UserGroup> { | ||||||
| 			ownerId: userGroup.userId, | 			ownerId: userGroup.userId, | ||||||
| 			userIds: users.map(x => x.userId), | 			userIds: users.map(x => x.userId), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -1,16 +1,15 @@ | ||||||
| import { EntityRepository, Repository } from 'typeorm'; | import { db } from '@/db/postgre.js'; | ||||||
| import { UserList } from '@/models/entities/user-list.js'; | import { UserList } from '@/models/entities/user-list.js'; | ||||||
| import { UserListJoinings } from '../index.js'; | import { UserListJoinings } from '../index.js'; | ||||||
| import { Packed } from '@/misc/schema.js'; | import { Packed } from '@/misc/schema.js'; | ||||||
| 
 | 
 | ||||||
| @EntityRepository(UserList) | export const UserListRepository = db.getRepository(UserList).extend({ | ||||||
| export class UserListRepository extends Repository<UserList> { | 	async pack( | ||||||
| 	public async pack( |  | ||||||
| 		src: UserList['id'] | UserList, | 		src: UserList['id'] | UserList, | ||||||
| 	): Promise<Packed<'UserList'>> { | 	): Promise<Packed<'UserList'>> { | ||||||
| 		const userList = typeof src === 'object' ? src : await this.findOneOrFail(src); | 		const userList = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
| 		const users = await UserListJoinings.find({ | 		const users = await UserListJoinings.findBy({ | ||||||
| 			userListId: userList.id, | 			userListId: userList.id, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  | @ -20,5 +19,5 @@ export class UserListRepository extends Repository<UserList> { | ||||||
| 			name: userList.name, | 			name: userList.name, | ||||||
| 			userIds: users.map(x => x.userId), | 			userIds: users.map(x => x.userId), | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| } | }); | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import { getAntennas } from '@/misc/antenna-cache.js'; | ||||||
| import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; | import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; | ||||||
| import { Cache } from '@/misc/cache.js'; | import { Cache } from '@/misc/cache.js'; | ||||||
| import { Instance } from '../entities/instance.js'; | import { Instance } from '../entities/instance.js'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3); | const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3); | ||||||
| 
 | 
 | ||||||
|  | @ -23,51 +24,69 @@ type IsMeAndIsUserDetailed<ExpectsMe extends boolean | null, Detailed extends bo | ||||||
| 
 | 
 | ||||||
| const ajv = new Ajv(); | const ajv = new Ajv(); | ||||||
| 
 | 
 | ||||||
| @EntityRepository(User) | const localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const; | ||||||
| export class UserRepository extends Repository<User> { | const passwordSchema = { type: 'string', minLength: 1 } as const; | ||||||
| 	public localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const; | const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | ||||||
| 	public passwordSchema = { type: 'string', minLength: 1 } as const; | const descriptionSchema = { type: 'string', minLength: 1, maxLength: 500 } as const; | ||||||
| 	public nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | const locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | ||||||
| 	public descriptionSchema = { type: 'string', minLength: 1, maxLength: 500 } as const; | const birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; | ||||||
| 	public locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | 
 | ||||||
| 	public birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; | function isLocalUser(user: User): user is ILocalUser; | ||||||
|  | function isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; }; | ||||||
|  | function isLocalUser(user: User | { host: User['host'] }): boolean { | ||||||
|  | 	return user.host == null; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function isRemoteUser(user: User): user is IRemoteUser; | ||||||
|  | function isRemoteUser<T extends { host: User['host'] }>(user: T): user is T & { host: string; }; | ||||||
|  | function isRemoteUser(user: User | { host: User['host'] }): boolean { | ||||||
|  | 	return !isLocalUser(user); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const UserRepository = db.getRepository(User).extend({ | ||||||
|  | 	localUsernameSchema, | ||||||
|  | 	passwordSchema, | ||||||
|  | 	nameSchema, | ||||||
|  | 	descriptionSchema, | ||||||
|  | 	locationSchema, | ||||||
|  | 	birthdaySchema, | ||||||
| 
 | 
 | ||||||
| 	//#region Validators
 | 	//#region Validators
 | ||||||
| 	public validateLocalUsername = ajv.compile(this.localUsernameSchema); | 	validateLocalUsername: ajv.compile(localUsernameSchema), | ||||||
| 	public validatePassword = ajv.compile(this.passwordSchema); | 	validatePassword: ajv.compile(passwordSchema), | ||||||
| 	public validateName = ajv.compile(this.nameSchema); | 	validateName: ajv.compile(nameSchema), | ||||||
| 	public validateDescription = ajv.compile(this.descriptionSchema); | 	validateDescription: ajv.compile(descriptionSchema), | ||||||
| 	public validateLocation = ajv.compile(this.locationSchema); | 	validateLocation: ajv.compile(locationSchema), | ||||||
| 	public validateBirthday = ajv.compile(this.birthdaySchema); | 	validateBirthday: ajv.compile(birthdaySchema), | ||||||
| 	//#endregion
 | 	//#endregion
 | ||||||
| 
 | 
 | ||||||
| 	public async getRelation(me: User['id'], target: User['id']) { | 	async getRelation(me: User['id'], target: User['id']) { | ||||||
| 		const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([ | 		const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([ | ||||||
| 			Followings.findOne({ | 			Followings.findOneBy({ | ||||||
| 				followerId: me, | 				followerId: me, | ||||||
| 				followeeId: target, | 				followeeId: target, | ||||||
| 			}), | 			}), | ||||||
| 			Followings.findOne({ | 			Followings.findOneBy({ | ||||||
| 				followerId: target, | 				followerId: target, | ||||||
| 				followeeId: me, | 				followeeId: me, | ||||||
| 			}), | 			}), | ||||||
| 			FollowRequests.findOne({ | 			FollowRequests.findOneBy({ | ||||||
| 				followerId: me, | 				followerId: me, | ||||||
| 				followeeId: target, | 				followeeId: target, | ||||||
| 			}), | 			}), | ||||||
| 			FollowRequests.findOne({ | 			FollowRequests.findOneBy({ | ||||||
| 				followerId: target, | 				followerId: target, | ||||||
| 				followeeId: me, | 				followeeId: me, | ||||||
| 			}), | 			}), | ||||||
| 			Blockings.findOne({ | 			Blockings.findOneBy({ | ||||||
| 				blockerId: me, | 				blockerId: me, | ||||||
| 				blockeeId: target, | 				blockeeId: target, | ||||||
| 			}), | 			}), | ||||||
| 			Blockings.findOne({ | 			Blockings.findOneBy({ | ||||||
| 				blockerId: target, | 				blockerId: target, | ||||||
| 				blockeeId: me, | 				blockeeId: me, | ||||||
| 			}), | 			}), | ||||||
| 			Mutings.findOne({ | 			Mutings.findOneBy({ | ||||||
| 				muterId: me, | 				muterId: me, | ||||||
| 				muteeId: target, | 				muteeId: target, | ||||||
| 			}), | 			}), | ||||||
|  | @ -83,14 +102,14 @@ export class UserRepository extends Repository<User> { | ||||||
| 			isBlocked: fromBlocked != null, | 			isBlocked: fromBlocked != null, | ||||||
| 			isMuted: mute != null, | 			isMuted: mute != null, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async getHasUnreadMessagingMessage(userId: User['id']): Promise<boolean> { | 	async getHasUnreadMessagingMessage(userId: User['id']): Promise<boolean> { | ||||||
| 		const mute = await Mutings.find({ | 		const mute = await Mutings.findBy({ | ||||||
| 			muterId: userId, | 			muterId: userId, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		const joinings = await UserGroupJoinings.find({ userId: userId }); | 		const joinings = await UserGroupJoinings.findBy({ userId: userId }); | ||||||
| 
 | 
 | ||||||
| 		const groupQs = Promise.all(joinings.map(j => MessagingMessages.createQueryBuilder('message') | 		const groupQs = Promise.all(joinings.map(j => MessagingMessages.createQueryBuilder('message') | ||||||
| 			.where(`message.groupId = :groupId`, { groupId: j.userGroupId }) | 			.where(`message.groupId = :groupId`, { groupId: j.userGroupId }) | ||||||
|  | @ -112,44 +131,44 @@ export class UserRepository extends Repository<User> { | ||||||
| 		]); | 		]); | ||||||
| 
 | 
 | ||||||
| 		return withUser || withGroups.some(x => x); | 		return withUser || withGroups.some(x => x); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async getHasUnreadAnnouncement(userId: User['id']): Promise<boolean> { | 	async getHasUnreadAnnouncement(userId: User['id']): Promise<boolean> { | ||||||
| 		const reads = await AnnouncementReads.find({ | 		const reads = await AnnouncementReads.findBy({ | ||||||
| 			userId: userId, | 			userId: userId, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		const count = await Announcements.count(reads.length > 0 ? { | 		const count = await Announcements.countBy(reads.length > 0 ? { | ||||||
| 			id: Not(In(reads.map(read => read.announcementId))), | 			id: Not(In(reads.map(read => read.announcementId))), | ||||||
| 		} : {}); | 		} : {}); | ||||||
| 
 | 
 | ||||||
| 		return count > 0; | 		return count > 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async getHasUnreadAntenna(userId: User['id']): Promise<boolean> { | 	async getHasUnreadAntenna(userId: User['id']): Promise<boolean> { | ||||||
| 		const myAntennas = (await getAntennas()).filter(a => a.userId === userId); | 		const myAntennas = (await getAntennas()).filter(a => a.userId === userId); | ||||||
| 
 | 
 | ||||||
| 		const unread = myAntennas.length > 0 ? await AntennaNotes.findOne({ | 		const unread = myAntennas.length > 0 ? await AntennaNotes.findOneBy({ | ||||||
| 			antennaId: In(myAntennas.map(x => x.id)), | 			antennaId: In(myAntennas.map(x => x.id)), | ||||||
| 			read: false, | 			read: false, | ||||||
| 		}) : null; | 		}) : null; | ||||||
| 
 | 
 | ||||||
| 		return unread != null; | 		return unread != null; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async getHasUnreadChannel(userId: User['id']): Promise<boolean> { | 	async getHasUnreadChannel(userId: User['id']): Promise<boolean> { | ||||||
| 		const channels = await ChannelFollowings.find({ followerId: userId }); | 		const channels = await ChannelFollowings.findBy({ followerId: userId }); | ||||||
| 
 | 
 | ||||||
| 		const unread = channels.length > 0 ? await NoteUnreads.findOne({ | 		const unread = channels.length > 0 ? await NoteUnreads.findOneBy({ | ||||||
| 			userId: userId, | 			userId: userId, | ||||||
| 			noteChannelId: In(channels.map(x => x.followeeId)), | 			noteChannelId: In(channels.map(x => x.followeeId)), | ||||||
| 		}) : null; | 		}) : null; | ||||||
| 
 | 
 | ||||||
| 		return unread != null; | 		return unread != null; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async getHasUnreadNotification(userId: User['id']): Promise<boolean> { | 	async getHasUnreadNotification(userId: User['id']): Promise<boolean> { | ||||||
| 		const mute = await Mutings.find({ | 		const mute = await Mutings.findBy({ | ||||||
| 			muterId: userId, | 			muterId: userId, | ||||||
| 		}); | 		}); | ||||||
| 		const mutedUserIds = mute.map(m => m.muteeId); | 		const mutedUserIds = mute.map(m => m.muteeId); | ||||||
|  | @ -164,17 +183,17 @@ export class UserRepository extends Repository<User> { | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		return count > 0; | 		return count > 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async getHasPendingReceivedFollowRequest(userId: User['id']): Promise<boolean> { | 	async getHasPendingReceivedFollowRequest(userId: User['id']): Promise<boolean> { | ||||||
| 		const count = await FollowRequests.count({ | 		const count = await FollowRequests.countBy({ | ||||||
| 			followeeId: userId, | 			followeeId: userId, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		return count > 0; | 		return count > 0; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public getOnlineStatus(user: User): 'unknown' | 'online' | 'active' | 'offline' { | 	getOnlineStatus(user: User): 'unknown' | 'online' | 'active' | 'offline' { | ||||||
| 		if (user.hideOnlineStatus) return 'unknown'; | 		if (user.hideOnlineStatus) return 'unknown'; | ||||||
| 		if (user.lastActiveDate == null) return 'unknown'; | 		if (user.lastActiveDate == null) return 'unknown'; | ||||||
| 		const elapsed = Date.now() - user.lastActiveDate.getTime(); | 		const elapsed = Date.now() - user.lastActiveDate.getTime(); | ||||||
|  | @ -183,22 +202,22 @@ export class UserRepository extends Repository<User> { | ||||||
| 			elapsed < USER_ACTIVE_THRESHOLD ? 'active' : | 			elapsed < USER_ACTIVE_THRESHOLD ? 'active' : | ||||||
| 			'offline' | 			'offline' | ||||||
| 		); | 		); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public getAvatarUrl(user: User): string { | 	getAvatarUrl(user: User): string { | ||||||
| 		// TODO: avatarIdがあるがavatarがない(JOINされてない)場合のハンドリング
 | 		// TODO: avatarIdがあるがavatarがない(JOINされてない)場合のハンドリング
 | ||||||
| 		if (user.avatar) { | 		if (user.avatar) { | ||||||
| 			return DriveFiles.getPublicUrl(user.avatar, true) || this.getIdenticonUrl(user.id); | 			return DriveFiles.getPublicUrl(user.avatar, true) || this.getIdenticonUrl(user.id); | ||||||
| 		} else { | 		} else { | ||||||
| 			return this.getIdenticonUrl(user.id); | 			return this.getIdenticonUrl(user.id); | ||||||
| 		} | 		} | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public getIdenticonUrl(userId: User['id']): string { | 	getIdenticonUrl(userId: User['id']): string { | ||||||
| 		return `${config.url}/identicon/${userId}`; | 		return `${config.url}/identicon/${userId}`; | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>( | 	async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>( | ||||||
| 		src: User['id'] | User, | 		src: User['id'] | User, | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -215,11 +234,15 @@ export class UserRepository extends Repository<User> { | ||||||
| 
 | 
 | ||||||
| 		if (typeof src === 'object') { | 		if (typeof src === 'object') { | ||||||
| 			user = src; | 			user = src; | ||||||
| 			if (src.avatar === undefined && src.avatarId) src.avatar = await DriveFiles.findOne(src.avatarId) ?? null; | 			if (src.avatar === undefined && src.avatarId) src.avatar = await DriveFiles.findOneBy({ id: src.avatarId }) ?? null; | ||||||
| 			if (src.banner === undefined && src.bannerId) src.banner = await DriveFiles.findOne(src.bannerId) ?? null; | 			if (src.banner === undefined && src.bannerId) src.banner = await DriveFiles.findOneBy({ id: src.bannerId }) ?? null; | ||||||
| 		} else { | 		} else { | ||||||
| 			user = await this.findOneOrFail(src, { | 			user = await this.findOneOrFail({ | ||||||
| 				relations: ['avatar', 'banner'], | 				where: { id: src }, | ||||||
|  | 				relations: { | ||||||
|  | 					avatar: true, | ||||||
|  | 					banner: true, | ||||||
|  | 				}, | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -232,7 +255,7 @@ export class UserRepository extends Repository<User> { | ||||||
| 			.innerJoinAndSelect('pin.note', 'note') | 			.innerJoinAndSelect('pin.note', 'note') | ||||||
| 			.orderBy('pin.id', 'DESC') | 			.orderBy('pin.id', 'DESC') | ||||||
| 			.getMany() : []; | 			.getMany() : []; | ||||||
| 		const profile = opts.detail ? await UserProfiles.findOneOrFail(user.id) : null; | 		const profile = opts.detail ? await UserProfiles.findOneByOrFail({ userId: user.id }) : null; | ||||||
| 
 | 
 | ||||||
| 		const followingCount = profile == null ? null : | 		const followingCount = profile == null ? null : | ||||||
| 			(profile.ffVisibility === 'public') || isMe ? user.followingCount : | 			(profile.ffVisibility === 'public') || isMe ? user.followingCount : | ||||||
|  | @ -258,9 +281,8 @@ export class UserRepository extends Repository<User> { | ||||||
| 			isModerator: user.isModerator || falsy, | 			isModerator: user.isModerator || falsy, | ||||||
| 			isBot: user.isBot || falsy, | 			isBot: user.isBot || falsy, | ||||||
| 			isCat: user.isCat || falsy, | 			isCat: user.isCat || falsy, | ||||||
| 			// TODO: typeorm 3.0にしたら .then(x => x || null) は消せる
 |  | ||||||
| 			instance: user.host ? userInstanceCache.fetch(user.host, | 			instance: user.host ? userInstanceCache.fetch(user.host, | ||||||
| 				() => Instances.findOne({ host: user.host }).then(x => x || null), | 				() => Instances.findOneBy({ host: user.host! }), | ||||||
| 				v => v != null | 				v => v != null | ||||||
| 			).then(instance => instance ? { | 			).then(instance => instance ? { | ||||||
| 				name: instance.name, | 				name: instance.name, | ||||||
|  | @ -304,7 +326,7 @@ export class UserRepository extends Repository<User> { | ||||||
| 				twoFactorEnabled: profile!.twoFactorEnabled, | 				twoFactorEnabled: profile!.twoFactorEnabled, | ||||||
| 				usePasswordLessLogin: profile!.usePasswordLessLogin, | 				usePasswordLessLogin: profile!.usePasswordLessLogin, | ||||||
| 				securityKeys: profile!.twoFactorEnabled | 				securityKeys: profile!.twoFactorEnabled | ||||||
| 					? UserSecurityKeys.count({ | 					? UserSecurityKeys.countBy({ | ||||||
| 						userId: user.id, | 						userId: user.id, | ||||||
| 					}).then(result => result >= 1) | 					}).then(result => result >= 1) | ||||||
| 					: false, | 					: false, | ||||||
|  | @ -352,7 +374,11 @@ export class UserRepository extends Repository<User> { | ||||||
| 						where: { | 						where: { | ||||||
| 							userId: user.id, | 							userId: user.id, | ||||||
| 						}, | 						}, | ||||||
| 						select: ['id', 'name', 'lastUsed'], | 						select: { | ||||||
|  | 							id: true, | ||||||
|  | 							name: true, | ||||||
|  | 							lastUsed: true, | ||||||
|  | 						}, | ||||||
| 					}) | 					}) | ||||||
| 					: [], | 					: [], | ||||||
| 			} : {}), | 			} : {}), | ||||||
|  | @ -369,9 +395,9 @@ export class UserRepository extends Repository<User> { | ||||||
| 		} as Promiseable<Packed<'User'>> as Promiseable<IsMeAndIsUserDetailed<ExpectsMe, D>>; | 		} as Promiseable<Packed<'User'>> as Promiseable<IsMeAndIsUserDetailed<ExpectsMe, D>>; | ||||||
| 
 | 
 | ||||||
| 		return await awaitAll(packed); | 		return await awaitAll(packed); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public packMany<D extends boolean = false>( | 	packMany<D extends boolean = false>( | ||||||
| 		users: (User['id'] | User)[], | 		users: (User['id'] | User)[], | ||||||
| 		me?: { id: User['id'] } | null | undefined, | 		me?: { id: User['id'] } | null | undefined, | ||||||
| 		options?: { | 		options?: { | ||||||
|  | @ -380,17 +406,8 @@ export class UserRepository extends Repository<User> { | ||||||
| 		} | 		} | ||||||
| 	): Promise<IsUserDetailed<D>[]> { | 	): Promise<IsUserDetailed<D>[]> { | ||||||
| 		return Promise.all(users.map(u => this.pack(u, me, options))); | 		return Promise.all(users.map(u => this.pack(u, me, options))); | ||||||
| 	} | 	}, | ||||||
| 
 | 
 | ||||||
| 	public isLocalUser(user: User): user is ILocalUser; | 	isLocalUser, | ||||||
| 	public isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; }; | 	isRemoteUser, | ||||||
| 	public isLocalUser(user: User | { host: User['host'] }): boolean { | }); | ||||||
| 		return user.host == null; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public isRemoteUser(user: User): user is IRemoteUser; |  | ||||||
| 	public isRemoteUser<T extends { host: User['host'] }>(user: T): user is T & { host: string; }; |  | ||||||
| 	public isRemoteUser(user: User | { host: User['host'] }): boolean { |  | ||||||
| 		return !this.isLocalUser(user); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ const logger = queueLogger.createSubLogger('delete-account'); | ||||||
| export async function deleteAccount(job: Bull.Job<DbUserDeleteJobData>): Promise<string | void> { | export async function deleteAccount(job: Bull.Job<DbUserDeleteJobData>): Promise<string | void> { | ||||||
| 	logger.info(`Deleting account of ${job.data.user.id} ...`); | 	logger.info(`Deleting account of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -75,7 +75,7 @@ export async function deleteAccount(job: Bull.Job<DbUserDeleteJobData>): Promise | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	{ // Send email notification
 | 	{ // Send email notification
 | ||||||
| 		const profile = await UserProfiles.findOneOrFail(user.id); | 		const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); | ||||||
| 		if (profile.email && profile.emailVerified) { | 		if (profile.email && profile.emailVerified) { | ||||||
| 			sendEmail(profile.email, 'Account deleted', | 			sendEmail(profile.email, 'Account deleted', | ||||||
| 				`Your account has been deleted.`, | 				`Your account has been deleted.`, | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ const logger = queueLogger.createSubLogger('delete-drive-files'); | ||||||
| export async function deleteDriveFiles(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | export async function deleteDriveFiles(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Deleting drive files of ${job.data.user.id} ...`); | 	logger.info(`Deleting drive files of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  | @ -44,7 +44,7 @@ export async function deleteDriveFiles(job: Bull.Job<DbUserJobData>, done: any): | ||||||
| 			deletedCount++; | 			deletedCount++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const total = await DriveFiles.count({ | 		const total = await DriveFiles.countBy({ | ||||||
| 			userId: user.id, | 			userId: user.id, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ const logger = queueLogger.createSubLogger('export-blocking'); | ||||||
| export async function exportBlocking(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | export async function exportBlocking(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Exporting blocking of ${job.data.user.id} ...`); | 	logger.info(`Exporting blocking of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  | @ -56,7 +56,7 @@ export async function exportBlocking(job: Bull.Job<DbUserJobData>, done: any): P | ||||||
| 		cursor = blockings[blockings.length - 1].id; | 		cursor = blockings[blockings.length - 1].id; | ||||||
| 
 | 
 | ||||||
| 		for (const block of blockings) { | 		for (const block of blockings) { | ||||||
| 			const u = await Users.findOne({ id: block.blockeeId }); | 			const u = await Users.findOneBy({ id: block.blockeeId }); | ||||||
| 			if (u == null) { | 			if (u == null) { | ||||||
| 				exportedCount++; continue; | 				exportedCount++; continue; | ||||||
| 			} | 			} | ||||||
|  | @ -75,7 +75,7 @@ export async function exportBlocking(job: Bull.Job<DbUserJobData>, done: any): P | ||||||
| 			exportedCount++; | 			exportedCount++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const total = await Blockings.count({ | 		const total = await Blockings.countBy({ | ||||||
| 			blockerId: user.id, | 			blockerId: user.id, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,13 +12,14 @@ import { Users, Emojis } from '@/models/index.js'; | ||||||
| import {  } from '@/queue/types.js'; | import {  } from '@/queue/types.js'; | ||||||
| import { downloadUrl } from '@/misc/download-url.js'; | import { downloadUrl } from '@/misc/download-url.js'; | ||||||
| import config from '@/config/index.js'; | import config from '@/config/index.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const logger = queueLogger.createSubLogger('export-custom-emojis'); | const logger = queueLogger.createSubLogger('export-custom-emojis'); | ||||||
| 
 | 
 | ||||||
| export async function exportCustomEmojis(job: Bull.Job, done: () => void): Promise<void> { | export async function exportCustomEmojis(job: Bull.Job, done: () => void): Promise<void> { | ||||||
| 	logger.info(`Exporting custom emojis ...`); | 	logger.info(`Exporting custom emojis ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  | @ -57,7 +58,7 @@ export async function exportCustomEmojis(job: Bull.Job, done: () => void): Promi | ||||||
| 
 | 
 | ||||||
| 	const customEmojis = await Emojis.find({ | 	const customEmojis = await Emojis.find({ | ||||||
| 		where: { | 		where: { | ||||||
| 			host: null, | 			host: IsNull(), | ||||||
| 		}, | 		}, | ||||||
| 		order: { | 		order: { | ||||||
| 			id: 'ASC', | 			id: 'ASC', | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ const logger = queueLogger.createSubLogger('export-following'); | ||||||
| export async function exportFollowing(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> { | export async function exportFollowing(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> { | ||||||
| 	logger.info(`Exporting following of ${job.data.user.id} ...`); | 	logger.info(`Exporting following of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  | @ -36,7 +36,7 @@ export async function exportFollowing(job: Bull.Job<DbUserJobData>, done: () => | ||||||
| 
 | 
 | ||||||
| 	let cursor: Following['id'] | null = null; | 	let cursor: Following['id'] | null = null; | ||||||
| 
 | 
 | ||||||
| 	const mutings = job.data.excludeMuting ? await Mutings.find({ | 	const mutings = job.data.excludeMuting ? await Mutings.findBy({ | ||||||
| 		muterId: user.id, | 		muterId: user.id, | ||||||
| 	}) : []; | 	}) : []; | ||||||
| 
 | 
 | ||||||
|  | @ -60,7 +60,7 @@ export async function exportFollowing(job: Bull.Job<DbUserJobData>, done: () => | ||||||
| 		cursor = followings[followings.length - 1].id; | 		cursor = followings[followings.length - 1].id; | ||||||
| 
 | 
 | ||||||
| 		for (const following of followings) { | 		for (const following of followings) { | ||||||
| 			const u = await Users.findOne({ id: following.followeeId }); | 			const u = await Users.findOneBy({ id: following.followeeId }); | ||||||
| 			if (u == null) { | 			if (u == null) { | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ const logger = queueLogger.createSubLogger('export-mute'); | ||||||
| export async function exportMute(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | export async function exportMute(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Exporting mute of ${job.data.user.id} ...`); | 	logger.info(`Exporting mute of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  | @ -57,7 +57,7 @@ export async function exportMute(job: Bull.Job<DbUserJobData>, done: any): Promi | ||||||
| 		cursor = mutes[mutes.length - 1].id; | 		cursor = mutes[mutes.length - 1].id; | ||||||
| 
 | 
 | ||||||
| 		for (const mute of mutes) { | 		for (const mute of mutes) { | ||||||
| 			const u = await Users.findOne({ id: mute.muteeId }); | 			const u = await Users.findOneBy({ id: mute.muteeId }); | ||||||
| 			if (u == null) { | 			if (u == null) { | ||||||
| 				exportedCount++; continue; | 				exportedCount++; continue; | ||||||
| 			} | 			} | ||||||
|  | @ -76,7 +76,7 @@ export async function exportMute(job: Bull.Job<DbUserJobData>, done: any): Promi | ||||||
| 			exportedCount++; | 			exportedCount++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const total = await Mutings.count({ | 		const total = await Mutings.countBy({ | ||||||
| 			muterId: user.id, | 			muterId: user.id, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ const logger = queueLogger.createSubLogger('export-notes'); | ||||||
| export async function exportNotes(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | export async function exportNotes(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Exporting notes of ${job.data.user.id} ...`); | 	logger.info(`Exporting notes of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  | @ -74,7 +74,7 @@ export async function exportNotes(job: Bull.Job<DbUserJobData>, done: any): Prom | ||||||
| 		for (const note of notes) { | 		for (const note of notes) { | ||||||
| 			let poll: Poll | undefined; | 			let poll: Poll | undefined; | ||||||
| 			if (note.hasPoll) { | 			if (note.hasPoll) { | ||||||
| 				poll = await Polls.findOneOrFail({ noteId: note.id }); | 				poll = await Polls.findOneByOrFail({ noteId: note.id }); | ||||||
| 			} | 			} | ||||||
| 			const content = JSON.stringify(serialize(note, poll)); | 			const content = JSON.stringify(serialize(note, poll)); | ||||||
| 			const isFirst = exportedNotesCount === 0; | 			const isFirst = exportedNotesCount === 0; | ||||||
|  | @ -82,7 +82,7 @@ export async function exportNotes(job: Bull.Job<DbUserJobData>, done: any): Prom | ||||||
| 			exportedNotesCount++; | 			exportedNotesCount++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const total = await Notes.count({ | 		const total = await Notes.countBy({ | ||||||
| 			userId: user.id, | 			userId: user.id, | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,13 +15,13 @@ const logger = queueLogger.createSubLogger('export-user-lists'); | ||||||
| export async function exportUserLists(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | export async function exportUserLists(job: Bull.Job<DbUserJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Exporting user lists of ${job.data.user.id} ...`); | 	logger.info(`Exporting user lists of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const lists = await UserLists.find({ | 	const lists = await UserLists.findBy({ | ||||||
| 		userId: user.id, | 		userId: user.id, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | @ -38,8 +38,8 @@ export async function exportUserLists(job: Bull.Job<DbUserJobData>, done: any): | ||||||
| 	const stream = fs.createWriteStream(path, { flags: 'a' }); | 	const stream = fs.createWriteStream(path, { flags: 'a' }); | ||||||
| 
 | 
 | ||||||
| 	for (const list of lists) { | 	for (const list of lists) { | ||||||
| 		const joinings = await UserListJoinings.find({ userListId: list.id }); | 		const joinings = await UserListJoinings.findBy({ userListId: list.id }); | ||||||
| 		const users = await Users.find({ | 		const users = await Users.findBy({ | ||||||
| 			id: In(joinings.map(j => j.userId)), | 			id: In(joinings.map(j => j.userId)), | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,19 +8,20 @@ import { isSelfHost, toPuny } from '@/misc/convert-host.js'; | ||||||
| import { Users, DriveFiles, Blockings } from '@/models/index.js'; | import { Users, DriveFiles, Blockings } from '@/models/index.js'; | ||||||
| import { DbUserImportJobData } from '@/queue/types.js'; | import { DbUserImportJobData } from '@/queue/types.js'; | ||||||
| import block from '@/services/blocking/create.js'; | import block from '@/services/blocking/create.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const logger = queueLogger.createSubLogger('import-blocking'); | const logger = queueLogger.createSubLogger('import-blocking'); | ||||||
| 
 | 
 | ||||||
| export async function importBlocking(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | export async function importBlocking(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Importing blocking of ${job.data.user.id} ...`); | 	logger.info(`Importing blocking of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const file = await DriveFiles.findOne({ | 	const file = await DriveFiles.findOneBy({ | ||||||
| 		id: job.data.fileId, | 		id: job.data.fileId, | ||||||
| 	}); | 	}); | ||||||
| 	if (file == null) { | 	if (file == null) { | ||||||
|  | @ -39,10 +40,10 @@ export async function importBlocking(job: Bull.Job<DbUserImportJobData>, done: a | ||||||
| 			const acct = line.split(',')[0].trim(); | 			const acct = line.split(',')[0].trim(); | ||||||
| 			const { username, host } = Acct.parse(acct); | 			const { username, host } = Acct.parse(acct); | ||||||
| 
 | 
 | ||||||
| 			let target = isSelfHost(host!) ? await Users.findOne({ | 			let target = isSelfHost(host!) ? await Users.findOneBy({ | ||||||
| 				host: null, | 				host: IsNull(), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}) : await Users.findOne({ | 			}) : await Users.findOneBy({ | ||||||
| 				host: toPuny(host!), | 				host: toPuny(host!), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ import Bull from 'bull'; | ||||||
| import * as tmp from 'tmp'; | import * as tmp from 'tmp'; | ||||||
| import * as fs from 'node:fs'; | import * as fs from 'node:fs'; | ||||||
| import unzipper from 'unzipper'; | import unzipper from 'unzipper'; | ||||||
| import { getConnection } from 'typeorm'; |  | ||||||
| 
 | 
 | ||||||
| import { queueLogger } from '../../logger.js'; | import { queueLogger } from '../../logger.js'; | ||||||
| import { downloadUrl } from '@/misc/download-url.js'; | import { downloadUrl } from '@/misc/download-url.js'; | ||||||
|  | @ -10,6 +9,7 @@ import { DriveFiles, Emojis } from '@/models/index.js'; | ||||||
| import { DbUserImportJobData } from '@/queue/types.js'; | import { DbUserImportJobData } from '@/queue/types.js'; | ||||||
| import { addFile } from '@/services/drive/add-file.js'; | import { addFile } from '@/services/drive/add-file.js'; | ||||||
| import { genId } from '@/misc/gen-id.js'; | import { genId } from '@/misc/gen-id.js'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| const logger = queueLogger.createSubLogger('import-custom-emojis'); | const logger = queueLogger.createSubLogger('import-custom-emojis'); | ||||||
| 
 | 
 | ||||||
|  | @ -17,7 +17,7 @@ const logger = queueLogger.createSubLogger('import-custom-emojis'); | ||||||
| export async function importCustomEmojis(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | export async function importCustomEmojis(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Importing custom emojis ...`); | 	logger.info(`Importing custom emojis ...`); | ||||||
| 
 | 
 | ||||||
| 	const file = await DriveFiles.findOne({ | 	const file = await DriveFiles.findOneBy({ | ||||||
| 		id: job.data.fileId, | 		id: job.data.fileId, | ||||||
| 	}); | 	}); | ||||||
| 	if (file == null) { | 	if (file == null) { | ||||||
|  | @ -72,10 +72,10 @@ export async function importCustomEmojis(job: Bull.Job<DbUserImportJobData>, don | ||||||
| 				originalUrl: driveFile.url, | 				originalUrl: driveFile.url, | ||||||
| 				publicUrl: driveFile.webpublicUrl ?? driveFile.url, | 				publicUrl: driveFile.webpublicUrl ?? driveFile.url, | ||||||
| 				type: driveFile.webpublicType ?? driveFile.type, | 				type: driveFile.webpublicType ?? driveFile.type, | ||||||
| 			}).then(x => Emojis.findOneOrFail(x.identifiers[0])); | 			}).then(x => Emojis.findOneByOrFail(x.identifiers[0])); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		await getConnection().queryResultCache!.remove(['meta_emojis']); | 		await db.queryResultCache!.remove(['meta_emojis']); | ||||||
| 
 | 
 | ||||||
| 		cleanup(); | 		cleanup(); | ||||||
| 	 | 	 | ||||||
|  |  | ||||||
|  | @ -8,19 +8,20 @@ import { downloadTextFile } from '@/misc/download-text-file.js'; | ||||||
| import { isSelfHost, toPuny } from '@/misc/convert-host.js'; | import { isSelfHost, toPuny } from '@/misc/convert-host.js'; | ||||||
| import { Users, DriveFiles } from '@/models/index.js'; | import { Users, DriveFiles } from '@/models/index.js'; | ||||||
| import { DbUserImportJobData } from '@/queue/types.js'; | import { DbUserImportJobData } from '@/queue/types.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const logger = queueLogger.createSubLogger('import-following'); | const logger = queueLogger.createSubLogger('import-following'); | ||||||
| 
 | 
 | ||||||
| export async function importFollowing(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | export async function importFollowing(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Importing following of ${job.data.user.id} ...`); | 	logger.info(`Importing following of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const file = await DriveFiles.findOne({ | 	const file = await DriveFiles.findOneBy({ | ||||||
| 		id: job.data.fileId, | 		id: job.data.fileId, | ||||||
| 	}); | 	}); | ||||||
| 	if (file == null) { | 	if (file == null) { | ||||||
|  | @ -39,10 +40,10 @@ export async function importFollowing(job: Bull.Job<DbUserImportJobData>, done: | ||||||
| 			const acct = line.split(',')[0].trim(); | 			const acct = line.split(',')[0].trim(); | ||||||
| 			const { username, host } = Acct.parse(acct); | 			const { username, host } = Acct.parse(acct); | ||||||
| 
 | 
 | ||||||
| 			let target = isSelfHost(host!) ? await Users.findOne({ | 			let target = isSelfHost(host!) ? await Users.findOneBy({ | ||||||
| 				host: null, | 				host: IsNull(), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}) : await Users.findOne({ | 			}) : await Users.findOneBy({ | ||||||
| 				host: toPuny(host!), | 				host: toPuny(host!), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|  | @ -9,19 +9,20 @@ import { Users, DriveFiles, Mutings } from '@/models/index.js'; | ||||||
| import { DbUserImportJobData } from '@/queue/types.js'; | import { DbUserImportJobData } from '@/queue/types.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| import { genId } from '@/misc/gen-id.js'; | import { genId } from '@/misc/gen-id.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const logger = queueLogger.createSubLogger('import-muting'); | const logger = queueLogger.createSubLogger('import-muting'); | ||||||
| 
 | 
 | ||||||
| export async function importMuting(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | export async function importMuting(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Importing muting of ${job.data.user.id} ...`); | 	logger.info(`Importing muting of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const file = await DriveFiles.findOne({ | 	const file = await DriveFiles.findOneBy({ | ||||||
| 		id: job.data.fileId, | 		id: job.data.fileId, | ||||||
| 	}); | 	}); | ||||||
| 	if (file == null) { | 	if (file == null) { | ||||||
|  | @ -40,10 +41,10 @@ export async function importMuting(job: Bull.Job<DbUserImportJobData>, done: any | ||||||
| 			const acct = line.split(',')[0].trim(); | 			const acct = line.split(',')[0].trim(); | ||||||
| 			const { username, host } = Acct.parse(acct); | 			const { username, host } = Acct.parse(acct); | ||||||
| 
 | 
 | ||||||
| 			let target = isSelfHost(host!) ? await Users.findOne({ | 			let target = isSelfHost(host!) ? await Users.findOneBy({ | ||||||
| 				host: null, | 				host: IsNull(), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}) : await Users.findOne({ | 			}) : await Users.findOneBy({ | ||||||
| 				host: toPuny(host!), | 				host: toPuny(host!), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|  | @ -9,19 +9,20 @@ import { isSelfHost, toPuny } from '@/misc/convert-host.js'; | ||||||
| import { DriveFiles, Users, UserLists, UserListJoinings } from '@/models/index.js'; | import { DriveFiles, Users, UserLists, UserListJoinings } from '@/models/index.js'; | ||||||
| import { genId } from '@/misc/gen-id.js'; | import { genId } from '@/misc/gen-id.js'; | ||||||
| import { DbUserImportJobData } from '@/queue/types.js'; | import { DbUserImportJobData } from '@/queue/types.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const logger = queueLogger.createSubLogger('import-user-lists'); | const logger = queueLogger.createSubLogger('import-user-lists'); | ||||||
| 
 | 
 | ||||||
| export async function importUserLists(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | export async function importUserLists(job: Bull.Job<DbUserImportJobData>, done: any): Promise<void> { | ||||||
| 	logger.info(`Importing user lists of ${job.data.user.id} ...`); | 	logger.info(`Importing user lists of ${job.data.user.id} ...`); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne(job.data.user.id); | 	const user = await Users.findOneBy({ id: job.data.user.id }); | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const file = await DriveFiles.findOne({ | 	const file = await DriveFiles.findOneBy({ | ||||||
| 		id: job.data.fileId, | 		id: job.data.fileId, | ||||||
| 	}); | 	}); | ||||||
| 	if (file == null) { | 	if (file == null) { | ||||||
|  | @ -40,7 +41,7 @@ export async function importUserLists(job: Bull.Job<DbUserImportJobData>, done: | ||||||
| 			const listName = line.split(',')[0].trim(); | 			const listName = line.split(',')[0].trim(); | ||||||
| 			const { username, host } = Acct.parse(line.split(',')[1].trim()); | 			const { username, host } = Acct.parse(line.split(',')[1].trim()); | ||||||
| 
 | 
 | ||||||
| 			let list = await UserLists.findOne({ | 			let list = await UserLists.findOneBy({ | ||||||
| 				userId: user.id, | 				userId: user.id, | ||||||
| 				name: listName, | 				name: listName, | ||||||
| 			}); | 			}); | ||||||
|  | @ -51,13 +52,13 @@ export async function importUserLists(job: Bull.Job<DbUserImportJobData>, done: | ||||||
| 					createdAt: new Date(), | 					createdAt: new Date(), | ||||||
| 					userId: user.id, | 					userId: user.id, | ||||||
| 					name: listName, | 					name: listName, | ||||||
| 				}).then(x => UserLists.findOneOrFail(x.identifiers[0])); | 				}).then(x => UserLists.findOneByOrFail(x.identifiers[0])); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			let target = isSelfHost(host!) ? await Users.findOne({ | 			let target = isSelfHost(host!) ? await Users.findOneBy({ | ||||||
| 				host: null, | 				host: IsNull(), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}) : await Users.findOne({ | 			}) : await Users.findOneBy({ | ||||||
| 				host: toPuny(host!), | 				host: toPuny(host!), | ||||||
| 				usernameLower: username.toLowerCase(), | 				usernameLower: username.toLowerCase(), | ||||||
| 			}); | 			}); | ||||||
|  | @ -66,7 +67,7 @@ export async function importUserLists(job: Bull.Job<DbUserImportJobData>, done: | ||||||
| 				target = await resolveUser(username, host); | 				target = await resolveUser(username, host); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (await UserListJoinings.findOne({ userListId: list!.id, userId: target.id }) != null) continue; | 			if (await UserListJoinings.findOneBy({ userListId: list!.id, userId: target.id }) != null) continue; | ||||||
| 
 | 
 | ||||||
| 			pushUserToUserList(target, list!); | 			pushUserToUserList(target, list!); | ||||||
| 		} catch (e) { | 		} catch (e) { | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ import { createNotification } from '@/services/create-notification.js'; | ||||||
| const logger = queueLogger.createSubLogger('ended-poll-notification'); | const logger = queueLogger.createSubLogger('ended-poll-notification'); | ||||||
| 
 | 
 | ||||||
| export async function endedPollNotification(job: Bull.Job<EndedPollNotificationJobData>, done: any): Promise<void> { | export async function endedPollNotification(job: Bull.Job<EndedPollNotificationJobData>, done: any): Promise<void> { | ||||||
| 	const note = await Notes.findOne(job.data.noteId); | 	const note = await Notes.findOneBy({ id: job.data.noteId }); | ||||||
| 	if (note == null || !note.hasPoll) { | 	if (note == null || !note.hasPoll) { | ||||||
| 		done(); | 		done(); | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ export default async function cleanRemoteFiles(job: Bull.Job<Record<string, unkn | ||||||
| 
 | 
 | ||||||
| 		deletedCount += 8; | 		deletedCount += 8; | ||||||
| 
 | 
 | ||||||
| 		const total = await DriveFiles.count({ | 		const total = await DriveFiles.countBy({ | ||||||
| 			userHost: Not(IsNull()), | 			userHost: Not(IsNull()), | ||||||
| 			isLink: false, | 			isLink: false, | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|  | @ -24,13 +24,13 @@ export default class DbResolver { | ||||||
| 		const parsed = this.parseUri(value); | 		const parsed = this.parseUri(value); | ||||||
| 
 | 
 | ||||||
| 		if (parsed.id) { | 		if (parsed.id) { | ||||||
| 			return (await Notes.findOne({ | 			return (await Notes.findOneBy({ | ||||||
| 				id: parsed.id, | 				id: parsed.id, | ||||||
| 			})) || null; | 			})) || null; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (parsed.uri) { | 		if (parsed.uri) { | ||||||
| 			return (await Notes.findOne({ | 			return (await Notes.findOneBy({ | ||||||
| 				uri: parsed.uri, | 				uri: parsed.uri, | ||||||
| 			})) || null; | 			})) || null; | ||||||
| 		} | 		} | ||||||
|  | @ -42,13 +42,13 @@ export default class DbResolver { | ||||||
| 		const parsed = this.parseUri(value); | 		const parsed = this.parseUri(value); | ||||||
| 
 | 
 | ||||||
| 		if (parsed.id) { | 		if (parsed.id) { | ||||||
| 			return (await MessagingMessages.findOne({ | 			return (await MessagingMessages.findOneBy({ | ||||||
| 				id: parsed.id, | 				id: parsed.id, | ||||||
| 			})) || null; | 			})) || null; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (parsed.uri) { | 		if (parsed.uri) { | ||||||
| 			return (await MessagingMessages.findOne({ | 			return (await MessagingMessages.findOneBy({ | ||||||
| 				uri: parsed.uri, | 				uri: parsed.uri, | ||||||
| 			})) || null; | 			})) || null; | ||||||
| 		} | 		} | ||||||
|  | @ -63,13 +63,13 @@ export default class DbResolver { | ||||||
| 		const parsed = this.parseUri(value); | 		const parsed = this.parseUri(value); | ||||||
| 
 | 
 | ||||||
| 		if (parsed.id) { | 		if (parsed.id) { | ||||||
| 			return (await Users.findOne({ | 			return (await Users.findOneBy({ | ||||||
| 				id: parsed.id, | 				id: parsed.id, | ||||||
| 			})) || null; | 			})) || null; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (parsed.uri) { | 		if (parsed.uri) { | ||||||
| 			return (await Users.findOne({ | 			return (await Users.findOneBy({ | ||||||
| 				uri: parsed.uri, | 				uri: parsed.uri, | ||||||
| 			})) || null; | 			})) || null; | ||||||
| 		} | 		} | ||||||
|  | @ -85,7 +85,7 @@ export default class DbResolver { | ||||||
| 		key: UserPublickey; | 		key: UserPublickey; | ||||||
| 	} | null> { | 	} | null> { | ||||||
| 		const key = await publicKeyCache.fetch(keyId, async () => { | 		const key = await publicKeyCache.fetch(keyId, async () => { | ||||||
| 			const key = await UserPublickeys.findOne({ | 			const key = await UserPublickeys.findOneBy({ | ||||||
| 				keyId, | 				keyId, | ||||||
| 			}); | 			}); | ||||||
| 	 | 	 | ||||||
|  | @ -97,7 +97,7 @@ export default class DbResolver { | ||||||
| 		if (key == null) return null; | 		if (key == null) return null; | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			user: await userByIdCache.fetch(key.userId, () => Users.findOneOrFail(key.userId)) as CacheableRemoteUser, | 			user: await userByIdCache.fetch(key.userId, () => Users.findOneByOrFail({ id: key.userId })) as CacheableRemoteUser, | ||||||
| 			key, | 			key, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
|  | @ -113,7 +113,7 @@ export default class DbResolver { | ||||||
| 
 | 
 | ||||||
| 		if (user == null) return null; | 		if (user == null) return null; | ||||||
| 
 | 
 | ||||||
| 		const key = await publicKeyByUserIdCache.fetch(user.id, () => UserPublickeys.findOne(user.id).then(x => x || null), v => v != null); // TODO: typeorm 3.0 にしたら.then(x => x || null)は消せる
 | 		const key = await publicKeyByUserIdCache.fetch(user.id, () => UserPublickeys.findOneBy({ userId: user.id }), v => v != null);  | ||||||
| 
 | 
 | ||||||
| 		return { | 		return { | ||||||
| 			user, | 			user, | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ export default class DeliverManager { | ||||||
| 		for (const recipe of this.recipes) { | 		for (const recipe of this.recipes) { | ||||||
| 			if (isFollowers(recipe)) { | 			if (isFollowers(recipe)) { | ||||||
| 				// followers deliver
 | 				// followers deliver
 | ||||||
| 				const followers = await Followings.find({ | 				const followers = await Followings.findBy({ | ||||||
| 					followeeId: this.actor.id, | 					followeeId: this.actor.id, | ||||||
| 				}); | 				}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,6 @@ export default async (actor: CacheableRemoteUser, activity: IBlock): Promise<str | ||||||
| 		return `skip: ブロックしようとしているユーザーはローカルユーザーではありません`; | 		return `skip: ブロックしようとしているユーザーはローカルユーザーではありません`; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	await block(await Users.findOneOrFail(actor.id), blockee); | 	await block(await Users.findOneByOrFail({ id: actor.id }), blockee); | ||||||
| 	return `ok`; | 	return `ok`; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ export async function deleteActor(actor: CacheableRemoteUser, uri: string): Prom | ||||||
| 		return `skip: delete actor ${actor.uri} !== ${uri}`; | 		return `skip: delete actor ${actor.uri} !== ${uri}`; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOneOrFail(actor.id); | 	const user = await Users.findOneByOrFail({ id: actor.id }); | ||||||
| 	if (user.isDeleted) { | 	if (user.isDeleted) { | ||||||
| 		logger.info(`skip: already deleted`); | 		logger.info(`skip: already deleted`); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export default async (actor: CacheableRemoteUser, activity: IFlag): Promise<stri | ||||||
| 	const uris = getApIds(activity.object); | 	const uris = getApIds(activity.object); | ||||||
| 
 | 
 | ||||||
| 	const userIds = uris.filter(uri => uri.startsWith(config.url + '/users/')).map(uri => uri.split('/').pop()!); | 	const userIds = uris.filter(uri => uri.startsWith(config.url + '/users/')).map(uri => uri.split('/').pop()!); | ||||||
| 	const users = await Users.find({ | 	const users = await Users.findBy({ | ||||||
| 		id: In(userIds), | 		id: In(userIds), | ||||||
| 	}); | 	}); | ||||||
| 	if (users.length < 1) return `skip`; | 	if (users.length < 1) return `skip`; | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ export const performReadActivity = async (actor: CacheableRemoteUser, activity: | ||||||
| 
 | 
 | ||||||
| 	const messageId = id.split('/').pop(); | 	const messageId = id.split('/').pop(); | ||||||
| 
 | 
 | ||||||
| 	const message = await MessagingMessages.findOne(messageId); | 	const message = await MessagingMessages.findOneBy({ id: messageId }); | ||||||
| 	if (message == null) { | 	if (message == null) { | ||||||
| 		return `skip: message not found`; | 		return `skip: message not found`; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ export default async (actor: CacheableRemoteUser, activity: IAccept): Promise<st | ||||||
| 		return `skip: follower not found`; | 		return `skip: follower not found`; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const following = await Followings.findOne({ | 	const following = await Followings.findOneBy({ | ||||||
| 		followerId: follower.id, | 		followerId: follower.id, | ||||||
| 		followeeId: actor.id, | 		followeeId: actor.id, | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ import deleteNote from '@/services/note/delete.js'; | ||||||
| export const undoAnnounce = async (actor: CacheableRemoteUser, activity: IAnnounce): Promise<string> => { | export const undoAnnounce = async (actor: CacheableRemoteUser, activity: IAnnounce): Promise<string> => { | ||||||
| 	const uri = getApId(activity); | 	const uri = getApId(activity); | ||||||
| 
 | 
 | ||||||
| 	const note = await Notes.findOne({ | 	const note = await Notes.findOneBy({ | ||||||
| 		uri, | 		uri, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,6 +16,6 @@ export default async (actor: CacheableRemoteUser, activity: IBlock): Promise<str | ||||||
| 		return `skip: ブロック解除しようとしているユーザーはローカルユーザーではありません`; | 		return `skip: ブロック解除しようとしているユーザーはローカルユーザーではありません`; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	await unblock(await Users.findOneOrFail(actor.id), blockee); | 	await unblock(await Users.findOneByOrFail({ id: actor.id }), blockee); | ||||||
| 	return `ok`; | 	return `ok`; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -17,12 +17,12 @@ export default async (actor: CacheableRemoteUser, activity: IFollow): Promise<st | ||||||
| 		return `skip: フォロー解除しようとしているユーザーはローカルユーザーではありません`; | 		return `skip: フォロー解除しようとしているユーザーはローカルユーザーではありません`; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const req = await FollowRequests.findOne({ | 	const req = await FollowRequests.findOneBy({ | ||||||
| 		followerId: actor.id, | 		followerId: actor.id, | ||||||
| 		followeeId: followee.id, | 		followeeId: followee.id, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	const following = await Followings.findOne({ | 	const following = await Followings.findOneBy({ | ||||||
| 		followerId: actor.id, | 		followerId: actor.id, | ||||||
| 		followeeId: followee.id, | 		followeeId: followee.id, | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ export async function createImage(actor: CacheableRemoteUser, value: any): Promi | ||||||
| 				uri: image.url, | 				uri: image.url, | ||||||
| 			}); | 			}); | ||||||
| 
 | 
 | ||||||
| 			file = await DriveFiles.findOneOrFail(file.id); | 			file = await DriveFiles.findOneByOrFail({ id: file.id }); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -141,7 +141,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s | ||||||
| 			const uri = getApId(note.inReplyTo); | 			const uri = getApId(note.inReplyTo); | ||||||
| 			if (uri.startsWith(config.url + '/')) { | 			if (uri.startsWith(config.url + '/')) { | ||||||
| 				const id = uri.split('/').pop(); | 				const id = uri.split('/').pop(); | ||||||
| 				const talk = await MessagingMessages.findOne(id); | 				const talk = await MessagingMessages.findOneBy({ id }); | ||||||
| 				if (talk) { | 				if (talk) { | ||||||
| 					isTalk = true; | 					isTalk = true; | ||||||
| 					return null; | 					return null; | ||||||
|  | @ -201,7 +201,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s | ||||||
| 
 | 
 | ||||||
| 	// vote
 | 	// vote
 | ||||||
| 	if (reply && reply.hasPoll) { | 	if (reply && reply.hasPoll) { | ||||||
| 		const poll = await Polls.findOneOrFail(reply.id); | 		const poll = await Polls.findOneByOrFail({ noteId: reply.id }); | ||||||
| 
 | 
 | ||||||
| 		const tryCreateVote = async (name: string, index: number): Promise<null> => { | 		const tryCreateVote = async (name: string, index: number): Promise<null> => { | ||||||
| 			if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) { | 			if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) { | ||||||
|  | @ -306,7 +306,7 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr | ||||||
| 		const name = tag.name!.replace(/^:/, '').replace(/:$/, ''); | 		const name = tag.name!.replace(/^:/, '').replace(/:$/, ''); | ||||||
| 		tag.icon = toSingle(tag.icon); | 		tag.icon = toSingle(tag.icon); | ||||||
| 
 | 
 | ||||||
| 		const exists = await Emojis.findOne({ | 		const exists = await Emojis.findOneBy({ | ||||||
| 			host, | 			host, | ||||||
| 			name, | 			name, | ||||||
| 		}); | 		}); | ||||||
|  | @ -327,7 +327,7 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr | ||||||
| 					updatedAt: new Date(), | 					updatedAt: new Date(), | ||||||
| 				}); | 				}); | ||||||
| 
 | 
 | ||||||
| 				return await Emojis.findOne({ | 				return await Emojis.findOneBy({ | ||||||
| 					host, | 					host, | ||||||
| 					name, | 					name, | ||||||
| 				}) as Emoji; | 				}) as Emoji; | ||||||
|  | @ -347,6 +347,6 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr | ||||||
| 			publicUrl: tag.icon!.url, | 			publicUrl: tag.icon!.url, | ||||||
| 			updatedAt: new Date(), | 			updatedAt: new Date(), | ||||||
| 			aliases: [], | 			aliases: [], | ||||||
| 		} as Partial<Emoji>).then(x => Emojis.findOneOrFail(x.identifiers[0])); | 		} as Partial<Emoji>).then(x => Emojis.findOneByOrFail(x.identifiers[0])); | ||||||
| 	})); | 	})); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ import { UserPublickey } from '@/models/entities/user-publickey.js'; | ||||||
| import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; | import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; | ||||||
| import { toPuny } from '@/misc/convert-host.js'; | import { toPuny } from '@/misc/convert-host.js'; | ||||||
| import { UserProfile } from '@/models/entities/user-profile.js'; | import { UserProfile } from '@/models/entities/user-profile.js'; | ||||||
| import { getConnection } from 'typeorm'; |  | ||||||
| import { toArray } from '@/prelude/array.js'; | import { toArray } from '@/prelude/array.js'; | ||||||
| import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js'; | import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js'; | ||||||
| import { normalizeForSearch } from '@/misc/normalize-for-search.js'; | import { normalizeForSearch } from '@/misc/normalize-for-search.js'; | ||||||
|  | @ -32,6 +31,7 @@ import { truncate } from '@/misc/truncate.js'; | ||||||
| import { StatusError } from '@/misc/fetch.js'; | import { StatusError } from '@/misc/fetch.js'; | ||||||
| import { uriPersonCache } from '@/services/user-cache.js'; | import { uriPersonCache } from '@/services/user-cache.js'; | ||||||
| import { publishInternalEvent } from '@/services/stream.js'; | import { publishInternalEvent } from '@/services/stream.js'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| const logger = apLogger; | const logger = apLogger; | ||||||
| 
 | 
 | ||||||
|  | @ -102,13 +102,13 @@ export async function fetchPerson(uri: string, resolver?: Resolver): Promise<Cac | ||||||
| 	// URIがこのサーバーを指しているならデータベースからフェッチ
 | 	// URIがこのサーバーを指しているならデータベースからフェッチ
 | ||||||
| 	if (uri.startsWith(config.url + '/')) { | 	if (uri.startsWith(config.url + '/')) { | ||||||
| 		const id = uri.split('/').pop(); | 		const id = uri.split('/').pop(); | ||||||
| 		const u = await Users.findOne(id).then(x => x || null); // TODO: typeorm 3.0 にしたら .then(x => x || null) を消す
 | 		const u = await Users.findOneBy({ id }); | ||||||
| 		if (u) uriPersonCache.set(uri, u); | 		if (u) uriPersonCache.set(uri, u); | ||||||
| 		return u; | 		return u; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//#region このサーバーに既に登録されていたらそれを返す
 | 	//#region このサーバーに既に登録されていたらそれを返す
 | ||||||
| 	const exist = await Users.findOne({ uri }); | 	const exist = await Users.findOneBy({ uri }); | ||||||
| 
 | 
 | ||||||
| 	if (exist) { | 	if (exist) { | ||||||
| 		uriPersonCache.set(uri, exist); | 		uriPersonCache.set(uri, exist); | ||||||
|  | @ -151,7 +151,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us | ||||||
| 	let user: IRemoteUser; | 	let user: IRemoteUser; | ||||||
| 	try { | 	try { | ||||||
| 		// Start transaction
 | 		// Start transaction
 | ||||||
| 		await getConnection().transaction(async transactionalEntityManager => { | 		await db.transaction(async transactionalEntityManager => { | ||||||
| 			user = await transactionalEntityManager.save(new User({ | 			user = await transactionalEntityManager.save(new User({ | ||||||
| 				id: genId(), | 				id: genId(), | ||||||
| 				avatarId: null, | 				avatarId: null, | ||||||
|  | @ -197,7 +197,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us | ||||||
| 		// duplicate key error
 | 		// duplicate key error
 | ||||||
| 		if (isDuplicateKeyValueError(e)) { | 		if (isDuplicateKeyValueError(e)) { | ||||||
| 			// /users/@a => /users/:id のように入力がaliasなときにエラーになることがあるのを対応
 | 			// /users/@a => /users/:id のように入力がaliasなときにエラーになることがあるのを対応
 | ||||||
| 			const u = await Users.findOne({ | 			const u = await Users.findOneBy({ | ||||||
| 				uri: person.id, | 				uri: person.id, | ||||||
| 			}); | 			}); | ||||||
| 
 | 
 | ||||||
|  | @ -280,7 +280,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//#region このサーバーに既に登録されているか
 | 	//#region このサーバーに既に登録されているか
 | ||||||
| 	const exist = await Users.findOne({ uri }) as IRemoteUser; | 	const exist = await Users.findOneBy({ uri }) as IRemoteUser; | ||||||
| 
 | 
 | ||||||
| 	if (exist == null) { | 	if (exist == null) { | ||||||
| 		return; | 		return; | ||||||
|  | @ -451,7 +451,7 @@ export function analyzeAttachments(attachments: IObject | IObject[] | undefined) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function updateFeatured(userId: User['id']) { | export async function updateFeatured(userId: User['id']) { | ||||||
| 	const user = await Users.findOneOrFail(userId); | 	const user = await Users.findOneByOrFail({ id: userId }); | ||||||
| 	if (!Users.isRemoteUser(user)) return; | 	if (!Users.isRemoteUser(user)) return; | ||||||
| 	if (!user.featured) return; | 	if (!user.featured) return; | ||||||
| 
 | 
 | ||||||
|  | @ -474,7 +474,7 @@ export async function updateFeatured(userId: User['id']) { | ||||||
| 		.slice(0, 5) | 		.slice(0, 5) | ||||||
| 		.map(item => limit(() => resolveNote(item, resolver)))); | 		.map(item => limit(() => resolveNote(item, resolver)))); | ||||||
| 
 | 
 | ||||||
| 	await getConnection().transaction(async transactionalEntityManager => { | 	await db.transaction(async transactionalEntityManager => { | ||||||
| 		await transactionalEntityManager.delete(UserNotePining, { userId: user.id }); | 		await transactionalEntityManager.delete(UserNotePining, { userId: user.id }); | ||||||
| 
 | 
 | ||||||
| 		// とりあえずidを別の時間で生成して順番を維持
 | 		// とりあえずidを別の時間で生成して順番を維持
 | ||||||
|  |  | ||||||
|  | @ -47,10 +47,10 @@ export async function updateQuestion(value: any) { | ||||||
| 	if (uri.startsWith(config.url + '/')) throw new Error('uri points local'); | 	if (uri.startsWith(config.url + '/')) throw new Error('uri points local'); | ||||||
| 
 | 
 | ||||||
| 	//#region このサーバーに既に登録されているか
 | 	//#region このサーバーに既に登録されているか
 | ||||||
| 	const note = await Notes.findOne({ uri }); | 	const note = await Notes.findOneBy({ uri }); | ||||||
| 	if (note == null) throw new Error('Question is not registed'); | 	if (note == null) throw new Error('Question is not registed'); | ||||||
| 
 | 
 | ||||||
| 	const poll = await Polls.findOne({ noteId: note.id }); | 	const poll = await Polls.findOneBy({ noteId: note.id }); | ||||||
| 	if (poll == null) throw new Error('Question is not registed'); | 	if (poll == null) throw new Error('Question is not registed'); | ||||||
| 	//#endregion
 | 	//#endregion
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,6 @@ import { User } from '@/models/entities/user.js'; | ||||||
|  * @param id Follower|Followee ID |  * @param id Follower|Followee ID | ||||||
|  */ |  */ | ||||||
| export default async function renderFollowUser(id: User['id']): Promise<any> { | export default async function renderFollowUser(id: User['id']): Promise<any> { | ||||||
| 	const user = await Users.findOneOrFail(id); | 	const user = await Users.findOneByOrFail({ id: id }); | ||||||
| 	return Users.isLocalUser(user) ? `${config.url}/users/${user.id}` : user.uri; | 	return Users.isLocalUser(user) ? `${config.url}/users/${user.id}` : user.uri; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ import config from '@/config/index.js'; | ||||||
| import { NoteReaction } from '@/models/entities/note-reaction.js'; | import { NoteReaction } from '@/models/entities/note-reaction.js'; | ||||||
| import { Note } from '@/models/entities/note.js'; | import { Note } from '@/models/entities/note.js'; | ||||||
| import { Emojis } from '@/models/index.js'; | import { Emojis } from '@/models/index.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| import renderEmoji from './emoji.js'; | import renderEmoji from './emoji.js'; | ||||||
| 
 | 
 | ||||||
| export const renderLike = async (noteReaction: NoteReaction, note: Note) => { | export const renderLike = async (noteReaction: NoteReaction, note: Note) => { | ||||||
|  | @ -18,9 +19,9 @@ export const renderLike = async (noteReaction: NoteReaction, note: Note) => { | ||||||
| 
 | 
 | ||||||
| 	if (reaction.startsWith(':')) { | 	if (reaction.startsWith(':')) { | ||||||
| 		const name = reaction.replace(/:/g, ''); | 		const name = reaction.replace(/:/g, ''); | ||||||
| 		const emoji = await Emojis.findOne({ | 		const emoji = await Emojis.findOneBy({ | ||||||
| 			name, | 			name, | ||||||
| 			host: null, | 			host: IsNull(), | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		if (emoji) object.tag = [ renderEmoji(emoji) ]; | 		if (emoji) object.tag = [ renderEmoji(emoji) ]; | ||||||
|  |  | ||||||
|  | @ -7,25 +7,25 @@ import toHtml from '../misc/get-note-html.js'; | ||||||
| import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js'; | import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js'; | ||||||
| import { DriveFile } from '@/models/entities/drive-file.js'; | import { DriveFile } from '@/models/entities/drive-file.js'; | ||||||
| import { DriveFiles, Notes, Users, Emojis, Polls } from '@/models/index.js'; | import { DriveFiles, Notes, Users, Emojis, Polls } from '@/models/index.js'; | ||||||
| import { In } from 'typeorm'; | import { In, IsNull } from 'typeorm'; | ||||||
| import { Emoji } from '@/models/entities/emoji.js'; | import { Emoji } from '@/models/entities/emoji.js'; | ||||||
| import { Poll } from '@/models/entities/poll.js'; | import { Poll } from '@/models/entities/poll.js'; | ||||||
| 
 | 
 | ||||||
| export default async function renderNote(note: Note, dive = true, isTalk = false): Promise<Record<string, unknown>> { | export default async function renderNote(note: Note, dive = true, isTalk = false): Promise<Record<string, unknown>> { | ||||||
| 	const getPromisedFiles = async (ids: string[]) => { | 	const getPromisedFiles = async (ids: string[]) => { | ||||||
| 		if (!ids || ids.length === 0) return []; | 		if (!ids || ids.length === 0) return []; | ||||||
| 		const items = await DriveFiles.find({ id: In(ids) }); | 		const items = await DriveFiles.findBy({ id: In(ids) }); | ||||||
| 		return ids.map(id => items.find(item => item.id === id)).filter(item => item != null) as DriveFile[]; | 		return ids.map(id => items.find(item => item.id === id)).filter(item => item != null) as DriveFile[]; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	let inReplyTo; | 	let inReplyTo; | ||||||
| 	let inReplyToNote: Note | undefined; | 	let inReplyToNote: Note | null; | ||||||
| 
 | 
 | ||||||
| 	if (note.replyId) { | 	if (note.replyId) { | ||||||
| 		inReplyToNote = await Notes.findOne(note.replyId); | 		inReplyToNote = await Notes.findOneBy({ id: note.replyId }); | ||||||
| 
 | 
 | ||||||
| 		if (inReplyToNote != null) { | 		if (inReplyToNote != null) { | ||||||
| 			const inReplyToUser = await Users.findOne(inReplyToNote.userId); | 			const inReplyToUser = await Users.findOneBy({ id: inReplyToNote.userId }); | ||||||
| 
 | 
 | ||||||
| 			if (inReplyToUser != null) { | 			if (inReplyToUser != null) { | ||||||
| 				if (inReplyToNote.uri) { | 				if (inReplyToNote.uri) { | ||||||
|  | @ -46,7 +46,7 @@ export default async function renderNote(note: Note, dive = true, isTalk = false | ||||||
| 	let quote; | 	let quote; | ||||||
| 
 | 
 | ||||||
| 	if (note.renoteId) { | 	if (note.renoteId) { | ||||||
| 		const renote = await Notes.findOne(note.renoteId); | 		const renote = await Notes.findOneBy({ id: note.renoteId }); | ||||||
| 
 | 
 | ||||||
| 		if (renote) { | 		if (renote) { | ||||||
| 			quote = renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`; | 			quote = renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`; | ||||||
|  | @ -73,7 +73,7 @@ export default async function renderNote(note: Note, dive = true, isTalk = false | ||||||
| 		to = mentions; | 		to = mentions; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const mentionedUsers = note.mentions.length > 0 ? await Users.find({ | 	const mentionedUsers = note.mentions.length > 0 ? await Users.findBy({ | ||||||
| 		id: In(note.mentions), | 		id: In(note.mentions), | ||||||
| 	}) : []; | 	}) : []; | ||||||
| 
 | 
 | ||||||
|  | @ -83,10 +83,10 @@ export default async function renderNote(note: Note, dive = true, isTalk = false | ||||||
| 	const files = await getPromisedFiles(note.fileIds); | 	const files = await getPromisedFiles(note.fileIds); | ||||||
| 
 | 
 | ||||||
| 	const text = note.text; | 	const text = note.text; | ||||||
| 	let poll: Poll | undefined; | 	let poll: Poll | null; | ||||||
| 
 | 
 | ||||||
| 	if (note.hasPoll) { | 	if (note.hasPoll) { | ||||||
| 		poll = await Polls.findOne({ noteId: note.id }); | 		poll = await Polls.findOneBy({ noteId: note.id }); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	let apText = text; | 	let apText = text; | ||||||
|  | @ -156,9 +156,9 @@ export async function getEmojis(names: string[]): Promise<Emoji[]> { | ||||||
| 	if (names == null || names.length === 0) return []; | 	if (names == null || names.length === 0) return []; | ||||||
| 
 | 
 | ||||||
| 	const emojis = await Promise.all( | 	const emojis = await Promise.all( | ||||||
| 		names.map(name => Emojis.findOne({ | 		names.map(name => Emojis.findOneBy({ | ||||||
| 			name, | 			name, | ||||||
| 			host: null, | 			host: IsNull(), | ||||||
| 		})) | 		})) | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,9 +17,9 @@ export async function renderPerson(user: ILocalUser) { | ||||||
| 	const isSystem = !!user.username.match(/\./); | 	const isSystem = !!user.username.match(/\./); | ||||||
| 
 | 
 | ||||||
| 	const [avatar, banner, profile] = await Promise.all([ | 	const [avatar, banner, profile] = await Promise.all([ | ||||||
| 		user.avatarId ? DriveFiles.findOne(user.avatarId) : Promise.resolve(undefined), | 		user.avatarId ? DriveFiles.findOneBy({ id: user.avatarId }) : Promise.resolve(undefined), | ||||||
| 		user.bannerId ? DriveFiles.findOne(user.bannerId) : Promise.resolve(undefined), | 		user.bannerId ? DriveFiles.findOneBy({ id: user.bannerId }) : Promise.resolve(undefined), | ||||||
| 		UserProfiles.findOneOrFail(user.id), | 		UserProfiles.findOneByOrFail({ userId: user.id }), | ||||||
| 	]); | 	]); | ||||||
| 
 | 
 | ||||||
| 	const attachment: { | 	const attachment: { | ||||||
|  |  | ||||||
|  | @ -7,15 +7,16 @@ import chalk from 'chalk'; | ||||||
| import { User, IRemoteUser } from '@/models/entities/user.js'; | import { User, IRemoteUser } from '@/models/entities/user.js'; | ||||||
| import { Users } from '@/models/index.js'; | import { Users } from '@/models/index.js'; | ||||||
| import { toPuny } from '@/misc/convert-host.js'; | import { toPuny } from '@/misc/convert-host.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| const logger = remoteLogger.createSubLogger('resolve-user'); | const logger = remoteLogger.createSubLogger('resolve-user'); | ||||||
| 
 | 
 | ||||||
| export async function resolveUser(username: string, host: string | null, option?: any, resync = false): Promise<User> { | export async function resolveUser(username: string, host: string | null): Promise<User> { | ||||||
| 	const usernameLower = username.toLowerCase(); | 	const usernameLower = username.toLowerCase(); | ||||||
| 
 | 
 | ||||||
| 	if (host == null) { | 	if (host == null) { | ||||||
| 		logger.info(`return local user: ${usernameLower}`); | 		logger.info(`return local user: ${usernameLower}`); | ||||||
| 		return await Users.findOne({ usernameLower, host: null }).then(u => { | 		return await Users.findOneBy({ usernameLower, host: IsNull() }).then(u => { | ||||||
| 			if (u == null) { | 			if (u == null) { | ||||||
| 				throw new Error('user not found'); | 				throw new Error('user not found'); | ||||||
| 			} else { | 			} else { | ||||||
|  | @ -28,7 +29,7 @@ export async function resolveUser(username: string, host: string | null, option? | ||||||
| 
 | 
 | ||||||
| 	if (config.host === host) { | 	if (config.host === host) { | ||||||
| 		logger.info(`return local user: ${usernameLower}`); | 		logger.info(`return local user: ${usernameLower}`); | ||||||
| 		return await Users.findOne({ usernameLower, host: null }).then(u => { | 		return await Users.findOneBy({ usernameLower, host: IsNull() }).then(u => { | ||||||
| 			if (u == null) { | 			if (u == null) { | ||||||
| 				throw new Error('user not found'); | 				throw new Error('user not found'); | ||||||
| 			} else { | 			} else { | ||||||
|  | @ -37,7 +38,7 @@ export async function resolveUser(username: string, host: string | null, option? | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ usernameLower, host }, option) as IRemoteUser | null; | 	const user = await Users.findOneBy({ usernameLower, host }) as IRemoteUser | null; | ||||||
| 
 | 
 | ||||||
| 	const acctLower = `${usernameLower}@${host}`; | 	const acctLower = `${usernameLower}@${host}`; | ||||||
| 
 | 
 | ||||||
|  | @ -48,8 +49,8 @@ export async function resolveUser(username: string, host: string | null, option? | ||||||
| 		return await createPerson(self.href); | 		return await createPerson(self.href); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// resyncオプション OR ユーザー情報が古い場合は、WebFilgerからやりなおして返す
 | 	// ユーザー情報が古い場合は、WebFilgerからやりなおして返す
 | ||||||
| 	if (resync || user.lastFetchedAt == null || Date.now() - user.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) { | 	if (user.lastFetchedAt == null || Date.now() - user.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) { | ||||||
| 		// 繋がらないインスタンスに何回も試行するのを防ぐ, 後続の同様処理の連続試行を防ぐ ため 試行前にも更新する
 | 		// 繋がらないインスタンスに何回も試行するのを防ぐ, 後続の同様処理の連続試行を防ぐ ため 試行前にも更新する
 | ||||||
| 		await Users.update(user.id, { | 		await Users.update(user.id, { | ||||||
| 			lastFetchedAt: new Date(), | 			lastFetchedAt: new Date(), | ||||||
|  | @ -82,7 +83,7 @@ export async function resolveUser(username: string, host: string | null, option? | ||||||
| 		await updatePerson(self.href); | 		await updatePerson(self.href); | ||||||
| 
 | 
 | ||||||
| 		logger.info(`return resynced remote user: ${acctLower}`); | 		logger.info(`return resynced remote user: ${acctLower}`); | ||||||
| 		return await Users.findOne({ uri: self.href }).then(u => { | 		return await Users.findOneBy({ uri: self.href }).then(u => { | ||||||
| 			if (u == null) { | 			if (u == null) { | ||||||
| 				throw new Error('user not found'); | 				throw new Error('user not found'); | ||||||
| 			} else { | 			} else { | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ import { inbox as processInbox } from '@/queue/index.js'; | ||||||
| import { isSelfHost } from '@/misc/convert-host.js'; | import { isSelfHost } from '@/misc/convert-host.js'; | ||||||
| import { Notes, Users, Emojis, NoteReactions } from '@/models/index.js'; | import { Notes, Users, Emojis, NoteReactions } from '@/models/index.js'; | ||||||
| import { ILocalUser, User } from '@/models/entities/user.js'; | import { ILocalUser, User } from '@/models/entities/user.js'; | ||||||
| import { In } from 'typeorm'; | import { In, IsNull } from 'typeorm'; | ||||||
| import { renderLike } from '@/remote/activitypub/renderer/like.js'; | import { renderLike } from '@/remote/activitypub/renderer/like.js'; | ||||||
| import { getUserKeypair } from '@/misc/keypair-store.js'; | import { getUserKeypair } from '@/misc/keypair-store.js'; | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +65,7 @@ router.post('/users/:user/inbox', json(), inbox); | ||||||
| router.get('/notes/:note', async (ctx, next) => { | router.get('/notes/:note', async (ctx, next) => { | ||||||
| 	if (!isActivityPubReq(ctx)) return await next(); | 	if (!isActivityPubReq(ctx)) return await next(); | ||||||
| 
 | 
 | ||||||
| 	const note = await Notes.findOne({ | 	const note = await Notes.findOneBy({ | ||||||
| 		id: ctx.params.note, | 		id: ctx.params.note, | ||||||
| 		visibility: In(['public' as const, 'home' as const]), | 		visibility: In(['public' as const, 'home' as const]), | ||||||
| 		localOnly: false, | 		localOnly: false, | ||||||
|  | @ -93,9 +93,9 @@ router.get('/notes/:note', async (ctx, next) => { | ||||||
| 
 | 
 | ||||||
| // note activity
 | // note activity
 | ||||||
| router.get('/notes/:note/activity', async ctx => { | router.get('/notes/:note/activity', async ctx => { | ||||||
| 	const note = await Notes.findOne({ | 	const note = await Notes.findOneBy({ | ||||||
| 		id: ctx.params.note, | 		id: ctx.params.note, | ||||||
| 		userHost: null, | 		userHost: IsNull(), | ||||||
| 		visibility: In(['public' as const, 'home' as const]), | 		visibility: In(['public' as const, 'home' as const]), | ||||||
| 		localOnly: false, | 		localOnly: false, | ||||||
| 	}); | 	}); | ||||||
|  | @ -126,9 +126,9 @@ router.get('/users/:user/collections/featured', Featured); | ||||||
| router.get('/users/:user/publickey', async ctx => { | router.get('/users/:user/publickey', async ctx => { | ||||||
| 	const userId = ctx.params.user; | 	const userId = ctx.params.user; | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
|  | @ -164,9 +164,9 @@ router.get('/users/:user', async (ctx, next) => { | ||||||
| 
 | 
 | ||||||
| 	const userId = ctx.params.user; | 	const userId = ctx.params.user; | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 		isSuspended: false, | 		isSuspended: false, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | @ -176,9 +176,9 @@ router.get('/users/:user', async (ctx, next) => { | ||||||
| router.get('/@:user', async (ctx, next) => { | router.get('/@:user', async (ctx, next) => { | ||||||
| 	if (!isActivityPubReq(ctx)) return await next(); | 	if (!isActivityPubReq(ctx)) return await next(); | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		usernameLower: ctx.params.user.toLowerCase(), | 		usernameLower: ctx.params.user.toLowerCase(), | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 		isSuspended: false, | 		isSuspended: false, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | @ -188,8 +188,8 @@ router.get('/@:user', async (ctx, next) => { | ||||||
| 
 | 
 | ||||||
| // emoji
 | // emoji
 | ||||||
| router.get('/emojis/:emoji', async ctx => { | router.get('/emojis/:emoji', async ctx => { | ||||||
| 	const emoji = await Emojis.findOne({ | 	const emoji = await Emojis.findOneBy({ | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 		name: ctx.params.emoji, | 		name: ctx.params.emoji, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | @ -205,14 +205,14 @@ router.get('/emojis/:emoji', async ctx => { | ||||||
| 
 | 
 | ||||||
| // like
 | // like
 | ||||||
| router.get('/likes/:like', async ctx => { | router.get('/likes/:like', async ctx => { | ||||||
| 	const reaction = await NoteReactions.findOne(ctx.params.like); | 	const reaction = await NoteReactions.findOneBy({ id: ctx.params.like }); | ||||||
| 
 | 
 | ||||||
| 	if (reaction == null) { | 	if (reaction == null) { | ||||||
| 		ctx.status = 404; | 		ctx.status = 404; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const note = await Notes.findOne(reaction.noteId); | 	const note = await Notes.findOneBy({ id: reaction.noteId }); | ||||||
| 
 | 
 | ||||||
| 	if (note == null) { | 	if (note == null) { | ||||||
| 		ctx.status = 404; | 		ctx.status = 404; | ||||||
|  |  | ||||||
|  | @ -5,13 +5,14 @@ import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-colle | ||||||
| import { setResponseType } from '../activitypub.js'; | import { setResponseType } from '../activitypub.js'; | ||||||
| import renderNote from '@/remote/activitypub/renderer/note.js'; | import renderNote from '@/remote/activitypub/renderer/note.js'; | ||||||
| import { Users, Notes, UserNotePinings } from '@/models/index.js'; | import { Users, Notes, UserNotePinings } from '@/models/index.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| export default async (ctx: Router.RouterContext) => { | export default async (ctx: Router.RouterContext) => { | ||||||
| 	const userId = ctx.params.user; | 	const userId = ctx.params.user; | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
|  | @ -25,7 +26,7 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	const pinnedNotes = await Promise.all(pinings.map(pining => | 	const pinnedNotes = await Promise.all(pinings.map(pining => | ||||||
| 		Notes.findOneOrFail(pining.noteId))); | 		Notes.findOneByOrFail({ id: pining.noteId }))); | ||||||
| 
 | 
 | ||||||
| 	const renderedNotes = await Promise.all(pinnedNotes.map(note => renderNote(note))); | 	const renderedNotes = await Promise.all(pinnedNotes.map(note => renderNote(note))); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-c | ||||||
| import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; | import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; | ||||||
| import { setResponseType } from '../activitypub.js'; | import { setResponseType } from '../activitypub.js'; | ||||||
| import { Users, Followings, UserProfiles } from '@/models/index.js'; | import { Users, Followings, UserProfiles } from '@/models/index.js'; | ||||||
| import { LessThan } from 'typeorm'; | import { IsNull, LessThan } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| export default async (ctx: Router.RouterContext) => { | export default async (ctx: Router.RouterContext) => { | ||||||
| 	const userId = ctx.params.user; | 	const userId = ctx.params.user; | ||||||
|  | @ -27,9 +27,9 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
|  | @ -38,7 +38,7 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//#region Check ff visibility
 | 	//#region Check ff visibility
 | ||||||
| 	const profile = await UserProfiles.findOneOrFail(user.id); | 	const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); | ||||||
| 
 | 
 | ||||||
| 	if (profile.ffVisibility === 'private') { | 	if (profile.ffVisibility === 'private') { | ||||||
| 		ctx.status = 403; | 		ctx.status = 403; | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-c | ||||||
| import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; | import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; | ||||||
| import { setResponseType } from '../activitypub.js'; | import { setResponseType } from '../activitypub.js'; | ||||||
| import { Users, Followings, UserProfiles } from '@/models/index.js'; | import { Users, Followings, UserProfiles } from '@/models/index.js'; | ||||||
| import { LessThan, FindConditions } from 'typeorm'; | import { LessThan, IsNull, FindOptionsWhere } from 'typeorm'; | ||||||
| import { Following } from '@/models/entities/following.js'; | import { Following } from '@/models/entities/following.js'; | ||||||
| 
 | 
 | ||||||
| export default async (ctx: Router.RouterContext) => { | export default async (ctx: Router.RouterContext) => { | ||||||
|  | @ -28,9 +28,9 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
|  | @ -39,7 +39,7 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//#region Check ff visibility
 | 	//#region Check ff visibility
 | ||||||
| 	const profile = await UserProfiles.findOneOrFail(user.id); | 	const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); | ||||||
| 
 | 
 | ||||||
| 	if (profile.ffVisibility === 'private') { | 	if (profile.ffVisibility === 'private') { | ||||||
| 		ctx.status = 403; | 		ctx.status = 403; | ||||||
|  | @ -58,7 +58,7 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 	if (page) { | 	if (page) { | ||||||
| 		const query = { | 		const query = { | ||||||
| 			followerId: user.id, | 			followerId: user.id, | ||||||
| 		} as FindConditions<Following>; | 		} as FindOptionsWhere<Following>; | ||||||
| 
 | 
 | ||||||
| 		// カーソルが指定されている場合
 | 		// カーソルが指定されている場合
 | ||||||
| 		if (cursor) { | 		if (cursor) { | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ import { countIf } from '@/prelude/array.js'; | ||||||
| import * as url from '@/prelude/url.js'; | import * as url from '@/prelude/url.js'; | ||||||
| import { Users, Notes } from '@/models/index.js'; | import { Users, Notes } from '@/models/index.js'; | ||||||
| import { makePaginationQuery } from '../api/common/make-pagination-query.js'; | import { makePaginationQuery } from '../api/common/make-pagination-query.js'; | ||||||
| import { Brackets } from 'typeorm'; | import { Brackets, IsNull } from 'typeorm'; | ||||||
| import { Note } from '@/models/entities/note.js'; | import { Note } from '@/models/entities/note.js'; | ||||||
| 
 | 
 | ||||||
| export default async (ctx: Router.RouterContext) => { | export default async (ctx: Router.RouterContext) => { | ||||||
|  | @ -35,9 +35,9 @@ export default async (ctx: Router.RouterContext) => { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOneBy({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
|  | @ -99,7 +99,7 @@ export default async (ctx: Router.RouterContext) => { | ||||||
|  */ |  */ | ||||||
| export async function packActivity(note: Note): Promise<any> { | export async function packActivity(note: Note): Promise<any> { | ||||||
| 	if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) { | 	if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) { | ||||||
| 		const renote = await Notes.findOneOrFail(note.renoteId); | 		const renote = await Notes.findOneByOrFail({ id: note.renoteId }); | ||||||
| 		return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`, note); | 		return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`, note); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,9 +21,8 @@ export default async (token: string | null): Promise<[CacheableLocalUser | null | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (isNativeToken(token)) { | 	if (isNativeToken(token)) { | ||||||
| 		// TODO: typeorm 3.0にしたら .then(x => x || null) は消せる
 |  | ||||||
| 		const user = await localUserByNativeTokenCache.fetch(token, | 		const user = await localUserByNativeTokenCache.fetch(token, | ||||||
| 			() => Users.findOne({ token }).then(x => x || null) as Promise<ILocalUser | null>); | 			() => Users.findOneBy({ token }) as Promise<ILocalUser | null>); | ||||||
| 
 | 
 | ||||||
| 		if (user == null) { | 		if (user == null) { | ||||||
| 			throw new AuthenticationError('user not found'); | 			throw new AuthenticationError('user not found'); | ||||||
|  | @ -48,13 +47,13 @@ export default async (token: string | null): Promise<[CacheableLocalUser | null | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		const user = await localUserByIdCache.fetch(accessToken.userId, | 		const user = await localUserByIdCache.fetch(accessToken.userId, | ||||||
| 			() => Users.findOne({ | 			() => Users.findOneBy({ | ||||||
| 				id: accessToken.userId, // findOne(accessToken.userId) のように書かないのは後方互換性のため
 | 				id: accessToken.userId, | ||||||
| 			}) as Promise<ILocalUser>); | 			}) as Promise<ILocalUser>); | ||||||
| 
 | 
 | ||||||
| 		if (accessToken.appId) { | 		if (accessToken.appId) { | ||||||
| 			const app = await appCache.fetch(accessToken.appId, | 			const app = await appCache.fetch(accessToken.appId, | ||||||
| 				() => Apps.findOneOrFail(accessToken.appId!)); | 				() => Apps.findOneByOrFail({ id: accessToken.appId! })); | ||||||
| 
 | 
 | ||||||
| 			return [user, { | 			return [user, { | ||||||
| 				id: accessToken.id, | 				id: accessToken.id, | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ import { Notes, Users } from '@/models/index.js'; | ||||||
|  * Get note for API processing |  * Get note for API processing | ||||||
|  */ |  */ | ||||||
| export async function getNote(noteId: Note['id']) { | export async function getNote(noteId: Note['id']) { | ||||||
| 	const note = await Notes.findOne(noteId); | 	const note = await Notes.findOneBy({ id: noteId }); | ||||||
| 
 | 
 | ||||||
| 	if (note == null) { | 	if (note == null) { | ||||||
| 		throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.'); | 		throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.'); | ||||||
|  | @ -20,7 +20,7 @@ export async function getNote(noteId: Note['id']) { | ||||||
|  * Get user for API processing |  * Get user for API processing | ||||||
|  */ |  */ | ||||||
| export async function getUser(userId: User['id']) { | export async function getUser(userId: User['id']) { | ||||||
| 	const user = await Users.findOne(userId); | 	const user = await Users.findOneBy({ id: userId }); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', 'No such user.'); | 		throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', 'No such user.'); | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export async function injectFeatured(timeline: Note[], user?: User | null) { | ||||||
| 	if (timeline.length < 5) return; | 	if (timeline.length < 5) return; | ||||||
| 
 | 
 | ||||||
| 	if (user) { | 	if (user) { | ||||||
| 		const profile = await UserProfiles.findOneOrFail(user.id); | 		const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); | ||||||
| 		if (!profile.injectFeaturedNote) return; | 		if (!profile.injectFeaturedNote) return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ export async function injectPromo(timeline: Note[], user?: User | null) { | ||||||
| 
 | 
 | ||||||
| 	// TODO: readやexpireフィルタはクエリ側でやる
 | 	// TODO: readやexpireフィルタはクエリ側でやる
 | ||||||
| 
 | 
 | ||||||
| 	const reads = user ? await PromoReads.find({ | 	const reads = user ? await PromoReads.findBy({ | ||||||
| 		userId: user.id, | 		userId: user.id, | ||||||
| 	}) : []; | 	}) : []; | ||||||
| 
 | 
 | ||||||
|  | @ -22,10 +22,10 @@ export async function injectPromo(timeline: Note[], user?: User | null) { | ||||||
| 	// Pick random promo
 | 	// Pick random promo
 | ||||||
| 	const promo = promos[Math.floor(Math.random() * promos.length)]; | 	const promo = promos[Math.floor(Math.random() * promos.length)]; | ||||||
| 
 | 
 | ||||||
| 	const note = await Notes.findOneOrFail(promo.noteId); | 	const note = await Notes.findOneByOrFail({ id: promo.noteId }); | ||||||
| 
 | 
 | ||||||
| 	// Join
 | 	// Join
 | ||||||
| 	note.user = await Users.findOneOrFail(note.userId); | 	note.user = await Users.findOneByOrFail({ id: note.userId }); | ||||||
| 
 | 
 | ||||||
| 	(note as any)._prId_ = rndstr('a-z0-9', 8); | 	(note as any)._prId_ = rndstr('a-z0-9', 8); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ export async function readUserMessagingMessage( | ||||||
| ) { | ) { | ||||||
| 	if (messageIds.length === 0) return; | 	if (messageIds.length === 0) return; | ||||||
| 
 | 
 | ||||||
| 	const messages = await MessagingMessages.find({ | 	const messages = await MessagingMessages.findBy({ | ||||||
| 		id: In(messageIds), | 		id: In(messageIds), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | @ -64,7 +64,7 @@ export async function readGroupMessagingMessage( | ||||||
| 	if (messageIds.length === 0) return; | 	if (messageIds.length === 0) return; | ||||||
| 
 | 
 | ||||||
| 	// check joined
 | 	// check joined
 | ||||||
| 	const joining = await UserGroupJoinings.findOne({ | 	const joining = await UserGroupJoinings.findOneBy({ | ||||||
| 		userId: userId, | 		userId: userId, | ||||||
| 		userGroupId: groupId, | 		userGroupId: groupId, | ||||||
| 	}); | 	}); | ||||||
|  | @ -73,7 +73,7 @@ export async function readGroupMessagingMessage( | ||||||
| 		throw new IdentifiableError('930a270c-714a-46b2-b776-ad27276dc569', 'Access denied (group).'); | 		throw new IdentifiableError('930a270c-714a-46b2-b776-ad27276dc569', 'Access denied (group).'); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const messages = await MessagingMessages.find({ | 	const messages = await MessagingMessages.findBy({ | ||||||
| 		id: In(messageIds), | 		id: In(messageIds), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ export default function(ctx: Koa.Context, user: ILocalUser, redirect = false) { | ||||||
| 			ip: ctx.ip, | 			ip: ctx.ip, | ||||||
| 			headers: ctx.headers, | 			headers: ctx.headers, | ||||||
| 			success: true, | 			success: true, | ||||||
| 		}).then(x => Signins.findOneOrFail(x.identifiers[0])); | 		}).then(x => Signins.findOneByOrFail(x.identifiers[0])); | ||||||
| 
 | 
 | ||||||
| 		// Publish signin event
 | 		// Publish signin event
 | ||||||
| 		publishMainStream(user.id, 'signin', await Signins.pack(record)); | 		publishMainStream(user.id, 'signin', await Signins.pack(record)); | ||||||
|  |  | ||||||
|  | @ -4,12 +4,13 @@ import generateUserToken from './generate-native-user-token.js'; | ||||||
| import { User } from '@/models/entities/user.js'; | import { User } from '@/models/entities/user.js'; | ||||||
| import { Users, UsedUsernames } from '@/models/index.js'; | import { Users, UsedUsernames } from '@/models/index.js'; | ||||||
| import { UserProfile } from '@/models/entities/user-profile.js'; | import { UserProfile } from '@/models/entities/user-profile.js'; | ||||||
| import { getConnection } from 'typeorm'; | import { IsNull } from 'typeorm'; | ||||||
| import { genId } from '@/misc/gen-id.js'; | import { genId } from '@/misc/gen-id.js'; | ||||||
| import { toPunyNullable } from '@/misc/convert-host.js'; | import { toPunyNullable } from '@/misc/convert-host.js'; | ||||||
| import { UserKeypair } from '@/models/entities/user-keypair.js'; | import { UserKeypair } from '@/models/entities/user-keypair.js'; | ||||||
| import { usersChart } from '@/services/chart/index.js'; | import { usersChart } from '@/services/chart/index.js'; | ||||||
| import { UsedUsername } from '@/models/entities/used-username.js'; | import { UsedUsername } from '@/models/entities/used-username.js'; | ||||||
|  | import { db } from '@/db/postgre.js'; | ||||||
| 
 | 
 | ||||||
| export async function signup(opts: { | export async function signup(opts: { | ||||||
| 	username: User['username']; | 	username: User['username']; | ||||||
|  | @ -40,12 +41,12 @@ export async function signup(opts: { | ||||||
| 	const secret = generateUserToken(); | 	const secret = generateUserToken(); | ||||||
| 
 | 
 | ||||||
| 	// Check username duplication
 | 	// Check username duplication
 | ||||||
| 	if (await Users.findOne({ usernameLower: username.toLowerCase(), host: null })) { | 	if (await Users.findOneBy({ usernameLower: username.toLowerCase(), host: IsNull() })) { | ||||||
| 		throw new Error('DUPLICATED_USERNAME'); | 		throw new Error('DUPLICATED_USERNAME'); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Check deleted username duplication
 | 	// Check deleted username duplication
 | ||||||
| 	if (await UsedUsernames.findOne({ username: username.toLowerCase() })) { | 	if (await UsedUsernames.findOneBy({ username: username.toLowerCase() })) { | ||||||
| 		throw new Error('USED_USERNAME'); | 		throw new Error('USED_USERNAME'); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -69,10 +70,10 @@ export async function signup(opts: { | ||||||
| 	let account!: User; | 	let account!: User; | ||||||
| 
 | 
 | ||||||
| 	// Start transaction
 | 	// Start transaction
 | ||||||
| 	await getConnection().transaction(async transactionalEntityManager => { | 	await db.transaction(async transactionalEntityManager => { | ||||||
| 		const exist = await transactionalEntityManager.findOne(User, { | 		const exist = await transactionalEntityManager.findOneBy(User, { | ||||||
| 			usernameLower: username.toLowerCase(), | 			usernameLower: username.toLowerCase(), | ||||||
| 			host: null, | 			host: IsNull(), | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		if (exist) throw new Error(' the username is already used'); | 		if (exist) throw new Error(' the username is already used'); | ||||||
|  | @ -84,8 +85,8 @@ export async function signup(opts: { | ||||||
| 			usernameLower: username.toLowerCase(), | 			usernameLower: username.toLowerCase(), | ||||||
| 			host: toPunyNullable(host), | 			host: toPunyNullable(host), | ||||||
| 			token: secret, | 			token: secret, | ||||||
| 			isAdmin: (await Users.count({ | 			isAdmin: (await Users.countBy({ | ||||||
| 				host: null, | 				host: IsNull(), | ||||||
| 			})) === 0, | 			})) === 0, | ||||||
| 		})); | 		})); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| import define from '../../../define.js'; | import define from '../../../define.js'; | ||||||
| import { Users } from '@/models/index.js'; | import { Users } from '@/models/index.js'; | ||||||
| import { signup } from '../../../common/signup.js'; | import { signup } from '../../../common/signup.js'; | ||||||
|  | import { IsNull } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| export const meta = { | export const meta = { | ||||||
| 	tags: ['admin'], | 	tags: ['admin'], | ||||||
|  | @ -29,9 +30,9 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, _me) => { | export default define(meta, paramDef, async (ps, _me) => { | ||||||
| 	const me = _me ? await Users.findOneOrFail(_me.id) : null; | 	const me = _me ? await Users.findOneByOrFail({ id: _me.id }) : null; | ||||||
| 	const noUsers = (await Users.count({ | 	const noUsers = (await Users.countBy({ | ||||||
| 		host: null, | 		host: IsNull(), | ||||||
| 	})) === 0; | 	})) === 0; | ||||||
| 	if (!noUsers && !me?.isAdmin) throw new Error('access denied'); | 	if (!noUsers && !me?.isAdmin) throw new Error('access denied'); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const user = await Users.findOne(ps.userId); | 	const user = await Users.findOneBy({ id: ps.userId }); | ||||||
| 
 | 
 | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
| 		throw new Error('user not found'); | 		throw new Error('user not found'); | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const ad = await Ads.findOne(ps.id); | 	const ad = await Ads.findOneBy({ id: ps.id }); | ||||||
| 
 | 
 | ||||||
| 	if (ad == null) throw new ApiError(meta.errors.noSuchAd); | 	if (ad == null) throw new ApiError(meta.errors.noSuchAd); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const ad = await Ads.findOne(ps.id); | 	const ad = await Ads.findOneBy({ id: ps.id }); | ||||||
| 
 | 
 | ||||||
| 	if (ad == null) throw new ApiError(meta.errors.noSuchAd); | 	if (ad == null) throw new ApiError(meta.errors.noSuchAd); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -63,7 +63,7 @@ export default define(meta, paramDef, async (ps) => { | ||||||
| 		title: ps.title, | 		title: ps.title, | ||||||
| 		text: ps.text, | 		text: ps.text, | ||||||
| 		imageUrl: ps.imageUrl, | 		imageUrl: ps.imageUrl, | ||||||
| 	}).then(x => Announcements.findOneOrFail(x.identifiers[0])); | 	}).then(x => Announcements.findOneByOrFail(x.identifiers[0])); | ||||||
| 
 | 
 | ||||||
| 	return Object.assign({}, announcement, { createdAt: announcement.createdAt.toISOString(), updatedAt: null }); | 	return Object.assign({}, announcement, { createdAt: announcement.createdAt.toISOString(), updatedAt: null }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const announcement = await Announcements.findOne(ps.id); | 	const announcement = await Announcements.findOneBy({ id: ps.id }); | ||||||
| 
 | 
 | ||||||
| 	if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); | 	if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ export default define(meta, paramDef, async (ps) => { | ||||||
| 	const announcements = await query.take(ps.limit).getMany(); | 	const announcements = await query.take(ps.limit).getMany(); | ||||||
| 
 | 
 | ||||||
| 	for (const announcement of announcements) { | 	for (const announcement of announcements) { | ||||||
| 		(announcement as any).reads = await AnnouncementReads.count({ | 		(announcement as any).reads = await AnnouncementReads.countBy({ | ||||||
| 			announcementId: announcement.id, | 			announcementId: announcement.id, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const announcement = await Announcements.findOne(ps.id); | 	const announcement = await Announcements.findOneBy({ id: ps.id }); | ||||||
| 
 | 
 | ||||||
| 	if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); | 	if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const files = await DriveFiles.find({ | 	const files = await DriveFiles.findBy({ | ||||||
| 		userId: ps.userId, | 		userId: ps.userId, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ export const paramDef = { | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line import/no-default-export
 | // eslint-disable-next-line import/no-default-export
 | ||||||
| export default define(meta, paramDef, async (ps, me) => { | export default define(meta, paramDef, async (ps, me) => { | ||||||
| 	const files = await DriveFiles.find({ | 	const files = await DriveFiles.findBy({ | ||||||
| 		userId: IsNull(), | 		userId: IsNull(), | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue