Skip to content

Commit

Permalink
Merge branch 'develop' into fix-15097
Browse files Browse the repository at this point in the history
  • Loading branch information
kakkokari-gtyih authored Jan 11, 2025
2 parents 6fa6424 + c4192e8 commit 4ff5449
Show file tree
Hide file tree
Showing 57 changed files with 2,005 additions and 312 deletions.
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/01_bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ body:
* Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4
* Browser: Chrome 113.0.5672.126
* Server URL: misskey.example.com
* Misskey: 2024.x.x
* Misskey: 2025.x.x
value: |
* Model and OS of the device(s):
* Browser:
Expand All @@ -74,7 +74,7 @@ body:
Examples:
* Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment
* Misskey: 2024.x.x
* Misskey: 2025.x.x
* Node: 20.x.x
* PostgreSQL: 15.x.x
* Redis: 7.x.x
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,36 @@
-

### Client
- Enhance: PC画面でチャンネルが複数列で表示されるように
(Cherry-picked from https://github.com/Otaku-Social/maniakey/pull/13)
- Enhance: 照会に失敗した場合、その理由を表示するように
- Enhance: AiScriptのセーブデータを明示的に削除する関数`Mk:remove`を追加
- Enhance: AiScriptの拡張API関数において引数の型チェックをより厳格に
- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
- Fix: サーバー情報メニューに区切り線が不足していたのを修正
- Fix: ノートがログインしているユーザーしか見れない場合にログインダイアログを閉じるとその後の動線がなくなる問題を修正
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
- Fix: 絵文字管理画面で一部の絵文字が表示されない問題を修正
- Fix: ノート検索が使用できない場合でもチャンネルのノート検索欄がでていた問題を修正
- Fix: `Ui:C:select`で値の変更が画面に反映されない問題を修正
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
(Cherry-picked from https://github.com/TeamNijimiss/misskey/commit/800359623e41a662551d774de15b0437b6849bb4)
- Fix: ノート作成画面でファイルの添付可能個数を超えてもノートボタンが押せていた問題を修正
- Fix: 「アカウントを管理」画面で、ユーザー情報の取得に失敗したアカウント(削除されたアカウントなど)が表示されない問題を修正
- Fix: 言語データのキャッシュ状況によっては、埋め込みウィジェットが正しく起動しない問題を修正

### Server
- Enhance: pg_bigmが利用できるよう、ノートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように
- Enhance: チャート更新時にDBに同時接続しないように
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/830)
- Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
- Fix: ロックダウンされた期間指定のノートがStreaming経由でLTLに出現するのを修正 ( #15200 )
- Fix: disableClustering設定時の初期化ロジックを調整( #15223 )
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/869)
- Fix: `/api/pages/update`にて`name`を指定せずにリクエストするとエラーが発生する問題を修正

## 2024.11.0
Expand Down
2 changes: 1 addition & 1 deletion COPYING
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Unless otherwise stated this repository is
Copyright © 2014-2024 syuilo and contributors
Copyright © 2014-2025 syuilo and contributors

And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.4

ARG NODE_VERSION=22.11.0-bullseye
ARG NODE_VERSION=22.11.0-bookworm

# build assets & compile TypeScript

Expand Down
67 changes: 67 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2754,10 +2754,18 @@ export interface Locale extends ILocale {
* ワードミュート
*/
"wordMute": string;
/**
* 指定した語句を含むノートを最小化します。最小化されたノートをクリックすることで表示することができます。
*/
"wordMuteDescription": string;
/**
* ハードワードミュート
*/
"hardWordMute": string;
/**
* 指定した語句を含むノートを隠します。ワードミュートとは異なり、ノートは完全に表示されなくなります。
*/
"hardWordMuteDescription": string;
/**
* 正規表現エラー
*/
Expand Down Expand Up @@ -10601,6 +10609,65 @@ export interface Locale extends ILocale {
*/
"sent": string;
};
"_remoteLookupErrors": {
"_federationNotAllowed": {
/**
* このサーバーとは通信できません
*/
"title": string;
/**
* このサーバーとの通信が無効化されているか、このサーバーをブロックしている・ブロックされている可能性があります。
* サーバー管理者にお問い合わせください。
*/
"description": string;
};
"_uriInvalid": {
/**
* URIが不正です
*/
"title": string;
/**
* 入力されたURIに問題があります。URIに使用できない文字を入力していないか確認してください。
*/
"description": string;
};
"_requestFailed": {
/**
* リクエストに失敗しました
*/
"title": string;
/**
* このサーバーとの通信に失敗しました。相手サーバーがダウンしている可能性があります。また、不正なURIや存在しないURIを入力していないか確認してください。
*/
"description": string;
};
"_responseInvalid": {
/**
* レスポンスが不正です
*/
"title": string;
/**
* このサーバーと通信することはできましたが、得られたデータが不正なものでした。
*/
"description": string;
};
"_responseInvalidIdHostNotMatch": {
/**
* 入力されたURIのドメインと最終的に得られたURIのドメインとが異なります。第三者のサーバーを介してリモートのコンテンツを照会している場合は、発信元のサーバーで取得できるURIを使用して照会し直してください。
*/
"description": string;
};
"_noSuchObject": {
/**
* 見つかりません
*/
"title": string;
/**
* 要求されたリソースは見つかりませんでした。URIをもう一度お確かめください。
*/
"description": string;
};
};
}
declare const locales: {
[lang: string]: Locale;
Expand Down
21 changes: 21 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,9 @@ smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する"
smtpSecureInfo: "STARTTLS使用時はオフにします。"
testEmail: "配信テスト"
wordMute: "ワードミュート"
wordMuteDescription: "指定した語句を含むノートを最小化します。最小化されたノートをクリックすることで表示することができます。"
hardWordMute: "ハードワードミュート"
hardWordMuteDescription: "指定した語句を含むノートを隠します。ワードミュートとは異なり、ノートは完全に表示されなくなります。"
regexpError: "正規表現エラー"
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:"
instanceMute: "サーバーミュート"
Expand Down Expand Up @@ -2826,3 +2828,22 @@ _selfXssPrevention:
_followRequest:
recieved: "受け取った申請"
sent: "送った申請"

_remoteLookupErrors:
_federationNotAllowed:
title: "このサーバーとは通信できません"
description: "このサーバーとの通信が無効化されているか、このサーバーをブロックしている・ブロックされている可能性があります。\nサーバー管理者にお問い合わせください。"
_uriInvalid:
title: "URIが不正です"
description: "入力されたURIに問題があります。URIに使用できない文字を入力していないか確認してください。"
_requestFailed:
title: "リクエストに失敗しました"
description: "このサーバーとの通信に失敗しました。相手サーバーがダウンしている可能性があります。また、不正なURIや存在しないURIを入力していないか確認してください。"
_responseInvalid:
title: "レスポンスが不正です"
description: "このサーバーと通信することはできましたが、得られたデータが不正なものでした。"
_responseInvalidIdHostNotMatch:
description: "入力されたURIのドメインと最終的に得られたURIのドメインとが異なります。第三者のサーバーを介してリモートのコンテンツを照会している場合は、発信元のサーバーで取得できるURIを使用して照会し直してください。"
_noSuchObject:
title: "見つかりません"
description: "要求されたリソースは見つかりませんでした。URIをもう一度お確かめください。"
20 changes: 13 additions & 7 deletions packages/backend/src/boot/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,22 @@ process.on('exit', code => {

//#endregion

if (cluster.isPrimary || envOption.disableClustering) {
await masterMain();

if (!envOption.disableClustering) {
if (cluster.isPrimary) {
logger.info(`Start main process... pid: ${process.pid}`);
await masterMain();
ev.mount();
} else if (cluster.isWorker) {
logger.info(`Start worker process... pid: ${process.pid}`);
await workerMain();
} else {
throw new Error('Unknown process type');
}
}

if (cluster.isWorker || envOption.disableClustering) {
await workerMain();
} else {
// 非clusterの場合はMasterのみが起動するため、Workerの処理は行わない(cluster.isWorker === trueの状態でこのブロックに来ることはない)
logger.info(`Start main process... pid: ${process.pid}`);
await masterMain();
ev.mount();
}

readyRef.value = true;
Expand Down
24 changes: 18 additions & 6 deletions packages/backend/src/boot/master.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,37 @@ export async function masterMain() {
});
}

if (envOption.disableClustering) {
bootLogger.info(
`mode: [disableClustering: ${envOption.disableClustering}, onlyServer: ${envOption.onlyServer}, onlyQueue: ${envOption.onlyQueue}]`
);

if (!envOption.disableClustering) {
// clusterモジュール有効時

if (envOption.onlyServer) {
await server();
// onlyServer かつ enableCluster な場合、メインプロセスはforkのみに制限する(listenしない)。
// ワーカープロセス側でlistenすると、メインプロセスでポートへの着信を受け入れてワーカープロセスへの分配を行う動作をする。
// そのため、メインプロセスでも直接listenするとポートの競合が発生して起動に失敗してしまう。
// see: https://nodejs.org/api/cluster.html#cluster
} else if (envOption.onlyQueue) {
await jobQueue();
} else {
await server();
await jobQueue();
}

await spawnWorkers(config.clusterLimit);
} else {
// clusterモジュール無効時

if (envOption.onlyServer) {
// nop
await server();
} else if (envOption.onlyQueue) {
// nop
await jobQueue();
} else {
await server();
await jobQueue();
}

await spawnWorkers(config.clusterLimit);
}

if (envOption.onlyQueue) {
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/core/SearchService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export class SearchService {
}

query
.andWhere('note.text ILIKE :q', { q: `%${ sqlLikeEscape(q) }%` })
.andWhere('LOWER(note.text) LIKE :q', { q: `%${ sqlLikeEscape(q.toLowerCase()) }%` })
.innerJoinAndSelect('note.user', 'user')
.leftJoinAndSelect('note.reply', 'reply')
.leftJoinAndSelect('note.renote', 'renote')
Expand Down
25 changes: 13 additions & 12 deletions packages/backend/src/core/activitypub/ApResolverService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ApDbResolverService } from './ApDbResolverService.js';
import { ApRendererService } from './ApRendererService.js';
import { ApRequestService } from './ApRequestService.js';
import type { IObject, ICollection, IOrderedCollection } from './type.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';

export class Resolver {
private history: Set<string>;
Expand Down Expand Up @@ -66,7 +67,7 @@ export class Resolver {
if (isCollectionOrOrderedCollection(collection)) {
return collection;
} else {
throw new Error(`unrecognized collection type: ${collection.type}`);
throw new IdentifiableError('f100eccf-f347-43fb-9b45-96a0831fb635', `unrecognized collection type: ${collection.type}`);
}
}

Expand All @@ -80,15 +81,15 @@ export class Resolver {
// URLs with fragment parts cannot be resolved correctly because
// the fragment part does not get transmitted over HTTP(S).
// Avoid strange behaviour by not trying to resolve these at all.
throw new Error(`cannot resolve URL with fragment: ${value}`);
throw new IdentifiableError('b94fd5b1-0e3b-4678-9df2-dad4cd515ab2', `cannot resolve URL with fragment: ${value}`);
}

if (this.history.has(value)) {
throw new Error('cannot resolve already resolved one');
throw new IdentifiableError('0dc86cf6-7cd6-4e56-b1e6-5903d62d7ea5', 'cannot resolve already resolved one');
}

if (this.history.size > this.recursionLimit) {
throw new Error(`hit recursion limit: ${this.utilityService.extractDbHost(value)}`);
throw new IdentifiableError('d592da9f-822f-4d91-83d7-4ceefabcf3d2', `hit recursion limit: ${this.utilityService.extractDbHost(value)}`);
}

this.history.add(value);
Expand All @@ -99,7 +100,7 @@ export class Resolver {
}

if (!this.utilityService.isFederationAllowedHost(host)) {
throw new Error('Instance is blocked');
throw new IdentifiableError('09d79f9e-64f1-4316-9cfa-e75c4d091574', 'Instance is blocked');
}

if (this.config.signToActivityPubGet && !this.user) {
Expand All @@ -115,19 +116,19 @@ export class Resolver {
!(object['@context'] as unknown[]).includes('https://www.w3.org/ns/activitystreams') :
object['@context'] !== 'https://www.w3.org/ns/activitystreams'
) {
throw new Error('invalid response');
throw new IdentifiableError('72180409-793c-4973-868e-5a118eb5519b', 'invalid response');
}

// HttpRequestService / ApRequestService have already checked that
// `object.id` or `object.url` matches the URL used to fetch the
// object after redirects; here we double-check that no redirects
// bounced between hosts
if (object.id == null) {
throw new Error('invalid AP object: missing id');
throw new IdentifiableError('ad2dc287-75c1-44c4-839d-3d2e64576675', 'invalid AP object: missing id');
}

if (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value)) {
throw new Error(`invalid AP object ${value}: id ${object.id} has different host`);
throw new IdentifiableError('fd93c2fa-69a8-440f-880b-bf178e0ec877', `invalid AP object ${value}: id ${object.id} has different host`);
}

return object;
Expand All @@ -136,7 +137,7 @@ export class Resolver {
@bindThis
private resolveLocal(url: string): Promise<IObject> {
const parsed = this.apDbResolverService.parseUri(url);
if (!parsed.local) throw new Error('resolveLocal: not local');
if (!parsed.local) throw new IdentifiableError('02b40cd0-fa92-4b0c-acc9-fb2ada952ab8', 'resolveLocal: not local');

switch (parsed.type) {
case 'notes':
Expand Down Expand Up @@ -165,7 +166,7 @@ export class Resolver {
case 'follows':
return this.followRequestsRepository.findOneBy({ id: parsed.id })
.then(async followRequest => {
if (followRequest == null) throw new Error('resolveLocal: invalid follow request ID');
if (followRequest == null) throw new IdentifiableError('a9d946e5-d276-47f8-95fb-f04230289bb0', 'resolveLocal: invalid follow request ID');
const [follower, followee] = await Promise.all([
this.usersRepository.findOneBy({
id: followRequest.followerId,
Expand All @@ -177,12 +178,12 @@ export class Resolver {
}),
]);
if (follower == null || followee == null) {
throw new Error('resolveLocal: follower or followee does not exist');
throw new IdentifiableError('06ae3170-1796-4d93-a697-2611ea6d83b6', 'resolveLocal: follower or followee does not exist');
}
return this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url));
});
default:
throw new Error(`resolveLocal: type ${parsed.type} unhandled`);
throw new IdentifiableError('7a5d2fc0-94bc-4db6-b8b8-1bf24a2e23d0', `resolveLocal: type ${parsed.type} unhandled`);
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions packages/backend/src/core/chart/ChartManagementService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ export class ChartManagementService implements OnApplicationShutdown {
@bindThis
public async start() {
// 20分おきにメモリ情報をDBに書き込み
this.saveIntervalId = setInterval(() => {
this.saveIntervalId = setInterval(async () => {
for (const chart of this.charts) {
chart.save();
await chart.save();
}
}, 1000 * 60 * 20);
}
Expand All @@ -69,9 +69,9 @@ export class ChartManagementService implements OnApplicationShutdown {
public async dispose(): Promise<void> {
clearInterval(this.saveIntervalId);
if (process.env.NODE_ENV !== 'test') {
await Promise.all(
this.charts.map(chart => chart.save()),
);
for (const chart of this.charts) {
await chart.save();
}
}
}

Expand Down
Loading

0 comments on commit 4ff5449

Please sign in to comment.