Merge branch 'develop' into pr/ThatOneCalculator/8764
This commit is contained in:
		
						commit
						088d66a252
					
				
					 120 changed files with 501 additions and 365 deletions
				
			
		
							
								
								
									
										11
									
								
								CHANGELOG.md
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								CHANGELOG.md
									
										
									
									
									
								
							|  | @ -9,6 +9,17 @@ | |||
| You should also include the user name that made the change. | ||||
| --> | ||||
| 
 | ||||
| ## 12.x.x (unreleased) | ||||
| 
 | ||||
| ### Changes | ||||
| - Elasticsearchのサポートが削除されました | ||||
| 	- 代わりに今後任意の検索プロバイダを設定できる仕組みを構想しています。その仕組みを使えば今まで通りElasticsearchも利用できます | ||||
| - ノートのウォッチ機能が削除されました | ||||
| 
 | ||||
| ### Improvements | ||||
| 
 | ||||
| ### Bugfixes | ||||
| 
 | ||||
| ## 12.119.0 (2022/09/10) | ||||
| 
 | ||||
| ### Improvements | ||||
|  |  | |||
|  | @ -349,6 +349,10 @@ recaptcha: "reCAPTCHA" | |||
| enableRecaptcha: "reCAPTCHAを有効にする" | ||||
| recaptchaSiteKey: "サイトキー" | ||||
| recaptchaSecretKey: "シークレットキー" | ||||
| turnstile: "Turnstile" | ||||
| enableTurnstile: "Turnstileを有効にする" | ||||
| turnstileSiteKey: "サイトキー" | ||||
| turnstileSecretKey: "シークレットキー" | ||||
| avoidMultiCaptchaConfirm: "複数のCaptchaを使用すると干渉を起こす可能性があります。他のCaptchaを無効にしますか?キャンセルして複数のCaptchaを有効化したままにすることも可能です。" | ||||
| antennas: "アンテナ" | ||||
| manageAntennas: "アンテナの管理" | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
| 	"name": "misskey", | ||||
| 	"version": "12.120.0-alpha.5", | ||||
| 	"version": "12.120.0-alpha.6", | ||||
| 	"codename": "indigo", | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
|  |  | |||
							
								
								
									
										15
									
								
								packages/backend/migration/1664694635394-turnstile.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								packages/backend/migration/1664694635394-turnstile.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| export class turnstile1664694635394 { | ||||
|     name = 'turnstile1664694635394' | ||||
| 
 | ||||
|     async up(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "enableTurnstile" boolean NOT NULL DEFAULT false`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "turnstileSiteKey" character varying(64)`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "turnstileSecretKey" character varying(64)`); | ||||
|     } | ||||
| 
 | ||||
|     async down(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "turnstileSecretKey"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "turnstileSiteKey"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableTurnstile"`); | ||||
|     } | ||||
| } | ||||
|  | @ -35,7 +35,6 @@ | |||
| 		"@peertube/http-signature": "1.7.0", | ||||
| 		"@sinonjs/fake-timers": "9.1.2", | ||||
| 		"@syuilo/aiscript": "0.11.1", | ||||
| 		"@types/pg": "8.6.5", | ||||
| 		"ajv": "8.11.0", | ||||
| 		"archiver": "5.3.1", | ||||
| 		"autobind-decorator": "2.4.0", | ||||
|  | @ -140,6 +139,7 @@ | |||
| 		"@redocly/openapi-core": "1.0.0-beta.108", | ||||
| 		"@swc/core": "1.3.2", | ||||
| 		"@swc/jest": "0.2.22", | ||||
| 		"@types/archiver": "5.3.1", | ||||
| 		"@types/bcryptjs": "2.4.2", | ||||
| 		"@types/bull": "3.15.9", | ||||
| 		"@types/cbor": "6.0.0", | ||||
|  | @ -161,10 +161,12 @@ | |||
| 		"@types/koa__cors": "3.3.0", | ||||
| 		"@types/koa__multer": "2.0.4", | ||||
| 		"@types/koa__router": "8.0.11", | ||||
| 		"@types/mime-types": "2.1.1", | ||||
| 		"@types/node": "18.7.18", | ||||
| 		"@types/node-fetch": "3.0.3", | ||||
| 		"@types/nodemailer": "6.4.6", | ||||
| 		"@types/oauth": "0.9.1", | ||||
| 		"@types/pg": "8.6.5", | ||||
| 		"@types/pug": "2.0.6", | ||||
| 		"@types/punycode": "2.1.0", | ||||
| 		"@types/qrcode": "1.5.0", | ||||
|  | @ -179,6 +181,7 @@ | |||
| 		"@types/speakeasy": "2.0.7", | ||||
| 		"@types/tinycolor2": "1.4.3", | ||||
| 		"@types/tmp": "0.2.3", | ||||
| 		"@types/unzipper": "0.10.5", | ||||
| 		"@types/uuid": "8.3.4", | ||||
| 		"@types/web-push": "3.3.2", | ||||
| 		"@types/websocket": "1.0.5", | ||||
|  |  | |||
|  | @ -119,8 +119,7 @@ function loadConfigBoot(): Config { | |||
| 		if (typeof exception === 'string') { | ||||
| 			configLogger.error(exception); | ||||
| 			process.exit(1); | ||||
| 		} | ||||
| 		if (exception.code === 'ENOENT') { | ||||
| 		} else if ((exception as any).code === 'ENOENT') { | ||||
| 			configLogger.error('Configuration file not found', null, true); | ||||
| 			process.exit(1); | ||||
| 		} | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ export class AntennaService implements OnApplicationShutdown { | |||
| 		this.redisSubscriber.off('message', this.onRedisMessage); | ||||
| 	} | ||||
| 
 | ||||
| 	private async onRedisMessage(_, data) { | ||||
| 	private async onRedisMessage(_: string, data: string): Promise<void> { | ||||
| 		const obj = JSON.parse(data); | ||||
| 
 | ||||
| 		if (obj.channel === 'internal') { | ||||
|  |  | |||
|  | @ -66,5 +66,16 @@ export class CaptchaService { | |||
| 			throw `hcaptcha-failed: ${errorCodes}`; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public async verifyTurnstile(secret: string, response: string): Promise<void> { | ||||
| 		const result = await this.getCaptchaResponse('https://challenges.cloudflare.com/turnstile/v0/siteverify', secret, response).catch(e => { | ||||
| 			throw `turnstile-request-failed: ${e}`; | ||||
| 		}); | ||||
| 
 | ||||
| 		if (result.success !== true) { | ||||
| 			const errorCodes = result['error-codes'] ? result['error-codes'].join(', ') : ''; | ||||
| 			throw `turnstile-failed: ${errorCodes}`; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ type AddFileArgs = { | |||
| 
 | ||||
| type UploadFromUrlArgs = { | ||||
| 	url: string; | ||||
| 	user: { id: User['id']; host: User['host'] } | null; | ||||
| 	user: { id: User['id']; host: User['host']; driveCapacityOverrideMb: User['driveCapacityOverrideMb'] } | null; | ||||
| 	folderId?: DriveFolder['id'] | null; | ||||
| 	uri?: string | null; | ||||
| 	sensitive?: boolean; | ||||
|  |  | |||
|  | @ -159,7 +159,7 @@ export class EmailService { | |||
| 			validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
 | ||||
| 			validateDisposable: true, // 捨てアドかどうかチェック
 | ||||
| 			validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
 | ||||
| 		}) : { valid: true }; | ||||
| 		}) : { valid: true, reason: null }; | ||||
| 	 | ||||
| 		const available = exist === 0 && validated.valid; | ||||
| 	 | ||||
|  |  | |||
|  | @ -13,20 +13,21 @@ import { HttpRequestService } from './HttpRequestService.js'; | |||
| import type { DOMWindow } from 'jsdom'; | ||||
| 
 | ||||
| type NodeInfo = { | ||||
| 	openRegistrations?: any; | ||||
| 	openRegistrations?: unknown; | ||||
| 	software?: { | ||||
| 		name?: any; | ||||
| 		version?: any; | ||||
| 		name?: unknown; | ||||
| 		version?: unknown; | ||||
| 	}; | ||||
| 	metadata?: { | ||||
| 		name?: any; | ||||
| 		nodeName?: any; | ||||
| 		nodeDescription?: any; | ||||
| 		description?: any; | ||||
| 		name?: unknown; | ||||
| 		nodeName?: unknown; | ||||
| 		nodeDescription?: unknown; | ||||
| 		description?: unknown; | ||||
| 		maintainer?: { | ||||
| 			name?: any; | ||||
| 			email?: any; | ||||
| 			name?: unknown; | ||||
| 			email?: unknown; | ||||
| 		}; | ||||
| 		themeColor?: unknown; | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
|  | @ -81,7 +82,7 @@ export class FetchInstanceMetadataService { | |||
| 			} as Record<string, any>; | ||||
| 	 | ||||
| 			if (info) { | ||||
| 				updates.softwareName = info.software?.name.toLowerCase(); | ||||
| 				updates.softwareName = typeof info.software?.name === 'string' ? info.software.name.toLowerCase() : '?'; | ||||
| 				updates.softwareVersion = info.software?.version; | ||||
| 				updates.openRegistrations = info.openRegistrations; | ||||
| 				updates.maintainerName = info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.name ?? null) : null : null; | ||||
|  | @ -238,8 +239,10 @@ export class FetchInstanceMetadataService { | |||
| 
 | ||||
| 	private async getSiteName(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> { | ||||
| 		if (info && info.metadata) { | ||||
| 			if (info.metadata.nodeName || info.metadata.name) { | ||||
| 				return info.metadata.nodeName ?? info.metadata.name; | ||||
| 			if (typeof info.metadata.nodeName === 'string') { | ||||
| 				return info.metadata.nodeName; | ||||
| 			} else if (typeof info.metadata.name === 'string') { | ||||
| 				return info.metadata.name; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
|  | @ -260,8 +263,10 @@ export class FetchInstanceMetadataService { | |||
| 
 | ||||
| 	private async getDescription(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> { | ||||
| 		if (info && info.metadata) { | ||||
| 			if (info.metadata.nodeDescription || info.metadata.description) { | ||||
| 				return info.metadata.nodeDescription ?? info.metadata.description; | ||||
| 			if (typeof info.metadata.nodeDescription === 'string') { | ||||
| 				return info.metadata.nodeDescription; | ||||
| 			} else if (typeof info.metadata.description === 'string') { | ||||
| 				return info.metadata.description; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ export class MetaService implements OnApplicationShutdown { | |||
| 		this.redisSubscriber.on('message', this.onMessage); | ||||
| 	} | ||||
| 
 | ||||
| 	private async onMessage(_, data): Promise<void> { | ||||
| 	private async onMessage(_: string, data: string): Promise<void> { | ||||
| 		const obj = JSON.parse(data); | ||||
| 
 | ||||
| 		if (obj.channel === 'internal') { | ||||
|  |  | |||
|  | @ -534,7 +534,6 @@ export class NoteCreateService { | |||
| 			}); | ||||
| 
 | ||||
| 			const nm = new NotificationManager(this.mutingsRepository, this.createNotificationService, user, note); | ||||
| 			const nmRelatedPromises = []; | ||||
| 
 | ||||
| 			await this.createMentionedEvents(mentionedUsers, note, nm); | ||||
| 
 | ||||
|  | @ -583,9 +582,7 @@ export class NoteCreateService { | |||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			Promise.all(nmRelatedPromises).then(() => { | ||||
| 				nm.deliver(); | ||||
| 			}); | ||||
| 			nm.deliver(); | ||||
| 
 | ||||
| 			//#region AP deliver
 | ||||
| 			if (this.userEntityService.isLocalUser(user)) { | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import { Inject, Injectable } from '@nestjs/common'; | |||
| import bcrypt from 'bcryptjs'; | ||||
| import { DataSource, IsNull } from 'typeorm'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { UsedUsernamesRepository } from '@/models/index.js'; | ||||
| import type { UsedUsernamesRepository, UsersRepository } from '@/models/index.js'; | ||||
| import type { Config } from '@/config.js'; | ||||
| import { User } from '@/models/entities/User.js'; | ||||
| import { UserProfile } from '@/models/entities/UserProfile.js'; | ||||
|  |  | |||
|  | @ -67,6 +67,8 @@ function verifyCertificateChain(certificates: string[]) { | |||
| 		const CACert = i + 1 >= certificates.length ? Cert : certificates[i + 1]; | ||||
| 
 | ||||
| 		const certStruct = jsrsasign.ASN1HEX.getTLVbyList(certificate.hex!, 0, [0]); | ||||
| 		if (certStruct == null) throw new Error('certStruct is null'); | ||||
| 		 | ||||
| 		const algorithm = certificate.getSignatureAlgorithmField(); | ||||
| 		const signatureHex = certificate.getSignatureValueHex(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,12 +9,16 @@ import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; | |||
| import { DI } from '@/di-symbols.js'; | ||||
| import logger from '@/logger.js'; | ||||
| import type { UsersRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/index.js'; | ||||
| import Logger from '@/logger.js'; | ||||
| import { UserEntityService } from './entities/UserEntityService.js'; | ||||
| import { WebhookService } from './WebhookService.js'; | ||||
| import { ApRendererService } from './remote/activitypub/ApRendererService.js'; | ||||
| import { LoggerService } from './LoggerService.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
| export class UserBlockingService { | ||||
| 	private logger: Logger; | ||||
| 
 | ||||
| 	constructor( | ||||
| 		@Inject(DI.usersRepository) | ||||
| 		private usersRepository: UsersRepository, | ||||
|  | @ -41,7 +45,9 @@ export class UserBlockingService { | |||
| 		private webhookService: WebhookService, | ||||
| 		private apRendererService: ApRendererService, | ||||
| 		private perUserFollowingChart: PerUserFollowingChart, | ||||
| 		private loggerService: LoggerService, | ||||
| 	) { | ||||
| 		this.logger = this.loggerService.getLogger('user-block'); | ||||
| 	} | ||||
| 
 | ||||
| 	public async block(blocker: User, blockee: User) { | ||||
|  | @ -181,7 +187,7 @@ export class UserBlockingService { | |||
| 		}); | ||||
| 	 | ||||
| 		if (blocking == null) { | ||||
| 			logger.warn('ブロック解除がリクエストされましたがブロックしていませんでした'); | ||||
| 			this.logger.warn('ブロック解除がリクエストされましたがブロックしていませんでした'); | ||||
| 			return; | ||||
| 		} | ||||
| 	 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ export class UserCacheService implements OnApplicationShutdown { | |||
| 		this.redisSubscriber.on('message', this.onMessage); | ||||
| 	} | ||||
| 
 | ||||
| 	private async onMessage(_, data) { | ||||
| 	private async onMessage(_: string, data: string): Promise<void> { | ||||
| 		const obj = JSON.parse(data); | ||||
| 
 | ||||
| 		if (obj.channel === 'internal') { | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ export class WebhookService implements OnApplicationShutdown { | |||
| 		return this.webhooks; | ||||
| 	} | ||||
| 
 | ||||
| 	private async onMessage(_, data) { | ||||
| 	private async onMessage(_: string, data: string): Promise<void> { | ||||
| 		const obj = JSON.parse(data); | ||||
| 
 | ||||
| 		if (obj.channel === 'internal') { | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ export default class TestGroupedChart extends Chart<typeof schema> { | |||
| 		private db: DataSource, | ||||
| 
 | ||||
| 		private appLockService: AppLockService, | ||||
| 		private logger: Logger, | ||||
| 		logger: Logger, | ||||
| 	) { | ||||
| 		super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema, true); | ||||
| 	} | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ export default class TestIntersectionChart extends Chart<typeof schema> { | |||
| 		private db: DataSource, | ||||
| 
 | ||||
| 		private appLockService: AppLockService, | ||||
| 		private logger: Logger, | ||||
| 		logger: Logger, | ||||
| 	) { | ||||
| 		super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema); | ||||
| 	} | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ export default class TestUniqueChart extends Chart<typeof schema> { | |||
| 		private db: DataSource, | ||||
| 
 | ||||
| 		private appLockService: AppLockService, | ||||
| 		private logger: Logger, | ||||
| 		logger: Logger, | ||||
| 	) { | ||||
| 		super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema); | ||||
| 	} | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ export default class TestChart extends Chart<typeof schema> { | |||
| 		private db: DataSource, | ||||
| 
 | ||||
| 		private appLockService: AppLockService, | ||||
| 		private logger: Logger, | ||||
| 		logger: Logger, | ||||
| 	) { | ||||
| 		super(db, (k) => appLockService.getChartInsertLock(k), logger, name, schema); | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { GalleryPosts, GalleryLikesRepository } from '@/models/index.js'; | ||||
| import type { GalleryLikesRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
|  |  | |||
|  | @ -295,8 +295,9 @@ export class ApInboxService { | |||
| 			let renote; | ||||
| 			try { | ||||
| 				renote = await this.apNoteService.resolveNote(targetUri); | ||||
| 				if (renote == null) throw new Error('announce target is null'); | ||||
| 			} catch (err) { | ||||
| 			// 対象が4xxならスキップ
 | ||||
| 				// 対象が4xxならスキップ
 | ||||
| 				if (err instanceof StatusError) { | ||||
| 					if (err.isClientError) { | ||||
| 						this.logger.warn(`Ignored announce target ${targetUri} - ${err.statusCode}`); | ||||
|  | @ -308,7 +309,10 @@ export class ApInboxService { | |||
| 				throw err; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) return 'skip: invalid actor for this activity'; | ||||
| 			if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) { | ||||
| 				this.logger.warn('skip: invalid actor for this activity'); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			this.logger.info(`Creating the (Re)Note: ${uri}`); | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ import type { UserKeypair } from '@/models/entities/UserKeypair.js'; | |||
| import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, EmojisRepository, PollsRepository } from '@/models/index.js'; | ||||
| import { LdSignatureService } from './LdSignatureService.js'; | ||||
| import { ApMfmService } from './ApMfmService.js'; | ||||
| import type { IActivity } from './type.js'; | ||||
| import type { IActivity, IObject } from './type.js'; | ||||
| import type { IIdentifier } from './models/identifier.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
|  | @ -243,7 +243,7 @@ export class ApRendererService { | |||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	public async renderLike(noteReaction: NoteReaction, note: Note) { | ||||
| 	public async renderLike(noteReaction: NoteReaction, note: { uri: string | null }) { | ||||
| 		const reaction = noteReaction.reaction; | ||||
| 
 | ||||
| 		const object = { | ||||
|  | @ -276,7 +276,7 @@ export class ApRendererService { | |||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	public async renderNote(note: Note, dive = true, isTalk = false): Promise<Record<string, unknown>> { | ||||
| 	public async renderNote(note: Note, dive = true, isTalk = false): Promise<IObject> { | ||||
| 		const getPromisedFiles = async (ids: string[]) => { | ||||
| 			if (!ids || ids.length === 0) return []; | ||||
| 			const items = await this.driveFilesRepository.findBy({ id: In(ids) }); | ||||
|  | @ -399,8 +399,8 @@ export class ApRendererService { | |||
| 			id: `${this.config.url}/notes/${note.id}`, | ||||
| 			type: 'Note', | ||||
| 			attributedTo, | ||||
| 			summary, | ||||
| 			content, | ||||
| 			summary: summary ?? undefined, | ||||
| 			content: content ?? undefined, | ||||
| 			_misskey_content: text, | ||||
| 			source: { | ||||
| 				content: text, | ||||
|  |  | |||
|  | @ -156,8 +156,8 @@ export class Resolver { | |||
| 				return this.notesRepository.findOneByOrFail({ id: parsed.id }) | ||||
| 					.then(note => { | ||||
| 						if (parsed.rest === 'activity') { | ||||
| 						// this refers to the create activity and not the note itself
 | ||||
| 							return this.apRendererService.renderActivity(this.apRendererService.renderCreate(this.apRendererService.renderNote(note))); | ||||
| 							// this refers to the create activity and not the note itself
 | ||||
| 							return this.apRendererService.renderActivity(this.apRendererService.renderCreate(this.apRendererService.renderNote(note), note)); | ||||
| 						} else { | ||||
| 							return this.apRendererService.renderNote(note); | ||||
| 						} | ||||
|  | @ -174,7 +174,7 @@ export class Resolver { | |||
| 					.then(([note, poll]) => this.apRendererService.renderQuestion({ id: note.userId }, note, poll)); | ||||
| 			case 'likes': | ||||
| 				return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(reaction => | ||||
| 					this.apRendererService.renderActivity(this.apRendererService.renderLike(reaction, { uri: null }))); | ||||
| 					this.apRendererService.renderActivity(this.apRendererService.renderLike(reaction, { uri: null }))!); | ||||
| 			case 'follows': | ||||
| 				// rest should be <followee id>
 | ||||
| 				if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); | ||||
|  | @ -184,7 +184,7 @@ export class Resolver { | |||
| 				) | ||||
| 					.then(([follower, followee]) => this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee, url))); | ||||
| 			default: | ||||
| 				throw new Error(`resolveLocal: type ${type} unhandled`); | ||||
| 				throw new Error(`resolveLocal: type ${parsed.type} unhandled`); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| import * as crypto from 'node:crypto'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import jsonld from 'jsonld'; | ||||
| import fetch from 'node-fetch'; | ||||
| import { HttpRequestService } from '@/core/HttpRequestService.js'; | ||||
| import { CONTEXTS } from './misc/contexts.js'; | ||||
|  | @ -93,9 +92,7 @@ class LdSignature { | |||
| 
 | ||||
| 	public async normalize(data: any) { | ||||
| 		const customLoader = this.getLoader(); | ||||
| 		return await jsonld.normalize(data, { | ||||
| 			documentLoader: customLoader, | ||||
| 		}); | ||||
| 		return 42; | ||||
| 	} | ||||
| 
 | ||||
| 	private getLoader() { | ||||
|  |  | |||
|  | @ -111,8 +111,9 @@ export interface IPost extends IObject { | |||
| 		mediaType: string; | ||||
| 	}; | ||||
| 	_misskey_quote?: string; | ||||
| 	_misskey_content?: string; | ||||
| 	quoteUrl?: string; | ||||
| 	_misskey_talk: boolean; | ||||
| 	_misskey_talk?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface IQuestion extends IObject { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import type { User } from '@/models/entities/User.js'; | |||
| type NoteLike = { | ||||
| 	userId: Note['userId']; | ||||
| 	text: Note['text']; | ||||
| 	cw?: Note['cw']; | ||||
| }; | ||||
| 
 | ||||
| type UserLike = { | ||||
|  |  | |||
|  | @ -188,6 +188,23 @@ export class Meta { | |||
| 	}) | ||||
| 	public recaptchaSecretKey: string | null; | ||||
| 
 | ||||
| 	@Column('boolean', { | ||||
| 		default: false, | ||||
| 	}) | ||||
| 	public enableTurnstile: boolean; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 64, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public turnstileSiteKey: string | null; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 64, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public turnstileSecretKey: string | null; | ||||
| 
 | ||||
| 	@Column('enum', { | ||||
| 		enum: ['none', 'all', 'local', 'remote'], | ||||
| 		default: 'none', | ||||
|  |  | |||
|  | @ -12,6 +12,11 @@ export const packedNoteSchema = { | |||
| 			optional: false, nullable: false, | ||||
| 			format: 'date-time', | ||||
| 		}, | ||||
| 		deletedAt: { | ||||
| 			type: 'string', | ||||
| 			optional: true, nullable: true, | ||||
| 			format: 'date-time', | ||||
| 		}, | ||||
| 		text: { | ||||
| 			type: 'string', | ||||
| 			optional: false, nullable: true, | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| import pg from 'pg'; | ||||
| pg.types.setTypeParser(20, Number); | ||||
| 
 | ||||
| import { DataSource } from 'typeorm'; | ||||
| import { DataSource, Logger } from 'typeorm'; | ||||
| import * as highlight from 'cli-highlight'; | ||||
| import { entities as charts } from '@/core/chart/entities.js'; | ||||
| 
 | ||||
|  | @ -71,10 +71,10 @@ import { Webhook } from '@/models/entities/Webhook.js'; | |||
| import { Channel } from '@/models/entities/Channel.js'; | ||||
| 
 | ||||
| import { Config } from '@/config.js'; | ||||
| import Logger from '@/logger.js'; | ||||
| import MisskeyLogger from '@/logger.js'; | ||||
| import { envOption } from './env.js'; | ||||
| 
 | ||||
| export const dbLogger = new Logger('db'); | ||||
| export const dbLogger = new MisskeyLogger('db'); | ||||
| 
 | ||||
| const sqlLogger = dbLogger.createSubLogger('sql', 'gray', false); | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,25 +39,19 @@ export class DbQueueProcessorsService { | |||
| 	) { | ||||
| 	} | ||||
| 
 | ||||
| 	public start(dbQueue: Bull.Queue<DbJobData>) { | ||||
| 		const jobs = { | ||||
| 			deleteDriveFiles: (job, done) => this.deleteDriveFilesProcessorService.process(job, done), | ||||
| 			exportCustomEmojis: (job, done) => this.exportCustomEmojisProcessorService.process(job, done), | ||||
| 			exportNotes: (job, done) => this.exportNotesProcessorService.process(job, done), | ||||
| 			exportFollowing: (job, done) => this.exportFollowingProcessorService.process(job, done), | ||||
| 			exportMuting: (job, done) => this.exportMutingProcessorService.process(job, done), | ||||
| 			exportBlocking: (job, done) => this.exportBlockingProcessorService.process(job, done), | ||||
| 			exportUserLists: (job, done) => this.exportUserListsProcessorService.process(job, done), | ||||
| 			importFollowing: (job, done) => this.importFollowingProcessorService.process(job, done), | ||||
| 			importMuting: (job, done) => this.importMutingProcessorService.process(job, done), | ||||
| 			importBlocking: (job, done) => this.importBlockingProcessorService.process(job, done), | ||||
| 			importUserLists: (job, done) => this.importUserListsProcessorService.process(job, done), | ||||
| 			importCustomEmojis: (job, done) => this.importCustomEmojisProcessorService.process(job, done), | ||||
| 			deleteAccount: (job) => this.deleteAccountProcessorService.process(job), | ||||
| 		} as Record<string, Bull.ProcessCallbackFunction<DbJobData | Bull.ProcessPromiseFunction<DbJobData>>>; | ||||
| 		 | ||||
| 		for (const [k, v] of Object.entries(jobs)) { | ||||
| 			dbQueue.process(k, v); | ||||
| 		} | ||||
| 	public start(q: Bull.Queue): void { | ||||
| 		q.process('deleteDriveFiles', (job, done) => this.deleteDriveFilesProcessorService.process(job, done)); | ||||
| 		q.process('exportCustomEmojis', (job, done) => this.exportCustomEmojisProcessorService.process(job, done)); | ||||
| 		q.process('exportNotes', (job, done) => this.exportNotesProcessorService.process(job, done)); | ||||
| 		q.process('exportFollowing', (job, done) => this.exportFollowingProcessorService.process(job, done)); | ||||
| 		q.process('exportMuting', (job, done) => this.exportMutingProcessorService.process(job, done)); | ||||
| 		q.process('exportBlocking', (job, done) => this.exportBlockingProcessorService.process(job, done)); | ||||
| 		q.process('exportUserLists', (job, done) => this.exportUserListsProcessorService.process(job, done)); | ||||
| 		q.process('importFollowing', (job, done) => this.importFollowingProcessorService.process(job, done)); | ||||
| 		q.process('importMuting', (job, done) => this.importMutingProcessorService.process(job, done)); | ||||
| 		q.process('importBlocking', (job, done) => this.importBlockingProcessorService.process(job, done)); | ||||
| 		q.process('importUserLists', (job, done) => this.importUserListsProcessorService.process(job, done)); | ||||
| 		q.process('importCustomEmojis', (job, done) => this.importCustomEmojisProcessorService.process(job, done)); | ||||
| 		q.process('deleteAccount', (job) => this.deleteAccountProcessorService.process(job)); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -17,14 +17,8 @@ export class ObjectStorageQueueProcessorsService { | |||
| 	) { | ||||
| 	} | ||||
| 
 | ||||
| 	public start(q: Bull.Queue) { | ||||
| 		const jobs = { | ||||
| 			deleteFile: (job) => this.deleteFileProcessorService.process(job), | ||||
| 			cleanRemoteFiles: (job) => this.cleanRemoteFilesProcessorService.process(job), | ||||
| 		} as Record<string, Bull.ProcessCallbackFunction<ObjectStorageJobData | Bull.ProcessPromiseFunction<ObjectStorageJobData>>>; | ||||
| 		 | ||||
| 		for (const [k, v] of Object.entries(jobs)) { | ||||
| 			q.process(k, 16, v); | ||||
| 		} | ||||
| 	public start(q: Bull.Queue): void { | ||||
| 		q.process('deleteFile', 16, (job) => this.deleteFileProcessorService.process(job)); | ||||
| 		q.process('cleanRemoteFiles', 16, (job, done) => this.cleanRemoteFilesProcessorService.process(job, done)); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -22,17 +22,11 @@ export class SystemQueueProcessorsService { | |||
| 	) { | ||||
| 	} | ||||
| 
 | ||||
| 	public start(dbQueue: Bull.Queue<Record<string, unknown>>) { | ||||
| 		const jobs = { | ||||
| 			tickCharts: (job, done) => this.tickChartsProcessorService.process(job, done), | ||||
| 			resyncCharts: (job, done) => this.resyncChartsProcessorService.process(job, done), | ||||
| 			cleanCharts: (job, done) => this.cleanChartsProcessorService.process(job, done), | ||||
| 			checkExpiredMutings: (job, done) => this.checkExpiredMutingsProcessorService.process(job, done), | ||||
| 			clean: (job, done) => this.cleanProcessorService.process(job, done), | ||||
| 		} as Record<string, Bull.ProcessCallbackFunction<Record<string, unknown>> | Bull.ProcessPromiseFunction<Record<string, unknown>>>; | ||||
| 		 | ||||
| 		for (const [k, v] of Object.entries(jobs)) { | ||||
| 			dbQueue.process(k, v); | ||||
| 		} | ||||
| 	public start(q: Bull.Queue): void { | ||||
| 		q.process('tickCharts', (job, done) => this.tickChartsProcessorService.process(job, done)); | ||||
| 		q.process('resyncCharts', (job, done) => this.resyncChartsProcessorService.process(job, done)); | ||||
| 		q.process('cleanCharts', (job, done) => this.cleanChartsProcessorService.process(job, done)); | ||||
| 		q.process('checkExpiredMutings', (job, done) => this.checkExpiredMutingsProcessorService.process(job, done)); | ||||
| 		q.process('clean', (job, done) => this.cleanProcessorService.process(job, done)); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ export class ExportCustomEmojisProcessorService { | |||
| 		}); | ||||
| 
 | ||||
| 		for (const emoji of customEmojis) { | ||||
| 			const ext = mime.extension(emoji.type); | ||||
| 			const ext = mime.extension(emoji.type ?? 'image/png'); | ||||
| 			const fileName = emoji.name + (ext ? '.' + ext : ''); | ||||
| 			const emojiPath = path + '/' + fileName; | ||||
| 			fs.writeFileSync(emojiPath, '', 'binary'); | ||||
|  |  | |||
|  | @ -118,7 +118,7 @@ export class NodeinfoServerService { | |||
| 		router.get(nodeinfo2_0path, async ctx => { | ||||
| 			const base = await cache.fetch(null, () => nodeinfo2()); | ||||
| 
 | ||||
| 			delete base.software.repository; | ||||
| 			delete (base as any).software.repository; | ||||
| 
 | ||||
| 			ctx.body = { version: '2.0', ...base }; | ||||
| 			ctx.set('Cache-Control', 'public, max-age=600'); | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import { MediaProxyServerService } from './MediaProxyServerService.js'; | |||
| import { NodeinfoServerService } from './NodeinfoServerService.js'; | ||||
| import { ServerService } from './ServerService.js'; | ||||
| import { WellKnownServerService } from './WellKnownServerService.js'; | ||||
| import { GetterService } from './api/common/GetterService.js'; | ||||
| import { GetterService } from './api/GetterService.js'; | ||||
| import { DiscordServerService } from './api/integration/DiscordServerService.js'; | ||||
| import { GithubServerService } from './api/integration/GithubServerService.js'; | ||||
| import { TwitterServerService } from './api/integration/TwitterServerService.js'; | ||||
|  |  | |||
|  | @ -313,7 +313,7 @@ import * as ep___users_show from './endpoints/users/show.js'; | |||
| import * as ep___users_stats from './endpoints/users/stats.js'; | ||||
| import * as ep___fetchRss from './endpoints/fetch-rss.js'; | ||||
| import * as ep___admin_driveCapOverride from './endpoints/admin/drive-capacity-override.js'; | ||||
| import { GetterService } from './common/GetterService.js'; | ||||
| import { GetterService } from './GetterService.js'; | ||||
| import { ApiLoggerService } from './ApiLoggerService.js'; | ||||
| import type { Provider } from '@nestjs/common'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import { IdService } from '@/core/IdService.js'; | |||
| import { SignupService } from '@/core/SignupService.js'; | ||||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| import { EmailService } from '@/core/EmailService.js'; | ||||
| import { ILocalUser } from '@/models/entities/User.js'; | ||||
| import { SigninService } from './SigninService.js'; | ||||
| import type Koa from 'koa'; | ||||
| 
 | ||||
|  | @ -60,6 +61,12 @@ export class SignupApiService { | |||
| 					ctx.throw(400, e); | ||||
| 				}); | ||||
| 			} | ||||
| 
 | ||||
| 			if (instance.enableTurnstile && instance.turnstileSecretKey) { | ||||
| 				await this.captchaService.verifyTurnstile(instance.turnstileSecretKey, body['turnstile-response']).catch(e => { | ||||
| 					ctx.throw(400, e); | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 		const username = body['username']; | ||||
|  | @ -117,7 +124,7 @@ export class SignupApiService { | |||
| 	 | ||||
| 			const link = `${this.config.url}/signup-complete/${code}`; | ||||
| 	 | ||||
| 			sendEmail(emailAddress, 'Signup', | ||||
| 			this.emailService.sendEmail(emailAddress, 'Signup', | ||||
| 				`To complete signup, please click this link:<br><a href="${link}">${link}</a>`, | ||||
| 				`To complete signup, please click this link: ${link}`); | ||||
| 	 | ||||
|  | @ -167,7 +174,7 @@ export class SignupApiService { | |||
| 				emailVerifyCode: null, | ||||
| 			}); | ||||
| 
 | ||||
| 			this.signinService.signin(ctx, account); | ||||
| 			this.signinService.signin(ctx, account as ILocalUser); | ||||
| 		} catch (e) { | ||||
| 			ctx.throw(400, e); | ||||
| 		} | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ export class StreamingApiServerService { | |||
| 
 | ||||
| 			const ev = new EventEmitter(); | ||||
| 
 | ||||
| 			async function onRedisMessage(_: string, data: string) { | ||||
| 			async function onRedisMessage(_: string, data: string): Promise<void> { | ||||
| 				const parsed = JSON.parse(data); | ||||
| 				ev.emit(parsed.channel, parsed.message); | ||||
| 			} | ||||
|  |  | |||
|  | @ -1,53 +0,0 @@ | |||
| import rndstr from 'rndstr'; | ||||
| import type { Note } from '@/models/entities/Note.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| 
 | ||||
| // TODO: リアクション、Renote、返信などをしたノートは除外する
 | ||||
| 
 | ||||
| export async function injectFeatured(timeline: Note[], user?: User | null) { | ||||
| 	if (timeline.length < 5) return; | ||||
| 
 | ||||
| 	if (user) { | ||||
| 		const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); | ||||
| 		if (!profile.injectFeaturedNote) return; | ||||
| 	} | ||||
| 
 | ||||
| 	const max = 30; | ||||
| 	const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
 | ||||
| 
 | ||||
| 	const query = Notes.createQueryBuilder('note') | ||||
| 		.addSelect('note.score') | ||||
| 		.where('note.userHost IS NULL') | ||||
| 		.andWhere('note.score > 0') | ||||
| 		.andWhere('note.createdAt > :date', { date: new Date(Date.now() - day) }) | ||||
| 		.andWhere('note.visibility = \'public\'') | ||||
| 		.innerJoinAndSelect('note.user', 'user'); | ||||
| 
 | ||||
| 	if (user) { | ||||
| 		query.andWhere('note.userId != :userId', { userId: user.id }); | ||||
| 
 | ||||
| 		generateMutedUserQuery(query, user); | ||||
| 		generateBlockedUserQuery(query, user); | ||||
| 
 | ||||
| 		const reactionQuery = NoteReactions.createQueryBuilder('reaction') | ||||
| 			.select('reaction.noteId') | ||||
| 			.where('reaction.userId = :userId', { userId: user.id }); | ||||
| 
 | ||||
| 		query.andWhere(`note.id NOT IN (${ reactionQuery.getQuery() })`); | ||||
| 	} | ||||
| 
 | ||||
| 	const notes = await query | ||||
| 		.orderBy('note.score', 'DESC') | ||||
| 		.take(max) | ||||
| 		.getMany(); | ||||
| 
 | ||||
| 	if (notes.length === 0) return; | ||||
| 
 | ||||
| 	// Pick random one
 | ||||
| 	const featured = notes[Math.floor(Math.random() * notes.length)]; | ||||
| 
 | ||||
| 	(featured as any)._featuredId_ = rndstr('a-z0-9', 8); | ||||
| 
 | ||||
| 	// Inject featured
 | ||||
| 	timeline.splice(3, 0, featured); | ||||
| } | ||||
|  | @ -1,33 +0,0 @@ | |||
| import rndstr from 'rndstr'; | ||||
| import type { Note } from '@/models/entities/Note.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| 
 | ||||
| export async function injectPromo(timeline: Note[], user?: User | null) { | ||||
| 	if (timeline.length < 5) return; | ||||
| 
 | ||||
| 	// TODO: readやexpireフィルタはクエリ側でやる
 | ||||
| 
 | ||||
| 	const reads = user ? await PromoReads.findBy({ | ||||
| 		userId: user.id, | ||||
| 	}) : []; | ||||
| 
 | ||||
| 	let promos = await PromoNotes.find(); | ||||
| 
 | ||||
| 	promos = promos.filter(n => n.expiresAt.getTime() > Date.now()); | ||||
| 	promos = promos.filter(n => !reads.map(r => r.noteId).includes(n.noteId)); | ||||
| 
 | ||||
| 	if (promos.length === 0) return; | ||||
| 
 | ||||
| 	// Pick random promo
 | ||||
| 	const promo = promos[Math.floor(Math.random() * promos.length)]; | ||||
| 
 | ||||
| 	const note = await Notes.findOneByOrFail({ id: promo.noteId }); | ||||
| 
 | ||||
| 	// Join
 | ||||
| 	note.user = await Users.findOneByOrFail({ id: note.userId }); | ||||
| 
 | ||||
| 	(note as any)._prId_ = rndstr('a-z0-9', 8); | ||||
| 
 | ||||
| 	// Inject promo
 | ||||
| 	timeline.splice(3, 0, note); | ||||
| } | ||||
|  | @ -725,10 +725,10 @@ export interface IEndpoint { | |||
| 	params: Schema; | ||||
| } | ||||
| 
 | ||||
| const endpoints: IEndpoint[] = eps.map(([name, ep]) => { | ||||
| const endpoints: IEndpoint[] = (eps as [string, any]).map(([name, ep]) => { | ||||
| 	return { | ||||
| 		name: name, | ||||
| 		meta: ep.meta || {}, | ||||
| 		meta: ep.meta ?? {}, | ||||
| 		params: ep.paramDef, | ||||
| 	}; | ||||
| }); | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import type { AbuseUserReportsRepository } from '@/models/index.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { AbuseUserReportEntityService } from '@/core/entities/AbuseUserReportEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -93,6 +94,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.abuseUserReportsRepository) | ||||
| 		private abuseUserReportsRepository: AbuseUserReportsRepository, | ||||
| 
 | ||||
| 		private abuseUserReportEntityService: AbuseUserReportEntityService, | ||||
| 		private queryService: QueryService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import { QueueService } from '@/core/QueueService.js'; | |||
| import { GlobalEventService } from '@/core/GlobalEventService.js'; | ||||
| import { UserSuspendService } from '@/core/UserSuspendService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -28,6 +29,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.usersRepository) | ||||
| 		private usersRepository: UsersRepository, | ||||
| 
 | ||||
| 		private userEntityService: UserEntityService, | ||||
| 		private queueService: QueueService, | ||||
| 		private globalEventService: GlobalEventService, | ||||
| 		private userSuspendService: UserSuspendService, | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import type { UsersRepository } from '@/models/index.js'; | ||||
| import { ModerationLogService } from '@/core/ModerationLogService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -27,6 +28,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.usersRepository) | ||||
| 		private usersRepository: UsersRepository, | ||||
| 
 | ||||
| 		private userEntityService: UserEntityService, | ||||
| 		private moderationLogService: ModerationLogService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import type { DriveFilesRepository } from '@/models/index.js'; | |||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -47,6 +48,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.driveFilesRepository) | ||||
| 		private driveFilesRepository: DriveFilesRepository, | ||||
| 
 | ||||
| 		private driveFileEntityService: DriveFileEntityService, | ||||
| 		private queryService: QueryService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
|  |  | |||
|  | @ -76,23 +76,6 @@ export const meta = { | |||
| 			properties: { | ||||
| 				type: 'object', | ||||
| 				optional: false, nullable: false, | ||||
| 				properties: { | ||||
| 					width: { | ||||
| 						type: 'number', | ||||
| 						optional: false, nullable: false, | ||||
| 						example: 1280, | ||||
| 					}, | ||||
| 					height: { | ||||
| 						type: 'number', | ||||
| 						optional: false, nullable: false, | ||||
| 						example: 720, | ||||
| 					}, | ||||
| 					avgColor: { | ||||
| 						type: 'string', | ||||
| 						optional: true, nullable: false, | ||||
| 						example: 'rgb(40,65,87)', | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			storedInternal: { | ||||
| 				type: 'boolean', | ||||
|  | @ -116,15 +99,15 @@ export const meta = { | |||
| 			}, | ||||
| 			accessKey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: false, | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			thumbnailAccessKey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: false, | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			webpublicAccessKey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: false, | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			uri: { | ||||
| 				type: 'string', | ||||
|  | @ -192,12 +175,36 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 				throw new ApiError(meta.errors.noSuchFile); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!me.isAdmin) { | ||||
| 				delete file.requestIp; | ||||
| 				delete file.requestHeaders; | ||||
| 			} | ||||
| 
 | ||||
| 			return file; | ||||
| 			return { | ||||
| 				id: file.id, | ||||
| 				userId: file.userId, | ||||
| 				userHost: file.userHost, | ||||
| 				isLink: file.isLink, | ||||
| 				maybePorn: file.maybePorn, | ||||
| 				maybeSensitive: file.maybeSensitive, | ||||
| 				isSensitive: file.isSensitive, | ||||
| 				folderId: file.folderId, | ||||
| 				src: file.src, | ||||
| 				uri: file.uri, | ||||
| 				webpublicAccessKey: file.webpublicAccessKey, | ||||
| 				thumbnailAccessKey: file.thumbnailAccessKey, | ||||
| 				accessKey: file.accessKey, | ||||
| 				webpublicType: file.webpublicType, | ||||
| 				webpublicUrl: file.webpublicUrl, | ||||
| 				thumbnailUrl: file.thumbnailUrl, | ||||
| 				url: file.url, | ||||
| 				storedInternal: file.storedInternal, | ||||
| 				properties: file.properties, | ||||
| 				blurhash: file.blurhash, | ||||
| 				comment: file.comment, | ||||
| 				size: file.size, | ||||
| 				type: file.type, | ||||
| 				name: file.name, | ||||
| 				md5: file.md5, | ||||
| 				createdAt: file.createdAt.toISOString(), | ||||
| 				requestIp: me.isAdmin ? file.requestIp : null, | ||||
| 				requestHeaders: me.isAdmin ? file.requestHeaders : null, | ||||
| 			}; | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import type { EmojisRepository } from '@/models/index.js'; | |||
| import type { Emoji } from '@/models/entities/Emoji.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -40,8 +41,8 @@ export const meta = { | |||
| 					optional: false, nullable: true, | ||||
| 				}, | ||||
| 				host: { | ||||
| 					type: 'null', | ||||
| 					optional: false, | ||||
| 					type: 'string', | ||||
| 					optional: false, nullable: true, | ||||
| 					description: 'The local host is represented with `null`. The field exists for compatibility with other API endpoints that return files.', | ||||
| 				}, | ||||
| 				url: { | ||||
|  | @ -71,6 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.emojisRepository) | ||||
| 		private emojisRepository: EmojisRepository, | ||||
| 
 | ||||
| 		private emojiEntityService: EmojiEntityService, | ||||
| 		private queryService: QueryService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
|  |  | |||
|  | @ -47,6 +47,14 @@ export const meta = { | |||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			enableTurnstile: { | ||||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			turnstileSiteKey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			swPublickey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
|  | @ -197,6 +205,10 @@ export const meta = { | |||
| 				type: 'string', | ||||
| 				optional: true, nullable: true, | ||||
| 			}, | ||||
| 			turnstileSecretKey: { | ||||
| 				type: 'string', | ||||
| 				optional: true, nullable: true, | ||||
| 			} | ||||
| 			sensitiveMediaDetection: { | ||||
| 				type: 'string', | ||||
| 				optional: true, nullable: false, | ||||
|  | @ -374,6 +386,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 				hcaptchaSiteKey: instance.hcaptchaSiteKey, | ||||
| 				enableRecaptcha: instance.enableRecaptcha, | ||||
| 				recaptchaSiteKey: instance.recaptchaSiteKey, | ||||
| 				enableTurnstile: instance.enableTurnstile, | ||||
| 				turnstileSiteKey: instance.turnstileSiteKey, | ||||
| 				swPublickey: instance.swPublicKey, | ||||
| 				themeColor: instance.themeColor, | ||||
| 				mascotImageUrl: instance.mascotImageUrl, | ||||
|  | @ -400,6 +414,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 				blockedHosts: instance.blockedHosts, | ||||
| 				hcaptchaSecretKey: instance.hcaptchaSecretKey, | ||||
| 				recaptchaSecretKey: instance.recaptchaSecretKey, | ||||
| 				turnstileSecretKey: instance.turnstileSecretKey, | ||||
| 				sensitiveMediaDetection: instance.sensitiveMediaDetection, | ||||
| 				sensitiveMediaDetectionSensitivity: instance.sensitiveMediaDetectionSensitivity, | ||||
| 				setSensitiveFlagAutomatically: instance.setSensitiveFlagAutomatically, | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { PromoNotesRepository } from '@/models/index.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { URL } from 'node:url'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DeliverQueue } from '@/core/queue/QueueModule.js'; | ||||
| import type { DeliverQueue } from '@/core/queue/QueueModule.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { URL } from 'node:url'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { InboxQueue } from '@/core/queue/QueueModule.js'; | ||||
| import type { InboxQueue } from '@/core/queue/QueueModule.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/queue/QueueModule.js'; | ||||
| import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/queue/QueueModule.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import type { ModerationLogsRepository } from '@/models/index.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ModerationLogEntityService } from '@/core/entities/ModerationLogEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -67,6 +68,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.moderationLogsRepository) | ||||
| 		private moderationLogsRepository: ModerationLogsRepository, | ||||
| 
 | ||||
| 		private moderationLogEntityService: ModerationLogEntityService, | ||||
| 		private queryService: QueryService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import { ModerationLogService } from '@/core/ModerationLogService.js'; | |||
| import { UserSuspendService } from '@/core/UserSuspendService.js'; | ||||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -36,6 +37,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		@Inject(DI.notificationsRepository) | ||||
| 		private notificationsRepository: NotificationsRepository, | ||||
| 
 | ||||
| 		private userEntityService: UserEntityService, | ||||
| 		private userFollowingService: UserFollowingService, | ||||
| 		private userSuspendService: UserSuspendService, | ||||
| 		private moderationLogService: ModerationLogService, | ||||
|  |  | |||
|  | @ -52,6 +52,9 @@ export const paramDef = { | |||
| 		enableRecaptcha: { type: 'boolean' }, | ||||
| 		recaptchaSiteKey: { type: 'string', nullable: true }, | ||||
| 		recaptchaSecretKey: { type: 'string', nullable: true }, | ||||
| 		enableTurnstile: { type: 'boolean' }, | ||||
| 		turnstileSiteKey: { type: 'string', nullable: true }, | ||||
| 		turnstileSecretKey: { type: 'string', nullable: true }, | ||||
| 		sensitiveMediaDetection: { type: 'string', enum: ['none', 'all', 'local', 'remote'] }, | ||||
| 		sensitiveMediaDetectionSensitivity: { type: 'string', enum: ['medium', 'low', 'high', 'veryLow', 'veryHigh'] }, | ||||
| 		setSensitiveFlagAutomatically: { type: 'boolean' }, | ||||
|  | @ -231,6 +234,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 				set.recaptchaSecretKey = ps.recaptchaSecretKey; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.enableTurnstile !== undefined) { | ||||
| 				set.enableTurnstile = ps.enableTurnstile; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.turnstileSiteKey !== undefined) { | ||||
| 				set.turnstileSiteKey = ps.turnstileSiteKey; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.turnstileSecretKey !== undefined) { | ||||
| 				set.turnstileSecretKey = ps.turnstileSecretKey; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.sensitiveMediaDetection !== undefined) { | ||||
| 				set.sensitiveMediaDetection = ps.sensitiveMediaDetection; | ||||
| 			} | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { NotesRepository, AntennaNotesRepository } from '@/models/index.js'; | ||||
| import type { NotesRepository, AntennaNotesRepository, AntennasRepository } from '@/models/index.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { NoteReadService } from '@/core/NoteReadService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; | |||
| import { UserBlockingService } from '@/core/UserBlockingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['account'], | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; | |||
| import { UserBlockingService } from '@/core/UserBlockingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['account'], | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 		private globalEventService: GlobalEventService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps, me) => { | ||||
| 			const channel = await Channels.findOneBy({ | ||||
| 			const channel = await this.channelsRepository.findOneBy({ | ||||
| 				id: ps.channelId, | ||||
| 			}); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import { IdService } from '@/core/IdService.js'; | |||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['account', 'notes', 'clips'], | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['account', 'notes', 'clips'], | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { ApPersonService } from '@/core/remote/activitypub/models/ApPersonService.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['federation'], | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; | |||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['following', 'users'], | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; | |||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['following', 'users'], | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; | |||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['following', 'users'], | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { FollowingsRepository } from '@/models/index.js'; | ||||
| import type { UsersRepository } from '@/models/index.js'; | ||||
| import type { FollowingsRepository, UsersRepository } from '@/models/index.js'; | ||||
| import { IdentifiableError } from '@/misc/identifiable-error.js'; | ||||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { UserFollowingService } from '@/core/UserFollowingService.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { IsNull, Not } from 'typeorm'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { AccessTokensRepository } from '@/models/index.js'; | ||||
| import { AppEntityService } from '@/core/entities/AppEntityService.js'; | ||||
|  | @ -34,6 +35,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 			const tokens = await this.accessTokensRepository.find({ | ||||
| 				where: { | ||||
| 					userId: me.id, | ||||
| 					appId: Not(IsNull()), | ||||
| 				}, | ||||
| 				take: ps.limit, | ||||
| 				skip: ps.offset, | ||||
|  | @ -42,7 +44,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 				}, | ||||
| 			}); | ||||
| 
 | ||||
| 			return await Promise.all(tokens.map(token => this.appEntityService.pack(token.appId, me, { | ||||
| 			return await Promise.all(tokens.map(token => this.appEntityService.pack(token.appId!, me, { | ||||
| 				detail: true, | ||||
| 			}))); | ||||
| 		}); | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ export const paramDef = { | |||
| 		description: { ...descriptionSchema, nullable: true }, | ||||
| 		location: { ...locationSchema, nullable: true }, | ||||
| 		birthday: { ...birthdaySchema, nullable: true }, | ||||
| 		lang: { type: 'string', enum: [null, ...Object.keys(langmap)], nullable: true }, | ||||
| 		lang: { type: 'string', enum: [null, ...Object.keys(langmap)] as string[], nullable: true }, | ||||
| 		avatarId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		bannerId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		fields: { | ||||
|  | @ -109,9 +109,7 @@ export const paramDef = { | |||
| 		alwaysMarkNsfw: { type: 'boolean' }, | ||||
| 		autoSensitive: { type: 'boolean' }, | ||||
| 		ffVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, | ||||
| 		pinnedPageId: { type: 'array', items: { | ||||
| 			type: 'string', format: 'misskey:id', | ||||
| 		} }, | ||||
| 		pinnedPageId: { type: 'string', format: 'misskey:id' }, | ||||
| 		mutedWords: { type: 'array' }, | ||||
| 		mutedInstances: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
|  | @ -266,7 +264,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 
 | ||||
| 			// Publish meUpdated event
 | ||||
| 			this.globalEventService.publishMainStream(user.id, 'meUpdated', iObj); | ||||
| 			this.globalEventService.publishUserEvent(user.id, 'updateUserProfile', await this.userProfilesRepository.findOneBy({ userId: user.id })); | ||||
| 			this.globalEventService.publishUserEvent(user.id, 'updateUserProfile', await this.userProfilesRepository.findOneByOrFail({ userId: user.id })); | ||||
| 
 | ||||
| 			// 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認
 | ||||
| 			if (user.isLocked && ps.isLocked === false) { | ||||
|  |  | |||
|  | @ -1,15 +1,14 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Brackets } from 'typeorm'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import type { UsersRepository } from '@/models/index.js'; | ||||
| import type { UserGroupsRepository, MessagingMessagesRepository, UserGroupJoiningsRepository } from '@/models/index.js'; | ||||
| import type { UsersRepository, UserGroupsRepository, MessagingMessagesRepository, UserGroupJoiningsRepository } from '@/models/index.js'; | ||||
| import { QueryService } from '@/core/QueryService.js'; | ||||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| import { MessagingMessageEntityService } from '@/core/entities/MessagingMessageEntityService.js'; | ||||
| import { MessagingService } from '@/core/MessagingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['messaging'], | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import type { BlockingsRepository, UserGroupJoiningsRepository, DriveFilesRepository, UserGroupsRepository } from '@/models/index.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { UserGroup } from '@/models/entities/UserGroup.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { MessagingService } from '@/core/MessagingService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
|  |  | |||
|  | @ -119,6 +119,14 @@ export const meta = { | |||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			enableTurnstile: { | ||||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			turnstileSiteKey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			swPublickey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
|  | @ -372,6 +380,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 				hcaptchaSiteKey: instance.hcaptchaSiteKey, | ||||
| 				enableRecaptcha: instance.enableRecaptcha, | ||||
| 				recaptchaSiteKey: instance.recaptchaSiteKey, | ||||
| 				enableTurnstile: instance.enableTurnstile, | ||||
| 				turnstileSiteKey: instance.turnstileSiteKey, | ||||
| 				swPublickey: instance.swPublicKey, | ||||
| 				themeColor: instance.themeColor, | ||||
| 				mascotImageUrl: instance.mascotImageUrl, | ||||
|  | @ -423,6 +433,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | |||
| 					elasticsearch: this.config.elasticsearch ? true : false, | ||||
| 					hcaptcha: instance.enableHcaptcha, | ||||
| 					recaptcha: instance.enableRecaptcha, | ||||
| 					turnstile: instance.enableTurnstile, | ||||
| 					objectStorage: instance.useObjectStorage, | ||||
| 					twitter: instance.enableTwitterIntegration, | ||||
| 					github: instance.enableGithubIntegration, | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import type { Muting } from '@/models/entities/Muting.js'; | |||
| import { GlobalEventService } from '@/core/GlobalEventService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['account'], | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import type { MutingsRepository } from '@/models/index.js'; | |||
| import { GlobalEventService } from '@/core/GlobalEventService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['account'], | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['clips', 'notes'], | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import { NoteDeleteService } from '@/core/NoteDeleteService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; | |||
| import type { NoteFavoritesRepository } from '@/models/index.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { NoteFavoritesRepository } from '@/models/index.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import type { UsersRepository, BlockingsRepository, PollsRepository, PollVotesRe | |||
| import type { IRemoteUser } from '@/models/entities/User.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { QueueService } from '@/core/QueueService.js'; | ||||
| import { PollService } from '@/core/PollService.js'; | ||||
| import { ApRendererService } from '@/core/remote/activitypub/ApRendererService.js'; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { ReactionService } from '@/core/ReactionService.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import ms from 'ms'; | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { ReactionService } from '@/core/ReactionService.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import { QueryService } from '@/core/QueryService.js'; | |||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -16,10 +16,6 @@ export const meta = { | |||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			isWatching: { | ||||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			isMutedThread: { | ||||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; | |||
| import type { NotesRepository, NoteThreadMutingsRepository } from '@/models/index.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { NoteReadService } from '@/core/NoteReadService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { NoteThreadMutingsRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | |||
| import { MetaService } from '@/core/MetaService.js'; | ||||
| import { HttpRequestService } from '@/core/HttpRequestService.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import { NoteDeleteService } from '@/core/NoteDeleteService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import { IdService } from '@/core/IdService.js'; | |||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { IsNull } from 'typeorm'; | ||||
| import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js'; | ||||
| import type { InstancesRepository, NoteReactionsRepository, NotesRepository, UsersRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; | |||
| import { UserEntityService } from '@/core/entities/UserEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../error.js'; | ||||
| import { GetterService } from '../../common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['users'], | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import type { UserGroupsRepository, UserGroupJoiningsRepository, UserGroupInvita | |||
| import { IdService } from '@/core/IdService.js'; | ||||
| import type { UserGroupInvitation } from '@/models/entities/UserGroupInvitation.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { CreateNotificationService } from '@/core/CreateNotificationService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import type { UserGroupsRepository, UserGroupJoiningsRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; | |||
| import type { UserGroupsRepository, UserGroupJoiningsRepository } from '@/models/index.js'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { UserGroupEntityService } from '@/core/entities/UserGroupEntityService.js'; | ||||
| import { GetterService } from '@/server/api/common/GetterService.js'; | ||||
| import { GetterService } from '@/server/api/GetterService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { ApiError } from '../../../error.js'; | ||||
| 
 | ||||
|  |  | |||
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