Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
This commit is contained in:
commit
b7b8fd4b59
|
@ -15,7 +15,10 @@ jobs:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v3.3.0
|
uses: actions/checkout@v3.3.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v2.3.0
|
uses: docker/setup-buildx-action@v2.3.0
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
|
@ -27,10 +30,13 @@ jobs:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: Build and Push to Docker Hub
|
- name: Build and Push to Docker Hub
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
platforms: ${{ steps.buildx.outputs.platforms }}
|
||||||
|
provenance: false
|
||||||
tags: misskey/misskey:develop
|
tags: misskey/misskey:develop
|
||||||
labels: develop
|
labels: develop
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
|
|
|
@ -13,6 +13,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v3.3.0
|
uses: actions/checkout@v3.3.0
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v2.3.0
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
|
@ -31,9 +36,14 @@ jobs:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: Build and Push to Docker Hub
|
- name: Build and Push to Docker Hub
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
platforms: ${{ steps.buildx.outputs.platforms }}
|
||||||
|
provenance: false
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
14
Dockerfile
14
Dockerfile
|
@ -1,3 +1,5 @@
|
||||||
|
# syntax = docker/dockerfile:1.4
|
||||||
|
|
||||||
ARG NODE_VERSION=18.13.0-bullseye
|
ARG NODE_VERSION=18.13.0-bullseye
|
||||||
|
|
||||||
FROM node:${NODE_VERSION} AS builder
|
FROM node:${NODE_VERSION} AS builder
|
||||||
|
@ -14,16 +16,16 @@ RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /misskey
|
WORKDIR /misskey
|
||||||
|
|
||||||
COPY ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||||
COPY ["scripts", "./scripts"]
|
COPY --link ["scripts", "./scripts"]
|
||||||
COPY ["packages/backend/package.json", "./packages/backend/"]
|
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||||
COPY ["packages/frontend/package.json", "./packages/frontend/"]
|
COPY --link ["packages/frontend/package.json", "./packages/frontend/"]
|
||||||
COPY ["packages/sw/package.json", "./packages/sw/"]
|
COPY --link ["packages/sw/package.json", "./packages/sw/"]
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||||
pnpm i --frozen-lockfile --aggregate-output
|
pnpm i --frozen-lockfile --aggregate-output
|
||||||
|
|
||||||
COPY . ./
|
COPY --link . ./
|
||||||
|
|
||||||
ARG NODE_ENV=production
|
ARG NODE_ENV=production
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { DI } from '@/di-symbols.js';
|
||||||
import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js';
|
import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import Logger from '@/logger.js';
|
import Logger from '@/logger.js';
|
||||||
import type { IRemoteUser, User } from '@/models/entities/User.js';
|
import type { RemoteUser, User } from '@/models/entities/User.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { DriveFile } from '@/models/entities/DriveFile.js';
|
import { DriveFile } from '@/models/entities/DriveFile.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
|
@ -255,7 +255,7 @@ export class DriveService {
|
||||||
return {
|
return {
|
||||||
webpublic: null,
|
webpublic: null,
|
||||||
thumbnail: null,
|
thumbnail: null,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -399,7 +399,7 @@ export class DriveService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async deleteOldFile(user: IRemoteUser) {
|
private async deleteOldFile(user: RemoteUser) {
|
||||||
const q = this.driveFilesRepository.createQueryBuilder('file')
|
const q = this.driveFilesRepository.createQueryBuilder('file')
|
||||||
.where('file.userId = :userId', { userId: user.id })
|
.where('file.userId = :userId', { userId: user.id })
|
||||||
.andWhere('file.isLink = FALSE');
|
.andWhere('file.isLink = FALSE');
|
||||||
|
@ -500,7 +500,7 @@ export class DriveService {
|
||||||
throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
|
throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
|
||||||
} else {
|
} else {
|
||||||
// (アバターまたはバナーを含まず)最も古いファイルを削除する
|
// (アバターまたはバナーを含まず)最も古いファイルを削除する
|
||||||
this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as IRemoteUser);
|
this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as RemoteUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { IsNull } from 'typeorm';
|
import { IsNull } from 'typeorm';
|
||||||
import type { ILocalUser } from '@/models/entities/User.js';
|
import type { LocalUser } from '@/models/entities/User.js';
|
||||||
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 { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
@ -11,7 +11,7 @@ const ACTOR_USERNAME = 'instance.actor' as const;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InstanceActorService {
|
export class InstanceActorService {
|
||||||
private cache: Cache<ILocalUser>;
|
private cache: Cache<LocalUser>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
|
@ -19,24 +19,24 @@ export class InstanceActorService {
|
||||||
|
|
||||||
private createSystemUserService: CreateSystemUserService,
|
private createSystemUserService: CreateSystemUserService,
|
||||||
) {
|
) {
|
||||||
this.cache = new Cache<ILocalUser>(Infinity);
|
this.cache = new Cache<LocalUser>(Infinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async getInstanceActor(): Promise<ILocalUser> {
|
public async getInstanceActor(): Promise<LocalUser> {
|
||||||
const cached = this.cache.get(null);
|
const cached = this.cache.get(null);
|
||||||
if (cached) return cached;
|
if (cached) return cached;
|
||||||
|
|
||||||
const user = await this.usersRepository.findOneBy({
|
const user = await this.usersRepository.findOneBy({
|
||||||
host: IsNull(),
|
host: IsNull(),
|
||||||
username: ACTOR_USERNAME,
|
username: ACTOR_USERNAME,
|
||||||
}) as ILocalUser | undefined;
|
}) as LocalUser | undefined;
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
this.cache.set(null, user);
|
this.cache.set(null, user);
|
||||||
return user;
|
return user;
|
||||||
} else {
|
} else {
|
||||||
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as ILocalUser;
|
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as LocalUser;
|
||||||
this.cache.set(null, created);
|
this.cache.set(null, created);
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, RemoteUser } 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(),
|
||||||
|
@ -291,7 +291,7 @@ export class MessagingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async deliverReadActivity(user: { id: User['id']; host: null; }, recipient: IRemoteUser, messages: MessagingMessage | MessagingMessage[]) {
|
public async deliverReadActivity(user: { id: User['id']; host: null; }, recipient: RemoteUser, messages: MessagingMessage | MessagingMessage[]) {
|
||||||
messages = toArray(messages).filter(x => x.uri);
|
messages = toArray(messages).filter(x => x.uri);
|
||||||
const contents = messages.map(x => this.apRendererService.renderRead(user, x));
|
const contents = messages.map(x => this.apRendererService.renderRead(user, x));
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import type { DriveFile } from '@/models/entities/DriveFile.js';
|
||||||
import type { App } from '@/models/entities/App.js';
|
import type { App } from '@/models/entities/App.js';
|
||||||
import { concat } from '@/misc/prelude/array.js';
|
import { concat } from '@/misc/prelude/array.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js';
|
import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js';
|
||||||
import type { IPoll } from '@/models/entities/Poll.js';
|
import type { IPoll } from '@/models/entities/Poll.js';
|
||||||
import { Poll } from '@/models/entities/Poll.js';
|
import { Poll } from '@/models/entities/Poll.js';
|
||||||
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
|
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
|
||||||
|
@ -52,7 +52,7 @@ class NotificationManager {
|
||||||
private notifier: { id: User['id']; };
|
private notifier: { id: User['id']; };
|
||||||
private note: Note;
|
private note: Note;
|
||||||
private queue: {
|
private queue: {
|
||||||
target: ILocalUser['id'];
|
target: LocalUser['id'];
|
||||||
reason: NotificationType;
|
reason: NotificationType;
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class NotificationManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public push(notifiee: ILocalUser['id'], reason: NotificationType) {
|
public push(notifiee: LocalUser['id'], reason: NotificationType) {
|
||||||
// 自分自身へは通知しない
|
// 自分自身へは通知しない
|
||||||
if (this.notifier.id === notifiee) return;
|
if (this.notifier.id === notifiee) return;
|
||||||
|
|
||||||
|
@ -605,7 +605,7 @@ export class NoteCreateService {
|
||||||
|
|
||||||
// メンションされたリモートユーザーに配送
|
// メンションされたリモートユーザーに配送
|
||||||
for (const u of mentionedUsers.filter(u => this.userEntityService.isRemoteUser(u))) {
|
for (const u of mentionedUsers.filter(u => this.userEntityService.isRemoteUser(u))) {
|
||||||
dm.addDirectRecipe(u as IRemoteUser);
|
dm.addDirectRecipe(u as RemoteUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送
|
// 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Brackets, In } from 'typeorm';
|
import { Brackets, In } from 'typeorm';
|
||||||
import { Injectable, Inject } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js';
|
import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js';
|
||||||
import type { Note, IMentionedRemoteUsers } from '@/models/entities/Note.js';
|
import type { Note, IMentionedRemoteUsers } from '@/models/entities/Note.js';
|
||||||
import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js';
|
import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js';
|
||||||
import { RelayService } from '@/core/RelayService.js';
|
import { RelayService } from '@/core/RelayService.js';
|
||||||
|
@ -159,11 +159,11 @@ export class NoteDeleteService {
|
||||||
|
|
||||||
return await this.usersRepository.find({
|
return await this.usersRepository.find({
|
||||||
where,
|
where,
|
||||||
}) as IRemoteUser[];
|
}) as RemoteUser[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async deliverToConcerned(user: { id: ILocalUser['id']; host: null; }, note: Note, content: any) {
|
private async deliverToConcerned(user: { id: LocalUser['id']; host: null; }, note: Note, content: any) {
|
||||||
this.apDeliverManagerService.deliverToFollowers(user, content);
|
this.apDeliverManagerService.deliverToFollowers(user, content);
|
||||||
this.relayService.deliverToRelays(user, content);
|
this.relayService.deliverToRelays(user, content);
|
||||||
const remoteUsers = await this.getMentionedRemoteUsers(note);
|
const remoteUsers = await this.getMentionedRemoteUsers(note);
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import type { UsersRepository } from '@/models/index.js';
|
import type { UsersRepository } from '@/models/index.js';
|
||||||
import type { ILocalUser, User } from '@/models/entities/User.js';
|
import type { LocalUser, User } from '@/models/entities/User.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
@ -16,9 +16,9 @@ export class ProxyAccountService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async fetch(): Promise<ILocalUser | null> {
|
public async fetch(): Promise<LocalUser | null> {
|
||||||
const meta = await this.metaService.fetch();
|
const meta = await this.metaService.fetch();
|
||||||
if (meta.proxyAccountId == null) return null;
|
if (meta.proxyAccountId == null) return null;
|
||||||
return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as ILocalUser;
|
return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as LocalUser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { IsNull } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { EmojisRepository, BlockingsRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/index.js';
|
import type { EmojisRepository, BlockingsRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/index.js';
|
||||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||||
import type { IRemoteUser, User } from '@/models/entities/User.js';
|
import type { RemoteUser, User } from '@/models/entities/User.js';
|
||||||
import type { Note } from '@/models/entities/Note.js';
|
import type { Note } from '@/models/entities/Note.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import type { NoteReaction } from '@/models/entities/NoteReaction.js';
|
import type { NoteReaction } from '@/models/entities/NoteReaction.js';
|
||||||
|
@ -181,7 +181,7 @@ export class ReactionService {
|
||||||
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 });
|
||||||
dm.addDirectRecipe(reactee as IRemoteUser);
|
dm.addDirectRecipe(reactee as RemoteUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['public', 'home', 'followers'].includes(note.visibility)) {
|
if (['public', 'home', 'followers'].includes(note.visibility)) {
|
||||||
|
@ -189,7 +189,7 @@ export class ReactionService {
|
||||||
} else if (note.visibility === 'specified') {
|
} else if (note.visibility === 'specified') {
|
||||||
const visibleUsers = await Promise.all(note.visibleUserIds.map(id => this.usersRepository.findOneBy({ id })));
|
const visibleUsers = await Promise.all(note.visibleUserIds.map(id => this.usersRepository.findOneBy({ id })));
|
||||||
for (const u of visibleUsers.filter(u => u && this.userEntityService.isRemoteUser(u))) {
|
for (const u of visibleUsers.filter(u => u && this.userEntityService.isRemoteUser(u))) {
|
||||||
dm.addDirectRecipe(u as IRemoteUser);
|
dm.addDirectRecipe(u as RemoteUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ export class ReactionService {
|
||||||
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 });
|
||||||
dm.addDirectRecipe(reactee as IRemoteUser);
|
dm.addDirectRecipe(reactee as RemoteUser);
|
||||||
}
|
}
|
||||||
dm.addFollowersRecipe();
|
dm.addFollowersRecipe();
|
||||||
dm.execute();
|
dm.execute();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { IsNull } from 'typeorm';
|
import { IsNull } from 'typeorm';
|
||||||
import type { ILocalUser, User } from '@/models/entities/User.js';
|
import type { LocalUser, User } from '@/models/entities/User.js';
|
||||||
import type { RelaysRepository, UsersRepository } from '@/models/index.js';
|
import type { RelaysRepository, UsersRepository } from '@/models/index.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import { Cache } from '@/misc/cache.js';
|
import { Cache } from '@/misc/cache.js';
|
||||||
|
@ -34,16 +34,16 @@ export class RelayService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async getRelayActor(): Promise<ILocalUser> {
|
private async getRelayActor(): Promise<LocalUser> {
|
||||||
const user = await this.usersRepository.findOneBy({
|
const user = await this.usersRepository.findOneBy({
|
||||||
host: IsNull(),
|
host: IsNull(),
|
||||||
username: ACTOR_USERNAME,
|
username: ACTOR_USERNAME,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user) return user as ILocalUser;
|
if (user) return user as LocalUser;
|
||||||
|
|
||||||
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME);
|
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME);
|
||||||
return created as ILocalUser;
|
return created as LocalUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
|
|
@ -4,7 +4,7 @@ import chalk from 'chalk';
|
||||||
import { IsNull } from 'typeorm';
|
import { IsNull } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { UsersRepository } from '@/models/index.js';
|
import type { UsersRepository } from '@/models/index.js';
|
||||||
import type { IRemoteUser, User } from '@/models/entities/User.js';
|
import type { RemoteUser, User } from '@/models/entities/User.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
import { UtilityService } from '@/core/UtilityService.js';
|
import { UtilityService } from '@/core/UtilityService.js';
|
||||||
|
@ -60,7 +60,7 @@ export class RemoteUserResolveService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await this.usersRepository.findOneBy({ usernameLower, host }) as IRemoteUser | null;
|
const user = await this.usersRepository.findOneBy({ usernameLower, host }) as RemoteUser | null;
|
||||||
|
|
||||||
const acctLower = `${usernameLower}@${host}`;
|
const acctLower = `${usernameLower}@${host}`;
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ export class RemoteUserResolveService {
|
||||||
const self = await this.resolveSelf(acctLower);
|
const self = await this.resolveSelf(acctLower);
|
||||||
|
|
||||||
if (user.uri !== self.href) {
|
if (user.uri !== self.href) {
|
||||||
// if uri mismatch, Fix (user@host <=> AP's Person id(IRemoteUser.uri)) mapping.
|
// if uri mismatch, Fix (user@host <=> AP's Person id(RemoteUser.uri)) mapping.
|
||||||
this.logger.info(`uri missmatch: ${acctLower}`);
|
this.logger.info(`uri missmatch: ${acctLower}`);
|
||||||
this.logger.info(`recovery missmatch uri for (username=${username}, host=${host}) from ${user.uri} to ${self.href}`);
|
this.logger.info(`recovery missmatch uri for (username=${username}, host=${host}) from ${user.uri} to ${self.href}`);
|
||||||
|
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 { LocalUser, 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<LocalUser | null>;
|
||||||
public localUserByIdCache: Cache<CacheableLocalUser>;
|
public localUserByIdCache: Cache<LocalUser>;
|
||||||
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<LocalUser | null>(Infinity);
|
||||||
this.localUserByIdCache = new Cache<CacheableLocalUser>(Infinity);
|
this.localUserByIdCache = new Cache<LocalUser>(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)) {
|
||||||
|
@ -58,7 +58,7 @@ export class UserCacheService implements OnApplicationShutdown {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'userTokenRegenerated': {
|
case 'userTokenRegenerated': {
|
||||||
const user = await this.usersRepository.findOneByOrFail({ id: body.id }) as ILocalUser;
|
const user = await this.usersRepository.findOneByOrFail({ id: body.id }) as LocalUser;
|
||||||
this.localUserByNativeTokenCache.delete(body.oldToken);
|
this.localUserByNativeTokenCache.delete(body.oldToken);
|
||||||
this.localUserByNativeTokenCache.set(body.newToken, user);
|
this.localUserByNativeTokenCache.set(body.newToken, user);
|
||||||
break;
|
break;
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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 { LocalUser, RemoteUser, 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';
|
||||||
|
@ -21,16 +21,16 @@ import Logger from '../logger.js';
|
||||||
|
|
||||||
const logger = new Logger('following/create');
|
const logger = new Logger('following/create');
|
||||||
|
|
||||||
type Local = ILocalUser | {
|
type Local = LocalUser | {
|
||||||
id: ILocalUser['id'];
|
id: LocalUser['id'];
|
||||||
host: ILocalUser['host'];
|
host: LocalUser['host'];
|
||||||
uri: ILocalUser['uri']
|
uri: LocalUser['uri']
|
||||||
};
|
};
|
||||||
type Remote = IRemoteUser | {
|
type Remote = RemoteUser | {
|
||||||
id: IRemoteUser['id'];
|
id: RemoteUser['id'];
|
||||||
host: IRemoteUser['host'];
|
host: RemoteUser['host'];
|
||||||
uri: IRemoteUser['uri'];
|
uri: RemoteUser['uri'];
|
||||||
inbox: IRemoteUser['inbox'];
|
inbox: RemoteUser['inbox'];
|
||||||
};
|
};
|
||||||
type Both = Local | Remote;
|
type Both = Local | Remote;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
|
|
@ -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 { RemoteUser, 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: RemoteUser, 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: RemoteUser) {
|
||||||
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: RemoteUser) {
|
||||||
return (
|
return (
|
||||||
id === (actor.followersUri ?? `${actor.uri}/followers`)
|
id === (actor.followersUri ?? `${actor.uri}/followers`)
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 { RemoteUser, 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: RemoteUser;
|
||||||
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 RemoteUser,
|
||||||
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: RemoteUser;
|
||||||
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 RemoteUser;
|
||||||
|
|
||||||
if (user == null) return null;
|
if (user == null) return null;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { IsNull, Not } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { FollowingsRepository, UsersRepository } from '@/models/index.js';
|
import type { FollowingsRepository, UsersRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js';
|
import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.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';
|
||||||
|
@ -18,7 +18,7 @@ interface IFollowersRecipe extends IRecipe {
|
||||||
|
|
||||||
interface IDirectRecipe extends IRecipe {
|
interface IDirectRecipe extends IRecipe {
|
||||||
type: 'Direct';
|
type: 'Direct';
|
||||||
to: IRemoteUser;
|
to: RemoteUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isFollowers = (recipe: any): recipe is IFollowersRecipe =>
|
const isFollowers = (recipe: any): recipe is IFollowersRecipe =>
|
||||||
|
@ -50,7 +50,7 @@ export class ApDeliverManagerService {
|
||||||
* @param from Followee
|
* @param from Followee
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public async deliverToFollowers(actor: { id: ILocalUser['id']; host: null; }, activity: any) {
|
public async deliverToFollowers(actor: { id: LocalUser['id']; host: null; }, activity: any) {
|
||||||
const manager = new DeliverManager(
|
const manager = new DeliverManager(
|
||||||
this.userEntityService,
|
this.userEntityService,
|
||||||
this.followingsRepository,
|
this.followingsRepository,
|
||||||
|
@ -68,7 +68,7 @@ export class ApDeliverManagerService {
|
||||||
* @param to Target user
|
* @param to Target user
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public async deliverToUser(actor: { id: ILocalUser['id']; host: null; }, activity: any, to: IRemoteUser) {
|
public async deliverToUser(actor: { id: LocalUser['id']; host: null; }, activity: any, to: RemoteUser) {
|
||||||
const manager = new DeliverManager(
|
const manager = new DeliverManager(
|
||||||
this.userEntityService,
|
this.userEntityService,
|
||||||
this.followingsRepository,
|
this.followingsRepository,
|
||||||
|
@ -132,7 +132,7 @@ class DeliverManager {
|
||||||
* @param to To
|
* @param to To
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public addDirectRecipe(to: IRemoteUser) {
|
public addDirectRecipe(to: RemoteUser) {
|
||||||
const recipe = {
|
const recipe = {
|
||||||
type: 'Direct',
|
type: 'Direct',
|
||||||
to,
|
to,
|
||||||
|
|
|
@ -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 { RemoteUser } 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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: RemoteUser, 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';
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { v4 as uuid } from 'uuid';
|
||||||
import * as mfm from 'mfm-js';
|
import * as mfm from 'mfm-js';
|
||||||
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 { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js';
|
import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
|
||||||
import type { IMentionedRemoteUsers, Note } from '@/models/entities/Note.js';
|
import type { IMentionedRemoteUsers, Note } from '@/models/entities/Note.js';
|
||||||
import type { Blocking } from '@/models/entities/Blocking.js';
|
import type { Blocking } from '@/models/entities/Blocking.js';
|
||||||
import type { Relay } from '@/models/entities/Relay.js';
|
import type { Relay } from '@/models/entities/Relay.js';
|
||||||
|
@ -70,7 +70,7 @@ export class ApRendererService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public renderAdd(user: ILocalUser, target: any, object: any): IAdd {
|
public renderAdd(user: LocalUser, 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}`,
|
||||||
|
@ -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: IObject, content: string): IFlag {
|
public renderFlag(user: LocalUser, object: IObject | string | string[], content: string): IFlag {
|
||||||
return {
|
return {
|
||||||
type: 'Flag',
|
type: 'Flag',
|
||||||
actor: `${this.config.url}/users/${user.id}`,
|
actor: `${this.config.url}/users/${user.id}`,
|
||||||
|
@ -191,7 +191,7 @@ export class ApRendererService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public renderFollowRelay(relay: Relay, relayActor: ILocalUser): IFollow {
|
public renderFollowRelay(relay: Relay, relayActor: LocalUser): IFollow {
|
||||||
return {
|
return {
|
||||||
id: `${this.config.url}/activities/follow-relay/${relay.id}`,
|
id: `${this.config.url}/activities/follow-relay/${relay.id}`,
|
||||||
type: 'Follow',
|
type: 'Follow',
|
||||||
|
@ -244,7 +244,7 @@ export class ApRendererService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public renderKey(user: ILocalUser, key: UserKeypair, postfix?: string): IKey {
|
public renderKey(user: LocalUser, 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',
|
||||||
|
@ -287,8 +287,8 @@ export class ApRendererService {
|
||||||
public renderMention(mention: User): IApMention {
|
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 LocalUser).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 LocalUser).username}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ export class ApRendererService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async renderPerson(user: ILocalUser) {
|
public async renderPerson(user: LocalUser) {
|
||||||
const id = `${this.config.url}/users/${user.id}`;
|
const id = `${this.config.url}/users/${user.id}`;
|
||||||
const isSystem = !!user.username.match(/\./);
|
const isSystem = !!user.username.match(/\./);
|
||||||
|
|
||||||
|
@ -594,7 +594,7 @@ export class ApRendererService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser): ICreate {
|
public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: RemoteUser): 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}`,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import type { ILocalUser } from '@/models/entities/User.js';
|
import type { LocalUser } from '@/models/entities/User.js';
|
||||||
import { InstanceActorService } from '@/core/InstanceActorService.js';
|
import { InstanceActorService } from '@/core/InstanceActorService.js';
|
||||||
import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository } from '@/models/index.js';
|
import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
|
@ -18,7 +18,7 @@ import type { IObject, ICollection, IOrderedCollection } from './type.js';
|
||||||
|
|
||||||
export class Resolver {
|
export class Resolver {
|
||||||
private history: Set<string>;
|
private history: Set<string>;
|
||||||
private user?: ILocalUser;
|
private user?: LocalUser;
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -133,7 +133,7 @@ export class Resolver {
|
||||||
});
|
});
|
||||||
case 'users':
|
case 'users':
|
||||||
return this.usersRepository.findOneByOrFail({ id: parsed.id })
|
return this.usersRepository.findOneByOrFail({ id: parsed.id })
|
||||||
.then(user => this.apRendererService.renderPerson(user as ILocalUser));
|
.then(user => this.apRendererService.renderPerson(user as LocalUser));
|
||||||
case 'questions':
|
case 'questions':
|
||||||
// Polls are indexed by the note they are attached to.
|
// Polls are indexed by the note they are attached to.
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
|
|
|
@ -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 { RemoteUser } 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: RemoteUser, 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: RemoteUser, value: any): Promise<DriveFile> {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
// リモートサーバーからフェッチしてきて登録
|
// リモートサーバーからフェッチしてきて登録
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { RemoteUser } 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 RemoteUser;
|
||||||
|
|
||||||
// 投稿者が凍結されていたらスキップ
|
// 投稿者が凍結されていたらスキップ
|
||||||
if (actor.isSuspended) {
|
if (actor.isSuspended) {
|
||||||
|
|
|
@ -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 { RemoteUser } 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);
|
||||||
|
@ -259,7 +259,7 @@ export class ApPersonService implements OnModuleInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create user
|
// Create user
|
||||||
let user: IRemoteUser;
|
let user: RemoteUser;
|
||||||
try {
|
try {
|
||||||
// Start transaction
|
// Start transaction
|
||||||
await this.db.transaction(async transactionalEntityManager => {
|
await this.db.transaction(async transactionalEntityManager => {
|
||||||
|
@ -284,7 +284,7 @@ export class ApPersonService implements OnModuleInit {
|
||||||
isBot,
|
isBot,
|
||||||
isCat: (person as any).isCat === true,
|
isCat: (person as any).isCat === true,
|
||||||
showTimelineReplies: false,
|
showTimelineReplies: false,
|
||||||
})) as IRemoteUser;
|
})) as RemoteUser;
|
||||||
|
|
||||||
await transactionalEntityManager.save(new UserProfile({
|
await transactionalEntityManager.save(new UserProfile({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
|
@ -313,7 +313,7 @@ export class ApPersonService implements OnModuleInit {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (u) {
|
if (u) {
|
||||||
user = u as IRemoteUser;
|
user = u as RemoteUser;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('already registered');
|
throw new Error('already registered');
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ export class ApPersonService implements OnModuleInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region このサーバーに既に登録されているか
|
//#region このサーバーに既に登録されているか
|
||||||
const exist = await this.usersRepository.findOneBy({ uri }) as IRemoteUser;
|
const exist = await this.usersRepository.findOneBy({ uri }) as RemoteUser;
|
||||||
|
|
||||||
if (exist == null) {
|
if (exist == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -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
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||||
import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js';
|
import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js';
|
||||||
import { Cache } from '@/misc/cache.js';
|
import { Cache } from '@/misc/cache.js';
|
||||||
import type { Instance } from '@/models/entities/Instance.js';
|
import type { Instance } from '@/models/entities/Instance.js';
|
||||||
import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js';
|
import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
|
||||||
import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js';
|
import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js';
|
||||||
import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, MessagingMessagesRepository, UserGroupJoiningsRepository, AnnouncementsRepository, AntennaNotesRepository, PagesRepository, UserProfile } from '@/models/index.js';
|
import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, MessagingMessagesRepository, UserGroupJoiningsRepository, AnnouncementsRepository, AntennaNotesRepository, PagesRepository, UserProfile } from '@/models/index.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
@ -32,13 +32,13 @@ type IsMeAndIsUserDetailed<ExpectsMe extends boolean | null, Detailed extends bo
|
||||||
|
|
||||||
const ajv = new Ajv();
|
const ajv = new Ajv();
|
||||||
|
|
||||||
function isLocalUser(user: User): user is ILocalUser;
|
function isLocalUser(user: User): user is LocalUser;
|
||||||
function isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; };
|
function isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; };
|
||||||
function isLocalUser(user: User | { host: User['host'] }): boolean {
|
function isLocalUser(user: User | { host: User['host'] }): boolean {
|
||||||
return user.host == null;
|
return user.host == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRemoteUser(user: User): user is IRemoteUser;
|
function isRemoteUser(user: User): user is RemoteUser;
|
||||||
function isRemoteUser<T extends { host: User['host'] }>(user: T): user is T & { host: string; };
|
function isRemoteUser<T extends { host: User['host'] }>(user: T): user is T & { host: string; };
|
||||||
function isRemoteUser(user: User | { host: User['host'] }): boolean {
|
function isRemoteUser(user: User | { host: User['host'] }): boolean {
|
||||||
return !isLocalUser(user);
|
return !isLocalUser(user);
|
||||||
|
|
|
@ -215,21 +215,16 @@ export class User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILocalUser extends User {
|
export type LocalUser = User & {
|
||||||
host: null;
|
host: null;
|
||||||
|
uri: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRemoteUser extends User {
|
export type RemoteUser = User & {
|
||||||
host: string;
|
host: string;
|
||||||
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;
|
||||||
|
|
|
@ -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 { RemoteUser } 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: RemoteUser;
|
||||||
key: UserPublickey | null;
|
key: UserPublickey | null;
|
||||||
} | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId);
|
} | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId);
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as url from '@/misc/prelude/url.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
import type { ILocalUser, User } from '@/models/entities/User.js';
|
import type { LocalUser, User } from '@/models/entities/User.js';
|
||||||
import { UserKeypairStoreService } from '@/core/UserKeypairStoreService.js';
|
import { UserKeypairStoreService } from '@/core/UserKeypairStoreService.js';
|
||||||
import type { Following } from '@/models/entities/Following.js';
|
import type { Following } from '@/models/entities/Following.js';
|
||||||
import { countIf } from '@/misc/prelude/array.js';
|
import { countIf } from '@/misc/prelude/array.js';
|
||||||
|
@ -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.addContext(await this.apRendererService.renderPerson(user as ILocalUser)));
|
return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as LocalUser)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
|
|
@ -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 { LocalUser, 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';
|
||||||
|
@ -168,7 +168,7 @@ export class ApiCallService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async logIp(request: FastifyRequest, user: ILocalUser) {
|
private async logIp(request: FastifyRequest, user: LocalUser) {
|
||||||
const meta = await this.metaService.fetch();
|
const meta = await this.metaService.fetch();
|
||||||
if (!meta.enableIpLogging) return;
|
if (!meta.enableIpLogging) return;
|
||||||
const ip = request.ip;
|
const ip = request.ip;
|
||||||
|
@ -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: LocalUser | null | undefined,
|
||||||
token: AccessToken | null | undefined,
|
token: AccessToken | null | undefined,
|
||||||
data: any,
|
data: any,
|
||||||
file: {
|
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 { LocalUser } 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,14 +36,14 @@ 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<[LocalUser | null | undefined, AccessToken | null | undefined]> {
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
return [null, null];
|
return [null, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNativeToken(token)) {
|
if (isNativeToken(token)) {
|
||||||
const user = await this.userCacheService.localUserByNativeTokenCache.fetch(token,
|
const user = await this.userCacheService.localUserByNativeTokenCache.fetch(token,
|
||||||
() => this.usersRepository.findOneBy({ token }) as Promise<ILocalUser | null>);
|
() => this.usersRepository.findOneBy({ token }) as Promise<LocalUser | null>);
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new AuthenticationError('user not found');
|
throw new AuthenticationError('user not found');
|
||||||
|
@ -70,7 +70,7 @@ export class AuthenticateService {
|
||||||
const user = await this.userCacheService.localUserByIdCache.fetch(accessToken.userId,
|
const user = await this.userCacheService.localUserByIdCache.fetch(accessToken.userId,
|
||||||
() => this.usersRepository.findOneBy({
|
() => this.usersRepository.findOneBy({
|
||||||
id: accessToken.userId,
|
id: accessToken.userId,
|
||||||
}) as Promise<ILocalUser>);
|
}) as Promise<LocalUser>);
|
||||||
|
|
||||||
if (accessToken.appId) {
|
if (accessToken.appId) {
|
||||||
const app = await this.appCache.fetch(accessToken.appId,
|
const app = await this.appCache.fetch(accessToken.appId,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { DI } from '@/di-symbols.js';
|
||||||
import type { UserSecurityKeysRepository, SigninsRepository, UserProfilesRepository, AttestationChallengesRepository, UsersRepository } from '@/models/index.js';
|
import type { UserSecurityKeysRepository, SigninsRepository, UserProfilesRepository, AttestationChallengesRepository, UsersRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { getIpHash } from '@/misc/get-ip-hash.js';
|
import { getIpHash } from '@/misc/get-ip-hash.js';
|
||||||
import type { ILocalUser } from '@/models/entities/User.js';
|
import type { LocalUser } from '@/models/entities/User.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import { TwoFactorAuthenticationService } from '@/core/TwoFactorAuthenticationService.js';
|
import { TwoFactorAuthenticationService } from '@/core/TwoFactorAuthenticationService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
@ -105,7 +105,7 @@ export class SigninApiService {
|
||||||
const user = await this.usersRepository.findOneBy({
|
const user = await this.usersRepository.findOneBy({
|
||||||
usernameLower: username.toLowerCase(),
|
usernameLower: username.toLowerCase(),
|
||||||
host: IsNull(),
|
host: IsNull(),
|
||||||
}) as ILocalUser;
|
}) as LocalUser;
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return error(404, {
|
return error(404, {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { DI } from '@/di-symbols.js';
|
||||||
import type { SigninsRepository, UsersRepository } from '@/models/index.js';
|
import type { SigninsRepository, UsersRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import type { ILocalUser } from '@/models/entities/User.js';
|
import type { LocalUser } from '@/models/entities/User.js';
|
||||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||||
import { SigninEntityService } from '@/core/entities/SigninEntityService.js';
|
import { SigninEntityService } from '@/core/entities/SigninEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
@ -25,7 +25,7 @@ export class SigninService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public signin(request: FastifyRequest, reply: FastifyReply, user: ILocalUser) {
|
public signin(request: FastifyRequest, reply: FastifyReply, user: LocalUser) {
|
||||||
setImmediate(async () => {
|
setImmediate(async () => {
|
||||||
// Append signin history
|
// Append signin history
|
||||||
const record = await this.signinsRepository.insert({
|
const record = await this.signinsRepository.insert({
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { IdService } from '@/core/IdService.js';
|
||||||
import { SignupService } from '@/core/SignupService.js';
|
import { SignupService } from '@/core/SignupService.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { EmailService } from '@/core/EmailService.js';
|
import { EmailService } from '@/core/EmailService.js';
|
||||||
import { ILocalUser } from '@/models/entities/User.js';
|
import { LocalUser } from '@/models/entities/User.js';
|
||||||
import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
|
import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { SigninService } from './SigninService.js';
|
import { SigninService } from './SigninService.js';
|
||||||
|
@ -194,7 +194,7 @@ export class SignupApiService {
|
||||||
emailVerifyCode: null,
|
emailVerifyCode: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.signinService.signin(request, reply, account as ILocalUser);
|
return this.signinService.signin(request, reply, account as LocalUser);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new FastifyReplyError(400, typeof err === 'string' ? err : (err as Error).toString());
|
throw new FastifyReplyError(400, typeof err === 'string' ? err : (err as Error).toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { LocalUser } 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 ? LocalUser : LocalUser | 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 ? LocalUser : LocalUser | 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 ? LocalUser : LocalUser | 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) {
|
||||||
|
|
|
@ -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 { LocalUser, 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: LocalUser | 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: LocalUser | 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',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Not } from 'typeorm';
|
import { Not } from 'typeorm';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import type { UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js';
|
import type { UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js';
|
||||||
import type { IRemoteUser } from '@/models/entities/User.js';
|
import type { RemoteUser } from '@/models/entities/User.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { GetterService } from '@/server/api/GetterService.js';
|
import { GetterService } from '@/server/api/GetterService.js';
|
||||||
|
@ -160,7 +160,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 RemoteUser;
|
||||||
|
|
||||||
this.queueService.deliver(me, this.apRendererService.addContext(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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import type { UserGroupJoiningsRepository, UsersRepository, MessagingMessagesRepository } from '@/models/index.js';
|
import type { UserGroupJoiningsRepository, UsersRepository, MessagingMessagesRepository } from '@/models/index.js';
|
||||||
import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js';
|
import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js';
|
||||||
import type { UserGroup } from '@/models/entities/UserGroup.js';
|
import type { UserGroup } from '@/models/entities/UserGroup.js';
|
||||||
import { MessagingService } from '@/core/MessagingService.js';
|
import { MessagingService } from '@/core/MessagingService.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
|
@ -89,7 +89,7 @@ class MessagingChannel extends Channel {
|
||||||
// リモートユーザーからのメッセージだったら既読配信
|
// リモートユーザーからのメッセージだったら既読配信
|
||||||
if (this.userEntityService.isLocalUser(this.user!) && this.userEntityService.isRemoteUser(this.otherparty!)) {
|
if (this.userEntityService.isLocalUser(this.user!) && this.userEntityService.isRemoteUser(this.otherparty!)) {
|
||||||
this.messagingMessagesRepository.findOneBy({ id: body.id }).then(message => {
|
this.messagingMessagesRepository.findOneBy({ id: body.id }).then(message => {
|
||||||
if (message) this.messagingService.deliverReadActivity(this.user as ILocalUser, this.otherparty as IRemoteUser, message);
|
if (message) this.messagingService.deliverReadActivity(this.user as LocalUser, this.otherparty as RemoteUser, message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (this.groupId) {
|
} else if (this.groupId) {
|
||||||
|
|
Loading…
Reference in New Issue