refactor: fix types

This commit is contained in:
syuilo 2023-02-12 18:47:30 +09:00
parent d7a2d59f41
commit 451bc0b444
24 changed files with 142 additions and 130 deletions

View file

@ -32,7 +32,7 @@ export class AccountUpdateService {
// フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信 // フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user));
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);
} }

View file

@ -135,7 +135,7 @@ export class MessagingService {
}))), }))),
} as Note; } as Note;
const activity = this.apRendererService.renderActivity(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false, true), note)); const activity = this.apRendererService.addContext(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false, true), note));
this.queueService.deliver(user, activity, recipientUser.inbox); this.queueService.deliver(user, activity, recipientUser.inbox);
} }
@ -158,7 +158,7 @@ export class MessagingService {
if (this.userEntityService.isLocalUser(recipient)) this.globalEventService.publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id); if (this.userEntityService.isLocalUser(recipient)) this.globalEventService.publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id);
if (this.userEntityService.isLocalUser(user) && this.userEntityService.isRemoteUser(recipient)) { if (this.userEntityService.isLocalUser(user) && this.userEntityService.isRemoteUser(recipient)) {
const activity = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${message.id}`), user)); const activity = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${message.id}`), user));
this.queueService.deliver(user, activity, recipient.inbox); this.queueService.deliver(user, activity, recipient.inbox);
} }
} else if (message.groupId) { } else if (message.groupId) {
@ -297,10 +297,10 @@ export class MessagingService {
if (contents.length > 1) { if (contents.length > 1) {
const collection = this.apRendererService.renderOrderedCollection(null, contents.length, undefined, undefined, contents); const collection = this.apRendererService.renderOrderedCollection(null, contents.length, undefined, undefined, contents);
this.queueService.deliver(user, this.apRendererService.renderActivity(collection), recipient.inbox); this.queueService.deliver(user, this.apRendererService.addContext(collection), recipient.inbox);
} else { } else {
for (const content of contents) { for (const content of contents) {
this.queueService.deliver(user, this.apRendererService.renderActivity(content), recipient.inbox); this.queueService.deliver(user, this.apRendererService.addContext(content), recipient.inbox);
} }
} }
} }

View file

@ -711,7 +711,7 @@ export class NoteCreateService {
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note) ? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note); : this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note);
return this.apRendererService.renderActivity(content); return this.apRendererService.addContext(content);
} }
@bindThis @bindThis

View file

@ -78,7 +78,7 @@ export class NoteDeleteService {
}); });
} }
const content = this.apRendererService.renderActivity(renote const content = this.apRendererService.addContext(renote
? this.apRendererService.renderUndo(this.apRendererService.renderAnnounce(renote.uri ?? `${this.config.url}/notes/${renote.id}`, note), user) ? this.apRendererService.renderUndo(this.apRendererService.renderAnnounce(renote.uri ?? `${this.config.url}/notes/${renote.id}`, note), user)
: this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user)); : this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user));
@ -90,7 +90,7 @@ export class NoteDeleteService {
for (const cascadingNote of cascadingNotes) { for (const cascadingNote of cascadingNotes) {
if (!cascadingNote.user) continue; if (!cascadingNote.user) continue;
if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue; if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue;
const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user));
this.deliverToConcerned(cascadingNote.user, cascadingNote, content); this.deliverToConcerned(cascadingNote.user, cascadingNote, content);
} }
//#endregion //#endregion

View file

@ -115,7 +115,7 @@ export class NotePiningService {
const target = `${this.config.url}/users/${user.id}/collections/featured`; const target = `${this.config.url}/users/${user.id}/collections/featured`;
const item = `${this.config.url}/notes/${noteId}`; const item = `${this.config.url}/notes/${noteId}`;
const content = this.apRendererService.renderActivity(isAddition ? this.apRendererService.renderAdd(user, target, item) : this.apRendererService.renderRemove(user, target, item)); const content = this.apRendererService.addContext(isAddition ? this.apRendererService.renderAdd(user, target, item) : this.apRendererService.renderRemove(user, target, item));
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);

View file

@ -97,7 +97,7 @@ export class PollService {
if (user == null) throw new Error('note not found'); if (user == null) throw new Error('note not found');
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user));
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);
} }

View file

@ -85,7 +85,7 @@ export class ReactionService {
} }
@bindThis @bindThis
public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string) { public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string | null) {
// Check blocking // Check blocking
if (note.userId !== user.id) { if (note.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id); const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
@ -177,7 +177,7 @@ export class ReactionService {
//#region 配信 //#region 配信
if (this.userEntityService.isLocalUser(user) && !note.localOnly) { if (this.userEntityService.isLocalUser(user) && !note.localOnly) {
const content = this.apRendererService.renderActivity(await this.apRendererService.renderLike(record, note)); const content = this.apRendererService.addContext(await this.apRendererService.renderLike(record, note));
const dm = this.apDeliverManagerService.createDeliverManager(user, content); const dm = this.apDeliverManagerService.createDeliverManager(user, content);
if (note.userHost !== null) { if (note.userHost !== null) {
const reactee = await this.usersRepository.findOneBy({ id: note.userId }); const reactee = await this.usersRepository.findOneBy({ id: note.userId });
@ -235,7 +235,7 @@ export class ReactionService {
//#region 配信 //#region 配信
if (this.userEntityService.isLocalUser(user) && !note.localOnly) { if (this.userEntityService.isLocalUser(user) && !note.localOnly) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(await this.apRendererService.renderLike(exist, note), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(await this.apRendererService.renderLike(exist, note), user));
const dm = this.apDeliverManagerService.createDeliverManager(user, content); const dm = this.apDeliverManagerService.createDeliverManager(user, content);
if (note.userHost !== null) { if (note.userHost !== null) {
const reactee = await this.usersRepository.findOneBy({ id: note.userId }); const reactee = await this.usersRepository.findOneBy({ id: note.userId });

View file

@ -56,7 +56,7 @@ export class RelayService {
const relayActor = await this.getRelayActor(); const relayActor = await this.getRelayActor();
const follow = await this.apRendererService.renderFollowRelay(relay, relayActor); const follow = await this.apRendererService.renderFollowRelay(relay, relayActor);
const activity = this.apRendererService.renderActivity(follow); const activity = this.apRendererService.addContext(follow);
this.queueService.deliver(relayActor, activity, relay.inbox); this.queueService.deliver(relayActor, activity, relay.inbox);
return relay; return relay;
@ -75,7 +75,7 @@ export class RelayService {
const relayActor = await this.getRelayActor(); const relayActor = await this.getRelayActor();
const follow = this.apRendererService.renderFollowRelay(relay, relayActor); const follow = this.apRendererService.renderFollowRelay(relay, relayActor);
const undo = this.apRendererService.renderUndo(follow, relayActor); const undo = this.apRendererService.renderUndo(follow, relayActor);
const activity = this.apRendererService.renderActivity(undo); const activity = this.apRendererService.addContext(undo);
this.queueService.deliver(relayActor, activity, relay.inbox); this.queueService.deliver(relayActor, activity, relay.inbox);
await this.relaysRepository.delete(relay.id); await this.relaysRepository.delete(relay.id);

View file

@ -117,7 +117,7 @@ export class UserBlockingService implements OnApplicationShutdown {
}); });
if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderBlock(blocking)); const content = this.apRendererService.addContext(this.apRendererService.renderBlock(blocking));
this.queueService.deliver(blocker, content, blockee.inbox); this.queueService.deliver(blocker, content, blockee.inbox);
} }
} }
@ -162,13 +162,13 @@ export class UserBlockingService implements OnApplicationShutdown {
// リモートにフォローリクエストをしていたらUndoFollow送信 // リモートにフォローリクエストをしていたらUndoFollow送信
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
// リモートからフォローリクエストを受けていたらReject送信 // リモートからフォローリクエストを受けていたらReject送信
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@ -210,13 +210,13 @@ export class UserBlockingService implements OnApplicationShutdown {
// リモートにフォローをしていたらUndoFollow送信 // リモートにフォローをしていたらUndoFollow送信
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
// リモートからフォローをされていたらRejectFollow送信 // リモートからフォローをされていたらRejectFollow送信
if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) { if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@ -261,7 +261,7 @@ export class UserBlockingService implements OnApplicationShutdown {
// deliver if remote bloking // deliver if remote bloking
if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker));
this.queueService.deliver(blocker, content, blockee.inbox); this.queueService.deliver(blocker, content, blockee.inbox);
} }
} }

View file

@ -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); this.userByIdCache.set(user.id, user as CacheableUser);
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); this.uriPersonCache.set(k, user as CacheableUser);
} }
} }
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 })); return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }) as Promise<CacheableUser>);
} }
@bindThis @bindThis

View file

@ -81,7 +81,7 @@ export class UserFollowingService {
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocked) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocked) {
// リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。 // リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, requestId), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, requestId), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
return; return;
} else if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocking) { } else if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocking) {
@ -130,7 +130,7 @@ export class UserFollowingService {
await this.insertFollowingDoc(followee, follower); await this.insertFollowingDoc(followee, follower);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@ -293,13 +293,13 @@ export class UserFollowingService {
} }
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) { if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) {
// local user has null host // local user has null host
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@ -388,7 +388,7 @@ export class UserFollowingService {
} }
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee)); const content = this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
} }
@ -403,7 +403,7 @@ export class UserFollowingService {
}, },
): Promise<void> { ): Promise<void> {
if (this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
if (this.userEntityService.isLocalUser(follower)) { // 本来このチェックは不要だけどTSに怒られるので if (this.userEntityService.isLocalUser(follower)) { // 本来このチェックは不要だけどTSに怒られるので
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
@ -448,7 +448,7 @@ export class UserFollowingService {
await this.insertFollowingDoc(followee, follower); await this.insertFollowingDoc(followee, follower);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
@ -556,7 +556,7 @@ export class UserFollowingService {
followerId: follower.id, followerId: follower.id,
}); });
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }

View file

@ -35,7 +35,7 @@ export class UserSuspendService {
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
// 知り得る全SharedInboxにDelete配信 // 知り得る全SharedInboxにDelete配信
const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user)); const content = this.apRendererService.addContext(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user));
const queue: string[] = []; const queue: string[] = [];
@ -65,7 +65,7 @@ export class UserSuspendService {
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
// 知り得る全SharedInboxにUndo Delete配信 // 知り得る全SharedInboxにUndo Delete配信
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user), user));
const queue: string[] = []; const queue: string[] = [];

View file

@ -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 ?? undefined)) ?? null; }).then(x => (x as CacheableUser | null) ?? 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>);
} }
} }

View file

@ -2,7 +2,7 @@ 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 } from '@/models/entities/User.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';
@ -22,6 +22,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { QueueService } from '@/core/QueueService.js'; 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 { 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';
@ -32,7 +33,6 @@ import { ApPersonService } from './models/ApPersonService.js';
import { ApQuestionService } from './models/ApQuestionService.js'; import { ApQuestionService } from './models/ApQuestionService.js';
import type { Resolver } from './ApResolverService.js'; import type { Resolver } from './ApResolverService.js';
import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IRead, IReject, IRemove, IUndo, IUpdate } from './type.js'; import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IRead, IReject, IRemove, IUndo, IUpdate } from './type.js';
import { bindThis } from '@/decorators.js';
@Injectable() @Injectable()
export class ApInboxService { export class ApInboxService {
@ -687,7 +687,7 @@ export class ApInboxService {
return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません'; return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません';
} }
await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }), blockee); await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }) as CacheableUser, blockee);
return 'ok'; return 'ok';
} }

View file

@ -24,7 +24,7 @@ import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFil
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { LdSignatureService } from './LdSignatureService.js'; import { LdSignatureService } from './LdSignatureService.js';
import { ApMfmService } from './ApMfmService.js'; import { ApMfmService } from './ApMfmService.js';
import type { IActivity, IObject } from './type.js'; import type { IAccept, IActivity, IAdd, IAnnounce, IApDocument, IApEmoji, IApHashtag, IApImage, IApMention, IBlock, ICreate, IDelete, IFlag, IFollow, IKey, ILike, IObject, IQuestion, IRead, IReject, IRemove, ITombstone, IUndo, IUpdate } from './type.js';
import type { IIdentifier } from './models/identifier.js'; import type { IIdentifier } from './models/identifier.js';
@Injectable() @Injectable()
@ -61,7 +61,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderAccept(object: any, user: { id: User['id']; host: null }) { public renderAccept(object: any, user: { id: User['id']; host: null }): IAccept {
return { return {
type: 'Accept', type: 'Accept',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -70,7 +70,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderAdd(user: ILocalUser, target: any, object: any) { public renderAdd(user: ILocalUser, target: any, object: any): IAdd {
return { return {
type: 'Add', type: 'Add',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -80,7 +80,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderAnnounce(object: any, note: Note) { public renderAnnounce(object: any, note: Note): IAnnounce {
const attributedTo = `${this.config.url}/users/${note.userId}`; const attributedTo = `${this.config.url}/users/${note.userId}`;
let to: string[] = []; let to: string[] = [];
@ -93,7 +93,7 @@ export class ApRendererService {
to = [`${attributedTo}/followers`]; to = [`${attributedTo}/followers`];
cc = ['https://www.w3.org/ns/activitystreams#Public']; cc = ['https://www.w3.org/ns/activitystreams#Public'];
} else { } else {
return null; throw new Error('renderAnnounce: cannot render non-public note');
} }
return { return {
@ -113,7 +113,7 @@ export class ApRendererService {
* @param block The block to be rendered. The blockee relation must be loaded. * @param block The block to be rendered. The blockee relation must be loaded.
*/ */
@bindThis @bindThis
public renderBlock(block: Blocking) { public renderBlock(block: Blocking): IBlock {
if (block.blockee?.uri == null) { if (block.blockee?.uri == null) {
throw new Error('renderBlock: missing blockee uri'); throw new Error('renderBlock: missing blockee uri');
} }
@ -127,14 +127,14 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderCreate(object: any, note: Note) { public renderCreate(object: IObject, note: Note): ICreate {
const activity = { const activity = {
id: `${this.config.url}/notes/${note.id}/activity`, id: `${this.config.url}/notes/${note.id}/activity`,
actor: `${this.config.url}/users/${note.userId}`, actor: `${this.config.url}/users/${note.userId}`,
type: 'Create', type: 'Create',
published: note.createdAt.toISOString(), published: note.createdAt.toISOString(),
object, object,
} as any; } as ICreate;
if (object.to) activity.to = object.to; if (object.to) activity.to = object.to;
if (object.cc) activity.cc = object.cc; if (object.cc) activity.cc = object.cc;
@ -143,7 +143,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderDelete(object: any, user: { id: User['id']; host: null }) { public renderDelete(object: IObject | string, user: { id: User['id']; host: null }): IDelete {
return { return {
type: 'Delete', type: 'Delete',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -153,7 +153,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderDocument(file: DriveFile) { public renderDocument(file: DriveFile): IApDocument {
return { return {
type: 'Document', type: 'Document',
mediaType: file.type, mediaType: file.type,
@ -163,12 +163,12 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderEmoji(emoji: Emoji) { public renderEmoji(emoji: Emoji): IApEmoji {
return { return {
id: `${this.config.url}/emojis/${emoji.name}`, id: `${this.config.url}/emojis/${emoji.name}`,
type: 'Emoji', type: 'Emoji',
name: `:${emoji.name}:`, name: `:${emoji.name}:`,
updated: emoji.updatedAt != null ? emoji.updatedAt.toISOString() : new Date().toISOString, updated: emoji.updatedAt != null ? emoji.updatedAt.toISOString() : new Date().toISOString(),
icon: { icon: {
type: 'Image', type: 'Image',
mediaType: emoji.type ?? 'image/png', mediaType: emoji.type ?? 'image/png',
@ -181,7 +181,7 @@ export class ApRendererService {
// to anonymise reporters, the reporting actor must be a system user // to anonymise reporters, the reporting actor must be a system user
// object has to be a uri or array of uris // object has to be a uri or array of uris
@bindThis @bindThis
public renderFlag(user: ILocalUser, object: [string], content: string) { public renderFlag(user: ILocalUser, object: IObject, content: string): IFlag {
return { return {
type: 'Flag', type: 'Flag',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -191,15 +191,13 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderFollowRelay(relay: Relay, relayActor: ILocalUser) { public renderFollowRelay(relay: Relay, relayActor: ILocalUser): IFollow {
const follow = { return {
id: `${this.config.url}/activities/follow-relay/${relay.id}`, id: `${this.config.url}/activities/follow-relay/${relay.id}`,
type: 'Follow', type: 'Follow',
actor: `${this.config.url}/users/${relayActor.id}`, actor: `${this.config.url}/users/${relayActor.id}`,
object: 'https://www.w3.org/ns/activitystreams#Public', object: 'https://www.w3.org/ns/activitystreams#Public',
}; };
return follow;
} }
/** /**
@ -217,19 +215,17 @@ export class ApRendererService {
follower: { id: User['id']; host: User['host']; uri: User['host'] }, follower: { id: User['id']; host: User['host']; uri: User['host'] },
followee: { id: User['id']; host: User['host']; uri: User['host'] }, followee: { id: User['id']; host: User['host']; uri: User['host'] },
requestId?: string, requestId?: string,
) { ): IFollow {
const follow = { return {
id: requestId ?? `${this.config.url}/follows/${follower.id}/${followee.id}`, id: requestId ?? `${this.config.url}/follows/${follower.id}/${followee.id}`,
type: 'Follow', type: 'Follow',
actor: this.userEntityService.isLocalUser(follower) ? `${this.config.url}/users/${follower.id}` : follower.uri, actor: this.userEntityService.isLocalUser(follower) ? `${this.config.url}/users/${follower.id}` : follower.uri!,
object: this.userEntityService.isLocalUser(followee) ? `${this.config.url}/users/${followee.id}` : followee.uri, object: this.userEntityService.isLocalUser(followee) ? `${this.config.url}/users/${followee.id}` : followee.uri!,
} as any; };
return follow;
} }
@bindThis @bindThis
public renderHashtag(tag: string) { public renderHashtag(tag: string): IApHashtag {
return { return {
type: 'Hashtag', type: 'Hashtag',
href: `${this.config.url}/tags/${encodeURIComponent(tag)}`, href: `${this.config.url}/tags/${encodeURIComponent(tag)}`,
@ -238,7 +234,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderImage(file: DriveFile) { public renderImage(file: DriveFile): IApImage {
return { return {
type: 'Image', type: 'Image',
url: this.driveFileEntityService.getPublicUrl(file), url: this.driveFileEntityService.getPublicUrl(file),
@ -248,7 +244,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderKey(user: ILocalUser, key: UserKeypair, postfix?: string) { public renderKey(user: ILocalUser, key: UserKeypair, postfix?: string): IKey {
return { return {
id: `${this.config.url}/users/${user.id}${postfix ?? '/publickey'}`, id: `${this.config.url}/users/${user.id}${postfix ?? '/publickey'}`,
type: 'Key', type: 'Key',
@ -261,7 +257,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public async renderLike(noteReaction: NoteReaction, note: { uri: string | null }) { public async renderLike(noteReaction: NoteReaction, note: { uri: string | null }): Promise<ILike> {
const reaction = noteReaction.reaction; const reaction = noteReaction.reaction;
const object = { const object = {
@ -271,10 +267,11 @@ export class ApRendererService {
object: note.uri ? note.uri : `${this.config.url}/notes/${noteReaction.noteId}`, object: note.uri ? note.uri : `${this.config.url}/notes/${noteReaction.noteId}`,
content: reaction, content: reaction,
_misskey_reaction: reaction, _misskey_reaction: reaction,
} as any; } as ILike;
if (reaction.startsWith(':')) { if (reaction.startsWith(':')) {
const name = reaction.replaceAll(':', ''); const name = reaction.replaceAll(':', '');
// TODO: cache
const emoji = await this.emojisRepository.findOneBy({ const emoji = await this.emojisRepository.findOneBy({
name, name,
host: IsNull(), host: IsNull(),
@ -287,10 +284,10 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderMention(mention: User) { public renderMention(mention: User): IApMention {
return { return {
type: 'Mention', type: 'Mention',
href: this.userEntityService.isRemoteUser(mention) ? mention.uri : `${this.config.url}/users/${(mention as ILocalUser).id}`, href: this.userEntityService.isRemoteUser(mention) ? mention.uri! : `${this.config.url}/users/${(mention as ILocalUser).id}`,
name: this.userEntityService.isRemoteUser(mention) ? `@${mention.username}@${mention.host}` : `@${(mention as ILocalUser).username}`, name: this.userEntityService.isRemoteUser(mention) ? `@${mention.username}@${mention.host}` : `@${(mention as ILocalUser).username}`,
}; };
} }
@ -518,8 +515,8 @@ export class ApRendererService {
} }
@bindThis @bindThis
public async renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll) { public async renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll): IQuestion {
const question = { return {
type: 'Question', type: 'Question',
id: `${this.config.url}/questions/${note.id}`, id: `${this.config.url}/questions/${note.id}`,
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -533,21 +530,19 @@ export class ApRendererService {
}, },
})), })),
}; };
return question;
} }
@bindThis @bindThis
public renderRead(user: { id: User['id'] }, message: MessagingMessage) { public renderRead(user: { id: User['id'] }, message: MessagingMessage): IRead {
return { return {
type: 'Read', type: 'Read',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
object: message.uri, object: message.uri!,
}; };
} }
@bindThis @bindThis
public renderReject(object: any, user: { id: User['id'] }) { public renderReject(object: any, user: { id: User['id'] }): IReject {
return { return {
type: 'Reject', type: 'Reject',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -556,7 +551,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderRemove(user: { id: User['id'] }, target: any, object: any) { public renderRemove(user: { id: User['id'] }, target: any, object: any): IRemove {
return { return {
type: 'Remove', type: 'Remove',
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -566,7 +561,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderTombstone(id: string) { public renderTombstone(id: string): ITombstone {
return { return {
id, id,
type: 'Tombstone', type: 'Tombstone',
@ -574,8 +569,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderUndo(object: any, user: { id: User['id'] }) { public renderUndo(object: any, user: { id: User['id'] }): IUndo {
if (object == null) return null;
const id = typeof object.id === 'string' && object.id.startsWith(this.config.url) ? `${object.id}/undo` : undefined; const id = typeof object.id === 'string' && object.id.startsWith(this.config.url) ? `${object.id}/undo` : undefined;
return { return {
@ -588,21 +582,19 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderUpdate(object: any, user: { id: User['id'] }) { public renderUpdate(object: any, user: { id: User['id'] }): IUpdate {
const activity = { return {
id: `${this.config.url}/users/${user.id}#updates/${new Date().getTime()}`, id: `${this.config.url}/users/${user.id}#updates/${new Date().getTime()}`,
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
type: 'Update', type: 'Update',
to: ['https://www.w3.org/ns/activitystreams#Public'], to: ['https://www.w3.org/ns/activitystreams#Public'],
object, object,
published: new Date().toISOString(), published: new Date().toISOString(),
} as any; };
return activity;
} }
@bindThis @bindThis
public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser) { public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser): ICreate {
return { return {
id: `${this.config.url}/users/${user.id}#votes/${vote.id}/activity`, id: `${this.config.url}/users/${user.id}#votes/${vote.id}/activity`,
actor: `${this.config.url}/users/${user.id}`, actor: `${this.config.url}/users/${user.id}`,
@ -621,9 +613,7 @@ export class ApRendererService {
} }
@bindThis @bindThis
public renderActivity(x: any): IActivity | null { public addContext<T extends IObject>(x: T): T & { '@context': any; id: string; } {
if (x == null) return null;
if (typeof x === 'object' && x.id == null) { if (typeof x === 'object' && x.id == null) {
x.id = `${this.config.url}/${uuid()}`; x.id = `${this.config.url}/${uuid()}`;
} }
@ -659,7 +649,7 @@ export class ApRendererService {
vcard: 'http://www.w3.org/2006/vcard/ns#', vcard: 'http://www.w3.org/2006/vcard/ns#',
}, },
], ],
}, x); }, x as T & { id: string; });
} }
@bindThis @bindThis

View file

@ -38,8 +38,7 @@ export class Resolver {
private recursionLimit = 100, private recursionLimit = 100,
) { ) {
this.history = new Set(); this.history = new Set();
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.logger = this.loggerService.getLogger('ap-resolve');
this.logger = this.loggerService?.getLogger('ap-resolve'); // なぜか TypeError: Cannot read properties of undefined (reading 'getLogger') と言われる
} }
@bindThis @bindThis
@ -124,10 +123,10 @@ export class Resolver {
switch (parsed.type) { switch (parsed.type) {
case 'notes': case 'notes':
return this.notesRepository.findOneByOrFail({ id: parsed.id }) return this.notesRepository.findOneByOrFail({ id: parsed.id })
.then(note => { .then(async note => {
if (parsed.rest === 'activity') { if (parsed.rest === 'activity') {
// this refers to the create activity and not the note itself // this refers to the create activity and not the note itself
return this.apRendererService.renderActivity(this.apRendererService.renderCreate(this.apRendererService.renderNote(note), note)); return this.apRendererService.addContext(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note), note));
} else { } else {
return this.apRendererService.renderNote(note); return this.apRendererService.renderNote(note);
} }
@ -143,8 +142,8 @@ export class Resolver {
]) ])
.then(([note, poll]) => this.apRendererService.renderQuestion({ id: note.userId }, note, poll)); .then(([note, poll]) => this.apRendererService.renderQuestion({ id: note.userId }, note, poll));
case 'likes': case 'likes':
return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(reaction => return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(async reaction =>
this.apRendererService.renderActivity(this.apRendererService.renderLike(reaction, { uri: null }))!); this.apRendererService.addContext(await this.apRendererService.renderLike(reaction, { uri: null })));
case 'follows': case 'follows':
// rest should be <followee id> // rest should be <followee id>
if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI');
@ -152,7 +151,7 @@ export class Resolver {
return Promise.all( return Promise.all(
[parsed.id, parsed.rest].map(id => this.usersRepository.findOneByOrFail({ id })), [parsed.id, parsed.rest].map(id => this.usersRepository.findOneByOrFail({ id })),
) )
.then(([follower, followee]) => this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee, url))); .then(([follower, followee]) => this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee, url)));
default: default:
throw new Error(`resolveLocal: type ${parsed.type} unhandled`); throw new Error(`resolveLocal: type ${parsed.type} unhandled`);
} }
@ -184,6 +183,7 @@ export class ApResolverService {
private httpRequestService: HttpRequestService, private httpRequestService: HttpRequestService,
private apRendererService: ApRendererService, private apRendererService: ApRendererService,
private apDbResolverService: ApDbResolverService, private apDbResolverService: ApDbResolverService,
private loggerService: LoggerService,
) { ) {
} }
@ -202,6 +202,7 @@ export class ApResolverService {
this.httpRequestService, this.httpRequestService,
this.apRendererService, this.apRendererService,
this.apDbResolverService, this.apDbResolverService,
this.loggerService,
); );
} }
} }

View file

@ -114,7 +114,7 @@ export class ApNoteService {
public async createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise<Note | null> { public async createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise<Note | null> {
if (resolver == null) resolver = this.apResolverService.createResolver(); if (resolver == null) resolver = this.apResolverService.createResolver();
const object: any = await resolver.resolve(value); const object = await resolver.resolve(value);
const entryUri = getApId(value); const entryUri = getApId(value);
const err = this.validateNote(object, entryUri); const err = this.validateNote(object, entryUri);
@ -129,7 +129,7 @@ export class ApNoteService {
throw new Error('invalid note'); throw new Error('invalid note');
} }
const note: IPost = object; const note: IPost = object as any;
this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`); this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`);
@ -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 CacheableRemoteUser;
// 投稿者が凍結されていたらスキップ // 投稿者が凍結されていたらスキップ
if (actor.isSuspended) { if (actor.isSuspended) {

View file

@ -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 }); const u = await this.usersRepository.findOneBy({ id }) as null | CacheableUser;
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 }); const exist = await this.usersRepository.findOneBy({ uri }) as null | CacheableUser;
if (exist) { if (exist) {
this.userCacheService.uriPersonCache.set(uri, exist); this.userCacheService.uriPersonCache.set(uri, exist);
@ -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); return await this.createPerson(uri, resolver) as CacheableUser;
} }
@bindThis @bindThis

View file

@ -2,24 +2,24 @@ export type obj = { [x: string]: any };
export type ApObject = IObject | string | (IObject | string)[]; export type ApObject = IObject | string | (IObject | string)[];
export interface IObject { export interface IObject {
'@context': string | string[] | obj | obj[]; '@context'?: string | string[] | obj | obj[];
type: string | string[]; type: string | string[];
id?: string; id?: string;
name?: string | null;
summary?: string; summary?: string;
published?: string; published?: string;
cc?: ApObject; cc?: ApObject;
to?: ApObject; to?: ApObject;
attributedTo: ApObject; attributedTo?: ApObject;
attachment?: any[]; attachment?: any[];
inReplyTo?: any; inReplyTo?: any;
replies?: ICollection; replies?: ICollection;
content?: string; content?: string;
name?: string;
startTime?: Date; startTime?: Date;
endTime?: Date; endTime?: Date;
icon?: any; icon?: any;
image?: any; image?: any;
url?: ApObject; url?: ApObject | string;
href?: string; href?: string;
tag?: IObject | IObject[]; tag?: IObject | IObject[];
sensitive?: boolean; sensitive?: boolean;
@ -118,6 +118,7 @@ export interface IPost extends IObject {
export interface IQuestion extends IObject { export interface IQuestion extends IObject {
type: 'Note' | 'Question'; type: 'Note' | 'Question';
actor: string;
source?: { source?: {
content: string; content: string;
mediaType: string; mediaType: string;
@ -200,6 +201,7 @@ export const isPropertyValue = (object: IObject): object is IApPropertyValue =>
export interface IApMention extends IObject { export interface IApMention extends IObject {
type: 'Mention'; type: 'Mention';
href: string; href: string;
name: string;
} }
export const isMention = (object: IObject): object is IApMention => export const isMention = (object: IObject): object is IApMention =>
@ -217,12 +219,30 @@ export const isHashtag = (object: IObject): object is IApHashtag =>
export interface IApEmoji extends IObject { export interface IApEmoji extends IObject {
type: 'Emoji'; type: 'Emoji';
updated: Date; name: string;
updated: string;
} }
export const isEmoji = (object: IObject): object is IApEmoji => export const isEmoji = (object: IObject): object is IApEmoji =>
getApType(object) === 'Emoji' && !Array.isArray(object.icon) && object.icon.url != null; getApType(object) === 'Emoji' && !Array.isArray(object.icon) && object.icon.url != null;
export interface IKey extends IObject {
type: 'Key';
owner: string;
publicKeyPem: string | Buffer;
}
export interface IApDocument extends IObject {
type: 'Document';
name: string | null;
mediaType: string;
}
export interface IApImage extends IObject {
type: 'Image';
name: string | null;
}
export interface ICreate extends IActivity { export interface ICreate extends IActivity {
type: 'Create'; type: 'Create';
} }

View file

@ -11,9 +11,9 @@ import type { DriveFile } from '@/models/entities/DriveFile.js';
import { appendQuery, query } from '@/misc/prelude/url.js'; import { appendQuery, query } from '@/misc/prelude/url.js';
import { deepClone } from '@/misc/clone.js'; import { deepClone } from '@/misc/clone.js';
import { UtilityService } from '../UtilityService.js'; import { UtilityService } from '../UtilityService.js';
import { VideoProcessingService } from '../VideoProcessingService.js';
import { UserEntityService } from './UserEntityService.js'; import { UserEntityService } from './UserEntityService.js';
import { DriveFolderEntityService } from './DriveFolderEntityService.js'; import { DriveFolderEntityService } from './DriveFolderEntityService.js';
import { VideoProcessingService } from '../VideoProcessingService.js';
type PackOptions = { type PackOptions = {
detail?: boolean, detail?: boolean,
@ -74,14 +74,14 @@ export class DriveFileEntityService {
} }
@bindThis @bindThis
private getProxiedUrl(url: string, mode?: 'static' | 'avatar'): string | null { private getProxiedUrl(url: string, mode?: 'static' | 'avatar'): string {
return appendQuery( return appendQuery(
`${this.config.mediaProxy}/${mode ?? 'image'}.webp`, `${this.config.mediaProxy}/${mode ?? 'image'}.webp`,
query({ query({
url, url,
...(mode ? { [mode]: '1' } : {}), ...(mode ? { [mode]: '1' } : {}),
}) }),
) );
} }
@bindThis @bindThis
@ -110,7 +110,7 @@ export class DriveFileEntityService {
} }
@bindThis @bindThis
public getPublicUrl(file: DriveFile, mode?: 'avatar'): string | null { // static = thumbnail public getPublicUrl(file: DriveFile, mode?: 'avatar'): string { // static = thumbnail
// リモートかつメディアプロキシ // リモートかつメディアプロキシ
if (file.uri != null && file.userHost != null && this.config.externalMediaProxyEnabled) { if (file.uri != null && file.userHost != null && this.config.externalMediaProxyEnabled) {
return this.getProxiedUrl(file.uri, mode); return this.getProxiedUrl(file.uri, mode);

View file

@ -221,6 +221,7 @@ export interface ILocalUser extends User {
export interface IRemoteUser extends User { export interface IRemoteUser extends User {
host: string; host: string;
uri: string;
} }
export type CacheableLocalUser = ILocalUser; export type CacheableLocalUser = ILocalUser;

View file

@ -183,13 +183,13 @@ export class ActivityPubServerService {
); );
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} else { } else {
// index page // index page
const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`); const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`);
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} }
} }
@ -271,13 +271,13 @@ export class ActivityPubServerService {
); );
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} else { } else {
// index page // index page
const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`); const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`);
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} }
} }
@ -312,7 +312,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} }
@bindThis @bindThis
@ -389,7 +389,7 @@ export class ActivityPubServerService {
); );
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} else { } else {
// index page // index page
const rendered = this.apRendererService.renderOrderedCollection(partOf, user.notesCount, const rendered = this.apRendererService.renderOrderedCollection(partOf, user.notesCount,
@ -398,7 +398,7 @@ export class ActivityPubServerService {
); );
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(rendered)); return (this.apRendererService.addContext(rendered));
} }
} }
@ -411,7 +411,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(await this.apRendererService.renderPerson(user as ILocalUser))); return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as ILocalUser)));
} }
@bindThis @bindThis
@ -481,7 +481,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(await this.apRendererService.renderNote(note, false))); return this.apRendererService.addContext(await this.apRendererService.renderNote(note, false));
}); });
// note activity // note activity
@ -502,7 +502,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(await this.packActivity(note))); return (this.apRendererService.addContext(await this.packActivity(note)));
}); });
// outbox // outbox
@ -545,7 +545,7 @@ export class ActivityPubServerService {
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(this.apRendererService.renderKey(user, keypair))); return (this.apRendererService.addContext(this.apRendererService.renderKey(user, keypair)));
} else { } else {
reply.code(400); reply.code(400);
return; return;
@ -589,7 +589,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(await this.apRendererService.renderEmoji(emoji))); return (this.apRendererService.addContext(await this.apRendererService.renderEmoji(emoji)));
}); });
// like // like
@ -610,7 +610,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(await this.apRendererService.renderLike(reaction, note))); return (this.apRendererService.addContext(await this.apRendererService.renderLike(reaction, note)));
}); });
// follow // follow
@ -636,7 +636,7 @@ export class ActivityPubServerService {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');
this.setResponseType(request, reply); this.setResponseType(request, reply);
return (this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee))); return (this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee)));
}); });
done(); done();

View file

@ -49,7 +49,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const actor = await this.instanceActorService.getInstanceActor(); const actor = await this.instanceActorService.getInstanceActor();
const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId });
this.queueService.deliver(actor, this.apRendererService.renderActivity(this.apRendererService.renderFlag(actor, [targetUser.uri!], report.comment)), targetUser.inbox); this.queueService.deliver(actor, this.apRendererService.addContext(this.apRendererService.renderFlag(actor, [targetUser.uri!], report.comment)), targetUser.inbox);
} }
await this.abuseUserReportsRepository.update(report.id, { await this.abuseUserReportsRepository.update(report.id, {

View file

@ -162,7 +162,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (note.userHost != null) { if (note.userHost != null) {
const pollOwner = await this.usersRepository.findOneByOrFail({ id: note.userId }) as IRemoteUser; const pollOwner = await this.usersRepository.findOneByOrFail({ id: note.userId }) as IRemoteUser;
this.queueService.deliver(me, this.apRendererService.renderActivity(await this.apRendererService.renderVote(me, vote, note, poll, pollOwner)), pollOwner.inbox); this.queueService.deliver(me, this.apRendererService.addContext(await this.apRendererService.renderVote(me, vote, note, poll, pollOwner)), pollOwner.inbox);
} }
// リモートフォロワーにUpdate配信 // リモートフォロワーにUpdate配信