mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-21 11:05:37 +02:00
Merge branch 'develop' into copilot/add-user-mute-settings
This commit is contained in:
@@ -40,17 +40,17 @@
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"@swc/core-darwin-arm64": "1.14.0",
|
||||
"@swc/core-darwin-x64": "1.14.0",
|
||||
"@swc/core-darwin-arm64": "1.15.2",
|
||||
"@swc/core-darwin-x64": "1.15.2",
|
||||
"@swc/core-freebsd-x64": "1.3.11",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.14.0",
|
||||
"@swc/core-linux-arm64-gnu": "1.14.0",
|
||||
"@swc/core-linux-arm64-musl": "1.14.0",
|
||||
"@swc/core-linux-x64-gnu": "1.14.0",
|
||||
"@swc/core-linux-x64-musl": "1.14.0",
|
||||
"@swc/core-win32-arm64-msvc": "1.14.0",
|
||||
"@swc/core-win32-ia32-msvc": "1.14.0",
|
||||
"@swc/core-win32-x64-msvc": "1.14.0",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.2",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.2",
|
||||
"@swc/core-linux-arm64-musl": "1.15.2",
|
||||
"@swc/core-linux-x64-gnu": "1.15.2",
|
||||
"@swc/core-linux-x64-musl": "1.15.2",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.2",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.2",
|
||||
"@swc/core-win32-x64-msvc": "1.15.2",
|
||||
"@tensorflow/tfjs": "4.22.0",
|
||||
"@tensorflow/tfjs-node": "4.22.0",
|
||||
"bufferutil": "4.0.9",
|
||||
@@ -70,8 +70,8 @@
|
||||
"utf-8-validate": "6.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.922.0",
|
||||
"@aws-sdk/lib-storage": "3.922.0",
|
||||
"@aws-sdk/client-s3": "3.936.0",
|
||||
"@aws-sdk/lib-storage": "3.936.0",
|
||||
"@discordapp/twemoji": "16.0.1",
|
||||
"@fastify/accepts": "5.0.3",
|
||||
"@fastify/cookie": "11.0.2",
|
||||
@@ -83,18 +83,18 @@
|
||||
"@fastify/view": "10.0.2",
|
||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||
"@misskey-dev/summaly": "5.2.5",
|
||||
"@napi-rs/canvas": "0.1.81",
|
||||
"@nestjs/common": "11.1.8",
|
||||
"@nestjs/core": "11.1.8",
|
||||
"@nestjs/testing": "11.1.8",
|
||||
"@napi-rs/canvas": "0.1.82",
|
||||
"@nestjs/common": "11.1.9",
|
||||
"@nestjs/core": "11.1.9",
|
||||
"@nestjs/testing": "11.1.9",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sentry/node": "10.22.0",
|
||||
"@sentry/profiling-node": "10.22.0",
|
||||
"@sentry/node": "10.26.0",
|
||||
"@sentry/profiling-node": "10.26.0",
|
||||
"@simplewebauthn/server": "12.0.0",
|
||||
"@sinonjs/fake-timers": "11.3.1",
|
||||
"@smithy/node-http-handler": "2.5.0",
|
||||
"@swc/cli": "0.7.8",
|
||||
"@swc/core": "1.14.0",
|
||||
"@swc/cli": "0.7.9",
|
||||
"@swc/core": "1.15.2",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@types/redis-info": "3.0.3",
|
||||
"accepts": "1.3.8",
|
||||
@@ -104,24 +104,23 @@
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "1.20.3",
|
||||
"bullmq": "5.63.0",
|
||||
"bullmq": "5.63.2",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"cbor": "9.0.2",
|
||||
"chalk": "5.6.2",
|
||||
"chalk-template": "1.1.2",
|
||||
"chokidar": "4.0.3",
|
||||
"cli-highlight": "2.1.11",
|
||||
"color-convert": "2.0.1",
|
||||
"content-disposition": "0.5.4",
|
||||
"date-fns": "2.30.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"fastify": "5.6.1",
|
||||
"fastify": "5.6.2",
|
||||
"fastify-raw-body": "5.0.0",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "21.0.0",
|
||||
"file-type": "21.1.1",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.4",
|
||||
"got": "14.6.1",
|
||||
"form-data": "4.0.5",
|
||||
"got": "14.6.4",
|
||||
"happy-dom": "20.0.10",
|
||||
"hpagent": "1.2.0",
|
||||
"htmlescape": "1.1.1",
|
||||
@@ -130,7 +129,7 @@
|
||||
"ip-cidr": "4.0.2",
|
||||
"ipaddr.js": "2.2.0",
|
||||
"is-svg": "5.1.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"js-yaml": "4.1.1",
|
||||
"jsdom": "26.1.0",
|
||||
"json5": "2.2.3",
|
||||
"jsonld": "8.3.3",
|
||||
@@ -162,7 +161,7 @@
|
||||
"qrcode": "1.5.4",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"re2": "1.22.1",
|
||||
"re2": "1.22.3",
|
||||
"redis-info": "3.1.0",
|
||||
"redis-lock": "0.1.4",
|
||||
"reflect-metadata": "0.2.2",
|
||||
@@ -171,8 +170,8 @@
|
||||
"rxjs": "7.8.2",
|
||||
"sanitize-html": "2.17.0",
|
||||
"secure-json-parse": "3.0.2",
|
||||
"sharp": "0.33.5",
|
||||
"semver": "7.7.3",
|
||||
"sharp": "0.33.5",
|
||||
"slacc": "0.0.10",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
@@ -192,7 +191,7 @@
|
||||
"devDependencies": {
|
||||
"@jest/globals": "29.7.0",
|
||||
"@nestjs/platform-express": "10.4.20",
|
||||
"@sentry/vue": "10.22.0",
|
||||
"@sentry/vue": "10.26.0",
|
||||
"@simplewebauthn/types": "12.0.0",
|
||||
"@swc/jest": "0.2.39",
|
||||
"@types/accepts": "1.3.7",
|
||||
@@ -211,7 +210,7 @@
|
||||
"@types/jsrsasign": "10.5.15",
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/ms": "0.7.34",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/nodemailer": "6.4.21",
|
||||
"@types/oauth": "0.9.6",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
@@ -232,8 +231,8 @@
|
||||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.46.2",
|
||||
"@typescript-eslint/parser": "8.46.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.47.0",
|
||||
"@typescript-eslint/parser": "8.47.0",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
@@ -241,7 +240,7 @@
|
||||
"fkill": "9.0.0",
|
||||
"jest": "29.7.0",
|
||||
"jest-mock": "29.7.0",
|
||||
"nodemon": "3.1.10",
|
||||
"nodemon": "3.1.11",
|
||||
"pid-port": "1.0.2",
|
||||
"simple-oauth2": "5.1.0",
|
||||
"supertest": "7.1.4"
|
||||
|
||||
@@ -41,7 +41,7 @@ function greet() {
|
||||
//#endregion
|
||||
|
||||
console.log(' Misskey is an open-source decentralized microblogging platform.');
|
||||
console.log(chalk.rgb(255, 136, 0)(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo'));
|
||||
console.log(chalk.rgb(255, 136, 0)(' If you like Misskey, please consider donating to support dev. https://misskey-hub.net/docs/donate/'));
|
||||
|
||||
console.log('');
|
||||
console.log(chalkTemplate`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`);
|
||||
|
||||
@@ -7,11 +7,11 @@ import * as fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import * as nsfw from 'nsfwjs';
|
||||
import si from 'systeminformation';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import fetch from 'node-fetch';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { NSFWJS, PredictionType } from 'nsfwjs';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
@@ -21,7 +21,7 @@ let isSupportedCpu: undefined | boolean = undefined;
|
||||
|
||||
@Injectable()
|
||||
export class AiService {
|
||||
private model: nsfw.NSFWJS;
|
||||
private model: NSFWJS;
|
||||
private modelLoadMutex: Mutex = new Mutex();
|
||||
|
||||
constructor(
|
||||
@@ -29,7 +29,7 @@ export class AiService {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async detectSensitive(source: string | Buffer): Promise<nsfw.PredictionType[] | null> {
|
||||
public async detectSensitive(source: string | Buffer): Promise<PredictionType[] | null> {
|
||||
try {
|
||||
if (isSupportedCpu === undefined) {
|
||||
isSupportedCpu = await this.computeIsSupportedCpu();
|
||||
@@ -44,6 +44,7 @@ export class AiService {
|
||||
tf.env().global.fetch = fetch;
|
||||
|
||||
if (this.model == null) {
|
||||
const nsfw = await import('nsfwjs');
|
||||
await this.modelLoadMutex.runExclusive(async () => {
|
||||
if (this.model == null) {
|
||||
this.model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
|
||||
|
||||
@@ -5,18 +5,9 @@
|
||||
|
||||
import {
|
||||
FindOneOptions,
|
||||
InsertQueryBuilder,
|
||||
ObjectLiteral,
|
||||
QueryRunner,
|
||||
Repository,
|
||||
SelectQueryBuilder,
|
||||
} from 'typeorm';
|
||||
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js';
|
||||
import { RelationCountLoader } from 'typeorm/query-builder/relation-count/RelationCountLoader.js';
|
||||
import { RelationIdLoader } from 'typeorm/query-builder/relation-id/RelationIdLoader.js';
|
||||
import {
|
||||
RawSqlResultsToEntityTransformer,
|
||||
} from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer.js';
|
||||
import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js';
|
||||
import { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
|
||||
import { MiAccessToken } from '@/models/AccessToken.js';
|
||||
@@ -96,66 +87,12 @@ import { MiWebhook } from '@/models/Webhook.js';
|
||||
import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js';
|
||||
|
||||
export interface MiRepository<T extends ObjectLiteral> {
|
||||
createTableColumnNames(this: Repository<T> & MiRepository<T>): string[];
|
||||
|
||||
insertOne(this: Repository<T> & MiRepository<T>, entity: QueryDeepPartialEntity<T>, findOptions?: Pick<FindOneOptions<T>, 'relations'>): Promise<T>;
|
||||
|
||||
insertOneImpl(this: Repository<T> & MiRepository<T>, entity: QueryDeepPartialEntity<T>, findOptions?: Pick<FindOneOptions<T>, 'relations'>, queryRunner?: QueryRunner): Promise<T>;
|
||||
|
||||
selectAliasColumnNames(this: Repository<T> & MiRepository<T>, queryBuilder: InsertQueryBuilder<T>, builder: SelectQueryBuilder<T>): void;
|
||||
}
|
||||
|
||||
export const miRepository = {
|
||||
createTableColumnNames() {
|
||||
return this.metadata.columns.filter(column => column.isSelect && !column.isVirtual).map(column => column.databaseName);
|
||||
},
|
||||
async insertOne(entity, findOptions?) {
|
||||
const opt = this.manager.connection.options as PostgresConnectionOptions;
|
||||
if (opt.replication) {
|
||||
const queryRunner = this.manager.connection.createQueryRunner('master');
|
||||
try {
|
||||
return this.insertOneImpl(entity, findOptions, queryRunner);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
} else {
|
||||
return this.insertOneImpl(entity, findOptions);
|
||||
}
|
||||
},
|
||||
async insertOneImpl(entity, findOptions?, queryRunner?) {
|
||||
// ---- insert + returningの結果を共通テーブル式(CTE)に保持するクエリを生成 ----
|
||||
|
||||
const queryBuilder = this.createQueryBuilder().insert().values(entity);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const mainAlias = queryBuilder.expressionMap.mainAlias!;
|
||||
const name = mainAlias.name;
|
||||
mainAlias.name = 't';
|
||||
const columnNames = this.createTableColumnNames();
|
||||
queryBuilder.returning(columnNames.reduce((a, c) => `${a}, ${queryBuilder.escape(c)}`, '').slice(2));
|
||||
|
||||
// ---- 共通テーブル式(CTE)から結果を取得 ----
|
||||
const builder = this.createQueryBuilder(undefined, queryRunner).addCommonTableExpression(queryBuilder, 'cte', { columnNames });
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
builder.expressionMap.mainAlias!.tablePath = 'cte';
|
||||
this.selectAliasColumnNames(queryBuilder, builder);
|
||||
if (findOptions) {
|
||||
builder.setFindOptions(findOptions);
|
||||
}
|
||||
const raw = await builder.execute();
|
||||
mainAlias.name = name;
|
||||
const relationId = await new RelationIdLoader(builder.connection, this.queryRunner, builder.expressionMap.relationIdAttributes).load(raw);
|
||||
const relationCount = await new RelationCountLoader(builder.connection, this.queryRunner, builder.expressionMap.relationCountAttributes).load(raw);
|
||||
const result = new RawSqlResultsToEntityTransformer(builder.expressionMap, builder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias);
|
||||
return result[0];
|
||||
},
|
||||
selectAliasColumnNames(queryBuilder, builder) {
|
||||
let selectOrAddSelect = (selection: string, selectionAliasName?: string) => {
|
||||
selectOrAddSelect = (selection, selectionAliasName) => builder.addSelect(selection, selectionAliasName);
|
||||
return builder.select(selection, selectionAliasName);
|
||||
};
|
||||
for (const columnName of this.createTableColumnNames()) {
|
||||
selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`);
|
||||
}
|
||||
return await this.insert(entity).then(x => this.findOneOrFail({ where: x.identifiers[0], ...findOptions }));
|
||||
},
|
||||
} satisfies MiRepository<ObjectLiteral>;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// https://github.com/typeorm/typeorm/issues/2400
|
||||
import pg from 'pg';
|
||||
import { DataSource, Logger, type QueryRunner } from 'typeorm';
|
||||
import * as highlight from 'cli-highlight';
|
||||
import { entities as charts } from '@/core/chart/entities.js';
|
||||
import { Config } from '@/config.js';
|
||||
import MisskeyLogger from '@/logger.js';
|
||||
@@ -25,7 +24,7 @@ import { MiAuthSession } from '@/models/AuthSession.js';
|
||||
import { MiBlocking } from '@/models/Blocking.js';
|
||||
import { MiChannelFollowing } from '@/models/ChannelFollowing.js';
|
||||
import { MiChannelFavorite } from '@/models/ChannelFavorite.js';
|
||||
import { MiChannelMuting } from "@/models/ChannelMuting.js";
|
||||
import { MiChannelMuting } from '@/models/ChannelMuting.js';
|
||||
import { MiClip } from '@/models/Clip.js';
|
||||
import { MiClipNote } from '@/models/ClipNote.js';
|
||||
import { MiClipFavorite } from '@/models/ClipFavorite.js';
|
||||
@@ -101,12 +100,6 @@ export type LoggerProps = {
|
||||
printReplicationMode?: boolean,
|
||||
};
|
||||
|
||||
function highlightSql(sql: string) {
|
||||
return highlight.highlight(sql, {
|
||||
language: 'sql', ignoreIllegals: true,
|
||||
});
|
||||
}
|
||||
|
||||
function truncateSql(sql: string) {
|
||||
return sql.length > 100 ? `${sql.substring(0, 100)}...` : sql;
|
||||
}
|
||||
@@ -132,7 +125,7 @@ class MyCustomLogger implements Logger {
|
||||
modded = truncateSql(modded);
|
||||
}
|
||||
|
||||
return highlightSql(modded);
|
||||
return modded;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { QueryService } from '@/core/QueryService.js';
|
||||
import type { ClipFavoritesRepository } from '@/models/_.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ClipEntityService } from '@/core/entities/ClipEntityService.js';
|
||||
@@ -31,11 +30,6 @@ export const meta = {
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||
sinceId: { type: 'string', format: 'misskey:id' },
|
||||
untilId: { type: 'string', format: 'misskey:id' },
|
||||
sinceDate: { type: 'integer' },
|
||||
untilDate: { type: 'integer' },
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
@@ -46,16 +40,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
@Inject(DI.clipFavoritesRepository)
|
||||
private clipFavoritesRepository: ClipFavoritesRepository,
|
||||
|
||||
private queryService: QueryService,
|
||||
private clipEntityService: ClipEntityService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const query = this.queryService.makePaginationQuery(this.clipFavoritesRepository.createQueryBuilder('favorite'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
||||
const query = this.clipFavoritesRepository.createQueryBuilder('favorite')
|
||||
.andWhere('favorite.userId = :meId', { meId: me.id })
|
||||
.leftJoinAndSelect('favorite.clip', 'clip');
|
||||
|
||||
const favorites = await query
|
||||
.limit(ps.limit)
|
||||
.getMany();
|
||||
|
||||
return this.clipEntityService.packMany(favorites.map(x => x.clip!), me);
|
||||
|
||||
@@ -295,8 +295,20 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
if (ps.chatScope !== undefined) updates.chatScope = ps.chatScope;
|
||||
|
||||
function checkMuteWordCount(mutedWords: (string[] | string)[], limit: number) {
|
||||
// TODO: ちゃんと数える
|
||||
const length = JSON.stringify(mutedWords).length;
|
||||
const count = (arr: (string[] | string)[]) => {
|
||||
let length = 0;
|
||||
for (const item of arr) {
|
||||
if (typeof item === 'string') {
|
||||
length += item.length;
|
||||
} else if (Array.isArray(item)) {
|
||||
for (const subItem of item) {
|
||||
length += subItem.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
return length;
|
||||
};
|
||||
const length = count(mutedWords);
|
||||
if (length > limit) {
|
||||
throw new ApiError(meta.errors.tooManyMutedWords);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
if (targetLang.includes('-')) targetLang = targetLang.split('-')[0];
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append('auth_key', this.serverSettings.deeplAuthKey);
|
||||
params.append('text', note.text);
|
||||
params.append('target_lang', targetLang);
|
||||
|
||||
@@ -104,6 +103,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
const res = await this.httpRequestService.send(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `DeepL-Auth-Key ${this.serverSettings.deeplAuthKey}`,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
Accept: 'application/json, */*',
|
||||
},
|
||||
|
||||
@@ -41,6 +41,10 @@ class ChannelChannel extends Channel {
|
||||
private async onNote(note: Packed<'Note'>) {
|
||||
if (note.channelId !== this.channelId) return;
|
||||
|
||||
if (note.user.requireSigninToViewContents && this.user == null) return;
|
||||
if (note.renote && note.renote.user.requireSigninToViewContents && this.user == null) return;
|
||||
if (note.reply && note.reply.user.requireSigninToViewContents && this.user == null) return;
|
||||
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
if (this.user && isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
||||
@@ -50,7 +50,7 @@ import { AnnouncementEntityService } from '@/core/entities/AnnouncementEntitySer
|
||||
import { FeedService } from './FeedService.js';
|
||||
import { UrlPreviewService } from './UrlPreviewService.js';
|
||||
import { ClientLoggerService } from './ClientLoggerService.js';
|
||||
import type { FastifyInstance, FastifyPluginOptions, FastifyReply } from 'fastify';
|
||||
import type { FastifyError, FastifyInstance, FastifyPluginOptions, FastifyReply } from 'fastify';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
@@ -918,7 +918,7 @@ export class ClientServerService {
|
||||
return await renderBase(reply);
|
||||
});
|
||||
|
||||
fastify.setErrorHandler(async (error, request, reply) => {
|
||||
fastify.setErrorHandler<FastifyError>(async (error, request, reply) => {
|
||||
const errId = randomUUID();
|
||||
this.clientLoggerService.logger.error(`Internal error occurred in ${request.routeOptions.url}: ${error.message}`, {
|
||||
path: request.routeOptions.url,
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
//#region Script
|
||||
async function importAppScript() {
|
||||
await import(CLIENT_ENTRY ? `/embed_vite/${CLIENT_ENTRY.replace('scripts', lang)}` : '/embed_vite/src/_boot_.ts')
|
||||
await import(CLIENT_ENTRY ? `/embed_vite/${CLIENT_ENTRY.replace('scripts', lang)}` : '/embed_vite/src/boot.ts')
|
||||
.catch(async e => {
|
||||
console.error(e);
|
||||
renderError('APP_IMPORT');
|
||||
|
||||
@@ -28,7 +28,7 @@ html
|
||||
meta(name='theme-color-orig' content= themeColor || '#86b300')
|
||||
meta(property='og:site_name' content= instanceName || 'Misskey')
|
||||
meta(property='instance_url' content= instanceUrl)
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover')
|
||||
meta(name='format-detection' content='telephone=no,date=no,address=no,email=no,url=no')
|
||||
link(rel='icon' href= icon || '/favicon.ico')
|
||||
link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png')
|
||||
|
||||
@@ -95,7 +95,7 @@ services:
|
||||
retries: 20
|
||||
|
||||
db:
|
||||
image: postgres:15-alpine
|
||||
image: postgres:18-alpine
|
||||
env_file:
|
||||
- ./.config/docker.env
|
||||
volumes:
|
||||
|
||||
@@ -5,7 +5,7 @@ services:
|
||||
- "127.0.0.1:56312:6379"
|
||||
|
||||
dbtest:
|
||||
image: postgres:15
|
||||
image: postgres:18
|
||||
ports:
|
||||
- "127.0.0.1:54312:5432"
|
||||
environment:
|
||||
|
||||
@@ -506,10 +506,10 @@ describe('クリップ', () => {
|
||||
});
|
||||
};
|
||||
|
||||
const myFavorites = async (parameters: Misskey.entities.ClipsMyFavoritesRequest, request: Partial<ApiRequest<'clips/my-favorites'>> = {}): Promise<Misskey.entities.Clip[]> => {
|
||||
const myFavorites = async (request: Partial<ApiRequest<'clips/my-favorites'>> = {}): Promise<Misskey.entities.Clip[]> => {
|
||||
return successfulApiCall({
|
||||
endpoint: 'clips/my-favorites',
|
||||
parameters,
|
||||
parameters: {},
|
||||
user: alice,
|
||||
...request,
|
||||
});
|
||||
@@ -562,9 +562,8 @@ describe('クリップ', () => {
|
||||
await favorite({ clipId: clip.id });
|
||||
}
|
||||
|
||||
const favorited = await myFavorites({
|
||||
limit: 30,
|
||||
});
|
||||
// pagenationはない。全部一気にとれる。
|
||||
const favorited = await myFavorites();
|
||||
assert.strictEqual(favorited.length, clips.length);
|
||||
for (const clip of favorited) {
|
||||
assert.strictEqual(clip.favoritedCount, 1);
|
||||
@@ -618,7 +617,7 @@ describe('クリップ', () => {
|
||||
const clip = await show({ clipId: aliceClip.id });
|
||||
assert.strictEqual(clip.favoritedCount, 0);
|
||||
assert.strictEqual(clip.isFavorited, false);
|
||||
assert.deepStrictEqual(await myFavorites({}), []);
|
||||
assert.deepStrictEqual(await myFavorites(), []);
|
||||
});
|
||||
|
||||
test.each([
|
||||
@@ -652,13 +651,13 @@ describe('クリップ', () => {
|
||||
|
||||
test('を取得できる。', async () => {
|
||||
await favorite({ clipId: aliceClip.id });
|
||||
const favorited = await myFavorites({});
|
||||
const favorited = await myFavorites();
|
||||
assert.deepStrictEqual(favorited, [await show({ clipId: aliceClip.id })]);
|
||||
});
|
||||
|
||||
test('を取得したとき他人のお気に入りは含まない。', async () => {
|
||||
await favorite({ clipId: aliceClip.id });
|
||||
const favorited = await myFavorites({}, { user: bob });
|
||||
const favorited = await myFavorites({ user: bob });
|
||||
assert.deepStrictEqual(favorited, []);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user