This commit is contained in:
syuilo 2022-09-19 03:11:50 +09:00
parent 92c78218bc
commit a2eac9fff6
82 changed files with 671 additions and 671 deletions

View File

@ -15,7 +15,7 @@ let isSupportedCpu: undefined | boolean = undefined;
@Injectable()
export class AiService {
#model: nsfw.NSFWJS;
private model: nsfw.NSFWJS;
constructor(
@Inject(DI.config)
@ -26,7 +26,7 @@ export class AiService {
public async detectSensitive(path: string): Promise<nsfw.predictionType[] | null> {
try {
if (isSupportedCpu === undefined) {
const cpuFlags = await this.#getCpuFlags();
const cpuFlags = await this.getCpuFlags();
isSupportedCpu = REQUIRED_CPU_FLAGS.every(required => cpuFlags.includes(required));
}
@ -37,12 +37,12 @@ export class AiService {
const tf = await import('@tensorflow/tfjs-node');
if (this.#model == null) this.#model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
if (this.model == null) this.model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
const buffer = await fs.promises.readFile(path);
const image = await tf.node.decodeImage(buffer, 3) as any;
try {
const predictions = await this.#model.classify(image);
const predictions = await this.model.classify(image);
return predictions;
} finally {
image.dispose();
@ -53,7 +53,7 @@ export class AiService {
}
}
async #getCpuFlags(): Promise<string[]> {
private async getCpuFlags(): Promise<string[]> {
const str = await si.cpuFlags();
return str.split(/\s+/);
}

View File

@ -16,9 +16,9 @@ import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
export class AntennaService implements OnApplicationShutdown {
#antennasFetched: boolean;
#antennas: Antenna[];
#blockingCache: Cache<User['id'][]>;
private antennasFetched: boolean;
private antennas: Antenna[];
private blockingCache: Cache<User['id'][]>;
constructor(
@Inject(DI.redisSubscriber)
@ -49,9 +49,9 @@ export class AntennaService implements OnApplicationShutdown {
private idService: IdService,
private globalEventServie: GlobalEventService,
) {
this.#antennasFetched = false;
this.#antennas = [];
this.#blockingCache = new Cache<User['id'][]>(1000 * 60 * 5);
this.antennasFetched = false;
this.antennas = [];
this.blockingCache = new Cache<User['id'][]>(1000 * 60 * 5);
this.redisSubscriber.on('message', this.onRedisMessage);
}
@ -67,13 +67,13 @@ export class AntennaService implements OnApplicationShutdown {
const { type, body } = obj.message;
switch (type) {
case 'antennaCreated':
this.#antennas.push(body);
this.antennas.push(body);
break;
case 'antennaUpdated':
this.#antennas[this.#antennas.findIndex(a => a.id === body.id)] = body;
this.antennas[this.antennas.findIndex(a => a.id === body.id)] = body;
break;
case 'antennaDeleted':
this.#antennas = this.#antennas.filter(a => a.id !== body.id);
this.antennas = this.antennas.filter(a => a.id !== body.id);
break;
default:
break;
@ -137,7 +137,7 @@ export class AntennaService implements OnApplicationShutdown {
if (note.visibility === 'specified') return false;
// アンテナ作成者がノート作成者にブロックされていたらスキップ
const blockings = await this.#blockingCache.fetch(noteUser.id, () => this.blockingsRepository.findBy({ blockerId: noteUser.id }).then(res => res.map(x => x.blockeeId)));
const blockings = await this.blockingCache.fetch(noteUser.id, () => this.blockingsRepository.findBy({ blockerId: noteUser.id }).then(res => res.map(x => x.blockeeId)));
if (blockings.some(blocking => blocking === antenna.userId)) return false;
if (note.visibility === 'followers') {
@ -218,11 +218,11 @@ export class AntennaService implements OnApplicationShutdown {
}
public async getAntennas() {
if (!this.#antennasFetched) {
this.#antennas = await this.antennasRepository.find();
this.#antennasFetched = true;
if (!this.antennasFetched) {
this.antennas = await this.antennasRepository.find();
this.antennasFetched = true;
}
return this.#antennas;
return this.antennas;
}
}

View File

@ -11,13 +11,13 @@ const retryDelay = 100;
@Injectable()
export class AppLockService {
#lock: (key: string, timeout?: number) => Promise<() => void>;
private lock: (key: string, timeout?: number) => Promise<() => void>;
constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
) {
this.#lock = promisify(redisLock(this.redisClient, retryDelay));
this.lock = promisify(redisLock(this.redisClient, retryDelay));
}
/**
@ -27,14 +27,14 @@ export class AppLockService {
* @returns Unlock function
*/
public getApLock(uri: string, timeout = 30 * 1000): Promise<() => void> {
return this.#lock(`ap-object:${uri}`, timeout);
return this.lock(`ap-object:${uri}`, timeout);
}
public getFetchInstanceMetadataLock(host: string, timeout = 30 * 1000): Promise<() => void> {
return this.#lock(`instance:${host}`, timeout);
return this.lock(`instance:${host}`, timeout);
}
public getChartInsertLock(lockKey: string, timeout = 30 * 1000): Promise<() => void> {
return this.#lock(`chart-insert:${lockKey}`, timeout);
return this.lock(`chart-insert:${lockKey}`, timeout);
}
}

View File

@ -19,7 +19,7 @@ export class CaptchaService {
) {
}
async #getCaptchaResponse(url: string, secret: string, response: string): Promise<CaptchaResponse> {
private async getCaptchaResponse(url: string, secret: string, response: string): Promise<CaptchaResponse> {
const params = new URLSearchParams({
secret,
response,
@ -46,7 +46,7 @@ export class CaptchaService {
}
public async verifyRecaptcha(secret: string, response: string): Promise<void> {
const result = await this.#getCaptchaResponse('https://www.recaptcha.net/recaptcha/api/siteverify', secret, response).catch(e => {
const result = await this.getCaptchaResponse('https://www.recaptcha.net/recaptcha/api/siteverify', secret, response).catch(e => {
throw `recaptcha-request-failed: ${e}`;
});
@ -57,7 +57,7 @@ export class CaptchaService {
}
public async verifyHcaptcha(secret: string, response: string): Promise<void> {
const result = await this.#getCaptchaResponse('https://hcaptcha.com/siteverify', secret, response).catch(e => {
const result = await this.getCaptchaResponse('https://hcaptcha.com/siteverify', secret, response).catch(e => {
throw `hcaptcha-request-failed: ${e}`;
});

View File

@ -78,8 +78,8 @@ export class CreateNotificationService {
this.globalEventServie.publishMainStream(notifieeId, 'unreadNotification', packed);
this.pushNotificationService.pushNotification(notifieeId, 'notification', packed);
if (type === 'follow') this.#emailNotificationFollow(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! }));
if (type === 'receiveFollowRequest') this.#emailNotificationReceiveFollowRequest(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! }));
if (type === 'follow') this.emailNotificationFollow(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! }));
if (type === 'receiveFollowRequest') this.emailNotificationReceiveFollowRequest(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! }));
}, 2000);
return notification;
@ -90,7 +90,7 @@ export class CreateNotificationService {
// TODO: locale ファイルをクライアント用とサーバー用で分けたい
async #emailNotificationFollow(userId: User['id'], follower: User) {
private async emailNotificationFollow(userId: User['id'], follower: User) {
/*
const userProfile = await UserProfiles.findOneByOrFail({ userId: userId });
if (!userProfile.email || !userProfile.emailNotificationTypes.includes('follow')) return;
@ -101,7 +101,7 @@ export class CreateNotificationService {
*/
}
async #emailNotificationReceiveFollowRequest(userId: User['id'], follower: User) {
private async emailNotificationReceiveFollowRequest(userId: User['id'], follower: User) {
/*
const userProfile = await UserProfiles.findOneByOrFail({ userId: userId });
if (!userProfile.email || !userProfile.emailNotificationTypes.includes('receiveFollowRequest')) return;

View File

@ -23,7 +23,7 @@ type PopulatedEmoji = {
@Injectable()
export class CustomEmojiService {
#cache: Cache<Emoji | null>;
private cache: Cache<Emoji | null>;
constructor(
@Inject(DI.config)
@ -40,7 +40,7 @@ export class CustomEmojiService {
private utilityService: UtilityService,
private reactionService: ReactionService,
) {
this.#cache = new Cache<Emoji | null>(1000 * 60 * 60 * 12);
this.cache = new Cache<Emoji | null>(1000 * 60 * 60 * 12);
}
public async add(data: {
@ -67,7 +67,7 @@ export class CustomEmojiService {
return emoji;
}
#normalizeHost(src: string | undefined, noteUserHost: string | null): string | null {
private normalizeHost(src: string | undefined, noteUserHost: string | null): string | null {
// クエリに使うホスト
let host = src === '.' ? null // .はローカルホスト (ここがマッチするのはリアクションのみ)
: src === undefined ? noteUserHost // ノートなどでホスト省略表記の場合はローカルホスト (ここがリアクションにマッチすることはない)
@ -79,14 +79,14 @@ export class CustomEmojiService {
return host;
}
#parseEmojiStr(emojiName: string, noteUserHost: string | null) {
private parseEmojiStr(emojiName: string, noteUserHost: string | null) {
const match = emojiName.match(/^(\w+)(?:@([\w.-]+))?$/);
if (!match) return { name: null, host: null };
const name = match[1];
// ホスト正規化
const host = this.utilityService.toPunyNullable(this.#normalizeHost(match[2], noteUserHost));
const host = this.utilityService.toPunyNullable(this.normalizeHost(match[2], noteUserHost));
return { name, host };
}
@ -98,7 +98,7 @@ export class CustomEmojiService {
* @returns , nullは未マッチを意味する
*/
public async populateEmoji(emojiName: string, noteUserHost: string | null): Promise<PopulatedEmoji | null> {
const { name, host } = this.#parseEmojiStr(emojiName, noteUserHost);
const { name, host } = this.parseEmojiStr(emojiName, noteUserHost);
if (name == null) return null;
const queryOrNull = async () => (await this.emojisRepository.findOneBy({
@ -106,7 +106,7 @@ export class CustomEmojiService {
host: host ?? IsNull(),
})) ?? null;
const emoji = await this.#cache.fetch(`${name} ${host}`, queryOrNull);
const emoji = await this.cache.fetch(`${name} ${host}`, queryOrNull);
if (emoji == null) return null;
@ -132,20 +132,20 @@ export class CustomEmojiService {
let emojis: { name: string | null; host: string | null; }[] = [];
for (const note of notes) {
emojis = emojis.concat(note.emojis
.map(e => this.#parseEmojiStr(e, note.userHost)));
.map(e => this.parseEmojiStr(e, note.userHost)));
if (note.renote) {
emojis = emojis.concat(note.renote.emojis
.map(e => this.#parseEmojiStr(e, note.renote!.userHost)));
.map(e => this.parseEmojiStr(e, note.renote!.userHost)));
if (note.renote.user) {
emojis = emojis.concat(note.renote.user.emojis
.map(e => this.#parseEmojiStr(e, note.renote!.userHost)));
.map(e => this.parseEmojiStr(e, note.renote!.userHost)));
}
}
const customReactions = Object.keys(note.reactions).map(x => this.reactionService.decodeReaction(x)).filter(x => x.name != null) as typeof emojis;
emojis = emojis.concat(customReactions);
if (note.user) {
emojis = emojis.concat(note.user.emojis
.map(e => this.#parseEmojiStr(e, note.userHost)));
.map(e => this.parseEmojiStr(e, note.userHost)));
}
}
return emojis.filter(x => x.name != null) as { name: string; host: string | null; }[];
@ -155,7 +155,7 @@ export class CustomEmojiService {
*
*/
public async prefetchEmojis(emojis: { name: string; host: string | null; }[]): Promise<void> {
const notCachedEmojis = emojis.filter(emoji => this.#cache.get(`${emoji.name} ${emoji.host}`) == null);
const notCachedEmojis = emojis.filter(emoji => this.cache.get(`${emoji.name} ${emoji.host}`) == null);
const emojisQuery: any[] = [];
const hosts = new Set(notCachedEmojis.map(e => e.host));
for (const host of hosts) {
@ -169,7 +169,7 @@ export class CustomEmojiService {
select: ['name', 'host', 'originalUrl', 'publicUrl'],
}) : [];
for (const emoji of _emojis) {
this.#cache.set(`${emoji.name} ${emoji.host}`, emoji);
this.cache.set(`${emoji.name} ${emoji.host}`, emoji);
}
}
}

View File

@ -18,7 +18,7 @@ const pipeline = util.promisify(stream.pipeline);
@Injectable()
export class DownloadService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -27,11 +27,11 @@ export class DownloadService {
private httpRequestService: HttpRequestService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('download');
this.logger = this.loggerService.getLogger('download');
}
public async downloadUrl(url: string, path: string): Promise<void> {
this.#logger.info(`Downloading ${chalk.cyan(url)} ...`);
this.logger.info(`Downloading ${chalk.cyan(url)} ...`);
const timeout = 30 * 1000;
const operationTimeout = 60 * 1000;
@ -60,8 +60,8 @@ export class DownloadService {
},
}).on('response', (res: Got.Response) => {
if ((process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') && !this.config.proxy && res.ip) {
if (this.#isPrivateIp(res.ip)) {
this.#logger.warn(`Blocked address: ${res.ip}`);
if (this.isPrivateIp(res.ip)) {
this.logger.warn(`Blocked address: ${res.ip}`);
req.destroy();
}
}
@ -70,13 +70,13 @@ export class DownloadService {
if (contentLength != null) {
const size = Number(contentLength);
if (size > maxSize) {
this.#logger.warn(`maxSize exceeded (${size} > ${maxSize}) on response`);
this.logger.warn(`maxSize exceeded (${size} > ${maxSize}) on response`);
req.destroy();
}
}
}).on('downloadProgress', (progress: Got.Progress) => {
if (progress.transferred > maxSize) {
this.#logger.warn(`maxSize exceeded (${progress.transferred} > ${maxSize}) on downloadProgress`);
this.logger.warn(`maxSize exceeded (${progress.transferred} > ${maxSize}) on downloadProgress`);
req.destroy();
}
});
@ -91,14 +91,14 @@ export class DownloadService {
}
}
this.#logger.succ(`Download finished: ${chalk.cyan(url)}`);
this.logger.succ(`Download finished: ${chalk.cyan(url)}`);
}
public async downloadTextFile(url: string): Promise<string> {
// Create temp file
const [path, cleanup] = await createTemp();
this.#logger.info(`text file: Temp file is ${path}`);
this.logger.info(`text file: Temp file is ${path}`);
try {
// write content at URL to temp file
@ -112,7 +112,7 @@ export class DownloadService {
}
}
#isPrivateIp(ip: string): boolean {
private isPrivateIp(ip: string): boolean {
for (const net of this.config.allowedPrivateNetworks ?? []) {
const cidr = new IPCIDR(net);
if (cidr.contains(ip)) {

View File

@ -74,8 +74,8 @@ type UploadFromUrlArgs = {
@Injectable()
export class DriveService {
#registerLogger: Logger;
#downloaderLogger: Logger;
private registerLogger: Logger;
private downloaderLogger: Logger;
constructor(
@Inject(DI.config)
@ -110,8 +110,8 @@ export class DriveService {
private instanceChart: InstanceChart,
) {
const logger = new Logger('drive', 'blue');
this.#registerLogger = logger.createSubLogger('register', 'yellow');
this.#downloaderLogger = logger.createSubLogger('downloader');
this.registerLogger = logger.createSubLogger('register', 'yellow');
this.downloaderLogger = logger.createSubLogger('downloader');
}
/***
@ -122,7 +122,7 @@ export class DriveService {
* @param hash Hash for original
* @param size Size for original
*/
async #save(file: DriveFile, path: string, name: string, type: string, hash: string, size: number): Promise<DriveFile> {
private async save(file: DriveFile, path: string, name: string, type: string, hash: string, size: number): Promise<DriveFile> {
// thunbnail, webpublic を必要なら生成
const alts = await this.generateAlts(path, type, !file.uri);
@ -161,25 +161,25 @@ export class DriveService {
//#endregion
//#region Uploads
this.#registerLogger.info(`uploading original: ${key}`);
this.registerLogger.info(`uploading original: ${key}`);
const uploads = [
this.#upload(key, fs.createReadStream(path), type, name),
this.upload(key, fs.createReadStream(path), type, name),
];
if (alts.webpublic) {
webpublicKey = `${meta.objectStoragePrefix}/webpublic-${uuid()}.${alts.webpublic.ext}`;
webpublicUrl = `${ baseUrl }/${ webpublicKey }`;
this.#registerLogger.info(`uploading webpublic: ${webpublicKey}`);
uploads.push(this.#upload(webpublicKey, alts.webpublic.data, alts.webpublic.type, name));
this.registerLogger.info(`uploading webpublic: ${webpublicKey}`);
uploads.push(this.upload(webpublicKey, alts.webpublic.data, alts.webpublic.type, name));
}
if (alts.thumbnail) {
thumbnailKey = `${meta.objectStoragePrefix}/thumbnail-${uuid()}.${alts.thumbnail.ext}`;
thumbnailUrl = `${ baseUrl }/${ thumbnailKey }`;
this.#registerLogger.info(`uploading thumbnail: ${thumbnailKey}`);
uploads.push(this.#upload(thumbnailKey, alts.thumbnail.data, alts.thumbnail.type));
this.registerLogger.info(`uploading thumbnail: ${thumbnailKey}`);
uploads.push(this.upload(thumbnailKey, alts.thumbnail.data, alts.thumbnail.type));
}
await Promise.all(uploads);
@ -211,12 +211,12 @@ export class DriveService {
if (alts.thumbnail) {
thumbnailUrl = this.internalStorageService.saveFromBuffer(thumbnailAccessKey, alts.thumbnail.data);
this.#registerLogger.info(`thumbnail stored: ${thumbnailAccessKey}`);
this.registerLogger.info(`thumbnail stored: ${thumbnailAccessKey}`);
}
if (alts.webpublic) {
webpublicUrl = this.internalStorageService.saveFromBuffer(webpublicAccessKey, alts.webpublic.data);
this.#registerLogger.info(`web stored: ${webpublicAccessKey}`);
this.registerLogger.info(`web stored: ${webpublicAccessKey}`);
}
file.storedInternal = true;
@ -251,7 +251,7 @@ export class DriveService {
thumbnail,
};
} catch (err) {
this.#registerLogger.warn(`GenerateVideoThumbnail failed: ${err}`);
this.registerLogger.warn(`GenerateVideoThumbnail failed: ${err}`);
return {
webpublic: null,
thumbnail: null,
@ -260,7 +260,7 @@ export class DriveService {
}
if (!['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml'].includes(type)) {
this.#registerLogger.debug('web image and thumbnail not created (not an required file)');
this.registerLogger.debug('web image and thumbnail not created (not an required file)');
return {
webpublic: null,
thumbnail: null,
@ -290,7 +290,7 @@ export class DriveService {
metadata.height && metadata.height <= 2048
);
} catch (err) {
this.#registerLogger.warn(`sharp failed: ${err}`);
this.registerLogger.warn(`sharp failed: ${err}`);
return {
webpublic: null,
thumbnail: null,
@ -301,7 +301,7 @@ export class DriveService {
let webpublic: IImage | null = null;
if (generateWeb && !satisfyWebpublic) {
this.#registerLogger.info('creating web image');
this.registerLogger.info('creating web image');
try {
if (['image/jpeg', 'image/webp'].includes(type)) {
@ -311,14 +311,14 @@ export class DriveService {
} else if (['image/svg+xml'].includes(type)) {
webpublic = await this.imageProcessingService.convertSharpToPng(img, 2048, 2048);
} else {
this.#registerLogger.debug('web image not created (not an required image)');
this.registerLogger.debug('web image not created (not an required image)');
}
} catch (err) {
this.#registerLogger.warn('web image not created (an error occured)', err as Error);
this.registerLogger.warn('web image not created (an error occured)', err as Error);
}
} else {
if (satisfyWebpublic) this.#registerLogger.info('web image not created (original satisfies webpublic)');
else this.#registerLogger.info('web image not created (from remote)');
if (satisfyWebpublic) this.registerLogger.info('web image not created (original satisfies webpublic)');
else this.registerLogger.info('web image not created (from remote)');
}
// #endregion webpublic
@ -329,10 +329,10 @@ export class DriveService {
if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml'].includes(type)) {
thumbnail = await this.imageProcessingService.convertSharpToWebp(img, 498, 280);
} else {
this.#registerLogger.debug('thumbnail not created (not an required file)');
this.registerLogger.debug('thumbnail not created (not an required file)');
}
} catch (err) {
this.#registerLogger.warn('thumbnail not created (an error occured)', err as Error);
this.registerLogger.warn('thumbnail not created (an error occured)', err as Error);
}
// #endregion thumbnail
@ -345,7 +345,7 @@ export class DriveService {
/**
* Upload to ObjectStorage
*/
async #upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) {
private async upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) {
if (type === 'image/apng') type = 'image/png';
if (!FILE_TYPE_BROWSERSAFE.includes(type)) type = 'application/octet-stream';
@ -369,10 +369,10 @@ export class DriveService {
});
const result = await upload.promise();
if (result) this.#registerLogger.debug(`Uploaded: ${result.Bucket}/${result.Key} => ${result.Location}`);
if (result) this.registerLogger.debug(`Uploaded: ${result.Bucket}/${result.Key} => ${result.Location}`);
}
async #deleteOldFile(user: IRemoteUser) {
private async deleteOldFile(user: IRemoteUser) {
const q = this.driveFilesRepository.createQueryBuilder('file')
.where('file.userId = :userId', { userId: user.id })
.andWhere('file.isLink = FALSE');
@ -430,7 +430,7 @@ export class DriveService {
sensitiveThresholdForPorn: 0.75,
enableSensitiveMediaDetectionForVideos: instance.enableSensitiveMediaDetectionForVideos,
});
this.#registerLogger.info(`${JSON.stringify(info)}`);
this.registerLogger.info(`${JSON.stringify(info)}`);
// 現状 false positive が多すぎて実用に耐えない
//if (info.porn && instance.disallowUploadWhenPredictedAsPorn) {
@ -448,7 +448,7 @@ export class DriveService {
});
if (much) {
this.#registerLogger.info(`file with same hash is found: ${much.id}`);
this.registerLogger.info(`file with same hash is found: ${much.id}`);
return much;
}
}
@ -463,11 +463,11 @@ export class DriveService {
if (this.userEntityService.isLocalUser(user) && u?.driveCapacityOverrideMb != null) {
driveCapacity = 1024 * 1024 * u.driveCapacityOverrideMb;
this.#registerLogger.debug('drive capacity override applied');
this.#registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
this.registerLogger.debug('drive capacity override applied');
this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
}
this.#registerLogger.debug(`drive usage is ${usage} (max: ${driveCapacity})`);
this.registerLogger.debug(`drive usage is ${usage} (max: ${driveCapacity})`);
// If usage limit exceeded
if (usage + info.size > driveCapacity) {
@ -475,7 +475,7 @@ export class DriveService {
throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
} else {
// (アバターまたはバナーを含まず)最も古いファイルを削除する
this.#deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as IRemoteUser);
this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as IRemoteUser);
}
}
}
@ -566,22 +566,22 @@ export class DriveService {
} catch (err) {
// duplicate key error (when already registered)
if (isDuplicateKeyValueError(err)) {
this.#registerLogger.info(`already registered ${file.uri}`);
this.registerLogger.info(`already registered ${file.uri}`);
file = await this.driveFilesRepository.findOneBy({
uri: file.uri!,
userId: user ? user.id : IsNull(),
}) as DriveFile;
} else {
this.#registerLogger.error(err as Error);
this.registerLogger.error(err as Error);
throw err;
}
}
} else {
file = await (this.#save(file, path, detectedName, info.type.mime, info.md5, info.size));
file = await (this.save(file, path, detectedName, info.type.mime, info.md5, info.size));
}
this.#registerLogger.succ(`drive file has been created ${file.id}`);
this.registerLogger.succ(`drive file has been created ${file.id}`);
if (user) {
this.driveFileEntityService.pack(file, { self: true }).then(packedFile => {
@ -624,7 +624,7 @@ export class DriveService {
}
}
this.#deletePostProcess(file, isExpired);
this.deletePostProcess(file, isExpired);
}
public async deleteFileSync(file: DriveFile, isExpired = false) {
@ -654,10 +654,10 @@ export class DriveService {
await Promise.all(promises);
}
this.#deletePostProcess(file, isExpired);
this.deletePostProcess(file, isExpired);
}
async #deletePostProcess(file: DriveFile, isExpired = false) {
private async deletePostProcess(file: DriveFile, isExpired = false) {
// リモートファイル期限切れ削除後は直リンクにする
if (isExpired && file.userHost !== null && file.uri != null) {
this.driveFilesRepository.update(file.id, {
@ -725,10 +725,10 @@ export class DriveService {
await this.downloadService.downloadUrl(url, path);
const driveFile = await this.addFile({ user, path, name, comment, folderId, force, isLink, url, uri, sensitive, requestIp, requestHeaders });
this.#downloaderLogger.succ(`Got: ${driveFile.id}`);
this.downloaderLogger.succ(`Got: ${driveFile.id}`);
return driveFile!;
} catch (err) {
this.#downloaderLogger.error(`Failed to create drive file: ${err}`, {
this.downloaderLogger.error(`Failed to create drive file: ${err}`, {
url: url,
e: err,
});

View File

@ -10,7 +10,7 @@ import { LoggerService } from '@/core/LoggerService.js';
@Injectable()
export class EmailService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -22,7 +22,7 @@ export class EmailService {
private metaService: MetaService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('email');
this.logger = this.loggerService.getLogger('email');
}
public async sendEmail(to: string, subject: string, html: string, text: string) {
@ -134,9 +134,9 @@ export class EmailService {
</html>`,
});
this.#logger.info(`Message sent: ${info.messageId}`);
this.logger.info(`Message sent: ${info.messageId}`);
} catch (err) {
this.#logger.error(err as Error);
this.logger.error(err as Error);
throw err;
}
}

View File

@ -8,7 +8,7 @@ import { UtilityService } from './UtilityService.js';
@Injectable()
export class FederatedInstanceService {
#cache: Cache<Instance>;
private cache: Cache<Instance>;
constructor(
@Inject(DI.instancesRepository)
@ -17,13 +17,13 @@ export class FederatedInstanceService {
private utilityService: UtilityService,
private idService: IdService,
) {
this.#cache = new Cache<Instance>(1000 * 60 * 60);
this.cache = new Cache<Instance>(1000 * 60 * 60);
}
public async registerOrFetchInstanceDoc(host: string): Promise<Instance> {
host = this.utilityService.toPuny(host);
const cached = this.#cache.get(host);
const cached = this.cache.get(host);
if (cached) return cached;
const index = await this.instancesRepository.findOneBy({ host });
@ -36,10 +36,10 @@ export class FederatedInstanceService {
lastCommunicatedAt: new Date(),
}).then(x => this.instancesRepository.findOneByOrFail(x.identifiers[0]));
this.#cache.set(host, i);
this.cache.set(host, i);
return i;
} else {
this.#cache.set(host, index);
this.cache.set(host, index);
return index;
}
}

View File

@ -32,7 +32,7 @@ type NodeInfo = {
@Injectable()
export class FetchInstanceMetadataService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.instancesRepository)
@ -42,7 +42,7 @@ export class FetchInstanceMetadataService {
private httpRequestService: HttpRequestService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('metadata', 'cyan');
this.logger = this.loggerService.getLogger('metadata', 'cyan');
}
public async fetchInstanceMetadata(instance: Instance, force = false): Promise<void> {
@ -57,24 +57,24 @@ export class FetchInstanceMetadataService {
}
}
this.#logger.info(`Fetching metadata of ${instance.host} ...`);
this.logger.info(`Fetching metadata of ${instance.host} ...`);
try {
const [info, dom, manifest] = await Promise.all([
this.#fetchNodeinfo(instance).catch(() => null),
this.#fetchDom(instance).catch(() => null),
this.#fetchManifest(instance).catch(() => null),
this.fetchNodeinfo(instance).catch(() => null),
this.fetchDom(instance).catch(() => null),
this.fetchManifest(instance).catch(() => null),
]);
const [favicon, icon, themeColor, name, description] = await Promise.all([
this.#fetchFaviconUrl(instance, dom).catch(() => null),
this.#fetchIconUrl(instance, dom, manifest).catch(() => null),
this.#getThemeColor(info, dom, manifest).catch(() => null),
this.#getSiteName(info, dom, manifest).catch(() => null),
this.#getDescription(info, dom, manifest).catch(() => null),
this.fetchFaviconUrl(instance, dom).catch(() => null),
this.fetchIconUrl(instance, dom, manifest).catch(() => null),
this.getThemeColor(info, dom, manifest).catch(() => null),
this.getSiteName(info, dom, manifest).catch(() => null),
this.getDescription(info, dom, manifest).catch(() => null),
]);
this.#logger.succ(`Successfuly fetched metadata of ${instance.host}`);
this.logger.succ(`Successfuly fetched metadata of ${instance.host}`);
const updates = {
infoUpdatedAt: new Date(),
@ -96,16 +96,16 @@ export class FetchInstanceMetadataService {
await this.instancesRepository.update(instance.id, updates);
this.#logger.succ(`Successfuly updated metadata of ${instance.host}`);
this.logger.succ(`Successfuly updated metadata of ${instance.host}`);
} catch (e) {
this.#logger.error(`Failed to update metadata of ${instance.host}: ${e}`);
this.logger.error(`Failed to update metadata of ${instance.host}: ${e}`);
} finally {
unlock();
}
}
async #fetchNodeinfo(instance: Instance): Promise<NodeInfo> {
this.#logger.info(`Fetching nodeinfo of ${instance.host} ...`);
private async fetchNodeinfo(instance: Instance): Promise<NodeInfo> {
this.logger.info(`Fetching nodeinfo of ${instance.host} ...`);
try {
const wellknown = await this.httpRequestService.getJson('https://' + instance.host + '/.well-known/nodeinfo')
@ -137,18 +137,18 @@ export class FetchInstanceMetadataService {
throw err.statusCode ?? err.message;
});
this.#logger.succ(`Successfuly fetched nodeinfo of ${instance.host}`);
this.logger.succ(`Successfuly fetched nodeinfo of ${instance.host}`);
return info as NodeInfo;
} catch (err) {
this.#logger.error(`Failed to fetch nodeinfo of ${instance.host}: ${err}`);
this.logger.error(`Failed to fetch nodeinfo of ${instance.host}: ${err}`);
throw err;
}
}
async #fetchDom(instance: Instance): Promise<DOMWindow['document']> {
this.#logger.info(`Fetching HTML of ${instance.host} ...`);
private async fetchDom(instance: Instance): Promise<DOMWindow['document']> {
this.logger.info(`Fetching HTML of ${instance.host} ...`);
const url = 'https://' + instance.host;
@ -160,7 +160,7 @@ export class FetchInstanceMetadataService {
return doc;
}
async #fetchManifest(instance: Instance): Promise<Record<string, unknown> | null> {
private async fetchManifest(instance: Instance): Promise<Record<string, unknown> | null> {
const url = 'https://' + instance.host;
const manifestUrl = url + '/manifest.json';
@ -170,7 +170,7 @@ export class FetchInstanceMetadataService {
return manifest;
}
async #fetchFaviconUrl(instance: Instance, doc: DOMWindow['document'] | null): Promise<string | null> {
private async fetchFaviconUrl(instance: Instance, doc: DOMWindow['document'] | null): Promise<string | null> {
const url = 'https://' + instance.host;
if (doc) {
@ -197,7 +197,7 @@ export class FetchInstanceMetadataService {
return null;
}
async #fetchIconUrl(instance: Instance, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
private async fetchIconUrl(instance: Instance, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
if (manifest && manifest.icons && manifest.icons.length > 0 && manifest.icons[0].src) {
const url = 'https://' + instance.host;
return (new URL(manifest.icons[0].src, url)).href;
@ -225,7 +225,7 @@ export class FetchInstanceMetadataService {
return null;
}
async #getThemeColor(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
private async getThemeColor(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
const themeColor = info?.metadata?.themeColor ?? doc?.querySelector('meta[name="theme-color"]')?.getAttribute('content') ?? manifest?.theme_color;
if (themeColor) {
@ -236,7 +236,7 @@ export class FetchInstanceMetadataService {
return null;
}
async #getSiteName(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
private async getSiteName(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
if (info && info.metadata) {
if (info.metadata.nodeName || info.metadata.name) {
return info.metadata.nodeName ?? info.metadata.name;
@ -258,7 +258,7 @@ export class FetchInstanceMetadataService {
return null;
}
async #getDescription(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
private async getDescription(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
if (info && info.metadata) {
if (info.metadata.nodeDescription || info.metadata.description) {
return info.metadata.nodeDescription ?? info.metadata.description;

View File

@ -61,7 +61,7 @@ export class FileInfoService {
const warnings = [] as string[];
const size = await this.getFileSize(path);
const md5 = await this.#calcHash(path);
const md5 = await this.calcHash(path);
let type = await this.detectType(path);
@ -71,7 +71,7 @@ export class FileInfoService {
let orientation: number | undefined;
if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/bmp', 'image/tiff', 'image/svg+xml', 'image/vnd.adobe.photoshop'].includes(type.mime)) {
const imageSize = await this.#detectImageSize(path).catch(e => {
const imageSize = await this.detectImageSize(path).catch(e => {
warnings.push(`detectImageSize failed: ${e}`);
return undefined;
});
@ -98,7 +98,7 @@ export class FileInfoService {
let blurhash: string | undefined;
if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/svg+xml'].includes(type.mime)) {
blurhash = await this.#getBlurhash(path).catch(e => {
blurhash = await this.getBlurhash(path).catch(e => {
warnings.push(`getBlurhash failed: ${e}`);
return undefined;
});
@ -108,7 +108,7 @@ export class FileInfoService {
let porn = false;
if (!opts.skipSensitiveDetection) {
await this.#detectSensitivity(
await this.detectSensitivity(
path,
type.mime,
opts.sensitiveThreshold ?? 0.5,
@ -135,7 +135,7 @@ export class FileInfoService {
};
}
async #detectSensitivity(source: string, mime: string, sensitiveThreshold: number, sensitiveThresholdForPorn: number, analyzeVideo: boolean): Promise<[sensitive: boolean, porn: boolean]> {
private async detectSensitivity(source: string, mime: string, sensitiveThreshold: number, sensitiveThresholdForPorn: number, analyzeVideo: boolean): Promise<[sensitive: boolean, porn: boolean]> {
let sensitive = false;
let porn = false;
@ -204,7 +204,7 @@ export class FileInfoService {
let frameIndex = 0;
let targetIndex = 0;
let nextIndex = 1;
for await (const path of this.#asyncIterateFrames(outDir, command)) {
for await (const path of this.asyncIterateFrames(outDir, command)) {
try {
const index = frameIndex++;
if (index !== targetIndex) {
@ -230,7 +230,7 @@ export class FileInfoService {
return [sensitive, porn];
}
async *#asyncIterateFrames(cwd: string, command: FFmpeg.FfmpegCommand): AsyncGenerator<string, void> {
private async *asyncIterateFrames(cwd: string, command: FFmpeg.FfmpegCommand): AsyncGenerator<string, void> {
const watcher = new FSWatcher({
cwd,
disableGlobbing: true,
@ -245,7 +245,7 @@ export class FileInfoService {
const current = `${i}.png`;
const next = `${i + 1}.png`;
const framePath = join(cwd, current);
if (await this.#exists(join(cwd, next))) {
if (await this.exists(join(cwd, next))) {
yield framePath;
} else if (!finished) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
watcher.add(next);
@ -261,7 +261,7 @@ export class FileInfoService {
command.once('error', reject);
});
yield framePath;
} else if (await this.#exists(framePath)) {
} else if (await this.exists(framePath)) {
yield framePath;
} else {
return;
@ -269,7 +269,7 @@ export class FileInfoService {
}
}
#exists(path: string): Promise<boolean> {
private exists(path: string): Promise<boolean> {
return fs.promises.access(path).then(() => true, () => false);
}
@ -333,7 +333,7 @@ export class FileInfoService {
/**
* Calculate MD5 hash
*/
async #calcHash(path: string): Promise<string> {
private async calcHash(path: string): Promise<string> {
const hash = crypto.createHash('md5').setEncoding('hex');
await pipeline(fs.createReadStream(path), hash);
return hash.read();
@ -342,7 +342,7 @@ export class FileInfoService {
/**
* Detect dimensions of image
*/
async #detectImageSize(path: string): Promise<{
private async detectImageSize(path: string): Promise<{
width: number;
height: number;
wUnits: string;
@ -358,7 +358,7 @@ export class FileInfoService {
/**
* Calculate average color of image
*/
#getBlurhash(path: string): Promise<string> {
private getBlurhash(path: string): Promise<string> {
return new Promise((resolve, reject) => {
sharp(path)
.raw()

View File

@ -15,12 +15,12 @@ export class HttpRequestService {
/**
* Get http non-proxy agent
*/
#http: http.Agent;
private http: http.Agent;
/**
* Get https non-proxy agent
*/
#https: https.Agent;
private https: https.Agent;
/**
* Get http proxy or non-proxy agent
@ -42,13 +42,13 @@ export class HttpRequestService {
lookup: false, // nativeのdns.lookupにfallbackしない
});
this.#http = new http.Agent({
this.http = new http.Agent({
keepAlive: true,
keepAliveMsecs: 30 * 1000,
lookup: cache.lookup,
} as http.AgentOptions);
this.#https = new https.Agent({
this.https = new https.Agent({
keepAlive: true,
keepAliveMsecs: 30 * 1000,
lookup: cache.lookup,
@ -65,7 +65,7 @@ export class HttpRequestService {
scheduling: 'lifo',
proxy: config.proxy,
})
: this.#http;
: this.http;
this.httpsAgent = config.proxy
? new HttpsProxyAgent({
@ -76,7 +76,7 @@ export class HttpRequestService {
scheduling: 'lifo',
proxy: config.proxy,
})
: this.#https;
: this.https;
}
/**
@ -86,7 +86,7 @@ export class HttpRequestService {
*/
public getAgentByUrl(url: URL, bypassProxy = false): http.Agent | https.Agent {
if (bypassProxy || (this.config.proxyBypassHosts || []).includes(url.hostname)) {
return url.protocol === 'http:' ? this.#http : this.#https;
return url.protocol === 'http:' ? this.http : this.https;
} else {
return url.protocol === 'http:' ? this.httpAgent : this.httpsAgent;
}

View File

@ -9,19 +9,19 @@ import { genObjectId } from '@/misc/id/object-id.js';
@Injectable()
export class IdService {
#metohd: string;
private metohd: string;
constructor(
@Inject(DI.config)
private config: Config,
) {
this.#metohd = config.id.toLowerCase();
this.metohd = config.id.toLowerCase();
}
public genId(date?: Date): string {
if (!date || (date > new Date())) date = new Date();
switch (this.#metohd) {
switch (this.metohd) {
case 'aid': return genAid(date);
case 'meid': return genMeid(date);
case 'meidg': return genMeidg(date);

View File

@ -10,7 +10,7 @@ const ACTOR_USERNAME = 'instance.actor' as const;
@Injectable()
export class InstanceActorService {
#cache: Cache<ILocalUser>;
private cache: Cache<ILocalUser>;
constructor(
@Inject(DI.usersRepository)
@ -18,11 +18,11 @@ export class InstanceActorService {
private createSystemUserService: CreateSystemUserService,
) {
this.#cache = new Cache<ILocalUser>(Infinity);
this.cache = new Cache<ILocalUser>(Infinity);
}
public async getInstanceActor(): Promise<ILocalUser> {
const cached = this.#cache.get(null);
const cached = this.cache.get(null);
if (cached) return cached;
const user = await this.usersRepository.findOneBy({
@ -31,11 +31,11 @@ export class InstanceActorService {
}) as ILocalUser | undefined;
if (user) {
this.#cache.set(null, user);
this.cache.set(null, user);
return user;
} else {
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as ILocalUser;
this.#cache.set(null, created);
this.cache.set(null, created);
return created;
}
}

View File

@ -6,14 +6,14 @@ import Logger from '@/logger.js';
@Injectable()
export class LoggerService {
#syslogClient;
private syslogClient;
constructor(
@Inject(DI.config)
private config: Config,
) {
if (this.config.syslog) {
this.#syslogClient = new SyslogPro.RFC5424({
this.syslogClient = new SyslogPro.RFC5424({
applacationName: 'Misskey',
timestamp: true,
encludeStructuredData: true,
@ -28,6 +28,6 @@ export class LoggerService {
}
public getLogger(domain: string, color?: string | undefined, store?: boolean) {
return new Logger(domain, color, store, this.#syslogClient);
return new Logger(domain, color, store, this.syslogClient);
}
}

View File

@ -142,10 +142,10 @@ export class MessagingService {
public async deleteMessage(message: MessagingMessage) {
await this.messagingMessagesRepository.delete(message.id);
this.#postDeleteMessage(message);
this.postDeleteMessage(message);
}
async #postDeleteMessage(message: MessagingMessage) {
private async postDeleteMessage(message: MessagingMessage) {
if (message.recipientId) {
const user = await this.usersRepository.findOneByOrFail({ id: message.userId });
const recipient = await this.usersRepository.findOneByOrFail({ id: message.recipientId });

View File

@ -7,24 +7,24 @@ import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
export class MetaService implements OnApplicationShutdown {
#cache: Meta | undefined;
#intervalId: NodeJS.Timer;
private cache: Meta | undefined;
private intervalId: NodeJS.Timer;
constructor(
@Inject(DI.db)
private db: DataSource,
) {
if (process.env.NODE_ENV !== 'test') {
this.#intervalId = setInterval(() => {
this.intervalId = setInterval(() => {
this.fetch(true).then(meta => {
this.#cache = meta;
this.cache = meta;
});
}, 1000 * 10);
}
}
async fetch(noCache = false): Promise<Meta> {
if (!noCache && this.#cache) return this.#cache;
if (!noCache && this.cache) return this.cache;
return await this.db.transaction(async transactionalEntityManager => {
// 過去のバグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する
@ -37,7 +37,7 @@ export class MetaService implements OnApplicationShutdown {
const meta = metas[0];
if (meta) {
this.#cache = meta;
this.cache = meta;
return meta;
} else {
// metaが空のときfetchMetaが同時に呼ばれるとここが同時に呼ばれてしまうことがあるのでフェイルセーフなupsertを使う
@ -51,13 +51,13 @@ export class MetaService implements OnApplicationShutdown {
)
.then((x) => transactionalEntityManager.findOneByOrFail(Meta, x.identifiers[0]));
this.#cache = saved;
this.cache = saved;
return saved;
}
});
}
public onApplicationShutdown(signal?: string | undefined) {
clearInterval(this.#intervalId);
clearInterval(this.intervalId);
}
}

View File

@ -277,7 +277,7 @@ export class NoteCreateService {
emojis = data.apEmojis ?? extractCustomEmojisFromMfm(combinedTokens);
mentionedUsers = data.apMentions ?? await this.#extractMentionedUsers(user, combinedTokens);
mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens);
}
tags = tags.filter(tag => Array.from(tag ?? '').length <= 128).splice(0, 32);
@ -300,14 +300,14 @@ export class NoteCreateService {
}
}
const note = await this.#insertNote(user, data, tags, emojis, mentionedUsers);
const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
setImmediate(() => this.#postNoteCreated(note, user, data, silent, tags!, mentionedUsers!));
setImmediate(() => this.postNoteCreated(note, user, data, silent, tags!, mentionedUsers!));
return note;
}
async #insertNote(user: { id: User['id']; host: User['host']; }, data: Option, tags: string[], emojis: string[], mentionedUsers: MinimumUser[]) {
private async insertNote(user: { id: User['id']; host: User['host']; }, data: Option, tags: string[], emojis: string[], mentionedUsers: MinimumUser[]) {
const insert = new Note({
id: this.idService.genId(data.createdAt!),
createdAt: data.createdAt!,
@ -403,7 +403,7 @@ export class NoteCreateService {
}
}
async #postNoteCreated(note: Note, user: {
private async postNoteCreated(note: Note, user: {
id: User['id'];
username: User['username'];
host: User['host'];
@ -428,7 +428,7 @@ export class NoteCreateService {
}
// Increment notes count (user)
this.#incNotesCountOfUser(user);
this.incNotesCountOfUser(user);
// Word mute
mutedWordsCache.fetch(null, () => this.userProfilesRepository.find({
@ -473,12 +473,12 @@ export class NoteCreateService {
}
if (data.reply) {
this.#saveReply(data.reply, note);
this.saveReply(data.reply, note);
}
// この投稿を除く指定したユーザーによる指定したノートのリノートが存在しないとき
if (data.renote && (await this.noteEntityService.countSameRenotes(user.id, data.renote.id, note.id) === 0)) {
this.#incRenoteCount(data.renote);
this.incRenoteCount(data.renote);
}
if (data.poll && data.poll.expiresAt) {
@ -536,7 +536,7 @@ export class NoteCreateService {
const nm = new NotificationManager(this.mutingsRepository, this.createNotificationService, user, note);
const nmRelatedPromises = [];
await this.#createMentionedEvents(mentionedUsers, note, nm);
await this.createMentionedEvents(mentionedUsers, note, nm);
// If has in reply to note
if (data.reply) {
@ -590,7 +590,7 @@ export class NoteCreateService {
//#region AP deliver
if (this.userEntityService.isLocalUser(user)) {
(async () => {
const noteActivity = await this.#renderNoteOrRenoteActivity(data, note);
const noteActivity = await this.renderNoteOrRenoteActivity(data, note);
const dm = this.apDeliverManagerService.createDeliverManager(user, noteActivity);
// メンションされたリモートユーザーに配送
@ -644,10 +644,10 @@ export class NoteCreateService {
}
// Register to search database
this.#index(note);
this.index(note);
}
#incRenoteCount(renote: Note) {
private incRenoteCount(renote: Note) {
this.notesRepository.createQueryBuilder().update()
.set({
renoteCount: () => '"renoteCount" + 1',
@ -657,7 +657,7 @@ export class NoteCreateService {
.execute();
}
async #createMentionedEvents(mentionedUsers: MinimumUser[], note: Note, nm: NotificationManager) {
private async createMentionedEvents(mentionedUsers: MinimumUser[], note: Note, nm: NotificationManager) {
for (const u of mentionedUsers.filter(u => this.userEntityService.isLocalUser(u))) {
const threadMuted = await this.noteThreadMutingsRepository.findOneBy({
userId: u.id,
@ -686,11 +686,11 @@ export class NoteCreateService {
}
}
#saveReply(reply: Note, note: Note) {
private saveReply(reply: Note, note: Note) {
this.notesRepository.increment({ id: reply.id }, 'repliesCount', 1);
}
async #renderNoteOrRenoteActivity(data: Option, note: Note) {
private async renderNoteOrRenoteActivity(data: Option, note: Note) {
if (data.localOnly) return null;
const content = data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length === 0)
@ -700,7 +700,7 @@ export class NoteCreateService {
return this.apRendererService.renderActivity(content);
}
#index(note: Note) {
private index(note: Note) {
if (note.text == null || this.config.elasticsearch == null) return;
/*
es!.index({
@ -714,7 +714,7 @@ export class NoteCreateService {
});*/
}
#incNotesCountOfUser(user: { id: User['id']; }) {
private incNotesCountOfUser(user: { id: User['id']; }) {
this.usersRepository.createQueryBuilder().update()
.set({
updatedAt: new Date(),
@ -724,7 +724,7 @@ export class NoteCreateService {
.execute();
}
async #extractMentionedUsers(user: { host: User['host']; }, tokens: mfm.MfmNode[]): Promise<User[]> {
private async extractMentionedUsers(user: { host: User['host']; }, tokens: mfm.MfmNode[]): Promise<User[]> {
if (tokens == null) return [];
const mentions = extractMentions(tokens);

View File

@ -79,16 +79,16 @@ export class NoteDeleteService {
? this.apRendererService.renderUndo(this.apRendererService.renderAnnounce(renote.uri ?? `${this.config.url}/notes/${renote.id}`, note), user)
: this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user));
this.#deliverToConcerned(user, note, content);
this.deliverToConcerned(user, note, content);
}
// also deliever delete activity to cascaded notes
const cascadingNotes = (await this.#findCascadingNotes(note)).filter(note => !note.localOnly); // filter out local-only notes
const cascadingNotes = (await this.findCascadingNotes(note)).filter(note => !note.localOnly); // filter out local-only notes
for (const cascadingNote of cascadingNotes) {
if (!cascadingNote.user) continue;
if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue;
const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user));
this.#deliverToConcerned(cascadingNote.user, cascadingNote, content);
this.deliverToConcerned(cascadingNote.user, cascadingNote, content);
}
//#endregion
@ -110,7 +110,7 @@ export class NoteDeleteService {
});
}
async #findCascadingNotes(note: Note) {
private async findCascadingNotes(note: Note) {
const cascadingNotes: Note[] = [];
const recursive = async (noteId: string) => {
@ -132,7 +132,7 @@ export class NoteDeleteService {
return cascadingNotes.filter(note => note.userHost === null); // filter out non-local users
}
async #getMentionedRemoteUsers(note: Note) {
private async getMentionedRemoteUsers(note: Note) {
const where = [] as any[];
// mention / reply / dm
@ -157,10 +157,10 @@ export class NoteDeleteService {
}) as IRemoteUser[];
}
async #deliverToConcerned(user: { id: ILocalUser['id']; host: null; }, note: Note, content: any) {
private async deliverToConcerned(user: { id: ILocalUser['id']; host: null; }, note: Note, content: any) {
this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content);
const remoteUsers = await this.#getMentionedRemoteUsers(note);
const remoteUsers = await this.getMentionedRemoteUsers(note);
for (const remoteUser of remoteUsers) {
this.apDeliverManagerService.deliverToUser(user, content, remoteUser);
}

View File

@ -38,8 +38,8 @@ export class NotificationService {
if (result.affected === 0) return;
if (!await this.userEntityService.getHasUnreadNotification(userId)) return this.#postReadAllNotifications(userId);
else return this.#postReadNotifications(userId, notificationIds);
if (!await this.userEntityService.getHasUnreadNotification(userId)) return this.postReadAllNotifications(userId);
else return this.postReadNotifications(userId, notificationIds);
}
public async readNotificationByQuery(
@ -55,12 +55,12 @@ export class NotificationService {
return this.readNotification(userId, notificationIds);
}
#postReadAllNotifications(userId: User['id']) {
private postReadAllNotifications(userId: User['id']) {
this.globalEventService.publishMainStream(userId, 'readAllNotifications');
return this.pushNotificationService.pushNotification(userId, 'readAllNotifications', undefined);
}
#postReadNotifications(userId: User['id'], notificationIds: Notification['id'][]) {
private postReadNotifications(userId: User['id'], notificationIds: Notification['id'][]) {
this.globalEventService.publishMainStream(userId, 'readNotifications', notificationIds);
return this.pushNotificationService.pushNotification(userId, 'readNotifications', { notificationIds });
}

View File

@ -14,7 +14,7 @@ const ACTOR_USERNAME = 'relay.actor' as const;
@Injectable()
export class RelayService {
#relaysCache: Cache<Relay[]>;
private relaysCache: Cache<Relay[]>;
constructor(
@Inject(DI.usersRepository)
@ -28,10 +28,10 @@ export class RelayService {
private createSystemUserService: CreateSystemUserService,
private apRendererService: ApRendererService,
) {
this.#relaysCache = new Cache<Relay[]>(1000 * 60 * 10);
this.relaysCache = new Cache<Relay[]>(1000 * 60 * 10);
}
async #getRelayActor(): Promise<ILocalUser> {
private async getRelayActor(): Promise<ILocalUser> {
const user = await this.usersRepository.findOneBy({
host: IsNull(),
username: ACTOR_USERNAME,
@ -50,7 +50,7 @@ export class RelayService {
status: 'requesting',
}).then(x => this.relaysRepository.findOneByOrFail(x.identifiers[0]));
const relayActor = await this.#getRelayActor();
const relayActor = await this.getRelayActor();
const follow = await this.apRendererService.renderFollowRelay(relay, relayActor);
const activity = this.apRendererService.renderActivity(follow);
this.queueService.deliver(relayActor, activity, relay.inbox);
@ -67,7 +67,7 @@ export class RelayService {
throw new Error('relay not found');
}
const relayActor = await this.#getRelayActor();
const relayActor = await this.getRelayActor();
const follow = this.apRendererService.renderFollowRelay(relay, relayActor);
const undo = this.apRendererService.renderUndo(follow, relayActor);
const activity = this.apRendererService.renderActivity(undo);
@ -100,7 +100,7 @@ export class RelayService {
public async deliverToRelays(user: { id: User['id']; host: null; }, activity: any): Promise<void> {
if (activity == null) return;
const relays = await this.#relaysCache.fetch(null, () => this.relaysRepository.findBy({
const relays = await this.relaysCache.fetch(null, () => this.relaysRepository.findBy({
status: 'accepted',
}));
if (relays.length === 0) return;

View File

@ -44,11 +44,11 @@ export class UserBlockingService {
public async block(blocker: User, blockee: User) {
await Promise.all([
this.#cancelRequest(blocker, blockee),
this.#cancelRequest(blockee, blocker),
this.#unFollow(blocker, blockee),
this.#unFollow(blockee, blocker),
this.#removeFromList(blockee, blocker),
this.cancelRequest(blocker, blockee),
this.cancelRequest(blockee, blocker),
this.unFollow(blocker, blockee),
this.unFollow(blockee, blocker),
this.removeFromList(blockee, blocker),
]);
const blocking = {
@ -68,7 +68,7 @@ export class UserBlockingService {
}
}
async #cancelRequest(follower: User, followee: User) {
private async cancelRequest(follower: User, followee: User) {
const request = await this.followRequestsRepository.findOneBy({
followeeId: followee.id,
followerId: follower.id,
@ -118,7 +118,7 @@ export class UserBlockingService {
}
}
async #unFollow(follower: User, followee: User) {
private async unFollow(follower: User, followee: User) {
const following = await this.followingsRepository.findOneBy({
followerId: follower.id,
followeeId: followee.id,
@ -159,7 +159,7 @@ export class UserBlockingService {
}
}
async #removeFromList(listOwner: User, user: User) {
private async removeFromList(listOwner: User, user: User) {
const userLists = await this.userListsRepository.findBy({
userId: listOwner.id,
});

View File

@ -131,7 +131,7 @@ export class UserFollowingService {
}
}
await this.#insertFollowingDoc(followee, follower);
await this.insertFollowingDoc(followee, follower);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
@ -139,7 +139,7 @@ export class UserFollowingService {
}
}
async #insertFollowingDoc(
private async insertFollowingDoc(
followee: {
id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']
},
@ -273,7 +273,7 @@ export class UserFollowingService {
await this.followingsRepository.delete(following.id);
this.#decrementFollowing(follower, followee);
this.decrementFollowing(follower, followee);
// Publish unfollow event
if (!silent && this.userEntityService.isLocalUser(follower)) {
@ -304,7 +304,7 @@ export class UserFollowingService {
}
}
async #decrementFollowing(
private async decrementFollowing(
follower: {id: User['id']; host: User['host']; },
followee: { id: User['id']; host: User['host']; },
): Promise<void> {
@ -445,7 +445,7 @@ export class UserFollowingService {
throw new IdentifiableError('8884c2dd-5795-4ac9-b27e-6a01d38190f9', 'No follow request.');
}
await this.#insertFollowingDoc(followee, follower);
await this.insertFollowingDoc(followee, follower);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee));
@ -477,13 +477,13 @@ export class UserFollowingService {
*/
public async rejectFollowRequest(user: Local, follower: Both): Promise<void> {
if (this.userEntityService.isRemoteUser(follower)) {
this.#deliverReject(user, follower);
this.deliverReject(user, follower);
}
await this.#removeFollowRequest(user, follower);
await this.removeFollowRequest(user, follower);
if (this.userEntityService.isLocalUser(follower)) {
this.#publishUnfollow(user, follower);
this.publishUnfollow(user, follower);
}
}
@ -492,13 +492,13 @@ export class UserFollowingService {
*/
public async rejectFollow(user: Local, follower: Both): Promise<void> {
if (this.userEntityService.isRemoteUser(follower)) {
this.#deliverReject(user, follower);
this.deliverReject(user, follower);
}
await this.#removeFollow(user, follower);
await this.removeFollow(user, follower);
if (this.userEntityService.isLocalUser(follower)) {
this.#publishUnfollow(user, follower);
this.publishUnfollow(user, follower);
}
}
@ -506,15 +506,15 @@ export class UserFollowingService {
* AP Reject/Follow
*/
public async remoteReject(actor: Remote, follower: Local): Promise<void> {
await this.#removeFollowRequest(actor, follower);
await this.#removeFollow(actor, follower);
this.#publishUnfollow(actor, follower);
await this.removeFollowRequest(actor, follower);
await this.removeFollow(actor, follower);
this.publishUnfollow(actor, follower);
}
/**
* Remove follow request record
*/
async #removeFollowRequest(followee: Both, follower: Both): Promise<void> {
private async removeFollowRequest(followee: Both, follower: Both): Promise<void> {
const request = await this.followRequestsRepository.findOneBy({
followeeId: followee.id,
followerId: follower.id,
@ -528,7 +528,7 @@ export class UserFollowingService {
/**
* Remove follow record
*/
async #removeFollow(followee: Both, follower: Both): Promise<void> {
private async removeFollow(followee: Both, follower: Both): Promise<void> {
const following = await this.followingsRepository.findOneBy({
followeeId: followee.id,
followerId: follower.id,
@ -537,13 +537,13 @@ export class UserFollowingService {
if (!following) return;
await this.followingsRepository.delete(following.id);
this.#decrementFollowing(follower, followee);
this.decrementFollowing(follower, followee);
}
/**
* Deliver Reject to remote
*/
async #deliverReject(followee: Local, follower: Remote): Promise<void> {
private async deliverReject(followee: Local, follower: Remote): Promise<void> {
const request = await this.followRequestsRepository.findOneBy({
followeeId: followee.id,
followerId: follower.id,
@ -556,7 +556,7 @@ export class UserFollowingService {
/**
* Publish unfollow to local
*/
async #publishUnfollow(followee: Both, follower: Local): Promise<void> {
private async publishUnfollow(followee: Both, follower: Local): Promise<void> {
const packedFollowee = await this.userEntityService.pack(followee.id, follower, {
detail: true,
});

View File

@ -7,16 +7,16 @@ import { DI } from '@/di-symbols.js';
@Injectable()
export class UserKeypairStoreService {
#cache: Cache<UserKeypair>;
private cache: Cache<UserKeypair>;
constructor(
@Inject(DI.userKeypairsRepository)
private userKeypairsRepository: UserKeypairsRepository,
) {
this.#cache = new Cache<UserKeypair>(Infinity);
this.cache = new Cache<UserKeypair>(Infinity);
}
public async getUserKeypair(userId: User['id']): Promise<UserKeypair> {
return await this.#cache.fetch(userId, () => this.userKeypairsRepository.findOneByOrFail({ userId: userId }));
return await this.cache.fetch(userId, () => this.userKeypairsRepository.findOneByOrFail({ userId: userId }));
}
}

View File

@ -7,8 +7,8 @@ import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
export class WebhookService implements OnApplicationShutdown {
#webhooksFetched = false;
#webhooks: Webhook[] = [];
private webhooksFetched = false;
private webhooks: Webhook[] = [];
constructor(
@Inject(DI.redisSubscriber)
@ -22,14 +22,14 @@ export class WebhookService implements OnApplicationShutdown {
}
public async getActiveWebhooks() {
if (!this.#webhooksFetched) {
this.#webhooks = await this.webhooksRepository.findBy({
if (!this.webhooksFetched) {
this.webhooks = await this.webhooksRepository.findBy({
active: true,
});
this.#webhooksFetched = true;
this.webhooksFetched = true;
}
return this.#webhooks;
return this.webhooks;
}
private async onMessage(_, data) {
@ -40,23 +40,23 @@ export class WebhookService implements OnApplicationShutdown {
switch (type) {
case 'webhookCreated':
if (body.active) {
this.#webhooks.push(body);
this.webhooks.push(body);
}
break;
case 'webhookUpdated':
if (body.active) {
const i = this.#webhooks.findIndex(a => a.id === body.id);
const i = this.webhooks.findIndex(a => a.id === body.id);
if (i > -1) {
this.#webhooks[i] = body;
this.webhooks[i] = body;
} else {
this.#webhooks.push(body);
this.webhooks.push(body);
}
} else {
this.#webhooks = this.#webhooks.filter(a => a.id !== body.id);
this.webhooks = this.webhooks.filter(a => a.id !== body.id);
}
break;
case 'webhookDeleted':
this.#webhooks = this.#webhooks.filter(a => a.id !== body.id);
this.webhooks = this.webhooks.filter(a => a.id !== body.id);
break;
default:
break;

View File

@ -109,7 +109,7 @@ export function getJsonSchema<S extends Schema>(schema: S): ToJsonSchema<Unflatt
*/
// eslint-disable-next-line import/no-default-export
export default abstract class Chart<T extends Schema> {
#logger: Logger;
private logger: Logger;
public schema: T;
@ -242,7 +242,7 @@ export default abstract class Chart<T extends Schema> {
this.name = name;
this.schema = schema;
this.lock = lock;
this.#logger = logger;
this.logger = logger;
const { hour, day } = Chart.schemaToEntity(name, schema, grouped);
this.repositoryForHour = db.getRepository<{ id: number; group?: string | null; date: number; }>(hour);
@ -333,7 +333,7 @@ export default abstract class Chart<T extends Schema> {
// 初期ログデータを作成
data = this.getNewLog(null);
this.#logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): Initial commit created`);
this.logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): Initial commit created`);
}
const date = Chart.dateToTimestamp(current);
@ -363,7 +363,7 @@ export default abstract class Chart<T extends Schema> {
...columns,
}).then(x => repository.findOneByOrFail(x.identifiers[0])) as RawRecord<T>;
this.#logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`);
this.logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`);
return log;
} finally {
@ -382,7 +382,7 @@ export default abstract class Chart<T extends Schema> {
public async save(): Promise<void> {
if (this.buffer.length === 0) {
this.#logger.info(`${this.name}: Write skipped`);
this.logger.info(`${this.name}: Write skipped`);
return;
}
@ -481,7 +481,7 @@ export default abstract class Chart<T extends Schema> {
.execute(),
]);
this.#logger.info(`${this.name + (logHour.group ? `:${logHour.group}` : '')}: Updated`);
this.logger.info(`${this.name + (logHour.group ? `:${logHour.group}` : '')}: Updated`);
// TODO: この一連の処理が始まった後に新たにbufferに入ったものは消さないようにする
this.buffer = this.buffer.filter(q => q.group != null && (q.group !== logHour.group));

View File

@ -68,7 +68,7 @@ export class NoteEntityService implements OnModuleInit {
this.reactionService = this.moduleRef.get('ReactionService');
}
async #hideNote(packedNote: Packed<'Note'>, meId: User['id'] | null) {
private async hideNote(packedNote: Packed<'Note'>, meId: User['id'] | null) {
// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
let hide = false;
@ -128,7 +128,7 @@ export class NoteEntityService implements OnModuleInit {
}
}
async #populatePoll(note: Note, meId: User['id'] | null) {
private async populatePoll(note: Note, meId: User['id'] | null) {
const poll = await this.pollsRepository.findOneByOrFail({ noteId: note.id });
const choices = poll.choices.map(c => ({
text: c,
@ -166,7 +166,7 @@ export class NoteEntityService implements OnModuleInit {
};
}
async #populateMyReaction(note: Note, meId: User['id'], _hint_?: {
private async populateMyReaction(note: Note, meId: User['id'], _hint_?: {
myReactions: Map<Note['id'], NoteReaction | null>;
}) {
if (_hint_?.myReactions) {
@ -319,10 +319,10 @@ export class NoteEntityService implements OnModuleInit {
_hint_: options?._hint_,
}) : undefined,
poll: note.hasPoll ? this.#populatePoll(note, meId) : undefined,
poll: note.hasPoll ? this.populatePoll(note, meId) : undefined,
...(meId ? {
myReaction: this.#populateMyReaction(note, meId, options?._hint_),
myReaction: this.populateMyReaction(note, meId, options?._hint_),
} : {}),
} : {}),
});
@ -339,7 +339,7 @@ export class NoteEntityService implements OnModuleInit {
}
if (!opts.skipHide) {
await this.#hideNote(packed, meId);
await this.hideNote(packed, meId);
}
return packed;

View File

@ -48,7 +48,7 @@ export class UserEntityService implements OnModuleInit {
private pageEntityService: PageEntityService;
private customEmojiService: CustomEmojiService;
private antennaService: AntennaService;
#userInstanceCache: Cache<Instance | null>;
private userInstanceCache: Cache<Instance | null>;
constructor(
private moduleRef: ModuleRef,
@ -119,7 +119,7 @@ export class UserEntityService implements OnModuleInit {
//private customEmojiService: CustomEmojiService,
//private antennaService: AntennaService,
) {
this.#userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3);
this.userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3);
}
onModuleInit() {
@ -384,7 +384,7 @@ export class UserEntityService implements OnModuleInit {
isModerator: user.isModerator ?? falsy,
isBot: user.isBot ?? falsy,
isCat: user.isCat ?? falsy,
instance: user.host ? this.#userInstanceCache.fetch(user.host,
instance: user.host ? this.userInstanceCache.fetch(user.host,
() => this.instancesRepository.findOneBy({ host: user.host! }),
v => v != null,
).then(instance => instance ? {

View File

@ -14,7 +14,7 @@ import { ApPersonService } from './activitypub/models/ApPersonService.js';
@Injectable()
export class ResolveUserService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -28,14 +28,14 @@ export class ResolveUserService {
private remoteLoggerService: RemoteLoggerService,
private apPersonService: ApPersonService,
) {
this.#logger = this.remoteLoggerService.logger.createSubLogger('resolve-user');
this.logger = this.remoteLoggerService.logger.createSubLogger('resolve-user');
}
public async resolveUser(username: string, host: string | null): Promise<User> {
const usernameLower = username.toLowerCase();
if (host == null) {
this.#logger.info(`return local user: ${usernameLower}`);
this.logger.info(`return local user: ${usernameLower}`);
return await this.usersRepository.findOneBy({ usernameLower, host: IsNull() }).then(u => {
if (u == null) {
throw new Error('user not found');
@ -48,7 +48,7 @@ export class ResolveUserService {
host = this.utilityService.toPuny(host);
if (this.config.host === host) {
this.#logger.info(`return local user: ${usernameLower}`);
this.logger.info(`return local user: ${usernameLower}`);
return await this.usersRepository.findOneBy({ usernameLower, host: IsNull() }).then(u => {
if (u == null) {
throw new Error('user not found');
@ -63,9 +63,9 @@ export class ResolveUserService {
const acctLower = `${usernameLower}@${host}`;
if (user == null) {
const self = await this.#resolveSelf(acctLower);
const self = await this.resolveSelf(acctLower);
this.#logger.succ(`return new remote user: ${chalk.magenta(acctLower)}`);
this.logger.succ(`return new remote user: ${chalk.magenta(acctLower)}`);
return await this.apPersonService.createPerson(self.href);
}
@ -76,13 +76,13 @@ export class ResolveUserService {
lastFetchedAt: new Date(),
});
this.#logger.info(`try resync: ${acctLower}`);
const self = await this.#resolveSelf(acctLower);
this.logger.info(`try resync: ${acctLower}`);
const self = await this.resolveSelf(acctLower);
if (user.uri !== self.href) {
// if uri mismatch, Fix (user@host <=> AP's Person id(IRemoteUser.uri)) mapping.
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(`uri missmatch: ${acctLower}`);
this.logger.info(`recovery missmatch uri for (username=${username}, host=${host}) from ${user.uri} to ${self.href}`);
// validate uri
const uri = new URL(self.href);
@ -97,12 +97,12 @@ export class ResolveUserService {
uri: self.href,
});
} else {
this.#logger.info(`uri is fine: ${acctLower}`);
this.logger.info(`uri is fine: ${acctLower}`);
}
await this.apPersonService.updatePerson(self.href);
this.#logger.info(`return resynced remote user: ${acctLower}`);
this.logger.info(`return resynced remote user: ${acctLower}`);
return await this.usersRepository.findOneBy({ uri: self.href }).then(u => {
if (u == null) {
throw new Error('user not found');
@ -112,19 +112,19 @@ export class ResolveUserService {
});
}
this.#logger.info(`return existing remote user: ${acctLower}`);
this.logger.info(`return existing remote user: ${acctLower}`);
return user;
}
async #resolveSelf(acctLower: string) {
this.#logger.info(`WebFinger for ${chalk.yellow(acctLower)}`);
private async resolveSelf(acctLower: string) {
this.logger.info(`WebFinger for ${chalk.yellow(acctLower)}`);
const finger = await this.webfingerService.webfinger(acctLower).catch(err => {
this.#logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: ${ err.statusCode ?? err.message }`);
this.logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: ${ err.statusCode ?? err.message }`);
throw new Error(`Failed to WebFinger for ${acctLower}: ${ err.statusCode ?? err.message }`);
});
const self = finger.links.find(link => link.rel != null && link.rel.toLowerCase() === 'self');
if (!self) {
this.#logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: self link not found`);
this.logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: self link not found`);
throw new Error('self link not found');
}
return self;

View File

@ -26,12 +26,12 @@ export class WebfingerService {
}
public async webfinger(query: string): Promise<IWebFinger> {
const url = this.#genUrl(query);
const url = this.genUrl(query);
return await this.httpRequestService.getJson(url, 'application/jrd+json, application/json') as IWebFinger;
}
#genUrl(query: string): string {
private genUrl(query: string): string {
if (query.match(/^https?:\/\//)) {
const u = new URL(query);
return `${u.protocol}//${u.hostname}/.well-known/webfinger?` + urlQuery({ resource: query });

View File

@ -25,8 +25,8 @@ export class ApAudienceService {
}
public async parseAudience(actor: CacheableRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise<AudienceInfo> {
const toGroups = this.#groupingAudience(getApIds(to), actor);
const ccGroups = this.#groupingAudience(getApIds(cc), actor);
const toGroups = this.groupingAudience(getApIds(to), actor);
const ccGroups = this.groupingAudience(getApIds(cc), actor);
const others = unique(concat([toGroups.other, ccGroups.other]));
@ -66,7 +66,7 @@ export class ApAudienceService {
};
}
#groupingAudience(ids: string[], actor: CacheableRemoteUser) {
private groupingAudience(ids: string[], actor: CacheableRemoteUser) {
const groups = {
public: [] as string[],
followers: [] as string[],
@ -74,9 +74,9 @@ export class ApAudienceService {
};
for (const id of ids) {
if (this.#isPublic(id)) {
if (this.isPublic(id)) {
groups.public.push(id);
} else if (this.#isFollowers(id, actor)) {
} else if (this.isFollowers(id, actor)) {
groups.followers.push(id);
} else {
groups.other.push(id);
@ -88,7 +88,7 @@ export class ApAudienceService {
return groups;
}
#isPublic(id: string) {
private isPublic(id: string) {
return [
'https://www.w3.org/ns/activitystreams#Public',
'as#Public',
@ -96,7 +96,7 @@ export class ApAudienceService {
].includes(id);
}
#isFollowers(id: string, actor: CacheableRemoteUser) {
private isFollowers(id: string, actor: CacheableRemoteUser) {
return (
id === (actor.followersUri ?? `${actor.uri}/followers`)
);

View File

@ -31,8 +31,8 @@ export type UriParseResult = {
@Injectable()
export class ApDbResolverService {
#publicKeyCache: Cache<UserPublickey | null>;
#publicKeyByUserIdCache: Cache<UserPublickey | null>;
private publicKeyCache: Cache<UserPublickey | null>;
private publicKeyByUserIdCache: Cache<UserPublickey | null>;
constructor(
@Inject(DI.config)
@ -53,8 +53,8 @@ export class ApDbResolverService {
private userCacheService: UserCacheService,
private apPersonService: ApPersonService,
) {
this.#publicKeyCache = new Cache<UserPublickey | null>(Infinity);
this.#publicKeyByUserIdCache = new Cache<UserPublickey | null>(Infinity);
this.publicKeyCache = new Cache<UserPublickey | null>(Infinity);
this.publicKeyByUserIdCache = new Cache<UserPublickey | null>(Infinity);
}
public parseUri(value: string | IObject): UriParseResult {
@ -140,7 +140,7 @@ export class ApDbResolverService {
user: CacheableRemoteUser;
key: UserPublickey;
} | null> {
const key = await this.#publicKeyCache.fetch(keyId, async () => {
const key = await this.publicKeyCache.fetch(keyId, async () => {
const key = await this.userPublickeysRepository.findOneBy({
keyId,
});
@ -169,7 +169,7 @@ export class ApDbResolverService {
if (user == null) return null;
const key = await this.#publicKeyByUserIdCache.fetch(user.id, () => this.userPublickeysRepository.findOneBy({ userId: user.id }), v => v != null);
const key = await this.publicKeyByUserIdCache.fetch(user.id, () => this.userPublickeysRepository.findOneBy({ userId: user.id }), v => v != null);
return {
user,

View File

@ -34,7 +34,7 @@ import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow
@Injectable()
export class ApInboxService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -81,7 +81,7 @@ export class ApInboxService {
private queueService: QueueService,
private messagingService: MessagingService,
) {
this.#logger = this.apLoggerService.logger;
this.logger = this.apLoggerService.logger;
}
public async performActivity(actor: CacheableRemoteUser, activity: IObject) {
@ -93,7 +93,7 @@ export class ApInboxService {
await this.performOneActivity(actor, act);
} catch (err) {
if (err instanceof Error || typeof err === 'string') {
this.#logger.error(err);
this.logger.error(err);
}
}
}
@ -115,39 +115,39 @@ export class ApInboxService {
if (actor.isSuspended) return;
if (isCreate(activity)) {
await this.#create(actor, activity);
await this.create(actor, activity);
} else if (isDelete(activity)) {
await this.#delete(actor, activity);
await this.delete(actor, activity);
} else if (isUpdate(activity)) {
await this.#update(actor, activity);
await this.update(actor, activity);
} else if (isRead(activity)) {
await this.#read(actor, activity);
await this.read(actor, activity);
} else if (isFollow(activity)) {
await this.#follow(actor, activity);
await this.follow(actor, activity);
} else if (isAccept(activity)) {
await this.#accept(actor, activity);
await this.accept(actor, activity);
} else if (isReject(activity)) {
await this.#reject(actor, activity);
await this.reject(actor, activity);
} else if (isAdd(activity)) {
await this.#add(actor, activity).catch(err => this.#logger.error(err));
await this.add(actor, activity).catch(err => this.logger.error(err));
} else if (isRemove(activity)) {
await this.#remove(actor, activity).catch(err => this.#logger.error(err));
await this.remove(actor, activity).catch(err => this.logger.error(err));
} else if (isAnnounce(activity)) {
await this.#announce(actor, activity);
await this.announce(actor, activity);
} else if (isLike(activity)) {
await this.#like(actor, activity);
await this.like(actor, activity);
} else if (isUndo(activity)) {
await this.#undo(actor, activity);
await this.undo(actor, activity);
} else if (isBlock(activity)) {
await this.#block(actor, activity);
await this.block(actor, activity);
} else if (isFlag(activity)) {
await this.#flag(actor, activity);
await this.flag(actor, activity);
} else {
this.#logger.warn(`unrecognized activity type: ${(activity as any).type}`);
this.logger.warn(`unrecognized activity type: ${(activity as any).type}`);
}
}
async #follow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
private async follow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
const followee = await this.apDbResolverService.getUserFromApId(activity.object);
if (followee == null) {
@ -162,7 +162,7 @@ export class ApInboxService {
return 'ok';
}
async #like(actor: CacheableRemoteUser, activity: ILike): Promise<string> {
private async like(actor: CacheableRemoteUser, activity: ILike): Promise<string> {
const targetUri = getApId(activity.object);
const note = await this.apNoteService.fetchNote(targetUri);
@ -179,7 +179,7 @@ export class ApInboxService {
}).then(() => 'ok');
}
async #read(actor: CacheableRemoteUser, activity: IRead): Promise<string> {
private async read(actor: CacheableRemoteUser, activity: IRead): Promise<string> {
const id = await getApId(activity.object);
if (!this.utilityService.isSelfHost(this.utilityService.extractDbHost(id))) {
@ -201,24 +201,24 @@ export class ApInboxService {
return `ok: mark as read (${message.userId} => ${message.recipientId} ${message.id})`;
}
async #accept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> {
private async accept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> {
const uri = activity.id ?? activity;
this.#logger.info(`Accept: ${uri}`);
this.logger.info(`Accept: ${uri}`);
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(err => {
this.#logger.error(`Resolution failed: ${err}`);
this.logger.error(`Resolution failed: ${err}`);
throw err;
});
if (isFollow(object)) return await this.#acceptFollow(actor, object);
if (isFollow(object)) return await this.acceptFollow(actor, object);
return `skip: Unknown Accept type: ${getApType(object)}`;
}
async #acceptFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
private async acceptFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
const follower = await this.apDbResolverService.getUserFromApId(activity.actor);
@ -241,7 +241,7 @@ export class ApInboxService {
return 'ok';
}
async #add(actor: CacheableRemoteUser, activity: IAdd): Promise<void> {
private async add(actor: CacheableRemoteUser, activity: IAdd): Promise<void> {
if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor');
}
@ -260,17 +260,17 @@ export class ApInboxService {
throw new Error(`unknown target: ${activity.target}`);
}
async #announce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<void> {
private async announce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<void> {
const uri = getApId(activity);
this.#logger.info(`Announce: ${uri}`);
this.logger.info(`Announce: ${uri}`);
const targetUri = getApId(activity.object);
this.#announceNote(actor, activity, targetUri);
this.announceNote(actor, activity, targetUri);
}
async #announceNote(actor: CacheableRemoteUser, activity: IAnnounce, targetUri: string): Promise<void> {
private async announceNote(actor: CacheableRemoteUser, activity: IAnnounce, targetUri: string): Promise<void> {
const uri = getApId(activity);
if (actor.isSuspended) {
@ -298,18 +298,18 @@ export class ApInboxService {
// 対象が4xxならスキップ
if (err instanceof StatusError) {
if (err.isClientError) {
this.#logger.warn(`Ignored announce target ${targetUri} - ${err.statusCode}`);
this.logger.warn(`Ignored announce target ${targetUri} - ${err.statusCode}`);
return;
}
this.#logger.warn(`Error in announce target ${targetUri} - ${err.statusCode ?? err}`);
this.logger.warn(`Error in announce target ${targetUri} - ${err.statusCode ?? err}`);
}
throw err;
}
if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) return 'skip: invalid actor for this activity';
this.#logger.info(`Creating the (Re)Note: ${uri}`);
this.logger.info(`Creating the (Re)Note: ${uri}`);
const activityAudience = await this.apAudienceService.parseAudience(actor, activity.to, activity.cc);
@ -325,7 +325,7 @@ export class ApInboxService {
}
}
async #block(actor: CacheableRemoteUser, activity: IBlock): Promise<string> {
private async block(actor: CacheableRemoteUser, activity: IBlock): Promise<string> {
// ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず
const blockee = await this.apDbResolverService.getUserFromApId(activity.object);
@ -342,10 +342,10 @@ export class ApInboxService {
return 'ok';
}
async #create(actor: CacheableRemoteUser, activity: ICreate): Promise<void> {
private async create(actor: CacheableRemoteUser, activity: ICreate): Promise<void> {
const uri = getApId(activity);
this.#logger.info(`Create: ${uri}`);
this.logger.info(`Create: ${uri}`);
// copy audiences between activity <=> object.
if (typeof activity.object === 'object') {
@ -366,18 +366,18 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.#logger.error(`Resolution failed: ${e}`);
this.logger.error(`Resolution failed: ${e}`);
throw e;
});
if (isPost(object)) {
this.#createNote(resolver, actor, object, false, activity);
this.createNote(resolver, actor, object, false, activity);
} else {
this.#logger.warn(`Unknown type: ${getApType(object)}`);
this.logger.warn(`Unknown type: ${getApType(object)}`);
}
}
async #createNote(resolver: Resolver, actor: CacheableRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise<string> {
private async createNote(resolver: Resolver, actor: CacheableRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise<string> {
const uri = getApId(note);
if (typeof note === 'object') {
@ -411,7 +411,7 @@ export class ApInboxService {
}
}
async #delete(actor: CacheableRemoteUser, activity: IDelete): Promise<string> {
private async delete(actor: CacheableRemoteUser, activity: IDelete): Promise<string> {
if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor');
}
@ -444,16 +444,16 @@ export class ApInboxService {
}
if (validPost.includes(formerType)) {
return await this.#deleteNote(actor, uri);
return await this.deleteNote(actor, uri);
} else if (validActor.includes(formerType)) {
return await this.#deleteActor(actor, uri);
return await this.deleteActor(actor, uri);
} else {
return `Unknown type ${formerType}`;
}
}
async #deleteActor(actor: CacheableRemoteUser, uri: string): Promise<string> {
this.#logger.info(`Deleting the Actor: ${uri}`);
private async deleteActor(actor: CacheableRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Actor: ${uri}`);
if (actor.uri !== uri) {
return `skip: delete actor ${actor.uri} !== ${uri}`;
@ -461,7 +461,7 @@ export class ApInboxService {
const user = await this.usersRepository.findOneByOrFail({ id: actor.id });
if (user.isDeleted) {
this.#logger.info('skip: already deleted');
this.logger.info('skip: already deleted');
}
const job = await this.queueService.createDeleteAccountJob(actor);
@ -473,8 +473,8 @@ export class ApInboxService {
return `ok: queued ${job.name} ${job.id}`;
}
async #deleteNote(actor: CacheableRemoteUser, uri: string): Promise<string> {
this.#logger.info(`Deleting the Note: ${uri}`);
private async deleteNote(actor: CacheableRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Note: ${uri}`);
const unlock = await this.appLockService.getApLock(uri);
@ -505,7 +505,7 @@ export class ApInboxService {
}
}
async #flag(actor: CacheableRemoteUser, activity: IFlag): Promise<string> {
private async flag(actor: CacheableRemoteUser, activity: IFlag): Promise<string> {
// objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので
// 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する
const uris = getApIds(activity.object);
@ -529,24 +529,24 @@ export class ApInboxService {
return 'ok';
}
async #reject(actor: CacheableRemoteUser, activity: IReject): Promise<string> {
private async reject(actor: CacheableRemoteUser, activity: IReject): Promise<string> {
const uri = activity.id ?? activity;
this.#logger.info(`Reject: ${uri}`);
this.logger.info(`Reject: ${uri}`);
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.#logger.error(`Resolution failed: ${e}`);
this.logger.error(`Resolution failed: ${e}`);
throw e;
});
if (isFollow(object)) return await this.#rejectFollow(actor, object);
if (isFollow(object)) return await this.rejectFollow(actor, object);
return `skip: Unknown Reject type: ${getApType(object)}`;
}
async #rejectFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
private async rejectFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
const follower = await this.apDbResolverService.getUserFromApId(activity.actor);
@ -569,7 +569,7 @@ export class ApInboxService {
return 'ok';
}
async #remove(actor: CacheableRemoteUser, activity: IRemove): Promise<void> {
private async remove(actor: CacheableRemoteUser, activity: IRemove): Promise<void> {
if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor');
}
@ -588,32 +588,32 @@ export class ApInboxService {
throw new Error(`unknown target: ${activity.target}`);
}
async #undo(actor: CacheableRemoteUser, activity: IUndo): Promise<string> {
private async undo(actor: CacheableRemoteUser, activity: IUndo): Promise<string> {
if ('actor' in activity && actor.uri !== activity.actor) {
throw new Error('invalid actor');
}
const uri = activity.id ?? activity;
this.#logger.info(`Undo: ${uri}`);
this.logger.info(`Undo: ${uri}`);
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.#logger.error(`Resolution failed: ${e}`);
this.logger.error(`Resolution failed: ${e}`);
throw e;
});
if (isFollow(object)) return await this.#undoFollow(actor, object);
if (isBlock(object)) return await this.#undoBlock(actor, object);
if (isLike(object)) return await this.#undoLike(actor, object);
if (isAnnounce(object)) return await this.#undoAnnounce(actor, object);
if (isAccept(object)) return await this.#undoAccept(actor, object);
if (isFollow(object)) return await this.undoFollow(actor, object);
if (isBlock(object)) return await this.undoBlock(actor, object);
if (isLike(object)) return await this.undoLike(actor, object);
if (isAnnounce(object)) return await this.undoAnnounce(actor, object);
if (isAccept(object)) return await this.undoAccept(actor, object);
return `skip: unknown object type ${getApType(object)}`;
}
async #undoAccept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> {
private async undoAccept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> {
const follower = await this.apDbResolverService.getUserFromApId(activity.object);
if (follower == null) {
return 'skip: follower not found';
@ -632,7 +632,7 @@ export class ApInboxService {
return 'skip: フォローされていない';
}
async #undoAnnounce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<string> {
private async undoAnnounce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<string> {
const uri = getApId(activity);
const note = await this.notesRepository.findOneBy({
@ -646,7 +646,7 @@ export class ApInboxService {
return 'ok: deleted';
}
async #undoBlock(actor: CacheableRemoteUser, activity: IBlock): Promise<string> {
private async undoBlock(actor: CacheableRemoteUser, activity: IBlock): Promise<string> {
const blockee = await this.apDbResolverService.getUserFromApId(activity.object);
if (blockee == null) {
@ -661,7 +661,7 @@ export class ApInboxService {
return 'ok';
}
async #undoFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
private async undoFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
const followee = await this.apDbResolverService.getUserFromApId(activity.object);
if (followee == null) {
return 'skip: followee not found';
@ -694,7 +694,7 @@ export class ApInboxService {
return 'skip: リクエストもフォローもされていない';
}
async #undoLike(actor: CacheableRemoteUser, activity: ILike): Promise<string> {
private async undoLike(actor: CacheableRemoteUser, activity: ILike): Promise<string> {
const targetUri = getApId(activity.object);
const note = await this.apNoteService.fetchNote(targetUri);
@ -708,17 +708,17 @@ export class ApInboxService {
return 'ok';
}
async #update(actor: CacheableRemoteUser, activity: IUpdate): Promise<string> {
private async update(actor: CacheableRemoteUser, activity: IUpdate): Promise<string> {
if ('actor' in activity && actor.uri !== activity.actor) {
return 'skip: invalid actor';
}
this.#logger.debug('Update');
this.logger.debug('Update');
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
this.#logger.error(`Resolution failed: ${e}`);
this.logger.error(`Resolution failed: ${e}`);
throw e;
});

View File

@ -365,7 +365,7 @@ export class ApRendererService {
text: apText,
}));
const emojis = await this.#getEmojis(note.emojis);
const emojis = await this.getEmojis(note.emojis);
const apemojis = emojis.map(emoji => this.renderEmoji(emoji));
const tag = [
@ -448,7 +448,7 @@ export class ApRendererService {
}
}
const emojis = await this.#getEmojis(user.emojis);
const emojis = await this.getEmojis(user.emojis);
const apemojis = emojis.map(emoji => this.renderEmoji(emoji));
const hashtagTags = (user.tags ?? []).map(tag => this.renderHashtag(tag));
@ -687,7 +687,7 @@ export class ApRendererService {
return page;
}
async #getEmojis(names: string[]): Promise<Emoji[]> {
private async getEmojis(names: string[]): Promise<Emoji[]> {
if (names == null || names.length === 0) return [];
const emojis = await Promise.all(

View File

@ -36,14 +36,14 @@ export class ApRequestService {
) {
}
#createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record<string, string> }): Signed {
private createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record<string, string> }): Signed {
const u = new URL(args.url);
const digestHeader = `SHA-256=${crypto.createHash('sha256').update(args.body).digest('base64')}`;
const request: Request = {
url: u.href,
method: 'POST',
headers: this.#objectAssignWithLcKey({
headers: this.objectAssignWithLcKey({
'Date': new Date().toUTCString(),
'Host': u.hostname,
'Content-Type': 'application/activity+json',
@ -51,7 +51,7 @@ export class ApRequestService {
}, args.additionalHeaders),
};
const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
const result = this.signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
return {
request,
@ -61,20 +61,20 @@ export class ApRequestService {
};
}
#createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed {
private createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed {
const u = new URL(args.url);
const request: Request = {
url: u.href,
method: 'GET',
headers: this.#objectAssignWithLcKey({
headers: this.objectAssignWithLcKey({
'Accept': 'application/activity+json, application/ld+json',
'Date': new Date().toUTCString(),
'Host': new URL(args.url).hostname,
}, args.additionalHeaders),
};
const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
const result = this.signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
return {
request,
@ -84,12 +84,12 @@ export class ApRequestService {
};
}
#signToRequest(request: Request, key: PrivateKey, includeHeaders: string[]): Signed {
const signingString = this.#genSigningString(request, includeHeaders);
private signToRequest(request: Request, key: PrivateKey, includeHeaders: string[]): Signed {
const signingString = this.genSigningString(request, includeHeaders);
const signature = crypto.sign('sha256', Buffer.from(signingString), key.privateKeyPem).toString('base64');
const signatureHeader = `keyId="${key.keyId}",algorithm="rsa-sha256",headers="${includeHeaders.join(' ')}",signature="${signature}"`;
request.headers = this.#objectAssignWithLcKey(request.headers, {
request.headers = this.objectAssignWithLcKey(request.headers, {
Signature: signatureHeader,
});
@ -101,8 +101,8 @@ export class ApRequestService {
};
}
#genSigningString(request: Request, includeHeaders: string[]): string {
request.headers = this.#lcObjectKey(request.headers);
private genSigningString(request: Request, includeHeaders: string[]): string {
request.headers = this.lcObjectKey(request.headers);
const results: string[] = [];
@ -117,14 +117,14 @@ export class ApRequestService {
return results.join('\n');
}
#lcObjectKey(src: Record<string, string>): Record<string, string> {
private lcObjectKey(src: Record<string, string>): Record<string, string> {
const dst: Record<string, string> = {};
for (const key of Object.keys(src).filter(x => x !== '__proto__' && typeof src[x] === 'string')) dst[key.toLowerCase()] = src[key];
return dst;
}
#objectAssignWithLcKey(a: Record<string, string>, b: Record<string, string>): Record<string, string> {
return Object.assign(this.#lcObjectKey(a), this.#lcObjectKey(b));
private objectAssignWithLcKey(a: Record<string, string>, b: Record<string, string>): Record<string, string> {
return Object.assign(this.lcObjectKey(a), this.lcObjectKey(b));
}
public async signedPost(user: { id: User['id'] }, url: string, object: any) {
@ -132,7 +132,7 @@ export class ApRequestService {
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id);
const req = this.#createSignedPost({
const req = this.createSignedPost({
key: {
privateKeyPem: keypair.privateKey,
keyId: `${this.config.url}/users/${user.id}#main-key`,
@ -160,7 +160,7 @@ export class ApRequestService {
public async signedGet(url: string, user: { id: User['id'] }) {
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id);
const req = this.#createSignedGet({
const req = this.createSignedGet({
key: {
privateKeyPem: keypair.privateKey,
keyId: `${this.config.url}/users/${user.id}#main-key`,

View File

@ -14,7 +14,7 @@ import { ApLoggerService } from '../ApLoggerService.js';
@Injectable()
export class ApImageService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -28,7 +28,7 @@ export class ApImageService {
private driveService: DriveService,
private apLoggerService: ApLoggerService,
) {
this.#logger = this.apLoggerService.logger;
this.logger = this.apLoggerService.logger;
}
/**
@ -46,7 +46,7 @@ export class ApImageService {
throw new Error('invalid image: url not privided');
}
this.#logger.info(`Creating the Image: ${image.url}`);
this.logger.info(`Creating the Image: ${image.url}`);
const instance = await this.metaService.fetch();

View File

@ -35,7 +35,7 @@ import type { IObject, IPost } from '../type.js';
@Injectable()
export class ApNoteService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -71,7 +71,7 @@ export class ApNoteService {
private apDbResolverService: ApDbResolverService,
private apLoggerService: ApLoggerService,
) {
this.#logger = this.apLoggerService.logger;
this.logger = this.apLoggerService.logger;
}
public validateNote(object: any, uri: string) {
@ -116,7 +116,7 @@ export class ApNoteService {
const entryUri = getApId(value);
const err = this.validateNote(object, entryUri);
if (err) {
this.#logger.error(`${err.message}`, {
this.logger.error(`${err.message}`, {
resolver: {
history: resolver.getHistory(),
},
@ -128,9 +128,9 @@ export class ApNoteService {
const note: IPost = object;
this.#logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`);
this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`);
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;
@ -174,7 +174,7 @@ export class ApNoteService {
const reply: Note | null = note.inReplyTo
? await this.resolveNote(note.inReplyTo, resolver).then(x => {
if (x == null) {
this.#logger.warn('Specified inReplyTo, but nout found');
this.logger.warn('Specified inReplyTo, but nout found');
throw new Error('inReplyTo not found');
} else {
return x;
@ -191,7 +191,7 @@ export class ApNoteService {
}
}
this.#logger.warn(`Error in inReplyTo ${note.inReplyTo} - ${err.statusCode ?? err}`);
this.logger.warn(`Error in inReplyTo ${note.inReplyTo} - ${err.statusCode ?? err}`);
throw err;
})
: null;
@ -255,9 +255,9 @@ export class ApNoteService {
const tryCreateVote = async (name: string, index: number): Promise<null> => {
if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) {
this.#logger.warn(`vote to expired poll from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`);
this.logger.warn(`vote to expired poll from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`);
} else if (index >= 0) {
this.#logger.info(`vote from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`);
this.logger.info(`vote from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`);
await this.pollService.vote(actor, reply, index);
// リモートフォロワーにUpdate配信
@ -272,7 +272,7 @@ export class ApNoteService {
}
const emojis = await this.extractEmojis(note.tag ?? [], actor.host).catch(e => {
this.#logger.info(`extractEmojis: ${e}`);
this.logger.info(`extractEmojis: ${e}`);
return [] as Emoji[];
});
@ -386,7 +386,7 @@ export class ApNoteService {
return exists;
}
this.#logger.info(`register emoji host=${host}, name=${name}`);
this.logger.info(`register emoji host=${host}, name=${name}`);
return await this.emojisRepository.insert({
id: this.idService.genId(),

View File

@ -91,7 +91,7 @@ export class ApPersonService implements OnModuleInit {
private usersChart: UsersChart;
private instanceChart: InstanceChart;
private apLoggerService: ApLoggerService;
#logger: Logger;
private logger: Logger;
constructor(
private moduleRef: ModuleRef,
@ -153,7 +153,7 @@ export class ApPersonService implements OnModuleInit {
this.usersChart = this.moduleRef.get('UsersChart');
this.instanceChart = this.moduleRef.get('InstanceChart');
this.apLoggerService = this.moduleRef.get('ApLoggerService');
this.#logger = this.apLoggerService.logger;
this.logger = this.apLoggerService.logger;
}
/**
@ -161,7 +161,7 @@ export class ApPersonService implements OnModuleInit {
* @param x Fetched object
* @param uri Fetch target URI
*/
#validateActor(x: IObject, uri: string): IActor {
private validateActor(x: IObject, uri: string): IActor {
const expectHost = this.utilityService.toPuny(new URL(uri).hostname);
if (x == null) {
@ -264,9 +264,9 @@ export class ApPersonService implements OnModuleInit {
const object = await resolver.resolve(uri) as any;
const person = this.#validateActor(object, uri);
const person = this.validateActor(object, uri);
this.#logger.info(`Creating the Person: ${person.id}`);
this.logger.info(`Creating the Person: ${person.id}`);
const host = this.utilityService.toPuny(new URL(object.id).hostname);
@ -338,7 +338,7 @@ export class ApPersonService implements OnModuleInit {
throw new Error('already registered');
}
} else {
this.#logger.error(e instanceof Error ? e : new Error(e as string));
this.logger.error(e instanceof Error ? e : new Error(e as string));
throw e;
}
}
@ -379,7 +379,7 @@ export class ApPersonService implements OnModuleInit {
//#region カスタム絵文字取得
const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host).catch(err => {
this.#logger.info(`extractEmojis: ${err}`);
this.logger.info(`extractEmojis: ${err}`);
return [] as Emoji[];
});
@ -390,7 +390,7 @@ export class ApPersonService implements OnModuleInit {
});
//#endregion
await this.updateFeatured(user!.id).catch(err => this.#logger.error(err));
await this.updateFeatured(user!.id).catch(err => this.logger.error(err));
return user!;
}
@ -422,9 +422,9 @@ export class ApPersonService implements OnModuleInit {
const object = hint ?? await resolver.resolve(uri);
const person = this.#validateActor(object, uri);
const person = this.validateActor(object, uri);
this.#logger.info(`Updating the Person: ${person.id}`);
this.logger.info(`Updating the Person: ${person.id}`);
// アバターとヘッダー画像をフェッチ
const [avatar, banner] = await Promise.all([
@ -438,7 +438,7 @@ export class ApPersonService implements OnModuleInit {
// カスタム絵文字取得
const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], exist.host).catch(e => {
this.#logger.info(`extractEmojis: ${e}`);
this.logger.info(`extractEmojis: ${e}`);
return [] as Emoji[];
});
@ -503,7 +503,7 @@ export class ApPersonService implements OnModuleInit {
followerSharedInbox: person.sharedInbox ?? (person.endpoints ? person.endpoints.sharedInbox : undefined),
});
await this.updateFeatured(exist.id).catch(err => this.#logger.error(err));
await this.updateFeatured(exist.id).catch(err => this.logger.error(err));
}
/**
@ -556,7 +556,7 @@ export class ApPersonService implements OnModuleInit {
if (!this.userEntityService.isRemoteUser(user)) return;
if (!user.featured) return;
this.#logger.info(`Updating the featured: ${user.uri}`);
this.logger.info(`Updating the featured: ${user.uri}`);
const resolver = this.apResolverService.createResolver();

View File

@ -12,7 +12,7 @@ import type { IObject, IQuestion } from '../type.js';
@Injectable()
export class ApQuestionService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -27,7 +27,7 @@ export class ApQuestionService {
private apResolverService: ApResolverService,
private apLoggerService: ApLoggerService,
) {
this.#logger = this.apLoggerService.logger;
this.logger = this.apLoggerService.logger;
}
public async extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
@ -82,7 +82,7 @@ export class ApQuestionService {
// resolve new Question object
const resolver = this.apResolverService.createResolver();
const question = await resolver.resolve(value) as IQuestion;
this.#logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
this.logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
if (question.type !== 'Question') throw new Error('object is not a Question');

View File

@ -8,7 +8,7 @@ const interval = 30 * 60 * 1000;
@Injectable()
export class JanitorService implements OnApplicationShutdown {
#intervalId: NodeJS.Timer;
private intervalId: NodeJS.Timer;
constructor(
@Inject(DI.attestationChallengesRepository)
@ -28,10 +28,10 @@ export class JanitorService implements OnApplicationShutdown {
tick();
this.#intervalId = setInterval(tick, interval);
this.intervalId = setInterval(tick, interval);
}
public onApplicationShutdown(signal?: string | undefined) {
clearInterval(this.#intervalId);
clearInterval(this.intervalId);
}
}

View File

@ -10,7 +10,7 @@ const interval = 10000;
@Injectable()
export class QueueStatsService implements OnApplicationShutdown {
#intervalId: NodeJS.Timer;
private intervalId: NodeJS.Timer;
constructor(
private queueService: QueueService,
@ -68,10 +68,10 @@ export class QueueStatsService implements OnApplicationShutdown {
tick();
this.#intervalId = setInterval(tick, interval);
this.intervalId = setInterval(tick, interval);
}
public onApplicationShutdown(signal?: string | undefined) {
clearInterval(this.#intervalId);
clearInterval(this.intervalId);
}
}

View File

@ -14,7 +14,7 @@ const round = (num: number) => Math.round(num * 10) / 10;
@Injectable()
export class ServerStatsService implements OnApplicationShutdown {
#intervalId: NodeJS.Timer;
private intervalId: NodeJS.Timer;
constructor(
) {
@ -58,11 +58,11 @@ export class ServerStatsService implements OnApplicationShutdown {
tick();
this.#intervalId = setInterval(tick, interval);
this.intervalId = setInterval(tick, interval);
}
public onApplicationShutdown(signal?: string | undefined) {
clearInterval(this.#intervalId);
clearInterval(this.intervalId);
}
}

View File

@ -16,7 +16,7 @@ import { QueueLoggerService } from './QueueLoggerService.js';
@Injectable()
export class QueueProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -32,7 +32,7 @@ export class QueueProcessorService {
private deliverProcessorService: DeliverProcessorService,
private inboxProcessorService: InboxProcessorService,
) {
this.#logger = this.queueLoggerService.logger;
this.logger = this.queueLoggerService.logger;
}
public start() {
@ -44,12 +44,12 @@ export class QueueProcessorService {
};
}
const systemLogger = this.#logger.createSubLogger('system');
const deliverLogger = this.#logger.createSubLogger('deliver');
const webhookLogger = this.#logger.createSubLogger('webhook');
const inboxLogger = this.#logger.createSubLogger('inbox');
const dbLogger = this.#logger.createSubLogger('db');
const objectStorageLogger = this.#logger.createSubLogger('objectStorage');
const systemLogger = this.logger.createSubLogger('system');
const deliverLogger = this.logger.createSubLogger('deliver');
const webhookLogger = this.logger.createSubLogger('webhook');
const inboxLogger = this.logger.createSubLogger('inbox');
const dbLogger = this.logger.createSubLogger('db');
const objectStorageLogger = this.logger.createSubLogger('objectStorage');
this.queueService.systemQueue
.on('waiting', (jobId) => systemLogger.debug(`waiting id=${jobId}`))

View File

@ -10,7 +10,7 @@ import type Bull from 'bull';
@Injectable()
export class CheckExpiredMutingsProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -22,11 +22,11 @@ export class CheckExpiredMutingsProcessorService {
private globalEventService: GlobalEventService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('check-expired-mutings');
this.logger = this.queueLoggerService.logger.createSubLogger('check-expired-mutings');
}
public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> {
this.#logger.info('Checking expired mutings...');
this.logger.info('Checking expired mutings...');
const expired = await this.mutingsRepository.createQueryBuilder('muting')
.where('muting.expiresAt IS NOT NULL')
@ -44,7 +44,7 @@ export class CheckExpiredMutingsProcessorService {
}
}
this.#logger.succ('All expired mutings checked.');
this.logger.succ('All expired mutings checked.');
done();
}
}

View File

@ -20,7 +20,7 @@ import type Bull from 'bull';
@Injectable()
export class CleanChartsProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -41,11 +41,11 @@ export class CleanChartsProcessorService {
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('clean-charts');
this.logger = this.queueLoggerService.logger.createSubLogger('clean-charts');
}
public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> {
this.#logger.info('Clean charts...');
this.logger.info('Clean charts...');
await Promise.all([
this.federationChart.clean(),
@ -62,7 +62,7 @@ export class CleanChartsProcessorService {
this.apRequestChart.clean(),
]);
this.#logger.succ('All charts successfully cleaned.');
this.logger.succ('All charts successfully cleaned.');
done();
}
}

View File

@ -9,7 +9,7 @@ import type Bull from 'bull';
@Injectable()
export class CleanProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -20,17 +20,17 @@ export class CleanProcessorService {
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('clean');
this.logger = this.queueLoggerService.logger.createSubLogger('clean');
}
public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> {
this.#logger.info('Cleaning...');
this.logger.info('Cleaning...');
this.userIpsRepository.delete({
createdAt: LessThan(new Date(Date.now() - (1000 * 60 * 60 * 24 * 90))),
});
this.#logger.succ('Cleaned.');
this.logger.succ('Cleaned.');
done();
}
}

View File

@ -10,7 +10,7 @@ import type Bull from 'bull';
@Injectable()
export class CleanRemoteFilesProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -22,11 +22,11 @@ export class CleanRemoteFilesProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('clean-remote-files');
this.logger = this.queueLoggerService.logger.createSubLogger('clean-remote-files');
}
public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> {
this.#logger.info('Deleting cached remote files...');
this.logger.info('Deleting cached remote files...');
let deletedCount = 0;
let cursor: any = null;
@ -63,7 +63,7 @@ export class CleanRemoteFilesProcessorService {
job.progress(deletedCount / total);
}
this.#logger.succ('All cahced remote files has been deleted.');
this.logger.succ('All cahced remote files has been deleted.');
done();
}
}

View File

@ -14,7 +14,7 @@ import type { DbUserDeleteJobData } from '../types.js';
@Injectable()
export class DeleteAccountProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -36,11 +36,11 @@ export class DeleteAccountProcessorService {
private emailService: EmailService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('delete-account');
this.logger = this.queueLoggerService.logger.createSubLogger('delete-account');
}
public async process(job: Bull.Job<DbUserDeleteJobData>): Promise<string | void> {
this.#logger.info(`Deleting account of ${job.data.user.id} ...`);
this.logger.info(`Deleting account of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -71,7 +71,7 @@ export class DeleteAccountProcessorService {
await this.notesRepository.delete(notes.map(note => note.id));
}
this.#logger.succ('All of notes deleted');
this.logger.succ('All of notes deleted');
}
{ // Delete files
@ -100,7 +100,7 @@ export class DeleteAccountProcessorService {
}
}
this.#logger.succ('All of files deleted');
this.logger.succ('All of files deleted');
}
{ // Send email notification

View File

@ -11,7 +11,7 @@ import type { DbUserJobData } from '../types.js';
@Injectable()
export class DeleteDriveFilesProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -26,11 +26,11 @@ export class DeleteDriveFilesProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('delete-drive-files');
this.logger = this.queueLoggerService.logger.createSubLogger('delete-drive-files');
}
public async process(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> {
this.#logger.info(`Deleting drive files of ${job.data.user.id} ...`);
this.logger.info(`Deleting drive files of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -72,7 +72,7 @@ export class DeleteDriveFilesProcessorService {
job.progress(deletedCount / total);
}
this.#logger.succ(`All drive files (${deletedCount}) of ${user.id} has been deleted.`);
this.logger.succ(`All drive files (${deletedCount}) of ${user.id} has been deleted.`);
done();
}
}

View File

@ -9,7 +9,7 @@ import type { ObjectStorageFileJobData } from '../types.js';
@Injectable()
export class DeleteFileProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -18,7 +18,7 @@ export class DeleteFileProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('delete-file');
this.logger = this.queueLoggerService.logger.createSubLogger('delete-file');
}
public async process(job: Bull.Job<ObjectStorageFileJobData>): Promise<string> {

View File

@ -21,9 +21,9 @@ import type { DeliverJobData } from '../types.js';
@Injectable()
export class DeliverProcessorService {
#logger: Logger;
#suspendedHostsCache: Cache<Instance[]>;
#latest: string | null;
private logger: Logger;
private suspendedHostsCache: Cache<Instance[]>;
private latest: string | null;
constructor(
@Inject(DI.config)
@ -45,9 +45,9 @@ export class DeliverProcessorService {
private federationChart: FederationChart,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('deliver');
this.#suspendedHostsCache = new Cache<Instance[]>(1000 * 60 * 60);
this.#latest = null;
this.logger = this.queueLoggerService.logger.createSubLogger('deliver');
this.suspendedHostsCache = new Cache<Instance[]>(1000 * 60 * 60);
this.latest = null;
}
public async process(job: Bull.Job<DeliverJobData>): Promise<string> {
@ -60,22 +60,22 @@ export class DeliverProcessorService {
}
// isSuspendedなら中断
let suspendedHosts = this.#suspendedHostsCache.get(null);
let suspendedHosts = this.suspendedHostsCache.get(null);
if (suspendedHosts == null) {
suspendedHosts = await this.instancesRepository.find({
where: {
isSuspended: true,
},
});
this.#suspendedHostsCache.set(null, suspendedHosts);
this.suspendedHostsCache.set(null, suspendedHosts);
}
if (suspendedHosts.map(x => x.host).includes(this.utilityService.toPuny(host))) {
return 'skip (suspended)';
}
try {
if (this.#latest !== (this.#latest = JSON.stringify(job.data.content, null, 2))) {
this.#logger.debug(`delivering ${this.#latest}`);
if (this.latest !== (this.latest = JSON.stringify(job.data.content, null, 2))) {
this.logger.debug(`delivering ${this.latest}`);
}
await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content);

View File

@ -11,7 +11,7 @@ import type { EndedPollNotificationJobData } from '../types.js';
@Injectable()
export class EndedPollNotificationProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -26,7 +26,7 @@ export class EndedPollNotificationProcessorService {
private createNotificationService: CreateNotificationService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('ended-poll-notification');
this.logger = this.queueLoggerService.logger.createSubLogger('ended-poll-notification');
}
public async process(job: Bull.Job<EndedPollNotificationJobData>, done: () => void): Promise<void> {

View File

@ -16,7 +16,7 @@ import type { DbUserJobData } from '../types.js';
@Injectable()
export class ExportBlockingProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -32,11 +32,11 @@ export class ExportBlockingProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('export-blocking');
this.logger = this.queueLoggerService.logger.createSubLogger('export-blocking');
}
public async process(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> {
this.#logger.info(`Exporting blocking of ${job.data.user.id} ...`);
this.logger.info(`Exporting blocking of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -47,7 +47,7 @@ export class ExportBlockingProcessorService {
// Create temp file
const [path, cleanup] = await createTemp();
this.#logger.info(`Temp file is ${path}`);
this.logger.info(`Temp file is ${path}`);
try {
const stream = fs.createWriteStream(path, { flags: 'a' });
@ -84,7 +84,7 @@ export class ExportBlockingProcessorService {
await new Promise<void>((res, rej) => {
stream.write(content + '\n', err => {
if (err) {
this.#logger.error(err);
this.logger.error(err);
rej(err);
} else {
res();
@ -102,12 +102,12 @@ export class ExportBlockingProcessorService {
}
stream.end();
this.#logger.succ(`Exported to: ${path}`);
this.logger.succ(`Exported to: ${path}`);
const fileName = 'blocking-' + dateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.csv';
const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true });
this.#logger.succ(`Exported to: ${driveFile.id}`);
this.logger.succ(`Exported to: ${driveFile.id}`);
} finally {
cleanup();
}

View File

@ -17,7 +17,7 @@ import type Bull from 'bull';
@Injectable()
export class ExportCustomEmojisProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -33,11 +33,11 @@ export class ExportCustomEmojisProcessorService {
private downloadService: DownloadService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('export-custom-emojis');
this.logger = this.queueLoggerService.logger.createSubLogger('export-custom-emojis');
}
public async process(job: Bull.Job, done: () => void): Promise<void> {
this.#logger.info('Exporting custom emojis ...');
this.logger.info('Exporting custom emojis ...');
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -47,7 +47,7 @@ export class ExportCustomEmojisProcessorService {
const [path, cleanup] = await createTempDir();
this.#logger.info(`Temp dir is ${path}`);
this.logger.info(`Temp dir is ${path}`);
const metaPath = path + '/meta.json';
@ -59,7 +59,7 @@ export class ExportCustomEmojisProcessorService {
return new Promise<void>((res, rej) => {
metaStream.write(text, err => {
if (err) {
this.#logger.error(err);
this.logger.error(err);
rej(err);
} else {
res();
@ -90,7 +90,7 @@ export class ExportCustomEmojisProcessorService {
await this.downloadService.downloadUrl(emoji.originalUrl, emojiPath);
downloaded = true;
} catch (e) { // TODO: 何度か再試行
this.#logger.error(e instanceof Error ? e : new Error(e as string));
this.logger.error(e instanceof Error ? e : new Error(e as string));
}
if (!downloaded) {
@ -118,12 +118,12 @@ export class ExportCustomEmojisProcessorService {
zlib: { level: 0 },
});
archiveStream.on('close', async () => {
this.#logger.succ(`Exported to: ${archivePath}`);
this.logger.succ(`Exported to: ${archivePath}`);
const fileName = 'custom-emojis-' + dateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.zip';
const driveFile = await this.driveService.addFile({ user, path: archivePath, name: fileName, force: true });
this.#logger.succ(`Exported to: ${driveFile.id}`);
this.logger.succ(`Exported to: ${driveFile.id}`);
cleanup();
archiveCleanup();
done();

View File

@ -16,7 +16,7 @@ import type { DbUserJobData } from '../types.js';
@Injectable()
export class ExportFollowingProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -35,11 +35,11 @@ export class ExportFollowingProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('export-following');
this.logger = this.queueLoggerService.logger.createSubLogger('export-following');
}
public async process(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> {
this.#logger.info(`Exporting following of ${job.data.user.id} ...`);
this.logger.info(`Exporting following of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -50,7 +50,7 @@ export class ExportFollowingProcessorService {
// Create temp file
const [path, cleanup] = await createTemp();
this.#logger.info(`Temp file is ${path}`);
this.logger.info(`Temp file is ${path}`);
try {
const stream = fs.createWriteStream(path, { flags: 'a' });
@ -94,7 +94,7 @@ export class ExportFollowingProcessorService {
await new Promise<void>((res, rej) => {
stream.write(content + '\n', err => {
if (err) {
this.#logger.error(err);
this.logger.error(err);
rej(err);
} else {
res();
@ -105,12 +105,12 @@ export class ExportFollowingProcessorService {
}
stream.end();
this.#logger.succ(`Exported to: ${path}`);
this.logger.succ(`Exported to: ${path}`);
const fileName = 'following-' + dateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.csv';
const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true });
this.#logger.succ(`Exported to: ${driveFile.id}`);
this.logger.succ(`Exported to: ${driveFile.id}`);
} finally {
cleanup();
}

View File

@ -15,7 +15,7 @@ import type { DbUserJobData } from '../types.js';
@Injectable()
export class ExportMutingProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -34,11 +34,11 @@ export class ExportMutingProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('export-muting');
this.logger = this.queueLoggerService.logger.createSubLogger('export-muting');
}
public async process(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> {
this.#logger.info(`Exporting muting of ${job.data.user.id} ...`);
this.logger.info(`Exporting muting of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -49,7 +49,7 @@ export class ExportMutingProcessorService {
// Create temp file
const [path, cleanup] = await createTemp();
this.#logger.info(`Temp file is ${path}`);
this.logger.info(`Temp file is ${path}`);
try {
const stream = fs.createWriteStream(path, { flags: 'a' });
@ -87,7 +87,7 @@ export class ExportMutingProcessorService {
await new Promise<void>((res, rej) => {
stream.write(content + '\n', err => {
if (err) {
this.#logger.error(err);
this.logger.error(err);
rej(err);
} else {
res();
@ -105,12 +105,12 @@ export class ExportMutingProcessorService {
}
stream.end();
this.#logger.succ(`Exported to: ${path}`);
this.logger.succ(`Exported to: ${path}`);
const fileName = 'mute-' + dateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.csv';
const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true });
this.#logger.succ(`Exported to: ${driveFile.id}`);
this.logger.succ(`Exported to: ${driveFile.id}`);
} finally {
cleanup();
}

View File

@ -16,7 +16,7 @@ import type { DbUserJobData } from '../types.js';
@Injectable()
export class ExportNotesProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -34,11 +34,11 @@ export class ExportNotesProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('export-notes');
this.logger = this.queueLoggerService.logger.createSubLogger('export-notes');
}
public async process(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> {
this.#logger.info(`Exporting notes of ${job.data.user.id} ...`);
this.logger.info(`Exporting notes of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -49,7 +49,7 @@ export class ExportNotesProcessorService {
// Create temp file
const [path, cleanup] = await createTemp();
this.#logger.info(`Temp file is ${path}`);
this.logger.info(`Temp file is ${path}`);
try {
const stream = fs.createWriteStream(path, { flags: 'a' });
@ -58,7 +58,7 @@ export class ExportNotesProcessorService {
return new Promise<void>((res, rej) => {
stream.write(text, err => {
if (err) {
this.#logger.error(err);
this.logger.error(err);
rej(err);
} else {
res();
@ -112,12 +112,12 @@ export class ExportNotesProcessorService {
await write(']');
stream.end();
this.#logger.succ(`Exported to: ${path}`);
this.logger.succ(`Exported to: ${path}`);
const fileName = 'notes-' + dateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.json';
const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true });
this.#logger.succ(`Exported to: ${driveFile.id}`);
this.logger.succ(`Exported to: ${driveFile.id}`);
} finally {
cleanup();
}

View File

@ -15,7 +15,7 @@ import type { DbUserJobData } from '../types.js';
@Injectable()
export class ExportUserListsProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -34,11 +34,11 @@ export class ExportUserListsProcessorService {
private driveService: DriveService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('export-user-lists');
this.logger = this.queueLoggerService.logger.createSubLogger('export-user-lists');
}
public async process(job: Bull.Job<DbUserJobData>, done: () => void): Promise<void> {
this.#logger.info(`Exporting user lists of ${job.data.user.id} ...`);
this.logger.info(`Exporting user lists of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -53,7 +53,7 @@ export class ExportUserListsProcessorService {
// Create temp file
const [path, cleanup] = await createTemp();
this.#logger.info(`Temp file is ${path}`);
this.logger.info(`Temp file is ${path}`);
try {
const stream = fs.createWriteStream(path, { flags: 'a' });
@ -70,7 +70,7 @@ export class ExportUserListsProcessorService {
await new Promise<void>((res, rej) => {
stream.write(content + '\n', err => {
if (err) {
this.#logger.error(err);
this.logger.error(err);
rej(err);
} else {
res();
@ -81,12 +81,12 @@ export class ExportUserListsProcessorService {
}
stream.end();
this.#logger.succ(`Exported to: ${path}`);
this.logger.succ(`Exported to: ${path}`);
const fileName = 'user-lists-' + dateFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss') + '.csv';
const driveFile = await this.driveService.addFile({ user, path, name: fileName, force: true });
this.#logger.succ(`Exported to: ${driveFile.id}`);
this.logger.succ(`Exported to: ${driveFile.id}`);
} finally {
cleanup();
}

View File

@ -15,7 +15,7 @@ import type { DbUserImportJobData } from '../types.js';
@Injectable()
export class ImportBlockingProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -36,11 +36,11 @@ export class ImportBlockingProcessorService {
private downloadService: DownloadService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('import-blocking');
this.logger = this.queueLoggerService.logger.createSubLogger('import-blocking');
}
public async process(job: Bull.Job<DbUserImportJobData>, done: () => void): Promise<void> {
this.#logger.info(`Importing blocking of ${job.data.user.id} ...`);
this.logger.info(`Importing blocking of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -88,15 +88,15 @@ export class ImportBlockingProcessorService {
// skip myself
if (target.id === job.data.user.id) continue;
this.#logger.info(`Block[${linenum}] ${target.id} ...`);
this.logger.info(`Block[${linenum}] ${target.id} ...`);
await this.userBlockingService.block(user, target);
} catch (e) {
this.#logger.warn(`Error in line:${linenum} ${e}`);
this.logger.warn(`Error in line:${linenum} ${e}`);
}
}
this.#logger.succ('Imported');
this.logger.succ('Imported');
done();
}
}

View File

@ -17,7 +17,7 @@ import type { DbUserImportJobData } from '../types.js';
// TODO: 名前衝突時の動作を選べるようにする
@Injectable()
export class ImportCustomEmojisProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -40,11 +40,11 @@ export class ImportCustomEmojisProcessorService {
private downloadService: DownloadService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('import-custom-emojis');
this.logger = this.queueLoggerService.logger.createSubLogger('import-custom-emojis');
}
public async process(job: Bull.Job<DbUserImportJobData>, done: () => void): Promise<void> {
this.#logger.info('Importing custom emojis ...');
this.logger.info('Importing custom emojis ...');
const file = await this.driveFilesRepository.findOneBy({
id: job.data.fileId,
@ -56,7 +56,7 @@ export class ImportCustomEmojisProcessorService {
const [path, cleanup] = await createTempDir();
this.#logger.info(`Temp dir is ${path}`);
this.logger.info(`Temp dir is ${path}`);
const destPath = path + '/emojis.zip';
@ -65,7 +65,7 @@ export class ImportCustomEmojisProcessorService {
await this.downloadService.downloadUrl(file.url, destPath);
} catch (e) { // TODO: 何度か再試行
if (e instanceof Error || typeof e === 'string') {
this.#logger.error(e);
this.logger.error(e);
}
throw e;
}
@ -101,10 +101,10 @@ export class ImportCustomEmojisProcessorService {
cleanup();
this.#logger.succ('Imported');
this.logger.succ('Imported');
done();
});
unzipStream.pipe(extractor);
this.#logger.succ(`Unzipping to ${outputPath}`);
this.logger.succ(`Unzipping to ${outputPath}`);
}
}

View File

@ -15,7 +15,7 @@ import type { DbUserImportJobData } from '../types.js';
@Injectable()
export class ImportFollowingProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -33,11 +33,11 @@ export class ImportFollowingProcessorService {
private downloadService: DownloadService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('import-following');
this.logger = this.queueLoggerService.logger.createSubLogger('import-following');
}
public async process(job: Bull.Job<DbUserImportJobData>, done: () => void): Promise<void> {
this.#logger.info(`Importing following of ${job.data.user.id} ...`);
this.logger.info(`Importing following of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -85,15 +85,15 @@ export class ImportFollowingProcessorService {
// skip myself
if (target.id === job.data.user.id) continue;
this.#logger.info(`Follow[${linenum}] ${target.id} ...`);
this.logger.info(`Follow[${linenum}] ${target.id} ...`);
this.userFollowingService.follow(user, target);
} catch (e) {
this.#logger.warn(`Error in line:${linenum} ${e}`);
this.logger.warn(`Error in line:${linenum} ${e}`);
}
}
this.#logger.succ('Imported');
this.logger.succ('Imported');
done();
}
}

View File

@ -16,7 +16,7 @@ import type { DbUserImportJobData } from '../types.js';
@Injectable()
export class ImportMutingProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -34,11 +34,11 @@ export class ImportMutingProcessorService {
private downloadService: DownloadService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('import-muting');
this.logger = this.queueLoggerService.logger.createSubLogger('import-muting');
}
public async process(job: Bull.Job<DbUserImportJobData>, done: () => void): Promise<void> {
this.#logger.info(`Importing muting of ${job.data.user.id} ...`);
this.logger.info(`Importing muting of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -86,15 +86,15 @@ export class ImportMutingProcessorService {
// skip myself
if (target.id === job.data.user.id) continue;
this.#logger.info(`Mute[${linenum}] ${target.id} ...`);
this.logger.info(`Mute[${linenum}] ${target.id} ...`);
await this.userMutingService.mute(user, target);
} catch (e) {
this.#logger.warn(`Error in line:${linenum} ${e}`);
this.logger.warn(`Error in line:${linenum} ${e}`);
}
}
this.#logger.succ('Imported');
this.logger.succ('Imported');
done();
}
}

View File

@ -16,7 +16,7 @@ import type { DbUserImportJobData } from '../types.js';
@Injectable()
export class ImportUserListsProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -41,11 +41,11 @@ export class ImportUserListsProcessorService {
private downloadService: DownloadService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('import-user-lists');
this.logger = this.queueLoggerService.logger.createSubLogger('import-user-lists');
}
public async process(job: Bull.Job<DbUserImportJobData>, done: () => void): Promise<void> {
this.#logger.info(`Importing user lists of ${job.data.user.id} ...`);
this.logger.info(`Importing user lists of ${job.data.user.id} ...`);
const user = await this.usersRepository.findOneBy({ id: job.data.user.id });
if (user == null) {
@ -102,11 +102,11 @@ export class ImportUserListsProcessorService {
this.userListService.push(target, list!);
} catch (e) {
this.#logger.warn(`Error in line:${linenum} ${e}`);
this.logger.warn(`Error in line:${linenum} ${e}`);
}
}
this.#logger.succ('Imported');
this.logger.succ('Imported');
done();
}
}

View File

@ -31,7 +31,7 @@ import type { DeliverJobData, InboxJobData } from '../types.js';
// ユーザーのinboxにアクティビティが届いた時の処理
@Injectable()
export class InboxProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -57,7 +57,7 @@ export class InboxProcessorService {
private federationChart: FederationChart,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('inbox');
this.logger = this.queueLoggerService.logger.createSubLogger('inbox');
}
public async process(job: Bull.Job<InboxJobData>): Promise<string> {
@ -67,7 +67,7 @@ export class InboxProcessorService {
//#region Log
const info = Object.assign({}, activity) as any;
delete info['@context'];
this.#logger.debug(JSON.stringify(info, null, 2));
this.logger.debug(JSON.stringify(info, null, 2));
//#endregion
const host = this.utilityService.toPuny(new URL(signature.keyId).hostname);

View File

@ -20,7 +20,7 @@ import type Bull from 'bull';
@Injectable()
export class ResyncChartsProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -41,11 +41,11 @@ export class ResyncChartsProcessorService {
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('resync-charts');
this.logger = this.queueLoggerService.logger.createSubLogger('resync-charts');
}
public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> {
this.#logger.info('Resync charts...');
this.logger.info('Resync charts...');
// TODO: ユーザーごとのチャートも更新する
// TODO: インスタンスごとのチャートも更新する
@ -55,7 +55,7 @@ export class ResyncChartsProcessorService {
this.usersChart.resync(),
]);
this.#logger.succ('All charts successfully resynced.');
this.logger.succ('All charts successfully resynced.');
done();
}
}

View File

@ -20,7 +20,7 @@ import type Bull from 'bull';
@Injectable()
export class TickChartsProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -41,11 +41,11 @@ export class TickChartsProcessorService {
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('tick-charts');
this.logger = this.queueLoggerService.logger.createSubLogger('tick-charts');
}
public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> {
this.#logger.info('Tick charts...');
this.logger.info('Tick charts...');
await Promise.all([
this.federationChart.tick(false),
@ -62,7 +62,7 @@ export class TickChartsProcessorService {
this.apRequestChart.tick(false),
]);
this.#logger.succ('All charts successfully ticked.');
this.logger.succ('All charts successfully ticked.');
done();
}
}

View File

@ -12,7 +12,7 @@ import type { WebhookDeliverJobData } from '../types.js';
@Injectable()
export class WebhookDeliverProcessorService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -24,12 +24,12 @@ export class WebhookDeliverProcessorService {
private httpRequestService: HttpRequestService,
private queueLoggerService: QueueLoggerService,
) {
this.#logger = this.queueLoggerService.logger.createSubLogger('webhook');
this.logger = this.queueLoggerService.logger.createSubLogger('webhook');
}
public async process(job: Bull.Job<WebhookDeliverJobData>): Promise<string> {
try {
this.#logger.debug(`delivering ${job.data.webhookId}`);
this.logger.debug(`delivering ${job.data.webhookId}`);
const res = await this.httpRequestService.getResponse({
url: job.data.to,

View File

@ -58,7 +58,7 @@ export class ActivityPubServerService {
) {
}
#setResponseType(ctx: Router.RouterContext) {
private setResponseType(ctx: Router.RouterContext) {
const accept = ctx.accepts(ACTIVITY_JSON, LD_JSON);
if (accept === LD_JSON) {
ctx.response.type = LD_JSON;
@ -71,7 +71,7 @@ export class ActivityPubServerService {
* Pack Create<Note> or Announce Activity
* @param note Note
*/
async #packActivity(note: Note): Promise<any> {
private async packActivity(note: Note): Promise<any> {
if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) {
const renote = await Notes.findOneByOrFail({ id: note.renoteId });
return this.apRendererService.renderAnnounce(renote.uri ? renote.uri : `${this.config.url}/notes/${renote.id}`, note);
@ -80,7 +80,7 @@ export class ActivityPubServerService {
return this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note);
}
#inbox(ctx: Router.RouterContext) {
private inbox(ctx: Router.RouterContext) {
let signature;
try {
@ -95,7 +95,7 @@ export class ActivityPubServerService {
ctx.status = 202;
}
async #followers(ctx: Router.RouterContext) {
private async followers(ctx: Router.RouterContext) {
const userId = ctx.params.user;
const cursor = ctx.request.query.cursor;
@ -169,17 +169,17 @@ export class ActivityPubServerService {
);
ctx.body = this.apRendererService.renderActivity(rendered);
this.#setResponseType(ctx);
this.setResponseType(ctx);
} else {
// index page
const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`);
ctx.body = this.apRendererService.renderActivity(rendered);
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
}
}
async #following(ctx: Router.RouterContext) {
private async following(ctx: Router.RouterContext) {
const userId = ctx.params.user;
const cursor = ctx.request.query.cursor;
@ -253,17 +253,17 @@ export class ActivityPubServerService {
);
ctx.body = this.apRendererService.renderActivity(rendered);
this.#setResponseType(ctx);
this.setResponseType(ctx);
} else {
// index page
const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`);
ctx.body = this.apRendererService.renderActivity(rendered);
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
}
}
async #featured(ctx: Router.RouterContext) {
private async featured(ctx: Router.RouterContext) {
const userId = ctx.params.user;
const user = await this.usersRepository.findOneBy({
@ -293,10 +293,10 @@ export class ActivityPubServerService {
ctx.body = this.apRendererService.renderActivity(rendered);
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
}
async #outbox(ctx: Router.RouterContext) {
private async outbox(ctx: Router.RouterContext) {
const userId = ctx.params.user;
const sinceId = ctx.request.query.since_id;
@ -344,7 +344,7 @@ export class ActivityPubServerService {
if (sinceId) notes.reverse();
const activities = await Promise.all(notes.map(note => this.#packActivity(note)));
const activities = await Promise.all(notes.map(note => this.packActivity(note)));
const rendered = this.apRendererService.renderOrderedCollectionPage(
`${partOf}?${url.query({
page: 'true',
@ -363,7 +363,7 @@ export class ActivityPubServerService {
);
ctx.body = this.apRendererService.renderActivity(rendered);
this.#setResponseType(ctx);
this.setResponseType(ctx);
} else {
// index page
const rendered = this.apRendererService.renderOrderedCollection(partOf, user.notesCount,
@ -372,11 +372,11 @@ export class ActivityPubServerService {
);
ctx.body = this.apRendererService.renderActivity(rendered);
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
}
}
async #userInfo(ctx: Router.RouterContext, user: User | null) {
private async userInfo(ctx: Router.RouterContext, user: User | null) {
if (user == null) {
ctx.status = 404;
return;
@ -384,7 +384,7 @@ export class ActivityPubServerService {
ctx.body = this.apRendererService.renderActivity(await this.apRendererService.renderPerson(user as ILocalUser));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
}
public createRouter() {
@ -399,8 +399,8 @@ export class ActivityPubServerService {
}
// inbox
router.post('/inbox', json(), ctx => this.#inbox(ctx));
router.post('/users/:user/inbox', json(), ctx => this.#inbox(ctx));
router.post('/inbox', json(), ctx => this.inbox(ctx));
router.post('/users/:user/inbox', json(), ctx => this.inbox(ctx));
// note
router.get('/notes/:note', async (ctx, next) => {
@ -429,7 +429,7 @@ export class ActivityPubServerService {
ctx.body = this.apRendererService.renderActivity(await this.apRendererService.renderNote(note, false));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
});
// note activity
@ -446,22 +446,22 @@ export class ActivityPubServerService {
return;
}
ctx.body = this.apRendererService.renderActivity(await this.#packActivity(note));
ctx.body = this.apRendererService.renderActivity(await this.packActivity(note));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
});
// outbox
router.get('/users/:user/outbox', (ctx) => this.#outbox(ctx));
router.get('/users/:user/outbox', (ctx) => this.outbox(ctx));
// followers
router.get('/users/:user/followers', (ctx) => this.#followers(ctx));
router.get('/users/:user/followers', (ctx) => this.followers(ctx));
// following
router.get('/users/:user/following', (ctx) => this.#following(ctx));
router.get('/users/:user/following', (ctx) => this.following(ctx));
// featured
router.get('/users/:user/collections/featured', (ctx) => this.#featured(ctx));
router.get('/users/:user/collections/featured', (ctx) => this.featured(ctx));
// publickey
router.get('/users/:user/publickey', async ctx => {
@ -482,7 +482,7 @@ export class ActivityPubServerService {
if (this.userEntityService.isLocalUser(user)) {
ctx.body = this.apRendererService.renderActivity(this.apRendererService.renderKey(user, keypair));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
} else {
ctx.status = 400;
}
@ -499,7 +499,7 @@ export class ActivityPubServerService {
isSuspended: false,
});
await this.#userInfo(ctx, user);
await this.userInfo(ctx, user);
});
router.get('/@:user', async (ctx, next) => {
@ -511,7 +511,7 @@ export class ActivityPubServerService {
isSuspended: false,
});
await this.#userInfo(ctx, user);
await this.userInfo(ctx, user);
});
//#endregion
@ -529,7 +529,7 @@ export class ActivityPubServerService {
ctx.body = this.apRendererService.renderActivity(await this.apRendererService.renderEmoji(emoji));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
});
// like
@ -550,7 +550,7 @@ export class ActivityPubServerService {
ctx.body = this.apRendererService.renderActivity(await this.apRendererService.renderLike(reaction, note));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
});
// follow
@ -576,7 +576,7 @@ export class ActivityPubServerService {
ctx.body = this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee));
ctx.set('Cache-Control', 'public, max-age=180');
this.#setResponseType(ctx);
this.setResponseType(ctx);
});
return router;

View File

@ -29,7 +29,7 @@ const assets = `${_dirname}/../../server/file/assets/`;
@Injectable()
export class FileServerService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -45,12 +45,12 @@ export class FileServerService {
private internalStorageService: InternalStorageService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('server', 'gray', false);
this.logger = this.loggerService.getLogger('server', 'gray', false);
}
public commonReadableHandlerGenerator(ctx: Koa.Context) {
return (e: Error): void => {
this.#logger.error(e);
this.logger.error(e);
ctx.status = 500;
ctx.set('Cache-Control', 'max-age=300');
};
@ -74,8 +74,8 @@ export class FileServerService {
ctx.set('Cache-Control', 'max-age=31536000, immutable');
});
router.get('/:key', ctx => this.#sendDriveFile(ctx));
router.get('/:key/(.*)', ctx => this.#sendDriveFile(ctx));
router.get('/:key', ctx => this.sendDriveFile(ctx));
router.get('/:key/(.*)', ctx => this.sendDriveFile(ctx));
// Register router
app.use(router.routes());
@ -83,7 +83,7 @@ export class FileServerService {
return app;
}
async #sendDriveFile(ctx: Koa.Context) {
private async sendDriveFile(ctx: Koa.Context) {
const key = ctx.params.key;
// Fetch drive file
@ -139,7 +139,7 @@ export class FileServerService {
ctx.set('Content-Type', FILE_TYPE_BROWSERSAFE.includes(image.type) ? image.type : 'application/octet-stream');
ctx.set('Cache-Control', 'max-age=31536000, immutable');
} catch (err) {
this.#logger.error(`${err}`);
this.logger.error(`${err}`);
if (err instanceof StatusError && err.isClientError) {
ctx.status = err.statusCode;

View File

@ -19,7 +19,7 @@ import { LoggerService } from '@/core/LoggerService.js';
@Injectable()
export class MediaProxyServerService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -30,7 +30,7 @@ export class MediaProxyServerService {
private imageProcessingService: ImageProcessingService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('server', 'gray', false);
this.logger = this.loggerService.getLogger('server', 'gray', false);
}
public createServer() {
@ -44,7 +44,7 @@ export class MediaProxyServerService {
// Init router
const router = new Router();
router.get('/:url*', ctx => this.#handler(ctx));
router.get('/:url*', ctx => this.handler(ctx));
// Register router
app.use(router.routes());
@ -52,7 +52,7 @@ export class MediaProxyServerService {
return app;
}
async #handler(ctx: Koa.Context) {
private async handler(ctx: Koa.Context) {
const url = 'url' in ctx.query ? ctx.query.url : 'https://' + ctx.params.url;
if (typeof url !== 'string') {
@ -126,7 +126,7 @@ export class MediaProxyServerService {
ctx.set('Cache-Control', 'max-age=31536000, immutable');
ctx.body = image.data;
} catch (err) {
this.#logger.error(`${err}`);
this.logger.error(`${err}`);
if (err instanceof StatusError && (err.statusCode === 302 || err.isClientError)) {
ctx.status = err.statusCode;

View File

@ -30,7 +30,7 @@ import { ClientServerService } from './web/ClientServerService.js';
@Injectable()
export class ServerService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -54,7 +54,7 @@ export class ServerService {
private globalEventService: GlobalEventService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('server', 'gray', false);
this.logger = this.loggerService.getLogger('server', 'gray', false);
}
public launch() {
@ -65,7 +65,7 @@ export class ServerService {
if (!['production', 'test'].includes(process.env.NODE_ENV ?? '')) {
// Logger
koa.use(koaLogger(str => {
this.#logger.info(str);
this.logger.info(str);
}));
// Delay
@ -157,13 +157,13 @@ export class ServerService {
server.on('error', err => {
switch ((err as any).code) {
case 'EACCES':
this.#logger.error(`You do not have permission to listen on port ${this.config.port}.`);
this.logger.error(`You do not have permission to listen on port ${this.config.port}.`);
break;
case 'EADDRINUSE':
this.#logger.error(`Port ${this.config.port} is already in use by another process.`);
this.logger.error(`Port ${this.config.port} is already in use by another process.`);
break;
default:
this.#logger.error(err);
this.logger.error(err);
break;
}

View File

@ -23,9 +23,9 @@ const accessDenied = {
@Injectable()
export class ApiCallService implements OnApplicationShutdown {
#logger: Logger;
#userIpHistories: Map<User['id'], Set<string>>;
#userIpHistoriesClearIntervalId: NodeJS.Timer;
private logger: Logger;
private userIpHistories: Map<User['id'], Set<string>>;
private userIpHistoriesClearIntervalId: NodeJS.Timer;
constructor(
@Inject(DI.userIpsRepository)
@ -36,11 +36,11 @@ export class ApiCallService implements OnApplicationShutdown {
private rateLimiterService: RateLimiterService,
private apiLoggerService: ApiLoggerService,
) {
this.#logger = this.apiLoggerService.logger;
this.#userIpHistories = new Map<User['id'], Set<string>>();
this.logger = this.apiLoggerService.logger;
this.userIpHistories = new Map<User['id'], Set<string>>();
this.#userIpHistoriesClearIntervalId = setInterval(() => {
this.#userIpHistories.clear();
this.userIpHistoriesClearIntervalId = setInterval(() => {
this.userIpHistories.clear();
}, 1000 * 60 * 60);
}
@ -76,7 +76,7 @@ export class ApiCallService implements OnApplicationShutdown {
// Authentication
this.authenticateService.authenticate(body['i']).then(([user, app]) => {
// API invoking
this.#call(endpoint, exec, user, app, body, ctx).then((res: any) => {
this.call(endpoint, exec, user, app, body, ctx).then((res: any) => {
if (ctx.method === 'GET' && endpoint.meta.cacheSec && !body['i'] && !user) {
ctx.set('Cache-Control', `public, max-age=${endpoint.meta.cacheSec}`);
}
@ -90,10 +90,10 @@ export class ApiCallService implements OnApplicationShutdown {
this.metaService.fetch().then(meta => {
if (!meta.enableIpLogging) return;
const ip = ctx.ip;
const ips = this.#userIpHistories.get(user.id);
const ips = this.userIpHistories.get(user.id);
if (ips == null || !ips.has(ip)) {
if (ips == null) {
this.#userIpHistories.set(user.id, new Set([ip]));
this.userIpHistories.set(user.id, new Set([ip]));
} else {
ips.add(ip);
}
@ -123,7 +123,7 @@ export class ApiCallService implements OnApplicationShutdown {
});
}
async #call(
private async call(
ep: IEndpoint,
exec: any,
user: CacheableLocalUser | null | undefined,
@ -225,7 +225,7 @@ export class ApiCallService implements OnApplicationShutdown {
if (err instanceof ApiError) {
throw err;
} else {
this.#logger.error(`Internal error occurred in ${ep.name}: ${err.message}`, {
this.logger.error(`Internal error occurred in ${ep.name}: ${err.message}`, {
ep: ep.name,
ps: data,
e: {
@ -247,12 +247,12 @@ export class ApiCallService implements OnApplicationShutdown {
const after = performance.now();
const time = after - before;
if (time > 1000) {
this.#logger.warn(`SLOW API CALL DETECTED: ${ep.name} (${time}ms)`);
this.logger.warn(`SLOW API CALL DETECTED: ${ep.name} (${time}ms)`);
}
});
}
public onApplicationShutdown(signal?: string | undefined) {
clearInterval(this.#userIpHistoriesClearIntervalId);
clearInterval(this.userIpHistoriesClearIntervalId);
}
}

View File

@ -17,7 +17,7 @@ export class AuthenticationError extends Error {
@Injectable()
export class AuthenticateService {
#appCache: Cache<App>;
private appCache: Cache<App>;
constructor(
@Inject(DI.usersRepository)
@ -31,7 +31,7 @@ export class AuthenticateService {
private userCacheService: UserCacheService,
) {
this.#appCache = new Cache<App>(Infinity);
this.appCache = new Cache<App>(Infinity);
}
public async authenticate(token: string | null): Promise<[CacheableLocalUser | null | undefined, AccessToken | null | undefined]> {
@ -71,7 +71,7 @@ export class AuthenticateService {
}) as Promise<ILocalUser>);
if (accessToken.appId) {
const app = await this.#appCache.fetch(accessToken.appId,
const app = await this.appCache.fetch(accessToken.appId,
() => this.appsRepository.findOneByOrFail({ id: accessToken.appId! }));
return [user, {

View File

@ -8,7 +8,7 @@ import type { IEndpointMeta } from './endpoints.js';
@Injectable()
export class RateLimiterService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.redis)
@ -16,7 +16,7 @@ export class RateLimiterService {
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('limiter');
this.logger = this.loggerService.getLogger('limiter');
}
public limit(limitation: IEndpointMeta['limit'] & { key: NonNullable<string> }, actor: string) {
@ -37,7 +37,7 @@ export class RateLimiterService {
return reject('ERR');
}
this.#logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);
this.logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);
if (info.remaining === 0) {
reject('BRIEF_REQUEST_INTERVAL');
@ -65,7 +65,7 @@ export class RateLimiterService {
return reject('ERR');
}
this.#logger.debug(`${actor} ${limitation.key} max remaining: ${info.remaining}`);
this.logger.debug(`${actor} ${limitation.key} max remaining: ${info.remaining}`);
if (info.remaining === 0) {
reject('RATE_LIMIT_EXCEEDED');

View File

@ -71,13 +71,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
(async () => {
await this.userSuspendService.doPostSuspend(user).catch(e => {});
await this.#unFollowAll(user).catch(e => {});
await this.#readAllNotify(user).catch(e => {});
await this.unFollowAll(user).catch(e => {});
await this.readAllNotify(user).catch(e => {});
})();
});
}
async #unFollowAll(follower: User) {
private async unFollowAll(follower: User) {
const followings = await this.followingsRepository.findBy({
followerId: follower.id,
});
@ -95,7 +95,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
}
async #readAllNotify(notifier: User) {
private async readAllNotify(notifier: User) {
await this.notificationsRepository.update({
notifierId: notifier.id,
isRead: false,

View File

@ -100,7 +100,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private apNoteService: ApNoteService,
) {
super(meta, paramDef, async (ps, me) => {
const object = await this.#fetchAny(ps.uri, me);
const object = await this.fetchAny(ps.uri, me);
if (object) {
return object;
} else {
@ -112,12 +112,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
/***
* URIからUserかNoteを解決する
*/
async #fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
private async fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
// ブロックしてたら中断
const fetchedMeta = await this.metaService.fetch();
if (fetchedMeta.blockedHosts.includes(this.utilityService.extractDbHost(uri))) return null;
let local = await this.#mergePack(me, ...await Promise.all([
let local = await this.mergePack(me, ...await Promise.all([
this.apDbResolverService.getUserFromApId(uri),
this.apDbResolverService.getNoteFromApId(uri),
]));
@ -130,21 +130,21 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
// /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する
// これはDBに存在する可能性があるため再度DB検索
if (uri !== object.id) {
local = await this.#mergePack(me, ...await Promise.all([
local = await this.mergePack(me, ...await Promise.all([
this.apDbResolverService.getUserFromApId(object.id),
this.apDbResolverService.getNoteFromApId(object.id),
]));
if (local != null) return local;
}
return await this.#mergePack(
return await this.mergePack(
me,
isActor(object) ? await this.apPersonService.createPerson(getApId(object)) : null,
isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, true) : null,
);
}
async #mergePack(me: CacheableLocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
private async mergePack(me: CacheableLocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
if (user != null) {
return {
type: 'User',

View File

@ -42,12 +42,12 @@ export class DiscordServerService {
const router = new Router();
router.get('/disconnect/discord', async ctx => {
if (!this.#compareOrigin(ctx)) {
if (!this.compareOrigin(ctx)) {
ctx.throw(400, 'invalid origin');
return;
}
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
if (!userToken) {
ctx.throw(400, 'signin required');
return;
@ -91,12 +91,12 @@ export class DiscordServerService {
};
router.get('/connect/discord', async ctx => {
if (!this.#compareOrigin(ctx)) {
if (!this.compareOrigin(ctx)) {
ctx.throw(400, 'invalid origin');
return;
}
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
if (!userToken) {
ctx.throw(400, 'signin required');
return;
@ -138,7 +138,7 @@ export class DiscordServerService {
});
router.get('/dc/cb', async ctx => {
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
const oauth2 = await getOAuth2();
@ -299,11 +299,11 @@ export class DiscordServerService {
return router;
}
#getUserToken(ctx: Koa.BaseContext): string | null {
private getUserToken(ctx: Koa.BaseContext): string | null {
return ((ctx.headers['cookie'] ?? '').match(/igi=(\w+)/) ?? [null, null])[1];
}
#compareOrigin(ctx: Koa.BaseContext): boolean {
private compareOrigin(ctx: Koa.BaseContext): boolean {
function normalizeUrl(url?: string): string {
return url ? url.endsWith('/') ? url.substr(0, url.length - 1) : url : '';
}

View File

@ -42,12 +42,12 @@ export class GithubServerService {
const router = new Router();
router.get('/disconnect/github', async ctx => {
if (!this.#compareOrigin(ctx)) {
if (!this.compareOrigin(ctx)) {
ctx.throw(400, 'invalid origin');
return;
}
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
if (!userToken) {
ctx.throw(400, 'signin required');
return;
@ -91,12 +91,12 @@ export class GithubServerService {
};
router.get('/connect/github', async ctx => {
if (!this.#compareOrigin(ctx)) {
if (!this.compareOrigin(ctx)) {
ctx.throw(400, 'invalid origin');
return;
}
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
if (!userToken) {
ctx.throw(400, 'signin required');
return;
@ -136,7 +136,7 @@ export class GithubServerService {
});
router.get('/gh/cb', async ctx => {
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
const oauth2 = await getOath2();
@ -271,11 +271,11 @@ export class GithubServerService {
return router;
}
#getUserToken(ctx: Koa.BaseContext): string | null {
private getUserToken(ctx: Koa.BaseContext): string | null {
return ((ctx.headers['cookie'] ?? '').match(/igi=(\w+)/) ?? [null, null])[1];
}
#compareOrigin(ctx: Koa.BaseContext): boolean {
private compareOrigin(ctx: Koa.BaseContext): boolean {
function normalizeUrl(url?: string): string {
return url ? url.endsWith('/') ? url.substr(0, url.length - 1) : url : '';
}

View File

@ -42,12 +42,12 @@ export class TwitterServerService {
const router = new Router();
router.get('/disconnect/twitter', async ctx => {
if (!this.#compareOrigin(ctx)) {
if (!this.compareOrigin(ctx)) {
ctx.throw(400, 'invalid origin');
return;
}
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
if (userToken == null) {
ctx.throw(400, 'signin required');
return;
@ -90,12 +90,12 @@ export class TwitterServerService {
};
router.get('/connect/twitter', async ctx => {
if (!this.#compareOrigin(ctx)) {
if (!this.compareOrigin(ctx)) {
ctx.throw(400, 'invalid origin');
return;
}
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
if (userToken == null) {
ctx.throw(400, 'signin required');
return;
@ -125,7 +125,7 @@ export class TwitterServerService {
});
router.get('/tw/cb', async ctx => {
const userToken = this.#getUserToken(ctx);
const userToken = this.getUserToken(ctx);
const twAuth = await getTwAuth();
@ -214,11 +214,11 @@ export class TwitterServerService {
return router;
}
#getUserToken(ctx: Koa.BaseContext): string | null {
private getUserToken(ctx: Koa.BaseContext): string | null {
return ((ctx.headers['cookie'] ?? '').match(/igi=(\w+)/) ?? [null, null])[1];
}
#compareOrigin(ctx: Koa.BaseContext): boolean {
private compareOrigin(ctx: Koa.BaseContext): boolean {
function normalizeUrl(url?: string): string {
return url ? url.endsWith('/') ? url.substr(0, url.length - 1) : url : '';
}

View File

@ -84,7 +84,7 @@ export class ClientServerService {
) {
}
async #manifestHandler(ctx: Koa.Context) {
private async manifestHandler(ctx: Koa.Context) {
// TODO
//const res = structuredClone(manifest);
const res = JSON.parse(JSON.stringify(manifest));
@ -264,7 +264,7 @@ export class ClientServerService {
});
// Manifest
router.get('/manifest.json', ctx => this.#manifestHandler(ctx));
router.get('/manifest.json', ctx => this.manifestHandler(ctx));
router.get('/robots.txt', async ctx => {
await send(ctx as any, '/robots.txt', {

View File

@ -12,7 +12,7 @@ import type Koa from 'koa';
@Injectable()
export class UrlPreviewService {
#logger: Logger;
private logger: Logger;
constructor(
@Inject(DI.config)
@ -25,10 +25,10 @@ export class UrlPreviewService {
private httpRequestService: HttpRequestService,
private loggerService: LoggerService,
) {
this.#logger = this.loggerService.getLogger('url-preview');
this.logger = this.loggerService.getLogger('url-preview');
}
#wrap(url?: string): string | null {
private wrap(url?: string): string | null {
return url != null
? url.match(/^https?:\/\//)
? `${this.config.url}/proxy/preview.webp?${query({
@ -54,7 +54,7 @@ export class UrlPreviewService {
const meta = await this.metaService.fetch();
this.#logger.info(meta.summalyProxy
this.logger.info(meta.summalyProxy
? `(Proxy) Getting preview of ${url}@${lang} ...`
: `Getting preview of ${url}@${lang} ...`);
@ -67,17 +67,17 @@ export class UrlPreviewService {
lang: lang ?? 'ja-JP',
});
this.#logger.succ(`Got preview of ${url}: ${summary.title}`);
this.logger.succ(`Got preview of ${url}: ${summary.title}`);
summary.icon = this.#wrap(summary.icon);
summary.thumbnail = this.#wrap(summary.thumbnail);
summary.icon = this.wrap(summary.icon);
summary.thumbnail = this.wrap(summary.thumbnail);
// Cache 7days
ctx.set('Cache-Control', 'max-age=604800, immutable');
ctx.body = summary;
} catch (err) {
this.#logger.warn(`Failed to get preview of ${url}: ${err}`);
this.logger.warn(`Failed to get preview of ${url}: ${err}`);
ctx.status = 200;
ctx.set('Cache-Control', 'max-age=86400, immutable');
ctx.body = '{}';