diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/index.ts index 694682e721..997c78b3ef 100644 --- a/packages/backend/src/boot/index.ts +++ b/packages/backend/src/boot/index.ts @@ -32,8 +32,8 @@ export default async function() { await workerMain(); } - // ユニットテスト時にMisskeyが子プロセスで起動された時のため - // それ以外のときは process.send は使えないので弾く + // For when Calckey is started in a child process during unit testing. + // Otherwise, process.send cannot be used, so start it. if (process.send) { process.send('ok'); } diff --git a/packages/backend/src/models/entities/notification.ts b/packages/backend/src/models/entities/notification.ts index db3dba3632..2cf8a19394 100644 --- a/packages/backend/src/models/entities/notification.ts +++ b/packages/backend/src/models/entities/notification.ts @@ -19,7 +19,7 @@ export class Notification { public createdAt: Date; /** - * 通知の受信者 + * Notification Recipient ID */ @Index() @Column({ @@ -35,7 +35,7 @@ export class Notification { public notifiee: User | null; /** - * 通知の送信者(initiator) + * Notification sender (initiator) */ @Index() @Column({ @@ -52,19 +52,19 @@ export class Notification { public notifier: User | null; /** - * 通知の種類。 - * follow - フォローされた - * mention - 投稿で自分が言及された - * reply - (自分または自分がWatchしている)投稿が返信された - * renote - (自分または自分がWatchしている)投稿がRenoteされた - * quote - (自分または自分がWatchしている)投稿が引用Renoteされた + * Notification types: + * follow - Follow request + * mention - User was referenced in a post. + * reply - A post that a user made (or was watching) has been replied to. + * renote - A post that a user made (or was watching) has been renoted. + * quote - A post that a user made (or was watching) has been quoted and renoted. * reaction - (自分または自分がWatchしている)投稿にリアクションされた * pollVote - (自分または自分がWatchしている)投稿のアンケートに投票された * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した * receiveFollowRequest - フォローリクエストされた - * followRequestAccepted - 自分の送ったフォローリクエストが承認された + * followRequestAccepted - A follow request has been accepted. * groupInvited - グループに招待された - * app - アプリ通知 + * app - App notifications. */ @Index() @Column('enum', { @@ -74,12 +74,12 @@ export class Notification { public type: typeof notificationTypes[number]; /** - * 通知が読まれたかどうか + * Whether the notification was read. */ @Index() @Column('boolean', { default: false, - comment: 'Whether the Notification is read.', + comment: 'Whether the notification was read.', }) public isRead: boolean; @@ -130,7 +130,7 @@ export class Notification { public choice: number | null; /** - * アプリ通知のbody + * App notification body */ @Column('varchar', { length: 2048, nullable: true, @@ -138,8 +138,8 @@ export class Notification { public customBody: string | null; /** - * アプリ通知のheader - * (省略時はアプリ名で表示されることを期待) + * App notification header + * (If omitted, it is expected to be displayed with the app name) */ @Column('varchar', { length: 256, nullable: true, @@ -147,8 +147,8 @@ export class Notification { public customHeader: string | null; /** - * アプリ通知のicon(URL) - * (省略時はアプリアイコンで表示されることを期待) + * App notification icon (URL) + * (If omitted, it is expected to be displayed as an app icon) */ @Column('varchar', { length: 1024, nullable: true, @@ -156,7 +156,7 @@ export class Notification { public customIcon: string | null; /** - * アプリ通知のアプリ(のトークン) + * App notification app (token for) */ @Index() @Column({ diff --git a/packages/backend/src/remote/activitypub/kernel/announce/note.ts b/packages/backend/src/remote/activitypub/kernel/announce/note.ts index 759cb4ae83..d062659412 100644 --- a/packages/backend/src/remote/activitypub/kernel/announce/note.ts +++ b/packages/backend/src/remote/activitypub/kernel/announce/note.ts @@ -14,7 +14,7 @@ import { Notes } from '@/models/index.js'; const logger = apLogger; /** - * アナウンスアクティビティを捌きます + * Handle announcement activities */ export default async function(resolver: Resolver, actor: CacheableRemoteUser, activity: IAnnounce, targetUri: string): Promise { const uri = getApId(activity); @@ -23,25 +23,25 @@ export default async function(resolver: Resolver, actor: CacheableRemoteUser, ac return; } - // アナウンス先をブロックしてたら中断 + // Interrupt if you block the announcement destination const meta = await fetchMeta(); if (meta.blockedHosts.includes(extractDbHost(uri))) return; const unlock = await getApLock(uri); try { - // 既に同じURIを持つものが登録されていないかチェック + // Check if something with the same URI is already registered const exist = await fetchNote(uri); if (exist) { return; } - // Announce対象をresolve + // Resolve Announce target let renote; try { renote = await resolveNote(targetUri); } catch (e) { - // 対象が4xxならスキップ + // Skip if target is 4xx if (e instanceof StatusError) { if (e.isClientError) { logger.warn(`Ignored announce target ${targetUri} - ${e.statusCode}`); diff --git a/packages/backend/src/remote/activitypub/kernel/create/note.ts b/packages/backend/src/remote/activitypub/kernel/create/note.ts index f8dabe06e2..d7ee2d8c72 100644 --- a/packages/backend/src/remote/activitypub/kernel/create/note.ts +++ b/packages/backend/src/remote/activitypub/kernel/create/note.ts @@ -7,7 +7,7 @@ import { extractDbHost } from '@/misc/convert-host.js'; import { StatusError } from '@/misc/fetch.js'; /** - * 投稿作成アクティビティを捌きます + * Handle post creation activity */ export default async function(resolver: Resolver, actor: CacheableRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { const uri = getApId(note); diff --git a/packages/backend/src/remote/activitypub/kernel/delete/index.ts b/packages/backend/src/remote/activitypub/kernel/delete/index.ts index c7064f553b..ac778c05b4 100644 --- a/packages/backend/src/remote/activitypub/kernel/delete/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/delete/index.ts @@ -5,18 +5,19 @@ import { toSingle } from '@/prelude/array.js'; import { deleteActor } from './actor.js'; /** - * 削除アクティビティを捌きます + * Handle delete activity */ export default async (actor: CacheableRemoteUser, activity: IDelete): Promise => { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } - // 削除対象objectのtype + // Type of object to be deleted let formerType: string | undefined; if (typeof activity.object === 'string') { - // typeが不明だけど、どうせ消えてるのでremote resolveしない + // The type is unknown, but it has disappeared + // anyway, so it does not remote resolve formerType = undefined; } else { const object = activity.object as IObject; @@ -29,12 +30,13 @@ export default async (actor: CacheableRemoteUser, activity: IDelete): Promise => { - // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので - // 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する + // The object is `(User | Note) | (User | Note) []`, but it cannot be + // matched with all patterns of the DB schema, so the target user is the first + // user and it is stored as a comment. const uris = getApIds(activity.object); const userIds = uris.filter(uri => uri.startsWith(config.url + '/users/')).map(uri => uri.split('/').pop()!); diff --git a/packages/backend/src/remote/activitypub/kernel/follow.ts b/packages/backend/src/remote/activitypub/kernel/follow.ts index a9e92fa229..5cd1ec82b0 100644 --- a/packages/backend/src/remote/activitypub/kernel/follow.ts +++ b/packages/backend/src/remote/activitypub/kernel/follow.ts @@ -12,7 +12,7 @@ export default async (actor: CacheableRemoteUser, activity: IFollow): Promise => { - // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある + // ※ `activity.actor` must be an existing local user, since `activity` is a follow request thrown from us. const dbResolver = new DbResolver(); const follower = await dbResolver.getUserFromApId(activity.actor); diff --git a/packages/backend/src/remote/activitypub/kernel/undo/accept.ts b/packages/backend/src/remote/activitypub/kernel/undo/accept.ts index a6e3929b0f..39ef923633 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/accept.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/accept.ts @@ -23,5 +23,5 @@ export default async (actor: CacheableRemoteUser, activity: IAccept): Promise => { if ('actor' in activity && actor.uri !== activity.actor) { diff --git a/packages/backend/src/remote/activitypub/models/image.ts b/packages/backend/src/remote/activitypub/models/image.ts index 102b7b1346..1022b17ecf 100644 --- a/packages/backend/src/remote/activitypub/models/image.ts +++ b/packages/backend/src/remote/activitypub/models/image.ts @@ -11,10 +11,10 @@ import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits.js'; const logger = apLogger; /** - * Imageを作成します。 + * create an Image. */ export async function createImage(actor: CacheableRemoteUser, value: any): Promise { - // 投稿者が凍結されていたらスキップ + // Skip if author is frozen. if (actor.isSuspended) { throw new Error('actor has been suspended'); } @@ -39,8 +39,8 @@ export async function createImage(actor: CacheableRemoteUser, value: any): Promi }); if (file.isLink) { - // URLが異なっている場合、同じ画像が以前に異なるURLで登録されていたということなので、 - // URLを更新する + // If the URL is different, it means that the same image was previously + // registered with a different URL, so update the URL if (file.url !== image.url) { await DriveFiles.update({ id: file.id }, { url: image.url, @@ -55,14 +55,14 @@ export async function createImage(actor: CacheableRemoteUser, value: any): Promi } /** - * Imageを解決します。 - * - * Misskeyに対象のImageが登録されていればそれを返し、そうでなければ - * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 - */ + * Resolve Image. + * + * If the target Image is registered in Calckey, return it, otherwise + * Fetch from remote server, register with Calckey and return it. + */ export async function resolveImage(actor: CacheableRemoteUser, value: any): Promise { // TODO - // リモートサーバーからフェッチしてきて登録 + // Fetch from remote server and register return await createImage(actor, value); } diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index d5db2a2cf8..8d700b14d0 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -53,17 +53,17 @@ export function validateNote(object: any, uri: string) { } /** - * Noteをフェッチします。 - * - * Misskeyに対象のNoteが登録されていればそれを返します。 - */ + * Fetch Notes. + * + * If the target Note is registered in Calckey, it will be returned. + */ export async function fetchNote(object: string | IObject): Promise { const dbResolver = new DbResolver(); return await dbResolver.getNoteFromApId(object); } /** - * Noteを作成します。 + * Create a Note. */ export async function createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise { if (resolver == null) resolver = new Resolver(); @@ -89,10 +89,10 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s logger.info(`Creating the Note: ${note.id}`); - // 投稿者をフェッチ + // Fetch author const actor = await resolvePerson(getOneApId(note.attributedTo), resolver) as CacheableRemoteUser; - // 投稿者が凍結されていたらスキップ + // Skip if author is suspended. if (actor.isSuspended) { throw new Error('actor has been suspended'); } @@ -101,10 +101,10 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s let visibility = noteAudience.visibility; const visibleUsers = noteAudience.visibleUsers; - // Audience (to, cc) が指定されてなかった場合 + // If Audience (to, cc) was not specified if (visibility === 'specified' && visibleUsers.length === 0) { - if (typeof value === 'string') { // 入力がstringならばresolverでGETが発生している - // こちらから匿名GET出来たものならばpublic + if (typeof value === 'string') { // If the input is a string, GET occurs in resolver + // Public if you can GET anonymously from here visibility = 'public'; } } @@ -114,7 +114,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s const apMentions = await extractApMentions(note.tag); const apHashtags = await extractApHashtags(note.tag); - // 添付ファイル + // Attachments // TODO: attachmentは必ずしもImageではない // TODO: attachmentは必ずしも配列ではない // Noteがsensitiveなら添付もsensitiveにする @@ -127,7 +127,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s .filter(image => image != null) : []; - // リプライ + // Reply const reply: Note | null = note.inReplyTo ? await resolveNote(note.inReplyTo, resolver).then(x => { if (x == null) { @@ -153,7 +153,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s }) : null; - // 引用 + // Quote let quote: Note | undefined | null; if (note._misskey_quote || note.quoteUrl) { @@ -196,7 +196,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s const cw = note.summary === '' ? null : note.summary; - // テキストのパース + // Text parsing let text: string | null = null; if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source?.content === 'string') { text = note.source.content; @@ -265,23 +265,23 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s } /** - * Noteを解決します。 - * - * Misskeyに対象のNoteが登録されていればそれを返し、そうでなければ - * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 - */ + * Resolve Note. + * + * If the target Note is registered in Calckey, return it, otherwise + * Fetch from remote server, register with Calckey and return it. + */ export async function resolveNote(value: string | IObject, resolver?: Resolver): Promise { const uri = typeof value === 'string' ? value : value.id; if (uri == null) throw new Error('missing uri'); - // ブロックしてたら中断 + // Abort if origin host is blocked const meta = await fetchMeta(); if (meta.blockedHosts.includes(extractDbHost(uri))) throw new StatusError('host blocked', 451, `host ${extractDbHost(uri)} is blocked`); const unlock = await getApLock(uri); try { - //#region このサーバーに既に登録されていたらそれを返す + //#region Returns if already registered with this server const exist = await fetchNote(uri); if (exist) { @@ -293,9 +293,9 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver): throw new StatusError('cannot resolve local note', 400, 'cannot resolve local note'); } - // リモートサーバーからフェッチしてきて登録 - // ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにノートが生成されるが - // 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。 + // Fetch from remote server and register + // If the attached `Note` Object is specified here instead of the uri, the note will be generated without going through the server fetch. + // Since the attached Note Object may be disguised, always specify the uri and fetch it from the server. return await createNote(uri, resolver, true); } finally { unlock(); diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 21ef83af7a..83f81f9797 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -101,17 +101,17 @@ function validateActor(x: IObject, uri: string): IActor { } /** - * Personをフェッチします。 - * - * Misskeyに対象のPersonが登録されていればそれを返します。 - */ + * Fetch a Person. + * + * If the target Person is registered in Calckey, it will be returned. + */ export async function fetchPerson(uri: string, resolver?: Resolver): Promise { if (typeof uri !== 'string') throw new Error('uri is not string'); const cached = uriPersonCache.get(uri); if (cached) return cached; - // URIがこのサーバーを指しているならデータベースからフェッチ + // Fetch from the database if the URI points to this server if (uri.startsWith(config.url + '/')) { const id = uri.split('/').pop(); const u = await Users.findOneBy({ id }); @@ -119,7 +119,7 @@ export async function fetchPerson(uri: string, resolver?: Resolver): Promise { if (typeof uri !== 'string') throw new Error('uri is not string'); @@ -210,7 +210,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise /users/:id のように入力がaliasなときにエラーになることがあるのを対応 + // /users/@a => /users/:id Corresponds to an error that may occur when the input is an alias like const u = await Users.findOneBy({ uri: person.id, }); @@ -235,10 +235,10 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise { logger.info(`extractEmojis: ${e}`); return [] as Emoji[]; diff --git a/packages/backend/src/remote/activitypub/models/question.ts b/packages/backend/src/remote/activitypub/models/question.ts index 94a50d4f71..b87d6ac1bc 100644 --- a/packages/backend/src/remote/activitypub/models/question.ts +++ b/packages/backend/src/remote/activitypub/models/question.ts @@ -43,10 +43,10 @@ export async function extractPollFromQuestion(source: string | IObject, resolver export async function updateQuestion(value: any, resolver?: Resolver) { const uri = typeof value === 'string' ? value : value.id; - // URIがこのサーバーを指しているならスキップ + // Skip if URI points to this server if (uri.startsWith(config.url + '/')) throw new Error('uri points local'); - //#region このサーバーに既に登録されているか + //#region Already registered with this server? const note = await Notes.findOneBy({ uri }); if (note == null) throw new Error('Question is not registed'); diff --git a/packages/backend/src/remote/activitypub/perform.ts b/packages/backend/src/remote/activitypub/perform.ts index a3c10ba945..d79043aafc 100644 --- a/packages/backend/src/remote/activitypub/perform.ts +++ b/packages/backend/src/remote/activitypub/perform.ts @@ -6,7 +6,7 @@ import { updatePerson } from './models/person.js'; export default async (actor: CacheableRemoteUser, activity: IObject): Promise => { await performActivity(actor, activity); - // ついでにリモートユーザーの情報が古かったら更新しておく + // Update the remote user information if it is out of date if (actor.uri) { if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) { setImmediate(() => { diff --git a/packages/backend/src/services/following/create.ts b/packages/backend/src/services/following/create.ts index 72c24676bb..ec6d2e6c99 100644 --- a/packages/backend/src/services/following/create.ts +++ b/packages/backend/src/services/following/create.ts @@ -58,7 +58,7 @@ export async function insertFollowingDoc(followee: { id: User['id']; host: User[ followerId: follower.id, }); - // 通知を作成 + // Create notification that request was accepted. createNotification(follower.id, 'followRequestAccepted', { notifierId: followee.id, }); diff --git a/packages/backend/src/services/following/requests/accept-all.ts b/packages/backend/src/services/following/requests/accept-all.ts index 5fbb549e01..31f3926c08 100644 --- a/packages/backend/src/services/following/requests/accept-all.ts +++ b/packages/backend/src/services/following/requests/accept-all.ts @@ -3,8 +3,8 @@ import { User } from '@/models/entities/user.js'; import { FollowRequests, Users } from '@/models/index.js'; /** - * 指定したユーザー宛てのフォローリクエストをすべて承認 - * @param user ユーザー + * Approve all follow requests for the specified user + * @param user User. */ export default async function(user: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }) { const requests = await FollowRequests.findBy({ diff --git a/packages/backend/src/services/suspend-user.ts b/packages/backend/src/services/suspend-user.ts index e96b06a351..83fc079fd6 100644 --- a/packages/backend/src/services/suspend-user.ts +++ b/packages/backend/src/services/suspend-user.ts @@ -11,7 +11,7 @@ export async function doPostSuspend(user: { id: User['id']; host: User['host'] } publishInternalEvent('userChangeSuspendedState', { id: user.id, isSuspended: true }); if (Users.isLocalUser(user)) { - // 知り得る全SharedInboxにDelete配信 + // Send Delete to all known SharedInboxes const content = renderActivity(renderDelete(`${config.url}/users/${user.id}`, user)); const queue: string[] = [];