refactor: fix types

This commit is contained in:
syuilo 2023-02-13 15:28:07 +09:00
parent a71682f6f0
commit f34f9f6ea5
19 changed files with 95 additions and 102 deletions

View file

@ -5,7 +5,7 @@ import type { Config } from '@/config.js';
import type { DriveFile } from '@/models/entities/DriveFile.js'; import type { DriveFile } from '@/models/entities/DriveFile.js';
import type { MessagingMessage } from '@/models/entities/MessagingMessage.js'; import type { MessagingMessage } from '@/models/entities/MessagingMessage.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import type { User, CacheableUser, IRemoteUser } from '@/models/entities/User.js'; import type { User, IRemoteUser } from '@/models/entities/User.js';
import type { UserGroup } from '@/models/entities/UserGroup.js'; import type { UserGroup } from '@/models/entities/UserGroup.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import { toArray } from '@/misc/prelude/array.js'; import { toArray } from '@/misc/prelude/array.js';
@ -48,7 +48,7 @@ export class MessagingService {
} }
@bindThis @bindThis
public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: CacheableUser | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) { public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: User | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) {
const message = { const message = {
id: this.idService.genId(), id: this.idService.genId(),
createdAt: new Date(), createdAt: new Date(),

View file

@ -1,10 +1,9 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { Not } from 'typeorm'; import { Not } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js'; import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository, User } from '@/models/index.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import { RelayService } from '@/core/RelayService.js'; import { RelayService } from '@/core/RelayService.js';
import type { CacheableUser } from '@/models/entities/User.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
@ -39,7 +38,7 @@ export class PollService {
} }
@bindThis @bindThis
public async vote(user: CacheableUser, note: Note, choice: number) { public async vote(user: User, note: Note, choice: number) {
const poll = await this.pollsRepository.findOneBy({ noteId: note.id }); const poll = await this.pollsRepository.findOneBy({ noteId: note.id });
if (poll == null) throw new Error('poll not found'); if (poll == null) throw new Error('poll not found');

View file

@ -3,7 +3,7 @@ import Redis from 'ioredis';
import { In } from 'typeorm'; import { In } from 'typeorm';
import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';

View file

@ -2,7 +2,7 @@
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { CacheableUser, User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import type { Blocking } from '@/models/entities/Blocking.js'; import type { Blocking } from '@/models/entities/Blocking.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
@ -236,7 +236,7 @@ export class UserBlockingService implements OnApplicationShutdown {
} }
@bindThis @bindThis
public async unblock(blocker: CacheableUser, blockee: CacheableUser) { public async unblock(blocker: User, blockee: User) {
const blocking = await this.blockingsRepository.findOneBy({ const blocking = await this.blockingsRepository.findOneBy({
blockerId: blocker.id, blockerId: blocker.id,
blockeeId: blockee.id, blockeeId: blockee.id,

View file

@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import type { UsersRepository } from '@/models/index.js'; import type { UsersRepository } from '@/models/index.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js'; import type { ILocalUser, User } from '@/models/entities/User.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@ -11,10 +11,10 @@ import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable() @Injectable()
export class UserCacheService implements OnApplicationShutdown { export class UserCacheService implements OnApplicationShutdown {
public userByIdCache: Cache<CacheableUser>; public userByIdCache: Cache<User>;
public localUserByNativeTokenCache: Cache<CacheableLocalUser | null>; public localUserByNativeTokenCache: Cache<ILocalUser | null>;
public localUserByIdCache: Cache<CacheableLocalUser>; public localUserByIdCache: Cache<ILocalUser>;
public uriPersonCache: Cache<CacheableUser | null>; public uriPersonCache: Cache<User | null>;
constructor( constructor(
@Inject(DI.redisSubscriber) @Inject(DI.redisSubscriber)
@ -27,10 +27,10 @@ export class UserCacheService implements OnApplicationShutdown {
) { ) {
//this.onMessage = this.onMessage.bind(this); //this.onMessage = this.onMessage.bind(this);
this.userByIdCache = new Cache<CacheableUser>(Infinity); this.userByIdCache = new Cache<User>(Infinity);
this.localUserByNativeTokenCache = new Cache<CacheableLocalUser | null>(Infinity); this.localUserByNativeTokenCache = new Cache<ILocalUser | null>(Infinity);
this.localUserByIdCache = new Cache<CacheableLocalUser>(Infinity); this.localUserByIdCache = new Cache<ILocalUser>(Infinity);
this.uriPersonCache = new Cache<CacheableUser | null>(Infinity); this.uriPersonCache = new Cache<User | null>(Infinity);
this.redisSubscriber.on('message', this.onMessage); this.redisSubscriber.on('message', this.onMessage);
} }
@ -45,10 +45,10 @@ export class UserCacheService implements OnApplicationShutdown {
case 'userChangeSuspendedState': case 'userChangeSuspendedState':
case 'remoteUserUpdated': { case 'remoteUserUpdated': {
const user = await this.usersRepository.findOneByOrFail({ id: body.id }); const user = await this.usersRepository.findOneByOrFail({ id: body.id });
this.userByIdCache.set(user.id, user as CacheableUser); this.userByIdCache.set(user.id, user);
for (const [k, v] of this.uriPersonCache.cache.entries()) { for (const [k, v] of this.uriPersonCache.cache.entries()) {
if (v.value?.id === user.id) { if (v.value?.id === user.id) {
this.uriPersonCache.set(k, user as CacheableUser); this.uriPersonCache.set(k, user);
} }
} }
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
@ -78,7 +78,7 @@ export class UserCacheService implements OnApplicationShutdown {
@bindThis @bindThis
public findById(userId: User['id']) { public findById(userId: User['id']) {
return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }) as Promise<CacheableUser>); return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }));
} }
@bindThis @bindThis

View file

@ -1,5 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import type { CacheableUser, ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
@ -434,7 +434,7 @@ export class UserFollowingService {
followee: { followee: {
id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox'];
}, },
follower: User | CacheableUser, follower: User,
): Promise<void> { ): Promise<void> {
const request = await this.followRequestsRepository.findOneBy({ const request = await this.followRequestsRepository.findOneBy({
followeeId: followee.id, followeeId: followee.id,

View file

@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import promiseLimit from 'promise-limit'; import promiseLimit from 'promise-limit';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js'; import type { IRemoteUser, User } from '@/models/entities/User.js';
import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
@ -14,8 +14,8 @@ type Visibility = 'public' | 'home' | 'followers' | 'specified';
type AudienceInfo = { type AudienceInfo = {
visibility: Visibility, visibility: Visibility,
mentionedUsers: CacheableUser[], mentionedUsers: User[],
visibleUsers: CacheableUser[], visibleUsers: User[],
}; };
@Injectable() @Injectable()
@ -26,16 +26,16 @@ export class ApAudienceService {
} }
@bindThis @bindThis
public async parseAudience(actor: CacheableRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise<AudienceInfo> { public async parseAudience(actor: IRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise<AudienceInfo> {
const toGroups = this.groupingAudience(getApIds(to), actor); const toGroups = this.groupingAudience(getApIds(to), actor);
const ccGroups = this.groupingAudience(getApIds(cc), actor); const ccGroups = this.groupingAudience(getApIds(cc), actor);
const others = unique(concat([toGroups.other, ccGroups.other])); const others = unique(concat([toGroups.other, ccGroups.other]));
const limit = promiseLimit<CacheableUser | null>(2); const limit = promiseLimit<User | null>(2);
const mentionedUsers = (await Promise.all( const mentionedUsers = (await Promise.all(
others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))), others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))),
)).filter((x): x is CacheableUser => x != null); )).filter((x): x is User => x != null);
if (toGroups.public.length > 0) { if (toGroups.public.length > 0) {
return { return {
@ -69,7 +69,7 @@ export class ApAudienceService {
} }
@bindThis @bindThis
private groupingAudience(ids: string[], actor: CacheableRemoteUser) { private groupingAudience(ids: string[], actor: IRemoteUser) {
const groups = { const groups = {
public: [] as string[], public: [] as string[],
followers: [] as string[], followers: [] as string[],
@ -101,7 +101,7 @@ export class ApAudienceService {
} }
@bindThis @bindThis
private isFollowers(id: string, actor: CacheableRemoteUser) { private isFollowers(id: string, actor: IRemoteUser) {
return ( return (
id === (actor.followersUri ?? `${actor.uri}/followers`) id === (actor.followersUri ?? `${actor.uri}/followers`)
); );

View file

@ -3,13 +3,13 @@ import escapeRegexp from 'escape-regexp';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { MessagingMessagesRepository, NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; import type { MessagingMessagesRepository, NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import type { UserPublickey } from '@/models/entities/UserPublickey.js'; import type { UserPublickey } from '@/models/entities/UserPublickey.js';
import { UserCacheService } from '@/core/UserCacheService.js'; import { UserCacheService } from '@/core/UserCacheService.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import type { MessagingMessage } from '@/models/entities/MessagingMessage.js'; import type { MessagingMessage } from '@/models/entities/MessagingMessage.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { IRemoteUser, User } from '@/models/entities/User.js';
import { getApId } from './type.js'; import { getApId } from './type.js';
import { ApPersonService } from './models/ApPersonService.js'; import { ApPersonService } from './models/ApPersonService.js';
import type { IObject } from './type.js'; import type { IObject } from './type.js';
@ -122,7 +122,7 @@ export class ApDbResolverService {
* AP Person => Misskey User in DB * AP Person => Misskey User in DB
*/ */
@bindThis @bindThis
public async getUserFromApId(value: string | IObject): Promise<CacheableUser | null> { public async getUserFromApId(value: string | IObject): Promise<User | null> {
const parsed = this.parseUri(value); const parsed = this.parseUri(value);
if (parsed.local) { if (parsed.local) {
@ -130,11 +130,11 @@ export class ApDbResolverService {
return await this.userCacheService.userByIdCache.fetchMaybe(parsed.id, () => this.usersRepository.findOneBy({ return await this.userCacheService.userByIdCache.fetchMaybe(parsed.id, () => this.usersRepository.findOneBy({
id: parsed.id, id: parsed.id,
}).then(x => (x as CacheableUser | null) ?? undefined)) ?? null; }).then(x => x ?? undefined)) ?? null;
} else { } else {
return await this.userCacheService.uriPersonCache.fetch(parsed.uri, () => this.usersRepository.findOneBy({ return await this.userCacheService.uriPersonCache.fetch(parsed.uri, () => this.usersRepository.findOneBy({
uri: parsed.uri, uri: parsed.uri,
}) as Promise<CacheableUser | null>); }));
} }
} }
@ -143,7 +143,7 @@ export class ApDbResolverService {
*/ */
@bindThis @bindThis
public async getAuthUserFromKeyId(keyId: string): Promise<{ public async getAuthUserFromKeyId(keyId: string): Promise<{
user: CacheableRemoteUser; user: IRemoteUser;
key: UserPublickey; key: UserPublickey;
} | null> { } | null> {
const key = await this.publicKeyCache.fetch(keyId, async () => { const key = await this.publicKeyCache.fetch(keyId, async () => {
@ -159,7 +159,7 @@ export class ApDbResolverService {
if (key == null) return null; if (key == null) return null;
return { return {
user: await this.userCacheService.findById(key.userId) as CacheableRemoteUser, user: await this.userCacheService.findById(key.userId) as IRemoteUser,
key, key,
}; };
} }
@ -169,10 +169,10 @@ export class ApDbResolverService {
*/ */
@bindThis @bindThis
public async getAuthUserFromApId(uri: string): Promise<{ public async getAuthUserFromApId(uri: string): Promise<{
user: CacheableRemoteUser; user: IRemoteUser;
key: UserPublickey | null; key: UserPublickey | null;
} | null> { } | null> {
const user = await this.apPersonService.resolvePerson(uri) as CacheableRemoteUser; const user = await this.apPersonService.resolvePerson(uri) as IRemoteUser;
if (user == null) return null; if (user == null) return null;

View file

@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js';
import { UserFollowingService } from '@/core/UserFollowingService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js';
import { ReactionService } from '@/core/ReactionService.js'; import { ReactionService } from '@/core/ReactionService.js';
import { RelayService } from '@/core/RelayService.js'; import { RelayService } from '@/core/RelayService.js';
@ -23,6 +22,7 @@ import { QueueService } from '@/core/QueueService.js';
import { MessagingService } from '@/core/MessagingService.js'; import { MessagingService } from '@/core/MessagingService.js';
import type { UsersRepository, NotesRepository, FollowingsRepository, MessagingMessagesRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, MessagingMessagesRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import type { IRemoteUser } from '@/models/entities/User.js';
import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
import { ApNoteService } from './models/ApNoteService.js'; import { ApNoteService } from './models/ApNoteService.js';
import { ApLoggerService } from './ApLoggerService.js'; import { ApLoggerService } from './ApLoggerService.js';
@ -87,7 +87,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
public async performActivity(actor: CacheableRemoteUser, activity: IObject) { public async performActivity(actor: IRemoteUser, activity: IObject) {
if (isCollectionOrOrderedCollection(activity)) { if (isCollectionOrOrderedCollection(activity)) {
const resolver = this.apResolverService.createResolver(); const resolver = this.apResolverService.createResolver();
for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) { for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) {
@ -115,7 +115,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
public async performOneActivity(actor: CacheableRemoteUser, activity: IObject): Promise<void> { public async performOneActivity(actor: IRemoteUser, activity: IObject): Promise<void> {
if (actor.isSuspended) return; if (actor.isSuspended) return;
if (isCreate(activity)) { if (isCreate(activity)) {
@ -152,7 +152,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async follow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> { private async follow(actor: IRemoteUser, activity: IFollow): Promise<string> {
const followee = await this.apDbResolverService.getUserFromApId(activity.object); const followee = await this.apDbResolverService.getUserFromApId(activity.object);
if (followee == null) { if (followee == null) {
@ -168,7 +168,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async like(actor: CacheableRemoteUser, activity: ILike): Promise<string> { private async like(actor: IRemoteUser, activity: ILike): Promise<string> {
const targetUri = getApId(activity.object); const targetUri = getApId(activity.object);
const note = await this.apNoteService.fetchNote(targetUri); const note = await this.apNoteService.fetchNote(targetUri);
@ -186,7 +186,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async read(actor: CacheableRemoteUser, activity: IRead): Promise<string> { private async read(actor: IRemoteUser, activity: IRead): Promise<string> {
const id = await getApId(activity.object); const id = await getApId(activity.object);
if (!this.utilityService.isSelfHost(this.utilityService.extractDbHost(id))) { if (!this.utilityService.isSelfHost(this.utilityService.extractDbHost(id))) {
@ -209,7 +209,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async accept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> { private async accept(actor: IRemoteUser, activity: IAccept): Promise<string> {
const uri = activity.id ?? activity; const uri = activity.id ?? activity;
this.logger.info(`Accept: ${uri}`); this.logger.info(`Accept: ${uri}`);
@ -227,7 +227,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async acceptFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> { private async acceptFollow(actor: IRemoteUser, activity: IFollow): Promise<string> {
// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
const follower = await this.apDbResolverService.getUserFromApId(activity.actor); const follower = await this.apDbResolverService.getUserFromApId(activity.actor);
@ -251,7 +251,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async add(actor: CacheableRemoteUser, activity: IAdd): Promise<void> { private async add(actor: IRemoteUser, activity: IAdd): Promise<void> {
if ('actor' in activity && actor.uri !== activity.actor) { if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor'); throw new Error('invalid actor');
} }
@ -271,7 +271,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async announce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<void> { private async announce(actor: IRemoteUser, activity: IAnnounce): Promise<void> {
const uri = getApId(activity); const uri = getApId(activity);
this.logger.info(`Announce: ${uri}`); this.logger.info(`Announce: ${uri}`);
@ -282,7 +282,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async announceNote(actor: CacheableRemoteUser, activity: IAnnounce, targetUri: string): Promise<void> { private async announceNote(actor: IRemoteUser, activity: IAnnounce, targetUri: string): Promise<void> {
const uri = getApId(activity); const uri = getApId(activity);
if (actor.isSuspended) { if (actor.isSuspended) {
@ -342,7 +342,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async block(actor: CacheableRemoteUser, activity: IBlock): Promise<string> { private async block(actor: IRemoteUser, activity: IBlock): Promise<string> {
// ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず // ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず
const blockee = await this.apDbResolverService.getUserFromApId(activity.object); const blockee = await this.apDbResolverService.getUserFromApId(activity.object);
@ -360,7 +360,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async create(actor: CacheableRemoteUser, activity: ICreate): Promise<void> { private async create(actor: IRemoteUser, activity: ICreate): Promise<void> {
const uri = getApId(activity); const uri = getApId(activity);
this.logger.info(`Create: ${uri}`); this.logger.info(`Create: ${uri}`);
@ -396,7 +396,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async createNote(resolver: Resolver, actor: CacheableRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise<string> { private async createNote(resolver: Resolver, actor: IRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise<string> {
const uri = getApId(note); const uri = getApId(note);
if (typeof note === 'object') { if (typeof note === 'object') {
@ -431,7 +431,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async delete(actor: CacheableRemoteUser, activity: IDelete): Promise<string> { private async delete(actor: IRemoteUser, activity: IDelete): Promise<string> {
if ('actor' in activity && actor.uri !== activity.actor) { if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor'); throw new Error('invalid actor');
} }
@ -473,7 +473,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async deleteActor(actor: CacheableRemoteUser, uri: string): Promise<string> { private async deleteActor(actor: IRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Actor: ${uri}`); this.logger.info(`Deleting the Actor: ${uri}`);
if (actor.uri !== uri) { if (actor.uri !== uri) {
@ -495,7 +495,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async deleteNote(actor: CacheableRemoteUser, uri: string): Promise<string> { private async deleteNote(actor: IRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Note: ${uri}`); this.logger.info(`Deleting the Note: ${uri}`);
const unlock = await this.appLockService.getApLock(uri); const unlock = await this.appLockService.getApLock(uri);
@ -528,7 +528,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async flag(actor: CacheableRemoteUser, activity: IFlag): Promise<string> { private async flag(actor: IRemoteUser, activity: IFlag): Promise<string> {
// objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので
// 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する // 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する
const uris = getApIds(activity.object); const uris = getApIds(activity.object);
@ -553,7 +553,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async reject(actor: CacheableRemoteUser, activity: IReject): Promise<string> { private async reject(actor: IRemoteUser, activity: IReject): Promise<string> {
const uri = activity.id ?? activity; const uri = activity.id ?? activity;
this.logger.info(`Reject: ${uri}`); this.logger.info(`Reject: ${uri}`);
@ -571,7 +571,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async rejectFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> { private async rejectFollow(actor: IRemoteUser, activity: IFollow): Promise<string> {
// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
const follower = await this.apDbResolverService.getUserFromApId(activity.actor); const follower = await this.apDbResolverService.getUserFromApId(activity.actor);
@ -595,7 +595,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async remove(actor: CacheableRemoteUser, activity: IRemove): Promise<void> { private async remove(actor: IRemoteUser, activity: IRemove): Promise<void> {
if ('actor' in activity && actor.uri !== activity.actor) { if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor'); throw new Error('invalid actor');
} }
@ -615,7 +615,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async undo(actor: CacheableRemoteUser, activity: IUndo): Promise<string> { private async undo(actor: IRemoteUser, activity: IUndo): Promise<string> {
if ('actor' in activity && actor.uri !== activity.actor) { if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor'); throw new Error('invalid actor');
} }
@ -641,7 +641,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async undoAccept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> { private async undoAccept(actor: IRemoteUser, activity: IAccept): Promise<string> {
const follower = await this.apDbResolverService.getUserFromApId(activity.object); const follower = await this.apDbResolverService.getUserFromApId(activity.object);
if (follower == null) { if (follower == null) {
return 'skip: follower not found'; return 'skip: follower not found';
@ -661,7 +661,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async undoAnnounce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<string> { private async undoAnnounce(actor: IRemoteUser, activity: IAnnounce): Promise<string> {
const uri = getApId(activity); const uri = getApId(activity);
const note = await this.notesRepository.findOneBy({ const note = await this.notesRepository.findOneBy({
@ -676,7 +676,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async undoBlock(actor: CacheableRemoteUser, activity: IBlock): Promise<string> { private async undoBlock(actor: IRemoteUser, activity: IBlock): Promise<string> {
const blockee = await this.apDbResolverService.getUserFromApId(activity.object); const blockee = await this.apDbResolverService.getUserFromApId(activity.object);
if (blockee == null) { if (blockee == null) {
@ -687,12 +687,12 @@ export class ApInboxService {
return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません'; return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません';
} }
await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }) as CacheableUser, blockee); await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }), blockee);
return 'ok'; return 'ok';
} }
@bindThis @bindThis
private async undoFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> { private async undoFollow(actor: IRemoteUser, activity: IFollow): Promise<string> {
const followee = await this.apDbResolverService.getUserFromApId(activity.object); const followee = await this.apDbResolverService.getUserFromApId(activity.object);
if (followee == null) { if (followee == null) {
return 'skip: followee not found'; return 'skip: followee not found';
@ -726,7 +726,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async undoLike(actor: CacheableRemoteUser, activity: ILike): Promise<string> { private async undoLike(actor: IRemoteUser, activity: ILike): Promise<string> {
const targetUri = getApId(activity.object); const targetUri = getApId(activity.object);
const note = await this.apNoteService.fetchNote(targetUri); const note = await this.apNoteService.fetchNote(targetUri);
@ -741,7 +741,7 @@ export class ApInboxService {
} }
@bindThis @bindThis
private async update(actor: CacheableRemoteUser, activity: IUpdate): Promise<string> { private async update(actor: IRemoteUser, activity: IUpdate): Promise<string> {
if ('actor' in activity && actor.uri !== activity.actor) { if ('actor' in activity && actor.uri !== activity.actor) {
return 'skip: invalid actor'; return 'skip: invalid actor';
} }

View file

@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { DriveFilesRepository } from '@/models/index.js'; import type { DriveFilesRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { CacheableRemoteUser } from '@/models/entities/User.js'; import type { IRemoteUser } from '@/models/entities/User.js';
import type { DriveFile } from '@/models/entities/DriveFile.js'; import type { DriveFile } from '@/models/entities/DriveFile.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { truncate } from '@/misc/truncate.js'; import { truncate } from '@/misc/truncate.js';
@ -36,7 +36,7 @@ export class ApImageService {
* Imageを作成します * Imageを作成します
*/ */
@bindThis @bindThis
public async createImage(actor: CacheableRemoteUser, value: any): Promise<DriveFile> { public async createImage(actor: IRemoteUser, value: any): Promise<DriveFile> {
// 投稿者が凍結されていたらスキップ // 投稿者が凍結されていたらスキップ
if (actor.isSuspended) { if (actor.isSuspended) {
throw new Error('actor has been suspended'); throw new Error('actor has been suspended');
@ -88,7 +88,7 @@ export class ApImageService {
* Misskeyに登録しそれを返します * Misskeyに登録しそれを返します
*/ */
@bindThis @bindThis
public async resolveImage(actor: CacheableRemoteUser, value: any): Promise<DriveFile> { public async resolveImage(actor: IRemoteUser, value: any): Promise<DriveFile> {
// TODO // TODO
// リモートサーバーからフェッチしてきて登録 // リモートサーバーからフェッチしてきて登録

View file

@ -1,15 +1,14 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import promiseLimit from 'promise-limit'; import promiseLimit from 'promise-limit';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { UsersRepository } from '@/models/index.js'; import type { User, UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { toArray, unique } from '@/misc/prelude/array.js'; import { toArray, unique } from '@/misc/prelude/array.js';
import type { CacheableUser } from '@/models/entities/User.js'; import { bindThis } from '@/decorators.js';
import { isMention } from '../type.js'; import { isMention } from '../type.js';
import { ApResolverService, Resolver } from '../ApResolverService.js'; import { ApResolverService, Resolver } from '../ApResolverService.js';
import { ApPersonService } from './ApPersonService.js'; import { ApPersonService } from './ApPersonService.js';
import type { IObject, IApMention } from '../type.js'; import type { IObject, IApMention } from '../type.js';
import { bindThis } from '@/decorators.js';
@Injectable() @Injectable()
export class ApMentionService { export class ApMentionService {
@ -26,10 +25,10 @@ export class ApMentionService {
public async extractApMentions(tags: IObject | IObject[] | null | undefined, resolver: Resolver) { public async extractApMentions(tags: IObject | IObject[] | null | undefined, resolver: Resolver) {
const hrefs = unique(this.extractApMentionObjects(tags).map(x => x.href as string)); const hrefs = unique(this.extractApMentionObjects(tags).map(x => x.href as string));
const limit = promiseLimit<CacheableUser | null>(2); const limit = promiseLimit<User | null>(2);
const mentionedUsers = (await Promise.all( const mentionedUsers = (await Promise.all(
hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))), hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))),
)).filter((x): x is CacheableUser => x != null); )).filter((x): x is User => x != null);
return mentionedUsers; return mentionedUsers;
} }

View file

@ -3,7 +3,7 @@ import promiseLimit from 'promise-limit';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { MessagingMessagesRepository, PollsRepository, EmojisRepository, UsersRepository } from '@/models/index.js'; import type { MessagingMessagesRepository, PollsRepository, EmojisRepository, UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { CacheableRemoteUser } from '@/models/entities/User.js'; import type { IRemoteUser } from '@/models/entities/User.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js';
import type { Emoji } from '@/models/entities/Emoji.js'; import type { Emoji } from '@/models/entities/Emoji.js';
@ -146,7 +146,7 @@ export class ApNoteService {
this.logger.info(`Creating the Note: ${note.id}`); this.logger.info(`Creating the Note: ${note.id}`);
// 投稿者をフェッチ // 投稿者をフェッチ
const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as CacheableRemoteUser; const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as IRemoteUser;
// 投稿者が凍結されていたらスキップ // 投稿者が凍結されていたらスキップ
if (actor.isSuspended) { if (actor.isSuspended) {

View file

@ -5,7 +5,7 @@ import { ModuleRef } from '@nestjs/core';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { CacheableUser, IRemoteUser } from '@/models/entities/User.js'; import type { IRemoteUser } from '@/models/entities/User.js';
import { User } from '@/models/entities/User.js'; import { User } from '@/models/entities/User.js';
import { truncate } from '@/misc/truncate.js'; import { truncate } from '@/misc/truncate.js';
import type { UserCacheService } from '@/core/UserCacheService.js'; import type { UserCacheService } from '@/core/UserCacheService.js';
@ -197,7 +197,7 @@ export class ApPersonService implements OnModuleInit {
* Misskeyに対象のPersonが登録されていればそれを返します * Misskeyに対象のPersonが登録されていればそれを返します
*/ */
@bindThis @bindThis
public async fetchPerson(uri: string, resolver?: Resolver): Promise<CacheableUser | null> { public async fetchPerson(uri: string, resolver?: Resolver): Promise<User | null> {
if (typeof uri !== 'string') throw new Error('uri is not string'); if (typeof uri !== 'string') throw new Error('uri is not string');
const cached = this.userCacheService.uriPersonCache.get(uri); const cached = this.userCacheService.uriPersonCache.get(uri);
@ -206,13 +206,13 @@ export class ApPersonService implements OnModuleInit {
// URIがこのサーバーを指しているならデータベースからフェッチ // URIがこのサーバーを指しているならデータベースからフェッチ
if (uri.startsWith(this.config.url + '/')) { if (uri.startsWith(this.config.url + '/')) {
const id = uri.split('/').pop(); const id = uri.split('/').pop();
const u = await this.usersRepository.findOneBy({ id }) as null | CacheableUser; const u = await this.usersRepository.findOneBy({ id });
if (u) this.userCacheService.uriPersonCache.set(uri, u); if (u) this.userCacheService.uriPersonCache.set(uri, u);
return u; return u;
} }
//#region このサーバーに既に登録されていたらそれを返す //#region このサーバーに既に登録されていたらそれを返す
const exist = await this.usersRepository.findOneBy({ uri }) as null | CacheableUser; const exist = await this.usersRepository.findOneBy({ uri });
if (exist) { if (exist) {
this.userCacheService.uriPersonCache.set(uri, exist); this.userCacheService.uriPersonCache.set(uri, exist);
@ -500,7 +500,7 @@ export class ApPersonService implements OnModuleInit {
* Misskeyに登録しそれを返します * Misskeyに登録しそれを返します
*/ */
@bindThis @bindThis
public async resolvePerson(uri: string, resolver?: Resolver): Promise<CacheableUser> { public async resolvePerson(uri: string, resolver?: Resolver): Promise<User> {
if (typeof uri !== 'string') throw new Error('uri is not string'); if (typeof uri !== 'string') throw new Error('uri is not string');
//#region このサーバーに既に登録されていたらそれを返す //#region このサーバーに既に登録されていたらそれを返す
@ -513,7 +513,7 @@ export class ApPersonService implements OnModuleInit {
// リモートサーバーからフェッチしてきて登録 // リモートサーバーからフェッチしてきて登録
if (resolver == null) resolver = this.apResolverService.createResolver(); if (resolver == null) resolver = this.apResolverService.createResolver();
return await this.createPerson(uri, resolver) as CacheableUser; return await this.createPerson(uri, resolver);
} }
@bindThis @bindThis

View file

@ -217,6 +217,7 @@ export class User {
export interface ILocalUser extends User { export interface ILocalUser extends User {
host: null; host: null;
uri: null;
} }
export interface IRemoteUser extends User { export interface IRemoteUser extends User {
@ -224,12 +225,6 @@ export interface IRemoteUser extends User {
uri: string; uri: string;
} }
export type CacheableLocalUser = ILocalUser;
export type CacheableRemoteUser = IRemoteUser;
export type CacheableUser = CacheableLocalUser | CacheableRemoteUser;
export const localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const; export const localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const;
export const passwordSchema = { type: 'string', minLength: 1 } as const; export const passwordSchema = { type: 'string', minLength: 1 } as const;
export const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; export const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const;

View file

@ -16,7 +16,7 @@ import InstanceChart from '@/core/chart/charts/instance.js';
import ApRequestChart from '@/core/chart/charts/ap-request.js'; import ApRequestChart from '@/core/chart/charts/ap-request.js';
import FederationChart from '@/core/chart/charts/federation.js'; import FederationChart from '@/core/chart/charts/federation.js';
import { getApId } from '@/core/activitypub/type.js'; import { getApId } from '@/core/activitypub/type.js';
import type { CacheableRemoteUser } from '@/models/entities/User.js'; import type { IRemoteUser } from '@/models/entities/User.js';
import type { UserPublickey } from '@/models/entities/UserPublickey.js'; import type { UserPublickey } from '@/models/entities/UserPublickey.js';
import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js'; import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js';
import { StatusError } from '@/misc/status-error.js'; import { StatusError } from '@/misc/status-error.js';
@ -87,7 +87,7 @@ export class InboxProcessorService {
// HTTP-Signature keyIdを元にDBから取得 // HTTP-Signature keyIdを元にDBから取得
let authUser: { let authUser: {
user: CacheableRemoteUser; user: IRemoteUser;
key: UserPublickey | null; key: UserPublickey | null;
} | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId); } | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId);

View file

@ -5,7 +5,7 @@ import { promisify } from 'node:util';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { getIpHash } from '@/misc/get-ip-hash.js'; import { getIpHash } from '@/misc/get-ip-hash.js';
import type { CacheableLocalUser, ILocalUser, User } from '@/models/entities/User.js'; import type { ILocalUser, User } from '@/models/entities/User.js';
import type { AccessToken } from '@/models/entities/AccessToken.js'; import type { AccessToken } from '@/models/entities/AccessToken.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import type { UserIpsRepository } from '@/models/index.js'; import type { UserIpsRepository } from '@/models/index.js';
@ -194,7 +194,7 @@ export class ApiCallService implements OnApplicationShutdown {
@bindThis @bindThis
private async call( private async call(
ep: IEndpoint & { exec: any }, ep: IEndpoint & { exec: any },
user: CacheableLocalUser | null | undefined, user: ILocalUser | null | undefined,
token: AccessToken | null | undefined, token: AccessToken | null | undefined,
data: any, data: any,
file: { file: {

View file

@ -1,7 +1,7 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/index.js'; import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/index.js';
import type { CacheableLocalUser, ILocalUser } from '@/models/entities/User.js'; import type { ILocalUser } from '@/models/entities/User.js';
import type { AccessToken } from '@/models/entities/AccessToken.js'; import type { AccessToken } from '@/models/entities/AccessToken.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import type { App } from '@/models/entities/App.js'; import type { App } from '@/models/entities/App.js';
@ -36,7 +36,7 @@ export class AuthenticateService {
} }
@bindThis @bindThis
public async authenticate(token: string | null | undefined): Promise<[CacheableLocalUser | null | undefined, AccessToken | null | undefined]> { public async authenticate(token: string | null | undefined): Promise<[ILocalUser | null | undefined, AccessToken | null | undefined]> {
if (token == null) { if (token == null) {
return [null, null]; return [null, null];
} }

View file

@ -1,7 +1,7 @@
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import Ajv from 'ajv'; import Ajv from 'ajv';
import type { Schema, SchemaType } from '@/misc/schema.js'; import type { Schema, SchemaType } from '@/misc/schema.js';
import type { CacheableLocalUser } from '@/models/entities/User.js'; import type { ILocalUser } from '@/models/entities/User.js';
import type { AccessToken } from '@/models/entities/AccessToken.js'; import type { AccessToken } from '@/models/entities/AccessToken.js';
import { ApiError } from './error.js'; import { ApiError } from './error.js';
import type { IEndpointMeta } from './endpoints.js'; import type { IEndpointMeta } from './endpoints.js';
@ -21,16 +21,16 @@ type File = {
// TODO: paramsの型をT['params']のスキーマ定義から推論する // TODO: paramsの型をT['params']のスキーマ定義から推論する
type executor<T extends IEndpointMeta, Ps extends Schema> = type executor<T extends IEndpointMeta, Ps extends Schema> =
(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) => (params: SchemaType<Ps>, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) =>
Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>; Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
export abstract class Endpoint<T extends IEndpointMeta, Ps extends Schema> { export abstract class Endpoint<T extends IEndpointMeta, Ps extends Schema> {
public exec: (params: any, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>; public exec: (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>;
constructor(meta: T, paramDef: Ps, cb: executor<T, Ps>) { constructor(meta: T, paramDef: Ps, cb: executor<T, Ps>) {
const validate = ajv.compile(paramDef); const validate = ajv.compile(paramDef);
this.exec = (params: any, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => { this.exec = (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => {
let cleanup: undefined | (() => void) = undefined; let cleanup: undefined | (() => void) = undefined;
if (meta.requireFile) { if (meta.requireFile) {

View file

@ -3,7 +3,7 @@ import ms from 'ms';
import { Endpoint } from '@/server/api/endpoint-base.js'; import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UsersRepository, NotesRepository } from '@/models/index.js'; import type { UsersRepository, NotesRepository } from '@/models/index.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import type { CacheableLocalUser, User } from '@/models/entities/User.js'; import type { ILocalUser, User } from '@/models/entities/User.js';
import { isActor, isPost, getApId } from '@/core/activitypub/type.js'; import { isActor, isPost, getApId } from '@/core/activitypub/type.js';
import type { SchemaType } from '@/misc/schema.js'; import type { SchemaType } from '@/misc/schema.js';
import { ApResolverService } from '@/core/activitypub/ApResolverService.js'; import { ApResolverService } from '@/core/activitypub/ApResolverService.js';
@ -114,7 +114,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
* URIからUserかNoteを解決する * URIからUserかNoteを解決する
*/ */
@bindThis @bindThis
private async fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> { private async fetchAny(uri: string, me: ILocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
// ブロックしてたら中断 // ブロックしてたら中断
const fetchedMeta = await this.metaService.fetch(); const fetchedMeta = await this.metaService.fetch();
if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null; if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null;
@ -147,7 +147,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
} }
@bindThis @bindThis
private async mergePack(me: CacheableLocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> { private async mergePack(me: ILocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
if (user != null) { if (user != null) {
return { return {
type: 'User', type: 'User',