+
diff --git a/src/docs/en-US/advanced/aiscript.md b/src/docs/en-US/advanced/aiscript.md
index fc2802fcd4..cfcdfebf96 100644
--- a/src/docs/en-US/advanced/aiscript.md
+++ b/src/docs/en-US/advanced/aiscript.md
@@ -3,5 +3,5 @@ AiScript is a scripting language for Misskey.
ℹ️ AiScript is open source and hosted in a separate repository from Misskey.
-## 使い方
+## Usage
AiScript documentation such as syntax and built-in functions can be found [here](https://github.com/syuilo/aiscript/tree/master/docs).
diff --git a/src/docs/en-US/advanced/api.md b/src/docs/en-US/advanced/api.md
index 76019b6145..ef1995b18e 100644
--- a/src/docs/en-US/advanced/api.md
+++ b/src/docs/en-US/advanced/api.md
@@ -4,7 +4,7 @@ MisskeyAPIを使ってMisskeyクライアント、Misskey連携Webサービス
APIを使い始めるには、まずアクセストークンを取得する必要があります。 このドキュメントでは、アクセストークンを取得する手順を説明した後、基本的なAPIの使い方を説明します。
-## アクセストークンの取得
+## Obtain an access token
基本的に、APIはリクエストにはアクセストークンが必要となります。 APIにリクエストするのが自分自身なのか、不特定の利用者に使ってもらうアプリケーションなのかによって取得手順は異なります。
* 前者の場合: [「自分自身のアクセストークンを手動発行する」](#自分自身のアクセストークンを手動発行する)に進む
@@ -20,7 +20,7 @@ APIを使い始めるには、まずアクセストークンを取得する必
#### Step 1
-UUIDを生成する。以後これをセッションIDと呼びます。
+Generate UUID.以後これをセッションIDと呼びます。
> このセッションIDは毎回生成し、使いまわさないようにしてください。
@@ -30,14 +30,14 @@ UUIDを生成する。以後これをセッションIDと呼びます。
> 例: `{_URL_}/miauth/c1f6d42b-468b-4fd2-8274-e58abdedef6f`
表示する際、URLにクエリパラメータとしていくつかのオプションを設定できます:
-* `name` ... アプリケーション名
+* `name` ... App name
* > 例: `MissDeck`
-* `icon` ... アプリケーションのアイコン画像URL
+* `icon` ... App icon URL
* > 例: `https://missdeck.example.com/icon.png`
* `callback` ... 認証が終わった後にリダイレクトするURL
* > 例: `https://missdeck.example.com/callback`
* リダイレクト時には、`session`というクエリパラメータでセッションIDが付きます
-* `permission` ... アプリケーションが要求する権限
+* `permission` ... App permissions
* > 例: `write:notes,write:following,read:drive`
* 要求する権限を`,`で区切って列挙します
* どのような権限があるかは[APIリファレンス](/api-doc)で確認できます
@@ -46,13 +46,13 @@ UUIDを生成する。以後これをセッションIDと呼びます。
ユーザーが発行を許可した後、`{_URL_}/api/miauth/{session}/check`にPOSTリクエストすると、レスポンスとしてアクセストークンを含むJSONが返ります。
レスポンスに含まれるプロパティ:
-* `token` ... ユーザーのアクセストークン
-* `user` ... ユーザーの情報
+* `token` ... User access token
+* `user` ... User info
[「APIの使い方」へ進む](#APIの使い方)
-## APIの使い方
-**APIはすべてPOSTで、リクエスト/レスポンスともにJSON形式です。RESTではありません。** アクセストークンは、`i`というパラメータ名でリクエストに含めます。
+## API usage
+**APIはすべてPOSTで、リクエスト/レスポンスともにJSON形式です。There is no REST support.** アクセストークンは、`i`というパラメータ名でリクエストに含めます。
-* [APIリファレンス](/api-doc)
-* [ストリーミングAPI](./stream)
+* [API Reference](/api-doc)
+* [Streaming API](./stream)
diff --git a/src/docs/en-US/advanced/create-plugin.md b/src/docs/en-US/advanced/create-plugin.md
index ec17b95186..3b8763dfd8 100644
--- a/src/docs/en-US/advanced/create-plugin.md
+++ b/src/docs/en-US/advanced/create-plugin.md
@@ -1,20 +1,20 @@
-# プラグインの作成
+# New Plugin
Misskey Webクライアントのプラグイン機能を使うと、クライアントを拡張し、様々な機能を追加できます。 ここではプラグインの作成にあたってのメタデータ定義や、AiScript APIリファレンスを掲載します。
## Metadata
プラグインは、AiScriptのメタデータ埋め込み機能を使って、デフォルトとしてプラグインのメタデータを定義する必要があります。 メタデータは次のプロパティを含むオブジェクトです。
### name
-プラグイン名
+Plugin name
### author
-プラグイン作者
+Plugin author
### version
-プラグインバージョン。数値を指定してください。
+プラグインバージョン。A number must be specified.
### description
-プラグインの説明
+Plugin description
### permissions
プラグインが要求する権限。MisskeyAPIにリクエストする際に用いられます。
@@ -34,7 +34,7 @@ Misskey Webクライアントのプラグイン機能を使うと、クライア
#### default
設定のデフォルト値
-## APIリファレンス
+## API Reference
AiScript標準で組み込まれているAPIは掲載しません。
### Mk:dialog(title text type)
diff --git a/src/docs/en-US/advanced/develop-bot.md b/src/docs/en-US/advanced/develop-bot.md
index 7f825e9bc4..c6a312e79e 100644
--- a/src/docs/en-US/advanced/develop-bot.md
+++ b/src/docs/en-US/advanced/develop-bot.md
@@ -1,4 +1,4 @@
-# Botの作成
+# Create a bot
[Misskey API](./api)を利用してBotの開発が可能です。 また、いくつかのBot実装が公開されているため、ぜひ参考にしてください。
- [syuilo/ai](https://github.com/syuilo/ai) ... Node.js上で動く、TypeScript製Bot実装
diff --git a/src/docs/en-US/advanced/stream.md b/src/docs/en-US/advanced/stream.md
index c0d0efc910..16b15c7619 100644
--- a/src/docs/en-US/advanced/stream.md
+++ b/src/docs/en-US/advanced/stream.md
@@ -1,4 +1,4 @@
-# ストリーミングAPI
+# Streaming API
ストリーミングAPIを使うと、リアルタイムで様々な情報(例えばタイムラインに新しい投稿が流れてきた、メッセージが届いた、フォローされた、など)を受け取ったり、様々な操作を行ったりすることができます。
diff --git a/src/docs/en-US/general/glossary.md b/src/docs/en-US/general/glossary.md
index 53164a0a59..139c3eab82 100644
--- a/src/docs/en-US/general/glossary.md
+++ b/src/docs/en-US/general/glossary.md
@@ -73,7 +73,7 @@ A feature allowing users to organize the files they have uploaded to Misskey.For
## Notes
Content which may include text, images, surveys and others that has been posted to Misskey.For details, see [here.](../features/note)
-## Misskist
+## Misskeyist
Users of Misskey.
## Moderator
diff --git a/src/docs/en-US/general/troubleshooting.md b/src/docs/en-US/general/troubleshooting.md
index e3dd5129e0..75051debe6 100644
--- a/src/docs/en-US/general/troubleshooting.md
+++ b/src/docs/en-US/general/troubleshooting.md
@@ -34,7 +34,7 @@ A blinking light indicates unread content.In cases where this light won't go awa
Followers-only notes cannot be renoted.
## Specific parts of the UI are not being displayed
-Problems like these can arise if you are using an Adblocker.Please turn these off on Misskey.
+Problems like these can arise if you are using an Adblocker. For an optimized experience on Misskey, please turn it off.
## Some parts of the UI are untranslated
In most cases, this is simply a matter of the translation not having been done yet instead of being a bug.Please wait until the translation of this area has been completed. You can alternatively also [participate in translation](./misskey) yourself.
diff --git a/src/docs/eo-UY/admin/faq.md b/src/docs/eo-UY/admin/faq.md
index 317b4e0655..5341c0f16f 100644
--- a/src/docs/eo-UY/admin/faq.md
+++ b/src/docs/eo-UY/admin/faq.md
@@ -1,4 +1,4 @@
-# よくある質問
+# Oftaj demandoj
ここでは、サーバー管理者向けのよくある質問を掲載しています。
## デフォルトテーマを設定したい
diff --git a/src/docs/eo-UY/advanced/create-plugin.md b/src/docs/eo-UY/advanced/create-plugin.md
index e7826037b8..7ed29bb824 100644
--- a/src/docs/eo-UY/advanced/create-plugin.md
+++ b/src/docs/eo-UY/advanced/create-plugin.md
@@ -1,4 +1,4 @@
-# プラグインの作成
+# Krei kromaĵo
Misskey Webクライアントのプラグイン機能を使うと、クライアントを拡張し、様々な機能を追加できます。 ここではプラグインの作成にあたってのメタデータ定義や、AiScript APIリファレンスを掲載します。
## Metadatumoj
diff --git a/src/docs/eo-UY/advanced/stream.md b/src/docs/eo-UY/advanced/stream.md
index 932da90f25..9f5cdbbcb0 100644
--- a/src/docs/eo-UY/advanced/stream.md
+++ b/src/docs/eo-UY/advanced/stream.md
@@ -1,4 +1,4 @@
-# ストリーミングAPI
+# API de Flui
ストリーミングAPIを使うと、リアルタイムで様々な情報(例えばタイムラインに新しい投稿が流れてきた、メッセージが届いた、フォローされた、など)を受け取ったり、様々な操作を行ったりすることができます。
diff --git a/src/docs/eo-UY/features/favorite.md b/src/docs/eo-UY/features/favorite.md
index 05c03fa2db..747c871a5d 100644
--- a/src/docs/eo-UY/features/favorite.md
+++ b/src/docs/eo-UY/features/favorite.md
@@ -1,4 +1,4 @@
-# Preferataĵoj
+# Preferaĵoj
[ノート](./node)をお気に入りとして登録できる機能です。 お気に入り登録したノートは、[お気に入りページ](./my/favorites)で一覧することができます。 お気に入りに登録したことは相手に通知されず、お気に入りは自分しか見ることができません。
ノートをお気に入り登録するには、ノートメニューの「お気に入り」を押します。お気に入り解除するには、ノートメニューの「お気に入り解除」を押します。
diff --git a/src/docs/eo-UY/features/keyboard-shortcut.md b/src/docs/eo-UY/features/keyboard-shortcut.md
index b4bb35b763..413bef16c1 100644
--- a/src/docs/eo-UY/features/keyboard-shortcut.md
+++ b/src/docs/eo-UY/features/keyboard-shortcut.md
@@ -4,21 +4,21 @@
これらのショートカットは基本的にどこでも使えます。
- Fulmoklavoj | 効果 | 由来 |
+ Fulmoklavoj | Rezultato | Deveno (angla) |
P, N | Skribi novan noton | Post, New, Note |
T | タイムラインの最も新しい投稿にフォーカス | Timeline, Top |
Shift + N | Malfermi sekcio de sciigoj | Notifications |
S | Serĉi | Search |
- H, ? | ヘルプを表示 | Help |
+ H, ? | Montru helpon | Help |
## 投稿にフォーカスされた状態
- Fulmoklavoj | 効果 | Deveno (angla) |
+ Fulmoklavoj | Rezultato | Deveno (angla) |
↑, K, Shift + Tab | 上の投稿にフォーカスを移動 | - |
@@ -28,7 +28,7 @@
Ctrl + Q | Tuj plusendos (sen la fasado) | - |
E, A, + | リアクションフォームを開く | Emote, reAction |
0-9 | 数字に対応したリアクションをする(対応については後述) | - |
- F, B | Aldoni vian liston de preferaĵoj | Favorite, Bookmark |
+ F, B | Aldoni al vian liston de preferaĵoj | Favorite, Bookmark |
Del, Ctrl + D | Forviŝi la noton | Delete |
M, O | Malfelmi poŝtaĵan menuon | More, Other |
S | CWで隠された部分を表示 or 隠す | Show, See |
@@ -48,11 +48,11 @@
-## リアクションフォーム
+## Elektilo de reago
デフォルトで「👍」にフォーカスが当たっている状態です。
- Fulmoklavoj | 効果 | Deveno (angla) |
+ Fulmoklavoj | Rezultato | Deveno (angla) |
↑, K | 上のリアクションにフォーカスを移動 | - |
diff --git a/src/docs/eo-UY/features/mfm.md b/src/docs/eo-UY/features/mfm.md
index 2970fbd7b2..7257033d8d 100644
--- a/src/docs/eo-UY/features/mfm.md
+++ b/src/docs/eo-UY/features/mfm.md
@@ -2,10 +2,10 @@
MFMは、Misskey Flavored Markdownの略で、Misskeyの様々な場所で使用できる専用のマークアップ言語です。 MFMで使用可能な構文は[MFMチートシート](/mfm-cheat-sheet)で確認できます。
## MFMが使用可能な場所の例
-- ノート本文
+- Teksto de notoj
- CW注釈
-- Nomo de uzanto
-- Profilo de uzanto
+- La nomo de uzantoj
+- La sinprezento de profiloj
## Informoj por programistoj
MFMのパーサー実装はライブラリとして公開されており、簡単にクライアントにMFMを組み込むことが可能です。
diff --git a/src/docs/eo-UY/features/note.md b/src/docs/eo-UY/features/note.md
index aa72981e24..2bfe10951c 100644
--- a/src/docs/eo-UY/features/note.md
+++ b/src/docs/eo-UY/features/note.md
@@ -1,5 +1,5 @@
# Notoj
-ノートは、Misskeyに投稿される、文章、ファイル、アンケートなどを含むコンテンツで、Misskeyの中心的概念です。また、そのノートを作成する行為自体もノートと呼ばれます。
+Notoj estas centraj konceptoj en Misskey kaj enhavoj kiuj konsistas el teksto, bildoj, dosieroj, balotujo k.t.p.Ankaŭ krei notojn estas nomata "noto" same kiel ili
ノートが作成されると、[タイムライン](./timeline)に追加され、自分の[フォロワー](./follow)やサーバーのユーザーが見れるようになります。
@@ -7,14 +7,14 @@
ノートを[お気に入り](./favorite)登録することで、後で簡単に見返すことができます。
-## ノートを作成する
+## Skribi notojn
ノートを作成するには、画面上にある鉛筆マークのボタンを押して、作成フォームを開きます。作成フォームに内容を入力し、「ノート」ボタンを押すことでノートが作成されます。 ノートには、画像、動画など任意のファイルや、[アンケート](./poll)を添付することができます。また、本文中には[MFM](./mfm)が使用でき、[メンション](./mention)や[ハッシュタグ](./hashtag)を含めることもできます。 他にも、CWや公開範囲といった設定も行えます(詳細は後述)。
ℹ️ コンピューターのクリップボードに画像データがある状態で、フォーム内のテキストボックスにペーストするとその画像を添付することができます。
ℹ️ テキストボックス内でCtrl + Enterを押すことでも投稿できます。
-## Plusendi la noton
+## Plusendi noton
既にあるノートを引用、もしくはそのノートを新しいノートとして共有する行為、またそれによって作成されたノートをRenoteと呼びます。 自分がフォローしているユーザーの、気に入ったノートを自分のフォロワーに共有したい場合や、過去の自分のノートを再度共有したい場合に使います。 同じノートに対して無制限にRenoteを行うことができますが、あまり連続して使用すると迷惑になる場合もあるので、注意しましょう。
-⚠️ 公開範囲がフォロワーやダイレクトのノートはRenoteできません
+⚠️ Se oni sendas notojn nur al sekvantoj aŭ rekte, iliaj ne estas plusendeblaj.
Renoteを削除するには、Renoteの時刻表示の隣にある「...」を押し、「Renote解除」を選択します。
@@ -31,10 +31,10 @@ Contents Warningの略で、ノートの内容を、閲覧者の操作なしに
### Hejma
全ての人に対してノートが公開されますが、フォロワー以外のローカルタイムライン、ソーシャルタイムライン、グローバルタイムラインにはノートは流れません。
-### Sekvantoj
-自分のフォロワーに対してのみノートを公開します。フォロワーの全てのタイムラインに流れます。
+### Nur al sekvantoj
+Viaj notoj estos senditaj nur al viaj sekvantoj.La noto aperos sur ĉiuj templinioj de viaj sekvantoj.
-### Rekta
+### Rekte
指定したユーザーに対してのみノートを公開します。指定したユーザーの全てのタイムラインに流れます。
### 「ローカルのみ」オプション
@@ -42,13 +42,13 @@ Contents Warningの略で、ノートの内容を、閲覧者の操作なしに
### 公開範囲の比較
- | Publika | Hejma | Sekvantoj | Rekta |
+ | Publika | Hejma | Nur al sekvantoj | Rekte |
フォロワーのLTL/STL/GTL | ✔ | ✔ | ✔ | |
非フォロワーのLTL/STL/GTL | ✔ | | | |
-## Alpingli al la profilo
+## Alpingli sur profilo
ノートをピン留めすると、ユーザーページに常にそのノートを表示しておくことができます。 ノートのメニューを開き、「ピン留め」を選択してピン留めできます。 複数のノートをピン留めできます。
## Observi
-Vi povas ricevi sciigojn pri reagoj, respondoj, ktp al noto, kiuj ne apartenas al vi. Por observu, malfermu respektivan menuon de noto, kaj elektu la "Observi" el ĝi.
+Vi povas ricevi tiuj sciigoj pri reagoj, respondoj, k.t.p al noto kiuj ne apartenas al vi estas ankaŭ ricevebla. Por komenci tion elektu la "Observi" el la menuon kuntekstan de la notoj respektivaj.
diff --git a/src/docs/eo-UY/general/faq.md b/src/docs/eo-UY/general/faq.md
index c272b2ad42..f7ede4c6cc 100644
--- a/src/docs/eo-UY/general/faq.md
+++ b/src/docs/eo-UY/general/faq.md
@@ -1,4 +1,4 @@
-# よくある質問
+# Oftaj demandoj
ここでは利用上のよくある質問について掲載しています。 Misskeyのプロジェクト自体についてのよくある質問は[こちら](./misskey)に掲載されています。
## iOS/Androidのアプリはありますか?
diff --git a/src/docs/eo-UY/general/glossary.md b/src/docs/eo-UY/general/glossary.md
index fe3b034181..25dd5f82c1 100644
--- a/src/docs/eo-UY/general/glossary.md
+++ b/src/docs/eo-UY/general/glossary.md
@@ -1,4 +1,4 @@
-# 用語集
+# Glosaro
Misskeyに関する用語集です。
## ActivityPub
@@ -49,7 +49,7 @@ Ai estas oficiala maskoto de Misskey.
## Nodo
todo
-## Personecigitaj emoĵioj
+## Emoĵioj personecigitaj
サーバーで用意された絵文字。カスタム絵文字ではない通常の絵文字は「Unicode絵文字」と区別して呼ばれる。
## Ŝaltpodio
@@ -68,10 +68,10 @@ todo
アカウントが使用不可に設定されている状態。
## Disko
-Misskeyにアップロードしたファイルを管理する機能。詳細は[こちら。](../features/drive)
+Funkcio ebligas al uzantoj administri dosierojn kiujn ili alŝutis al Misskey.Rigardu por sciu pli tie[.](../features/drive)
## Notoj
-Misskeyに投稿される、文章、ファイル、アンケートなどを含めることができるコンテンツ。Rigardu por sciu pli tie[.](../features/note)
+Enpoŝtigaĵoj en Misskey kiuj konsistas el teksto, dosiero, balotujo, ktp.Rigardu por sciu pli tie[.](../features/note)
## Miskiisto
Uzuloj de Misskey.
@@ -82,7 +82,7 @@ Uzuloj de Misskey.
## Transa, Surloka
他サーバーのことを指します。リモートユーザーといったように接頭辞としても使われます。ローカルの逆です。
-## Kunfederado
+## Federado
サーバー上で作成された情報が他のサーバーに伝わること。
## Loka
diff --git a/src/docs/eo-UY/general/misskey.md b/src/docs/eo-UY/general/misskey.md
index 506f7a8f24..ef287e5964 100644
--- a/src/docs/eo-UY/general/misskey.md
+++ b/src/docs/eo-UY/general/misskey.md
@@ -43,7 +43,7 @@ Misskeyはビジネスではなく、利用は無料であるため、収益は
## クレジット
Misskeyの開発者や、Misskeyに寄付をしてくださった方の一覧は[こちら](/about-misskey)で見ることができます。
-## よくある質問
+## Oftaj demandoj
### プロジェクトは何を目指していますか?
強いて言うと、漠然的になりますが広く使われる汎用的なプラットフォームになることを目指しています。 Misskeyは他のプロジェクトとは違い、何らかの思想(例えば、反中央集権)やビジョンに基づいて開発が行われているわけではなく、その点ではフラットです。 それが逆に、特定の方向性に縛られないフレキシブルさを生み出すことに繋がっていると感じています。
diff --git a/src/docs/es-ES/general/troubleshooting.md b/src/docs/es-ES/general/troubleshooting.md
index f895b49847..2bedfc3129 100644
--- a/src/docs/es-ES/general/troubleshooting.md
+++ b/src/docs/es-ES/general/troubleshooting.md
@@ -1,4 +1,4 @@
-# トラブルシューティング
+# Solución de problemas
問題が発生したときは、まずこちらをご確認ください。 該当する項目が無い、もしくは手順を試しても効果がない場合は、サーバーの管理者に連絡するか[不具合を報告](./report-issue)してください。
diff --git a/src/docs/fr-FR/general/apps.md b/src/docs/fr-FR/general/apps.md
index 7f9165a306..32a1274a59 100644
--- a/src/docs/fr-FR/general/apps.md
+++ b/src/docs/fr-FR/general/apps.md
@@ -1,6 +1,6 @@
# Liste des applications tierces
-## クライアント
+## Client
todo
-## 連携サービス
+## Services connexes
todo
diff --git a/src/docs/fr-FR/general/glossary.md b/src/docs/fr-FR/general/glossary.md
index 441a2b5bc4..d26d2e8ee6 100644
--- a/src/docs/fr-FR/general/glossary.md
+++ b/src/docs/fr-FR/general/glossary.md
@@ -1,65 +1,65 @@
-# 用語集
-Misskeyに関する用語集です。
+# Glossaire
+Glossaire des termes utilisés dans Misskey.
## ActivityPub
-(読み: あくてぃびてぃぱぶ) 分散型を実現するために用いられるプロトコル(仕様)。このプロトコルに則ってサーバー同士通信を行うことで、連合が行われ、Fediverseを形成しています。
+Nom du protocole (procédé technique) utilisé par Misskey pour pouvoir fonctionner comme service décentralisé. Ce protocole permet à tous les serveurs l'ayant adopté de communiquer entre eux et de former une sorte de fédération que l'on appelle « Fédiverse ».
## AiScript
-(読み: あいすくりぷと) Misskey上で使用できるプログラミング言語です。詳細は[こちら。](../advanced/aiscript)
+Langage de programmation qui peut être utilisé sur Misskey. [Voir ici pour plus d'informations.](../advanced/aiscript)
## API
-(読み: えーぴーあい) Misskeyのサーバーが公開している、プログラムからMisskeyを扱うためのインターフェース。詳細は[こちら。](../advanced/api)
+(読み: えーぴーあい) Misskeyのサーバーが公開している、プログラムからMisskeyを扱うためのインターフェース。[Voir ici pour plus d'informations. ](../advanced/api)
## Bot
-(読み: ぼっと) プログラムによって動作しているアカウント。
+Anglicisme désignant un compte géré par un programme informatique (vous le trouverez parfois aussi sous le terme de « robot »).
## CW
-(読み: こんてんつわーにんぐ) Contents Warningの略。ノートの内容を、操作なしには表示しないようにできる機能。主に長大な内容を隠すためや、ネタバレ防止などに使われます。
+Abréviation de « Content Warning » (qui signifie littéralement « alerte de contenu »). Fonctionnalité permettant d'assujettir l'affichage du contenu d'une note à une intervention de l'utilisateur·rice par le biais d'un bouton de masquage automatique. Principalement employée pour cacher le contenu des notes très longues, ou pour éviter de dévoiler publiquement des spoils potentiels, etc.
-## Fediverse
-(読み: ふぇでぃばーす) Misskeyを含む様々な分散型ソフトウェアのサーバーで構成されたネットワーク。
+## Fédiverse
+Nom du réseau social fédéré qui rassemble une multitude d'instances appartenant à différents services et dont fait partie Misskey.
-## GTL
-グローバルタイムライン(Global TimeLine)の略。タイムラインの詳細は[こちら。](../features/timeline)
+## FG
+Abréviation de « Fil global ». Pour en savoir plus sur les différents fils, [voir ici.](../features/timeline)
-## HTL
-ホームタイムライン(Home TimeLine)の略。タイムラインの詳細は[こちら。](../features/timeline)
+## FP
+Abréviation de « Fil principal ». Pour en savoir plus sur les différents fils, [voir ici.](../features/timeline)
-## LTL
-ローカルタイムライン(Local TimeLine)の略。タイムラインの詳細は[こちら。](../features/timeline)
+## FL
+Abréviation de « Fil local ». Pour en savoir plus sur les différents fils, [voir ici.](../features/timeline)
## MFM
-(読み: えむえふえむ) Misskey Flavored Markdownの略で、Misskey上で使用できるマークアップ言語です。詳細は[こちら。](../features/mfm)
+Abréviation de « Misskey Flavored Markdown », un langage Markdown qui peut être utilisé sur Misskey. [Voir ici pour plus d'informations.](../features/mfm)
## NSFW
-(読み: のっとせーふふぉーわーく) Not Safe For Workの略。画像を「閲覧注意」扱いにし、操作なしには表示しないようにすることができる機能。
+Abréviation de « Not Safe For Work » (qui signifie littéralement « pas sûr pour le travail »). Fonctionnalité permettant d'avertir que le contenu d'une note n'est pas approprié sur le lieu de travail et d'en assujettir l'affichage à une intervention de l'utilisateur·rice par le biais d'un bouton de masquage automatique.
## Renoter
-(読み: りのーと) 既にあるノートを引用、もしくはそのノートを新しいノートとして共有する行為、またそれによって作成されたノート。詳細は[こちら。](../features/note)
+Il s'agit du fait de citer une note existante ou de partager une note existante dans une nouvelle note. La note créée par l'un de ces deux biais est alors appelée une « Renote ». [Voir ici pour plus d'informations.](../features/note)
-## STL
-ソーシャルタイムライン(Social TimeLine)の略。タイムラインの詳細は[こちら。](../features/timeline)
+## FS
+Abréviation de « Fil social ». Pour en savoir plus sur les différents fils, [voir ici.](../features/timeline)
-## 藍
-(読み: あい) Misskeyの看板娘(公式キャラクター)です。
+## Ai
+Nom de la mascotte officielle de Misskey. (Le mot japonais, à prononcer « a-i », signifie littéralement « indigo »).
-## アクティブユーザー
-インスタンスにアカウントを作っているユーザーのうち、現在も実際にサービスを利用しているユーザーのこと。
+## Utilisateurices actif·ve·s
+Désigne les utilisateur·rice·s, parmi tou·te·s celleux inscrit·e·s sur l'instance, qui utilisent effectivement leur compte au moment présent.
## Instance
todo
## Émojis personnalisés
-サーバーで用意された絵文字。カスタム絵文字ではない通常の絵文字は「Unicode絵文字」と区別して呼ばれる。
+Désigne les émojis mis à disposition par votre instance. Par opposition, les émojis disponibles par défaut (donc pas « personnalisés ») sont appelés « émojis unicode ».
-## コントロールパネル
-インスタンスの設定画面のこと。
+## Panneau de contrôle
+Écran de contrôle des paramètres d'instance.
## Serveurs
todo
## Mettre en sourdine
-ノートをパブリックな公開範囲で投稿できなくされている状態。モデレーターの判断でユーザーごとに設定されます。詳細は[こちら。](../features/silence)
+ノートをパブリックな公開範囲で投稿できなくされている状態。モデレーターの判断でユーザーごとに設定されます。[Voir ici pour plus d'informations. ](../features/silence)
## File d’attente
アクティビティ配送などを順番に行うためのシステム。
@@ -68,15 +68,15 @@ todo
アカウントが使用不可に設定されている状態。
## Drive
-Misskeyにアップロードしたファイルを管理する機能。詳細は[こちら。](../features/drive)
+Fonctionnalité vous permettant de gérer les fichiers que vous avez téléversés sur Misskey. [Voir ici pour plus d'informations. ](../features/drive)
## Notes
-Misskeyに投稿される、文章、ファイル、アンケートなどを含めることができるコンテンツ。詳細は[こちら。](../features/note)
+Nom des publications sur Misskey. Leur contenu peut être du texte, mais aussi des fichiers, des enquêtes, etc. [Voir ici pour plus d'informations.](../features/note)
-## ミスキスト
-Misskeyを使う人のこと。
+## Misskeynaute
+Désigne les utilisateur·rice·s de Misskey.
-## Modérateurs
+## Modérateur·rice·s
スパムの凍結およびサイレンスや不適切な投稿の削除など、コミュニティ運営に関する権限を持つユーザー。
## Distant
diff --git a/src/docs/fr-FR/general/troubleshooting.md b/src/docs/fr-FR/general/troubleshooting.md
index f6a6771df2..3abcf34006 100644
--- a/src/docs/fr-FR/general/troubleshooting.md
+++ b/src/docs/fr-FR/general/troubleshooting.md
@@ -21,20 +21,20 @@ Essayez les solutions proposées ci-dessous :
- activer l'option « Réduire les animations dans l'interface » dans les paramètres du client
- désactiver l'option « Utiliser un effet de flou pour les modals » dans les paramètres du client
- activer l'accélération matérielle dans les paramètres de votre navigateur
-- お使いのデバイスのスペックを上げる
+- effectuer les mises à jour de votre appareil.
-## UIの一部の表示がおかしい(背景が透明になっている等)
-アップデートによりUIの改修が行われたときに、テーマのキャッシュシステムの影響でそのような表示になることがあります。 クライアントの設定の「キャッシュをクリア」すると直ります。
-⚠️ 「クライアントの」キャッシュクリアです。「ブラウザの」キャッシュクリアは行わないでください。
+## Certaines parties de l'interface ne s'affichent pas correctement (arrière-plan transparent, etc.)
+Cela peut être lié au système de mise en cache du thème lorsqu'une mise à jour visant à améliorer l'interface a eu lieu. Pour résoudre le problème, sélectionnez la touche « Vider le cache » dans les paramètres du client.
+⚠️ Attention de bien vider le cache du -client-... et pas celui du -navigateur- !
-## 通知やアンテナ等の点滅が消えない
-点滅は、未読のコンテンツがあることを示しています。通常点滅が消えない場合は、コンテンツを遡ると未読なコンテンツが残っています。 すべて既読にしたと思われるのに、それでもなお点滅が続く場合(おそらく不具合と思われます)は設定から強制的にすべて既読扱いにすることができます。
+## Les pastilles de notification clignotantes ne disparaissent pas
+Une pastille clignotante indique la présence de nouveau contenu que vous n'avez pas encore lu. Lorsque cette pastille ne disparaît pas, c'est généralement parce que du contenu laissé non lu a été repoussé par la réception de nouveau contenu. S'il s'avère que vous avez déjà lu le contenu dans sa totalité mais que la pastille continue tout de même de clignoter, il s'agit alors vraisemblablement d'un bug et vous pouvez forcer Misskey à tout marquer comme lu depuis vos paramètres généraux.
## La fonction « Renoter » ne fonctionne pas
Les notes dont l'audience est limitée aux « Abonné·e·s uniquement » ne peuvent pas être renotées.
## Des éléments spécifiques de l'interface ne s'affichent pas
-広告ブロッカーを使用しているとそのような不具合が発生することがあります。Misskeyではオフにしてご利用ください。
+Ce type de dysfonctionnement survient lorsque vous utilisez des bloqueurs de publicité. Désactivez-les pour profiter d'une expérience optimale sur Misskey.
## Certaines parties de l'interface ne sont pas traduites
La plupart du temps, cela n'est pas un bug mais simplement un problème de traduction qui n'a pas encore été faite. Merci de patienter jusqu'à ce que la traduction de la portion en question soit achevée. Vous pouvez également [aider à traduire](./misskey) Misskey.
diff --git a/src/docs/zh-CN/advanced/stream.md b/src/docs/zh-CN/advanced/stream.md
index 090f8475ea..3351f2d839 100644
--- a/src/docs/zh-CN/advanced/stream.md
+++ b/src/docs/zh-CN/advanced/stream.md
@@ -50,7 +50,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
}
```
-ここで、
+其中:
* `channel`には接続したいチャンネル名を設定します。チャンネルの種類については後述します。
* `id`にはそのチャンネルとやり取りするための任意のIDを設定します。ストリームでは様々なメッセージが流れるので、そのメッセージがどのチャンネルからのものなのか識別する必要があるからです。このIDは、UUIDや、乱数のようなもので構いません。
* `params`はチャンネルに接続する際のパラメータです。チャンネルによって接続時に必要とされるパラメータは異なります。パラメータ不要のチャンネルに接続する際は、このプロパティは省略可能です。
@@ -74,7 +74,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
}
```
-ここで、
+其中:
* `id`には前述したそのチャンネルに接続する際に設定したIDが設定されています。これで、このメッセージがどのチャンネルからのものなのか知ることができます。
* `type`にはメッセージの種類が設定されます。チャンネルによって、どのような種類のメッセージが流れてくるかは異なります。
* `body`にはメッセージの内容が設定されます。チャンネルによって、どのような内容のメッセージが流れてくるかは異なります。
@@ -96,7 +96,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
}
```
-ここで、
+其中:
* `id`には前述したそのチャンネルに接続する際に設定したIDを設定します。これで、このメッセージがどのチャンネルに向けたものなのか識別させることができます。
* `type`にはメッセージの種類を設定します。チャンネルによって、どのような種類のメッセージを受け付けるかは異なります。
* `body`にはメッセージの内容を設定します。チャンネルによって、どのような内容のメッセージを受け付けるかは異なります。
@@ -113,7 +113,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
}
```
-ここで、
+其中:
* `id`には前述したそのチャンネルに接続する際に設定したIDを設定します。
## ストリームを経由してAPIリクエストする
@@ -134,7 +134,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
}
```
-ここで、
+其中:
* `id`には、APIのレスポンスを識別するための、APIリクエストごとの一意なIDを設定する必要があります。UUIDや、簡単な乱数のようなもので構いません。
* `endpoint`には、あなたがリクエストしたいAPIのエンドポイントを指定します。
* `data`には、エンドポイントのパラメータを含めます。
@@ -154,7 +154,7 @@ APIへリクエストすると、レスポンスがストリームから次の
}
```
-ここで、
+其中:
* `xxxxxxxxxxxxxxxx`の部分には、リクエストの際に設定された`id`が含まれています。これにより、どのリクエストに対するレスポンスなのか判別することができます。
* `body`には、レスポンスが含まれています。
@@ -181,7 +181,7 @@ Misskeyは投稿のキャプチャと呼ばれる仕組みを提供していま
}
```
-ここで、
+其中:
* `id`にキャプチャしたい投稿の`id`を設定します。
このメッセージを送信すると、Misskeyにキャプチャを要請したことになり、以後、その投稿に関するイベントが流れてくるようになります。
@@ -202,7 +202,7 @@ Misskeyは投稿のキャプチャと呼ばれる仕組みを提供していま
}
```
-ここで、
+其中:
* `body`内の`id`に、イベントを発生させた投稿のIDが設定されます。
* `body`内の`type`に、イベントの種類が設定されます。
* `body`内の`body`に、イベントの詳細が設定されます。
@@ -285,7 +285,7 @@ Misskeyは投稿のキャプチャと呼ばれる仕組みを提供していま
}
```
-ここで、
+其中:
* `id`にキャプチャを解除したい投稿の`id`を設定します。
このメッセージを送信すると、以後、その投稿に関するイベントは流れてこないようになります。
diff --git a/src/docs/zh-CN/features/follow.md b/src/docs/zh-CN/features/follow.md
index 115a2786f6..2a95aa6dc4 100644
--- a/src/docs/zh-CN/features/follow.md
+++ b/src/docs/zh-CN/features/follow.md
@@ -1,2 +1,2 @@
-# 关注中
-ユーザーをフォローすると、タイムラインにそのユーザーの投稿が表示されるようになります。ただし、他のユーザーに対する返信は含まれません。 ユーザーをフォローするには、ユーザーページの「フォロー」ボタンをクリックします。フォローを解除するには、もう一度クリックします。
+# 关注
+当您关注一名用户时,您可以在您的时间线上看到该用户的发帖。但是不包含该用户对其他用户的回复。 要关注一名用户,请点击该用户页面上的“关注”按钮。如果需要取消关注,请再次点击该按钮。
diff --git a/src/docs/zh-CN/features/mfm.md b/src/docs/zh-CN/features/mfm.md
index d42350edf0..8bcaacbed7 100644
--- a/src/docs/zh-CN/features/mfm.md
+++ b/src/docs/zh-CN/features/mfm.md
@@ -1,12 +1,12 @@
# MFM
-MFMは、Misskey Flavored Markdownの略で、Misskeyの様々な場所で使用できる専用のマークアップ言語です。 MFMで使用可能な構文は[MFMチートシート](/mfm-cheat-sheet)で確認できます。
+MFM是Misskey Flavored Markdown的缩写,是一种专用的标记语言,可以用在Misskey的任何地方。 MFM中可用的语法可以在[MFM代码速查表](/mfm-cheat-sheet)中找到。
-## MFMが使用可能な場所の例
-- ノート本文
+## 使用 MFM 的位置示例
+- 帖子正文
- CW注释
-- ユーザーの名前
-- ユーザーの自己紹介
+- 用户姓名
+- 用户自我介绍
-## 開発者向け情報
-MFMのパーサー実装はライブラリとして公開されており、簡単にクライアントにMFMを組み込むことが可能です。
-- [misskey-dev/mfm.js](https://github.com/misskey-dev/mfm.js) - JavaScriptパーサー実装
+## 面向开发者的信息
+MFM 的解析器实现作为库发布,可以轻松地将 MFM 嵌入到客户端中。
+- [misskey-dev/mfm.js](https://github.com/misskey-dev/mfm.js) - JavaScript的解析器实现
diff --git a/src/misc/download-url.ts b/src/misc/download-url.ts
index 8a8640a8cd..c96b4fd1d6 100644
--- a/src/misc/download-url.ts
+++ b/src/misc/download-url.ts
@@ -2,7 +2,7 @@ import * as fs from 'fs';
import * as stream from 'stream';
import * as util from 'util';
import got, * as Got from 'got';
-import { httpAgent, httpsAgent } from './fetch';
+import { httpAgent, httpsAgent, StatusError } from './fetch';
import config from '@/config/index';
import * as chalk from 'chalk';
import Logger from '@/services/logger';
@@ -37,6 +37,7 @@ export async function downloadUrl(url: string, path: string) {
http: httpAgent,
https: httpsAgent,
},
+ http2: false, // default
retry: 0,
}).on('response', (res: Got.Response) => {
if ((process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') && !config.proxy && res.ip) {
@@ -59,17 +60,17 @@ export async function downloadUrl(url: string, path: string) {
logger.warn(`maxSize exceeded (${progress.transferred} > ${maxSize}) on downloadProgress`);
req.destroy();
}
- }).on('error', (e: any) => {
- if (e.name === 'HTTPError') {
- const statusCode = e.response?.statusCode;
- const statusMessage = e.response?.statusMessage;
- e.name = `StatusError`;
- e.statusCode = statusCode;
- e.message = `${statusCode} ${statusMessage}`;
- }
});
- await pipeline(req, fs.createWriteStream(path));
+ try {
+ await pipeline(req, fs.createWriteStream(path));
+ } catch (e) {
+ if (e instanceof Got.HTTPError) {
+ throw new StatusError(`${e.response.statusCode} ${e.response.statusMessage}`, e.response.statusCode, e.response.statusMessage);
+ } else {
+ throw e;
+ }
+ }
logger.succ(`Download finished: ${chalk.cyan(url)}`);
}
diff --git a/src/misc/fetch.ts b/src/misc/fetch.ts
index 82db2f2f8c..f4f16a27e2 100644
--- a/src/misc/fetch.ts
+++ b/src/misc/fetch.ts
@@ -1,51 +1,62 @@
import * as http from 'http';
import * as https from 'https';
import CacheableLookup from 'cacheable-lookup';
-import fetch, { HeadersInit } from 'node-fetch';
+import fetch from 'node-fetch';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
import config from '@/config/index';
import { URL } from 'url';
-export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: HeadersInit) {
- const res = await fetch(url, {
+export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: Record) {
+ const res = await getResponse({
+ url,
+ method: 'GET',
headers: Object.assign({
'User-Agent': config.userAgent,
Accept: accept
}, headers || {}),
- timeout,
- agent: getAgentByUrl,
+ timeout
});
- if (!res.ok) {
- throw {
- name: `StatusError`,
- statusCode: res.status,
- message: `${res.status} ${res.statusText}`,
- };
- }
-
return await res.json();
}
-export async function getHtml(url: string, accept = 'text/html, */*', timeout = 10000, headers?: HeadersInit) {
- const res = await fetch(url, {
+export async function getHtml(url: string, accept = 'text/html, */*', timeout = 10000, headers?: Record) {
+ const res = await getResponse({
+ url,
+ method: 'GET',
headers: Object.assign({
'User-Agent': config.userAgent,
Accept: accept
}, headers || {}),
+ timeout
+ });
+
+ return await res.text();
+}
+
+export async function getResponse(args: { url: string, method: string, body?: string, headers: Record, timeout?: number, size?: number }) {
+ const timeout = args?.timeout || 10 * 1000;
+
+ const controller = new AbortController();
+ setTimeout(() => {
+ controller.abort();
+ }, timeout * 6);
+
+ const res = await fetch(args.url, {
+ method: args.method,
+ headers: args.headers,
+ body: args.body,
timeout,
+ size: args?.size || 10 * 1024 * 1024,
agent: getAgentByUrl,
+ signal: controller.signal,
});
if (!res.ok) {
- throw {
- name: `StatusError`,
- statusCode: res.status,
- message: `${res.status} ${res.statusText}`,
- };
+ throw new StatusError(`${res.status} ${res.statusText}`, res.status, res.statusText);
}
- return await res.text();
+ return res;
}
const cache = new CacheableLookup({
@@ -114,3 +125,17 @@ export function getAgentByUrl(url: URL, bypassProxy = false) {
return url.protocol == 'http:' ? httpAgent : httpsAgent;
}
}
+
+export class StatusError extends Error {
+ public statusCode: number;
+ public statusMessage?: string;
+ public isClientError: boolean;
+
+ constructor(message: string, statusCode: number, statusMessage?: string) {
+ super(message);
+ this.name = 'StatusError';
+ this.statusCode = statusCode;
+ this.statusMessage = statusMessage;
+ this.isClientError = typeof this.statusCode === 'number' && this.statusCode >= 400 && this.statusCode < 500;
+ }
+}
diff --git a/src/models/entities/user-profile.ts b/src/models/entities/user-profile.ts
index a2da07d76f..1f450f223d 100644
--- a/src/models/entities/user-profile.ts
+++ b/src/models/entities/user-profile.ts
@@ -75,6 +75,11 @@ export class UserProfile {
})
public emailNotificationTypes: string[];
+ @Column('boolean', {
+ default: false,
+ })
+ public publicReactions: boolean;
+
@Column('varchar', {
length: 128, nullable: true,
})
diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts
index ba74076f6c..5d86065526 100644
--- a/src/models/repositories/note-reaction.ts
+++ b/src/models/repositories/note-reaction.ts
@@ -1,6 +1,6 @@
import { EntityRepository, Repository } from 'typeorm';
import { NoteReaction } from '@/models/entities/note-reaction';
-import { Users } from '../index';
+import { Notes, Users } from '../index';
import { Packed } from '@/misc/schema';
import { convertLegacyReaction } from '@/misc/reaction-lib';
import { User } from '@/models/entities/user';
@@ -9,8 +9,15 @@ import { User } from '@/models/entities/user';
export class NoteReactionRepository extends Repository {
public async pack(
src: NoteReaction['id'] | NoteReaction,
- me?: { id: User['id'] } | null | undefined
+ me?: { id: User['id'] } | null | undefined,
+ options?: {
+ withNote: boolean;
+ },
): Promise> {
+ const opts = Object.assign({
+ withNote: false,
+ }, options);
+
const reaction = typeof src === 'object' ? src : await this.findOneOrFail(src);
return {
@@ -18,6 +25,9 @@ export class NoteReactionRepository extends Repository {
createdAt: reaction.createdAt.toISOString(),
user: await Users.pack(reaction.userId, me),
type: convertLegacyReaction(reaction.reaction),
+ ...(opts.withNote ? {
+ note: await Notes.pack(reaction.noteId, me),
+ } : {})
};
}
}
diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts
index b6f27e32e2..2b77b613a8 100644
--- a/src/models/repositories/user.ts
+++ b/src/models/repositories/user.ts
@@ -231,6 +231,7 @@ export class UserRepository extends Repository {
}),
pinnedPageId: profile!.pinnedPageId,
pinnedPage: profile!.pinnedPageId ? Pages.pack(profile!.pinnedPageId, me) : null,
+ publicReactions: profile!.publicReactions,
twoFactorEnabled: profile!.twoFactorEnabled,
usePasswordLessLogin: profile!.usePasswordLessLogin,
securityKeys: profile!.twoFactorEnabled
diff --git a/src/queue/processors/deliver.ts b/src/queue/processors/deliver.ts
index 373e57cbd5..3c61896a2f 100644
--- a/src/queue/processors/deliver.ts
+++ b/src/queue/processors/deliver.ts
@@ -11,6 +11,7 @@ import { toPuny } from '@/misc/convert-host';
import { Cache } from '@/misc/cache';
import { Instance } from '@/models/entities/instance';
import { DeliverJobData } from '../types';
+import { StatusError } from '@/misc/fetch';
const logger = new Logger('deliver');
@@ -68,16 +69,16 @@ export default async (job: Bull.Job) => {
registerOrFetchInstanceDoc(host).then(i => {
Instances.update(i.id, {
latestRequestSentAt: new Date(),
- latestStatus: res != null && res.hasOwnProperty('statusCode') ? res.statusCode : null,
+ latestStatus: res instanceof StatusError ? res.statusCode : null,
isNotResponding: true
});
instanceChart.requestSent(i.host, false);
});
- if (res != null && res.hasOwnProperty('statusCode')) {
+ if (res instanceof StatusError) {
// 4xx
- if (res.statusCode >= 400 && res.statusCode < 500) {
+ if (res.isClientError) {
// HTTPステータスコード4xxはクライアントエラーであり、それはつまり
// 何回再送しても成功することはないということなのでエラーにはしないでおく
return `${res.statusCode} ${res.statusMessage}`;
diff --git a/src/queue/processors/inbox.ts b/src/queue/processors/inbox.ts
index e2c271cdf8..4032ce8653 100644
--- a/src/queue/processors/inbox.ts
+++ b/src/queue/processors/inbox.ts
@@ -14,6 +14,7 @@ import { InboxJobData } from '../types';
import DbResolver from '@/remote/activitypub/db-resolver';
import { resolvePerson } from '@/remote/activitypub/models/person';
import { LdSignature } from '@/remote/activitypub/misc/ld-signature';
+import { StatusError } from '@/misc/fetch';
const logger = new Logger('inbox');
@@ -53,7 +54,7 @@ export default async (job: Bull.Job): Promise => {
authUser = await dbResolver.getAuthUserFromApId(getApId(activity.actor));
} catch (e) {
// 対象が4xxならスキップ
- if (e.statusCode >= 400 && e.statusCode < 500) {
+ if (e instanceof StatusError && e.isClientError) {
return `skip: Ignored deleted actors on both ends ${activity.actor} - ${e.statusCode}`;
}
throw `Error in actor ${activity.actor} - ${e.statusCode || e}`;
diff --git a/src/remote/activitypub/ap-request.ts b/src/remote/activitypub/ap-request.ts
new file mode 100644
index 0000000000..76a3857140
--- /dev/null
+++ b/src/remote/activitypub/ap-request.ts
@@ -0,0 +1,104 @@
+import * as crypto from 'crypto';
+import { URL } from 'url';
+
+type Request = {
+ url: string;
+ method: string;
+ headers: Record;
+};
+
+type PrivateKey = {
+ privateKeyPem: string;
+ keyId: string;
+};
+
+export function createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record }) {
+ 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: objectAssignWithLcKey({
+ 'Date': new Date().toUTCString(),
+ 'Host': u.hostname,
+ 'Content-Type': 'application/activity+json',
+ 'Digest': digestHeader,
+ }, args.additionalHeaders),
+ };
+
+ const result = signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
+
+ return {
+ request,
+ signingString: result.signingString,
+ signature: result.signature,
+ signatureHeader: result.signatureHeader,
+ };
+}
+
+export function createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record }) {
+ const u = new URL(args.url);
+
+ const request: Request = {
+ url: u.href,
+ method: 'GET',
+ headers: objectAssignWithLcKey({
+ 'Accept': 'application/activity+json, application/ld+json',
+ 'Date': new Date().toUTCString(),
+ 'Host': new URL(args.url).hostname,
+ }, args.additionalHeaders),
+ };
+
+ const result = signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
+
+ return {
+ request,
+ signingString: result.signingString,
+ signature: result.signature,
+ signatureHeader: result.signatureHeader,
+ };
+}
+
+function signToRequest(request: Request, key: PrivateKey, includeHeaders: string[]) {
+ const signingString = 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 = objectAssignWithLcKey(request.headers, {
+ Signature: signatureHeader
+ });
+
+ return {
+ request,
+ signingString,
+ signature,
+ signatureHeader,
+ };
+}
+
+function genSigningString(request: Request, includeHeaders: string[]) {
+ request.headers = lcObjectKey(request.headers);
+
+ const results: string[] = [];
+
+ for (const key of includeHeaders.map(x => x.toLowerCase())) {
+ if (key === '(request-target)') {
+ results.push(`(request-target): ${request.method.toLowerCase()} ${new URL(request.url).pathname}`);
+ } else {
+ results.push(`${key}: ${request.headers[key]}`);
+ }
+ }
+
+ return results.join('\n');
+}
+
+function lcObjectKey(src: Record) {
+ const dst: Record = {};
+ for (const key of Object.keys(src).filter(x => x != '__proto__' && typeof src[x] === 'string')) dst[key.toLowerCase()] = src[key];
+ return dst;
+}
+
+function objectAssignWithLcKey(a: Record, b: Record) {
+ return Object.assign(lcObjectKey(a), lcObjectKey(b));
+}
diff --git a/src/remote/activitypub/kernel/announce/note.ts b/src/remote/activitypub/kernel/announce/note.ts
index b6ec090b99..5230867f24 100644
--- a/src/remote/activitypub/kernel/announce/note.ts
+++ b/src/remote/activitypub/kernel/announce/note.ts
@@ -8,6 +8,7 @@ import { extractDbHost } from '@/misc/convert-host';
import { fetchMeta } from '@/misc/fetch-meta';
import { getApLock } from '@/misc/app-lock';
import { parseAudience } from '../../audience';
+import { StatusError } from '@/misc/fetch';
const logger = apLogger;
@@ -41,7 +42,7 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
renote = await resolveNote(targetUri);
} catch (e) {
// 対象が4xxならスキップ
- if (e.statusCode >= 400 && e.statusCode < 500) {
+ if (e instanceof StatusError && e.isClientError) {
logger.warn(`Ignored announce target ${targetUri} - ${e.statusCode}`);
return;
}
diff --git a/src/remote/activitypub/kernel/create/note.ts b/src/remote/activitypub/kernel/create/note.ts
index 5dda85d0f5..14e311e4cd 100644
--- a/src/remote/activitypub/kernel/create/note.ts
+++ b/src/remote/activitypub/kernel/create/note.ts
@@ -4,6 +4,7 @@ import { createNote, fetchNote } from '../../models/note';
import { getApId, IObject, ICreate } from '../../type';
import { getApLock } from '@/misc/app-lock';
import { extractDbHost } from '@/misc/convert-host';
+import { StatusError } from '@/misc/fetch';
/**
* 投稿作成アクティビティを捌きます
@@ -32,7 +33,7 @@ export default async function(resolver: Resolver, actor: IRemoteUser, note: IObj
await createNote(note, resolver, silent);
return 'ok';
} catch (e) {
- if (e.statusCode >= 400 && e.statusCode < 500) {
+ if (e instanceof StatusError && e.isClientError) {
return `skip ${e.statusCode}`;
} else {
throw e;
diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts
index 25004cb4d2..cf68f3005d 100644
--- a/src/remote/activitypub/models/note.ts
+++ b/src/remote/activitypub/models/note.ts
@@ -26,6 +26,7 @@ import { createMessage } from '@/services/messages/create';
import { parseAudience } from '../audience';
import { extractApMentions } from './mention';
import DbResolver from '../db-resolver';
+import { StatusError } from '@/misc/fetch';
const logger = apLogger;
@@ -177,7 +178,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
}
} catch (e) {
return {
- status: e.statusCode >= 400 && e.statusCode < 500 ? 'permerror' : 'temperror'
+ status: (e instanceof StatusError && e.isClientError) ? 'permerror' : 'temperror'
};
}
};
diff --git a/src/remote/activitypub/request.ts b/src/remote/activitypub/request.ts
index fe1009243c..d6ced630c1 100644
--- a/src/remote/activitypub/request.ts
+++ b/src/remote/activitypub/request.ts
@@ -1,66 +1,31 @@
-import * as http from 'http';
-import * as https from 'https';
-import { sign } from 'http-signature';
-import * as crypto from 'crypto';
-
import config from '@/config/index';
-import { User } from '@/models/entities/user';
-import { getAgentByUrl } from '@/misc/fetch';
-import { URL } from 'url';
-import got from 'got';
-import * as Got from 'got';
import { getUserKeypair } from '@/misc/keypair-store';
+import { User } from '@/models/entities/user';
+import { getResponse } from '../../misc/fetch';
+import { createSignedPost, createSignedGet } from './ap-request';
export default async (user: { id: User['id'] }, url: string, object: any) => {
- const timeout = 10 * 1000;
-
- const { protocol, hostname, port, pathname, search } = new URL(url);
-
- const data = JSON.stringify(object);
-
- const sha256 = crypto.createHash('sha256');
- sha256.update(data);
- const hash = sha256.digest('base64');
+ const body = JSON.stringify(object);
const keypair = await getUserKeypair(user.id);
- await new Promise((resolve, reject) => {
- const req = https.request({
- agent: getAgentByUrl(new URL(`https://example.net`)),
- protocol,
- hostname,
- port,
- method: 'POST',
- path: pathname + search,
- timeout,
- headers: {
- 'User-Agent': config.userAgent,
- 'Content-Type': 'application/activity+json',
- 'Digest': `SHA-256=${hash}`
- }
- }, res => {
- if (res.statusCode! >= 400) {
- reject(res);
- } else {
- resolve();
- }
- });
+ const req = createSignedPost({
+ key: {
+ privateKeyPem: keypair.privateKey,
+ keyId: `${config.url}/users/${user.id}#main-key`
+ },
+ url,
+ body,
+ additionalHeaders: {
+ 'User-Agent': config.userAgent,
+ }
+ });
- sign(req, {
- authorizationHeaderName: 'Signature',
- key: keypair.privateKey,
- keyId: `${config.url}/users/${user.id}#main-key`,
- headers: ['(request-target)', 'date', 'host', 'digest']
- });
-
- req.on('timeout', () => req.abort());
-
- req.on('error', e => {
- if (req.aborted) reject('timeout');
- reject(e);
- });
-
- req.end(data);
+ await getResponse({
+ url,
+ method: req.request.method,
+ headers: req.request.headers,
+ body,
});
};
@@ -70,87 +35,24 @@ export default async (user: { id: User['id'] }, url: string, object: any) => {
* @param url URL to fetch
*/
export async function signedGet(url: string, user: { id: User['id'] }) {
- const timeout = 10 * 1000;
-
const keypair = await getUserKeypair(user.id);
- const req = got.get(url, {
- headers: {
- 'Accept': 'application/activity+json, application/ld+json',
+ const req = createSignedGet({
+ key: {
+ privateKeyPem: keypair.privateKey,
+ keyId: `${config.url}/users/${user.id}#main-key`
+ },
+ url,
+ additionalHeaders: {
'User-Agent': config.userAgent,
- },
- responseType: 'json',
- timeout,
- hooks: {
- beforeRequest: [
- options => {
- options.request = (url: URL, opt: http.RequestOptions, callback?: (response: any) => void) => {
- // Select custom agent by URL
- opt.agent = getAgentByUrl(url, false);
-
- // Wrap original https?.request
- const requestFunc = url.protocol === 'http:' ? http.request : https.request;
- const clientRequest = requestFunc(url, opt, callback) as http.ClientRequest;
-
- // HTTP-Signature
- sign(clientRequest, {
- authorizationHeaderName: 'Signature',
- key: keypair.privateKey,
- keyId: `${config.url}/users/${user.id}#main-key`,
- headers: ['(request-target)', 'host', 'date', 'accept']
- });
-
- return clientRequest;
- };
- },
- ],
- },
- retry: 0,
+ }
});
- const res = await receiveResponce(req, 10 * 1024 * 1024);
+ const res = await getResponse({
+ url,
+ method: req.request.method,
+ headers: req.request.headers
+ });
- return res.body;
-}
-
-/**
- * Receive response (with size limit)
- * @param req Request
- * @param maxSize size limit
- */
-export async function receiveResponce(req: Got.CancelableRequest>, maxSize: number) {
- // 応答ヘッダでサイズチェック
- req.on('response', (res: Got.Response) => {
- const contentLength = res.headers['content-length'];
- if (contentLength != null) {
- const size = Number(contentLength);
- if (size > maxSize) {
- req.cancel();
- }
- }
- });
-
- // 受信中のデータでサイズチェック
- req.on('downloadProgress', (progress: Got.Progress) => {
- if (progress.transferred > maxSize) {
- req.cancel();
- }
- });
-
- // 応答取得 with ステータスコードエラーの整形
- const res = await req.catch(e => {
- if (e.name === 'HTTPError') {
- const statusCode = (e as Got.HTTPError).response.statusCode;
- const statusMessage = (e as Got.HTTPError).response.statusMessage;
- throw {
- name: `StatusError`,
- statusCode,
- message: `${statusCode} ${statusMessage}`,
- };
- } else {
- throw e;
- }
- });
-
- return res;
+ return await res.json();
}
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 9dd637251d..3b8b1579ea 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -68,6 +68,10 @@ export const meta = {
validator: $.optional.bool,
},
+ publicReactions: {
+ validator: $.optional.bool,
+ },
+
carefulBot: {
validator: $.optional.bool,
},
@@ -180,6 +184,7 @@ export default define(meta, async (ps, _user, token) => {
if (typeof ps.isLocked === 'boolean') updates.isLocked = ps.isLocked;
if (typeof ps.isExplorable === 'boolean') updates.isExplorable = ps.isExplorable;
if (typeof ps.hideOnlineStatus === 'boolean') updates.hideOnlineStatus = ps.hideOnlineStatus;
+ if (typeof ps.publicReactions === 'boolean') profileUpdates.publicReactions = ps.publicReactions;
if (typeof ps.isBot === 'boolean') updates.isBot = ps.isBot;
if (typeof ps.carefulBot === 'boolean') profileUpdates.carefulBot = ps.carefulBot;
if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
diff --git a/src/server/api/endpoints/users/groups/leave.ts b/src/server/api/endpoints/users/groups/leave.ts
new file mode 100644
index 0000000000..0e52f2abdf
--- /dev/null
+++ b/src/server/api/endpoints/users/groups/leave.ts
@@ -0,0 +1,50 @@
+import $ from 'cafy';
+import { ID } from '@/misc/cafy-id';
+import define from '../../../define';
+import { ApiError } from '../../../error';
+import { UserGroups, UserGroupJoinings } from '@/models/index';
+
+export const meta = {
+ tags: ['groups', 'users'],
+
+ requireCredential: true as const,
+
+ kind: 'write:user-groups',
+
+ params: {
+ groupId: {
+ validator: $.type(ID),
+ },
+ },
+
+ errors: {
+ noSuchGroup: {
+ message: 'No such group.',
+ code: 'NO_SUCH_GROUP',
+ id: '62780270-1f67-5dc0-daca-3eb510612e31'
+ },
+
+ youAreOwner: {
+ message: 'Your are the owner.',
+ code: 'YOU_ARE_OWNER',
+ id: 'b6d6e0c2-ef8a-9bb8-653d-79f4a3107c69'
+ },
+ }
+};
+
+export default define(meta, async (ps, me) => {
+ // Fetch the group
+ const userGroup = await UserGroups.findOne({
+ id: ps.groupId,
+ });
+
+ if (userGroup == null) {
+ throw new ApiError(meta.errors.noSuchGroup);
+ }
+
+ if (me.id === userGroup.userId) {
+ throw new ApiError(meta.errors.youAreOwner);
+ }
+
+ await UserGroupJoinings.delete({ userGroupId: userGroup.id, userId: me.id });
+});
diff --git a/src/server/api/endpoints/users/reactions.ts b/src/server/api/endpoints/users/reactions.ts
new file mode 100644
index 0000000000..fe5e4d84a9
--- /dev/null
+++ b/src/server/api/endpoints/users/reactions.ts
@@ -0,0 +1,79 @@
+import $ from 'cafy';
+import { ID } from '@/misc/cafy-id';
+import define from '../../define';
+import { NoteReactions, UserProfiles } from '@/models/index';
+import { makePaginationQuery } from '../../common/make-pagination-query';
+import { generateVisibilityQuery } from '../../common/generate-visibility-query';
+import { ApiError } from '../../error';
+
+export const meta = {
+ tags: ['users', 'reactions'],
+
+ requireCredential: false as const,
+
+ params: {
+ userId: {
+ validator: $.type(ID),
+ },
+
+ limit: {
+ validator: $.optional.num.range(1, 100),
+ default: 10,
+ },
+
+ sinceId: {
+ validator: $.optional.type(ID),
+ },
+
+ untilId: {
+ validator: $.optional.type(ID),
+ },
+
+ sinceDate: {
+ validator: $.optional.num,
+ },
+
+ untilDate: {
+ validator: $.optional.num,
+ },
+ },
+
+ res: {
+ type: 'array' as const,
+ optional: false as const, nullable: false as const,
+ items: {
+ type: 'object' as const,
+ optional: false as const, nullable: false as const,
+ ref: 'NoteReaction',
+ }
+ },
+
+ errors: {
+ reactionsNotPublic: {
+ message: 'Reactions of the user is not public.',
+ code: 'REACTIONS_NOT_PUBLIC',
+ id: '673a7dd2-6924-1093-e0c0-e68456ceae5c'
+ },
+ }
+};
+
+export default define(meta, async (ps, me) => {
+ const profile = await UserProfiles.findOneOrFail(ps.userId);
+
+ if (me == null || (me.id !== ps.userId && !profile.publicReactions)) {
+ throw new ApiError(meta.errors.reactionsNotPublic);
+ }
+
+ const query = makePaginationQuery(NoteReactions.createQueryBuilder('reaction'),
+ ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
+ .andWhere(`reaction.userId = :userId`, { userId: ps.userId })
+ .leftJoinAndSelect('reaction.note', 'note');
+
+ generateVisibilityQuery(query, me);
+
+ const reactions = await query
+ .take(ps.limit!)
+ .getMany();
+
+ return await Promise.all(reactions.map(reaction => NoteReactions.pack(reaction, me, { withNote: true })));
+});
diff --git a/src/server/api/endpoints/users/search-by-username-and-host.ts b/src/server/api/endpoints/users/search-by-username-and-host.ts
index b9fbf48fb2..3b8d024af5 100644
--- a/src/server/api/endpoints/users/search-by-username-and-host.ts
+++ b/src/server/api/endpoints/users/search-by-username-and-host.ts
@@ -1,6 +1,8 @@
import $ from 'cafy';
import define from '../../define';
import { Users } from '@/models/index';
+import { Brackets } from 'typeorm';
+import { USER_ACTIVE_THRESHOLD } from '@/const';
export const meta = {
tags: ['users'],
@@ -44,13 +46,15 @@ export const meta = {
};
export default define(meta, async (ps, me) => {
+ const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
+
if (ps.host) {
const q = Users.createQueryBuilder('user')
.where('user.isSuspended = FALSE')
.andWhere('user.host LIKE :host', { host: ps.host.toLowerCase() + '%' });
if (ps.username) {
- q.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' });
+ q.andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' });
}
q.andWhere('user.updatedAt IS NOT NULL');
@@ -63,9 +67,12 @@ export default define(meta, async (ps, me) => {
let users = await Users.createQueryBuilder('user')
.where('user.host IS NULL')
.andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' })
- .andWhere('user.updatedAt IS NOT NULL')
- .orderBy('user.updatedAt', 'DESC')
+ .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
+ .andWhere(new Brackets(qb => { qb
+ .where('user.updatedAt IS NULL')
+ .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
+ }))
+ .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
.take(ps.limit!)
.skip(ps.offset)
.getMany();
@@ -74,7 +81,7 @@ export default define(meta, async (ps, me) => {
const otherUsers = await Users.createQueryBuilder('user')
.where('user.host IS NOT NULL')
.andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' })
+ .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
.andWhere('user.updatedAt IS NOT NULL')
.orderBy('user.updatedAt', 'DESC')
.take(ps.limit! - users.length)
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index 8011d90b3d..9aa988d9ed 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
import define from '../../define';
import { UserProfiles, Users } from '@/models/index';
import { User } from '@/models/entities/user';
+import { Brackets } from 'typeorm';
export const meta = {
tags: ['users'],
@@ -23,9 +24,9 @@ export const meta = {
default: 10,
},
- localOnly: {
- validator: $.optional.bool,
- default: false,
+ origin: {
+ validator: $.optional.str.or(['local', 'remote', 'combined']),
+ default: 'combined',
},
detail: {
@@ -46,63 +47,79 @@ export const meta = {
};
export default define(meta, async (ps, me) => {
+ const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
+
const isUsername = ps.query.startsWith('@');
let users: User[] = [];
if (isUsername) {
- users = await Users.createQueryBuilder('user')
- .where('user.host IS NULL')
- .andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
- .andWhere('user.updatedAt IS NOT NULL')
- .orderBy('user.updatedAt', 'DESC')
- .take(ps.limit!)
- .skip(ps.offset)
- .getMany();
+ const usernameQuery = Users.createQueryBuilder('user')
+ .where('user.usernameLower LIKE :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
+ .andWhere(new Brackets(qb => { qb
+ .where('user.updatedAt IS NULL')
+ .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
+ }))
+ .andWhere('user.isSuspended = FALSE');
- if (users.length < ps.limit! && !ps.localOnly) {
- const otherUsers = await Users.createQueryBuilder('user')
- .where('user.host IS NOT NULL')
- .andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
- .andWhere('user.updatedAt IS NOT NULL')
- .orderBy('user.updatedAt', 'DESC')
- .take(ps.limit! - users.length)
- .getMany();
-
- users = users.concat(otherUsers);
+ if (ps.origin === 'local') {
+ usernameQuery.andWhere('user.host IS NULL');
+ } else if (ps.origin === 'remote') {
+ usernameQuery.andWhere('user.host IS NOT NULL');
}
- } else {
- const profQuery = UserProfiles.createQueryBuilder('prof')
- .select('prof.userId')
- .where('prof.userHost IS NULL')
- .andWhere('prof.description ilike :query', { query: '%' + ps.query + '%' });
- users = await Users.createQueryBuilder('user')
- .where(`user.id IN (${ profQuery.getQuery() })`)
- .setParameters(profQuery.getParameters())
- .andWhere('user.updatedAt IS NOT NULL')
- .orderBy('user.updatedAt', 'DESC')
+ users = await usernameQuery
+ .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
+ .take(ps.limit!)
+ .skip(ps.offset)
+ .getMany();
+ } else {
+ const nameQuery = Users.createQueryBuilder('user')
+ .where('user.name ILIKE :query', { query: '%' + ps.query + '%' })
+ .andWhere(new Brackets(qb => { qb
+ .where('user.updatedAt IS NULL')
+ .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
+ }))
+ .andWhere('user.isSuspended = FALSE');
+
+ if (ps.origin === 'local') {
+ nameQuery.andWhere('user.host IS NULL');
+ } else if (ps.origin === 'remote') {
+ nameQuery.andWhere('user.host IS NOT NULL');
+ }
+
+ users = await nameQuery
+ .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
.take(ps.limit!)
.skip(ps.offset)
.getMany();
- if (users.length < ps.limit! && !ps.localOnly) {
- const profQuery2 = UserProfiles.createQueryBuilder('prof')
+ if (users.length < ps.limit!) {
+ const profQuery = UserProfiles.createQueryBuilder('prof')
.select('prof.userId')
- .where('prof.userHost IS NOT NULL')
- .andWhere('prof.description ilike :query', { query: '%' + ps.query + '%' });
+ .where('prof.description ILIKE :query', { query: '%' + ps.query + '%' });
- const otherUsers = await Users.createQueryBuilder('user')
- .where(`user.id IN (${ profQuery2.getQuery() })`)
- .setParameters(profQuery2.getParameters())
- .andWhere('user.updatedAt IS NOT NULL')
- .orderBy('user.updatedAt', 'DESC')
- .take(ps.limit! - users.length)
- .getMany();
+ if (ps.origin === 'local') {
+ profQuery.andWhere('prof.userHost IS NULL');
+ } else if (ps.origin === 'remote') {
+ profQuery.andWhere('prof.userHost IS NOT NULL');
+ }
- users = users.concat(otherUsers);
+ const query = Users.createQueryBuilder('user')
+ .where(`user.id IN (${ profQuery.getQuery() })`)
+ .andWhere(new Brackets(qb => { qb
+ .where('user.updatedAt IS NULL')
+ .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
+ }))
+ .andWhere('user.isSuspended = FALSE')
+ .setParameters(profQuery.getParameters());
+
+ users = users.concat(await query
+ .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
+ .take(ps.limit!)
+ .skip(ps.offset)
+ .getMany()
+ );
}
}
diff --git a/src/server/file/send-drive-file.ts b/src/server/file/send-drive-file.ts
index a73164ed21..1908c969a5 100644
--- a/src/server/file/send-drive-file.ts
+++ b/src/server/file/send-drive-file.ts
@@ -13,6 +13,7 @@ import { downloadUrl } from '@/misc/download-url';
import { detectType } from '@/misc/get-file-info';
import { convertToJpeg, convertToPngOrJpeg } from '@/services/drive/image-processor';
import { GenerateVideoThumbnail } from '@/services/drive/generate-video-thumbnail';
+import { StatusError } from '@/misc/fetch';
//const _filename = fileURLToPath(import.meta.url);
const _filename = __filename;
@@ -83,9 +84,9 @@ export default async function(ctx: Koa.Context) {
ctx.set('Content-Type', image.type);
ctx.set('Cache-Control', 'max-age=31536000, immutable');
} catch (e) {
- serverLogger.error(e.statusCode);
+ serverLogger.error(`${e}`);
- if (typeof e.statusCode === 'number' && e.statusCode >= 400 && e.statusCode < 500) {
+ if (e instanceof StatusError && e.isClientError) {
ctx.status = e.statusCode;
ctx.set('Cache-Control', 'max-age=86400');
} else {
diff --git a/src/server/proxy/proxy-media.ts b/src/server/proxy/proxy-media.ts
index 3bd65dfe67..9e13c0877f 100644
--- a/src/server/proxy/proxy-media.ts
+++ b/src/server/proxy/proxy-media.ts
@@ -5,6 +5,7 @@ import { IImage, convertToPng, convertToJpeg } from '@/services/drive/image-proc
import { createTemp } from '@/misc/create-temp';
import { downloadUrl } from '@/misc/download-url';
import { detectType } from '@/misc/get-file-info';
+import { StatusError } from '@/misc/fetch';
export async function proxyMedia(ctx: Koa.Context) {
const url = 'url' in ctx.query ? ctx.query.url : 'https://' + ctx.params.url;
@@ -37,9 +38,9 @@ export async function proxyMedia(ctx: Koa.Context) {
ctx.set('Cache-Control', 'max-age=31536000, immutable');
ctx.body = image.data;
} catch (e) {
- serverLogger.error(e);
+ serverLogger.error(`${e}`);
- if (typeof e.statusCode === 'number' && e.statusCode >= 400 && e.statusCode < 500) {
+ if (e instanceof StatusError && e.isClientError) {
ctx.status = e.statusCode;
} else {
ctx.status = 500;
diff --git a/test/ap-request.ts b/test/ap-request.ts
new file mode 100644
index 0000000000..4a9799eb99
--- /dev/null
+++ b/test/ap-request.ts
@@ -0,0 +1,55 @@
+import * as assert from 'assert';
+import { genRsaKeyPair } from '../src/misc/gen-key-pair';
+import { createSignedPost, createSignedGet } from '../src/remote/activitypub/ap-request';
+const httpSignature = require('http-signature');
+
+export const buildParsedSignature = (signingString: string, signature: string, algorithm: string) => {
+ return {
+ scheme: 'Signature',
+ params: {
+ keyId: 'KeyID', // dummy, not used for verify
+ algorithm: algorithm,
+ headers: [ '(request-target)', 'date', 'host', 'digest' ], // dummy, not used for verify
+ signature: signature,
+ },
+ signingString: signingString,
+ algorithm: algorithm?.toUpperCase(),
+ keyId: 'KeyID', // dummy, not used for verify
+ };
+};
+
+describe('ap-request', () => {
+ it('createSignedPost with verify', async () => {
+ const keypair = await genRsaKeyPair();
+ const key = { keyId: 'x', 'privateKeyPem': keypair.privateKey };
+ const url = 'https://example.com/inbox';
+ const activity = { a: 1 };
+ const body = JSON.stringify(activity);
+ const headers = {
+ 'User-Agent': 'UA'
+ };
+
+ const req = createSignedPost({ key, url, body, additionalHeaders: headers });
+
+ const parsed = buildParsedSignature(req.signingString, req.signature, 'rsa-sha256');
+
+ const result = httpSignature.verifySignature(parsed, keypair.publicKey);
+ assert.deepStrictEqual(result, true);
+ });
+
+ it('createSignedGet with verify', async () => {
+ const keypair = await genRsaKeyPair();
+ const key = { keyId: 'x', 'privateKeyPem': keypair.privateKey };
+ const url = 'https://example.com/outbox';
+ const headers = {
+ 'User-Agent': 'UA'
+ };
+
+ const req = createSignedGet({ key, url, additionalHeaders: headers });
+
+ const parsed = buildParsedSignature(req.signingString, req.signature, 'rsa-sha256');
+
+ const result = httpSignature.verifySignature(parsed, keypair.publicKey);
+ assert.deepStrictEqual(result, true);
+ });
+});
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
new file mode 100644
index 0000000000..c045e7c6c4
--- /dev/null
+++ b/test/docker-compose.yml
@@ -0,0 +1,15 @@
+version: "3"
+
+services:
+ redistest:
+ image: redis:4.0-alpine
+ ports:
+ - "127.0.0.1:56312:6379"
+
+ dbtest:
+ image: postgres:12.2-alpine
+ ports:
+ - "127.0.0.1:54312:5432"
+ environment:
+ POSTGRES_DB: "test-misskey"
+ POSTGRES_HOST_AUTH_METHOD: trust
diff --git a/test/test.yml b/test/test.yml
new file mode 100644
index 0000000000..2d3094653e
--- /dev/null
+++ b/test/test.yml
@@ -0,0 +1,12 @@
+url: 'http://misskey.local'
+port: 61812
+db:
+ host: localhost
+ port: 54312
+ db: test-misskey
+ user: postgres
+ pass: ''
+redis:
+ host: localhost
+ port: 56312
+id: aid
diff --git a/yarn.lock b/yarn.lock
index cde28625d3..e2140e185a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,13 +2,6 @@
# yarn lockfile v1
-"@babel/code-frame@7.12.11":
- version "7.12.11"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
- integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
- dependencies:
- "@babel/highlight" "^7.10.4"
-
"@babel/code-frame@^7.0.0":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658"
@@ -21,7 +14,7 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
-"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13":
+"@babel/highlight@^7.12.13":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c"
integrity sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==
@@ -61,10 +54,10 @@
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==
-"@cspotcode/source-map-support@0.6.1":
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz#118511f316e2e87ee4294761868e254d3da47960"
- integrity sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==
+"@cspotcode/source-map-support@0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5"
+ integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==
dependencies:
"@cspotcode/source-map-consumer" "0.8.0"
@@ -131,14 +124,14 @@
pump "^3.0.0"
secure-json-parse "^2.1.0"
-"@eslint/eslintrc@^0.4.3":
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
- integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
+"@eslint/eslintrc@^1.0.3":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.3.tgz#41f08c597025605f672251dcc4e8be66b5ed7366"
+ integrity sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==
dependencies:
ajv "^6.12.4"
- debug "^4.1.1"
- espree "^7.3.0"
+ debug "^4.3.2"
+ espree "^9.0.0"
globals "^13.9.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
@@ -158,10 +151,10 @@
dependencies:
"@hapi/hoek" "^9.0.0"
-"@humanwhocodes/config-array@^0.5.0":
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
- integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
+"@humanwhocodes/config-array@^0.6.0":
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.6.0.tgz#b5621fdb3b32309d2d16575456cbc277fa8f021a"
+ integrity sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==
dependencies:
"@humanwhocodes/object-schema" "^1.2.0"
debug "^4.1.1"
@@ -1189,144 +1182,144 @@
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71"
integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg==
-"@typescript-eslint/parser@4.33.0":
- version "4.33.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899"
- integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==
+"@typescript-eslint/parser@5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.0.0.tgz#50d1be2e0def82d73e863cceba74aeeac9973592"
+ integrity sha512-B6D5rmmQ14I1fdzs71eL3DAuvnPHTY/t7rQABrL9BLnx/H51Un8ox1xqYAchs0/V2trcoyxB1lMJLlrwrJCDgw==
dependencies:
- "@typescript-eslint/scope-manager" "4.33.0"
- "@typescript-eslint/types" "4.33.0"
- "@typescript-eslint/typescript-estree" "4.33.0"
+ "@typescript-eslint/scope-manager" "5.0.0"
+ "@typescript-eslint/types" "5.0.0"
+ "@typescript-eslint/typescript-estree" "5.0.0"
debug "^4.3.1"
-"@typescript-eslint/scope-manager@4.33.0":
- version "4.33.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3"
- integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==
+"@typescript-eslint/scope-manager@5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.0.0.tgz#aea0fb0e2480c1169a02e89d9005ac3f2835713f"
+ integrity sha512-5RFjdA/ain/MDUHYXdF173btOKncIrLuBmA9s6FJhzDrRAyVSA+70BHg0/MW6TE+UiKVyRtX91XpVS0gVNwVDQ==
dependencies:
- "@typescript-eslint/types" "4.33.0"
- "@typescript-eslint/visitor-keys" "4.33.0"
+ "@typescript-eslint/types" "5.0.0"
+ "@typescript-eslint/visitor-keys" "5.0.0"
-"@typescript-eslint/types@4.33.0":
- version "4.33.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
- integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
+"@typescript-eslint/types@5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.0.0.tgz#25d93f6d269b2d25fdc51a0407eb81ccba60eb0f"
+ integrity sha512-dU/pKBUpehdEqYuvkojmlv0FtHuZnLXFBn16zsDmlFF3LXkOpkAQ2vrKc3BidIIve9EMH2zfTlxqw9XM0fFN5w==
-"@typescript-eslint/typescript-estree@4.33.0":
- version "4.33.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609"
- integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==
+"@typescript-eslint/typescript-estree@5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.0.0.tgz#bc20f413c6e572c7309dbe5fa3be027984952af3"
+ integrity sha512-V/6w+PPQMhinWKSn+fCiX5jwvd1vRBm7AX7SJQXEGQtwtBvjMPjaU3YTQ1ik2UF1u96X7tsB96HMnulG3eLi9Q==
dependencies:
- "@typescript-eslint/types" "4.33.0"
- "@typescript-eslint/visitor-keys" "4.33.0"
+ "@typescript-eslint/types" "5.0.0"
+ "@typescript-eslint/visitor-keys" "5.0.0"
debug "^4.3.1"
globby "^11.0.3"
is-glob "^4.0.1"
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/visitor-keys@4.33.0":
- version "4.33.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
- integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==
+"@typescript-eslint/visitor-keys@5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.0.0.tgz#b789f7cd105e59bee5c0983a353942a5a48f56df"
+ integrity sha512-yRyd2++o/IrJdyHuYMxyFyBhU762MRHQ/bAGQeTnN3pGikfh+nEmM61XTqaDH1XDp53afZ+waXrk0ZvenoZ6xw==
dependencies:
- "@typescript-eslint/types" "4.33.0"
- eslint-visitor-keys "^2.0.0"
+ "@typescript-eslint/types" "5.0.0"
+ eslint-visitor-keys "^3.0.0"
"@ungap/promise-all-settled@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
-"@vue/compiler-core@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.19.tgz#b537dd377ce51fdb64e9b30ebfbff7cd70a64cb9"
- integrity sha512-8dOPX0YOtaXol0Zf2cfLQ4NU/yHYl2H7DCKsLEZ7gdvPK6ZSEwGLJ7IdghhY2YEshEpC5RB9QKdC5I07z8Dtjg==
+"@vue/compiler-core@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.20.tgz#af5a3c5237818835b0d0be837eb5885a8d21c160"
+ integrity sha512-vcEXlKXoPwBXFP5aUTHN9GTZaDfwCofa9Yu9bbW2C5O/QSa9Esdt7OG4+0RRd3EHEMxUvEdj4RZrd/KpQeiJbA==
dependencies:
"@babel/parser" "^7.15.0"
- "@vue/shared" "3.2.19"
+ "@vue/shared" "3.2.20"
estree-walker "^2.0.2"
source-map "^0.6.1"
-"@vue/compiler-dom@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.19.tgz#0607bc90de6af55fde73b09b3c4d0bf8cb597ed8"
- integrity sha512-WzQoE8rfkFjPtIioc7SSgTsnz9g2oG61DU8KHnzPrRS7fW/lji6H2uCYJfp4Z6kZE8GjnHc1Ljwl3/gxDes0cw==
+"@vue/compiler-dom@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.20.tgz#8e0ef354449c0faf41519b00bfc2045eae01dcb5"
+ integrity sha512-QnI77ec/JtV7R0YBbcVayYTDCRcI9OCbxiUQK6izVyqQO0658n0zQuoNwe+bYgtqnvGAIqTR3FShTd5y4oOjdg==
dependencies:
- "@vue/compiler-core" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/compiler-core" "3.2.20"
+ "@vue/shared" "3.2.20"
-"@vue/compiler-sfc@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.19.tgz#d412195a98ebd49b84602f171719294a1d9549be"
- integrity sha512-pLlbgkO1UHTO02MSpa/sFOXUwIDxSMiKZ1ozE5n71CY4DM+YmI+G3gT/ZHZ46WBId7f3VTF/D8pGwMygcQbrQA==
+"@vue/compiler-sfc@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.20.tgz#2d7668e76f066c566dd7c09c15c9acce4e876e0a"
+ integrity sha512-03aZo+6tQKiFLfunHKSPZvdK4Jsn/ftRCyaro8AQIWkuxJbvSosbKK6HTTn+D2c3nPScG155akJoxKENw7rftQ==
dependencies:
"@babel/parser" "^7.15.0"
- "@vue/compiler-core" "3.2.19"
- "@vue/compiler-dom" "3.2.19"
- "@vue/compiler-ssr" "3.2.19"
- "@vue/ref-transform" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/compiler-core" "3.2.20"
+ "@vue/compiler-dom" "3.2.20"
+ "@vue/compiler-ssr" "3.2.20"
+ "@vue/ref-transform" "3.2.20"
+ "@vue/shared" "3.2.20"
estree-walker "^2.0.2"
magic-string "^0.25.7"
postcss "^8.1.10"
source-map "^0.6.1"
-"@vue/compiler-ssr@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.19.tgz#3e91ecf70f8f961c5f63eacd2139bcdab9a7a07c"
- integrity sha512-oLon0Cn3O7WEYzzmzZavGoqXH+199LT+smdjBT3Uf3UX4HwDNuBFCmvL0TsqV9SQnIgKvBRbQ7lhbpnd4lqM3w==
+"@vue/compiler-ssr@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.20.tgz#9cceb6261d9932cb5568202610c1c28f86c5e521"
+ integrity sha512-rzzVVYivm+EjbfiGQvNeyiYZWzr6Hkej97RZLZvcumacQlnKv9176Xo9rRyeWwFbBlxmtNdrVMslRXtipMXk2w==
dependencies:
- "@vue/compiler-dom" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/compiler-dom" "3.2.20"
+ "@vue/shared" "3.2.20"
-"@vue/reactivity@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.19.tgz#fc6e0f0106f295226835cfed5ff5f84d927bea65"
- integrity sha512-FtachoYs2SnyrWup5UikP54xDX6ZJ1s5VgHcJp4rkGoutU3Ry61jhs+nCX7J64zjX992Mh9gGUC0LqTs8q9vCA==
+"@vue/reactivity@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.20.tgz#81fe1c368e7f20bc0ec1dec1045bbee253582de8"
+ integrity sha512-nSmoLojUTk+H8HNTAkrUduB4+yIUBK2HPihJo2uXVSH4Spry6oqN6lFzE5zpLK+F27Sja+UqR9R1+/kIOsHV5w==
dependencies:
- "@vue/shared" "3.2.19"
+ "@vue/shared" "3.2.20"
-"@vue/ref-transform@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/ref-transform/-/ref-transform-3.2.19.tgz#cf0f986486bb26838fbd09749e927bab19745600"
- integrity sha512-03wwUnoIAeKti5IGGx6Vk/HEBJ+zUcm5wrUM3+PQsGf7IYnXTbeIfHHpx4HeSeWhnLAjqZjADQwW8uA4rBmVbg==
+"@vue/ref-transform@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/ref-transform/-/ref-transform-3.2.20.tgz#2a59ec90caf8e5c7336776a0900bff0a8b81c090"
+ integrity sha512-Y42d3PGlYZ1lXcF3dbd3+qU/C/a3wYEZ949fyOI5ptzkjDWlkfU6vn74fmOjsLjEcjs10BXK2qO99FqQIK2r1Q==
dependencies:
"@babel/parser" "^7.15.0"
- "@vue/compiler-core" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/compiler-core" "3.2.20"
+ "@vue/shared" "3.2.20"
estree-walker "^2.0.2"
magic-string "^0.25.7"
-"@vue/runtime-core@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.19.tgz#807715b7f4728abb84fa4a8efdbe37d8ddb4c6d3"
- integrity sha512-qArZSWKxWsgKfxk9BelZ32nY0MZ31CAW2kUUyVJyxh4cTfHaXGbjiQB5JgsvKc49ROMNffv9t3/qjasQqAH+RQ==
+"@vue/runtime-core@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.20.tgz#8f63e956a3f88fb772541443c45a7701211012cb"
+ integrity sha512-d1xfUGhZPfiZzAN7SatStD4vRtT8deJSXib2+Cz3x0brjMWKxe32asQc154FF1E2fFgMCHtnfd4A90bQEzV4GQ==
dependencies:
- "@vue/reactivity" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/reactivity" "3.2.20"
+ "@vue/shared" "3.2.20"
-"@vue/runtime-dom@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.19.tgz#7e8bf645754703e360fa132e4be9113edf2377bb"
- integrity sha512-hIRboxXwafeHhbZEkZYNV0MiJXPNf4fP0X6hM2TJb0vssz8BKhD9cF92BkRgZztTQevecbhk0gu4uAPJ3dxL9A==
+"@vue/runtime-dom@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.20.tgz#8aa56ae6c30f9cd4a71ca0e9ec3c4bdc67148d15"
+ integrity sha512-4TCvZMLhESWCFHFYgqN4QmMA/onnINAlUovhopjlS8ST27G1A8Z0tyxPzLoXLa+b5JrOpbMPheEMPvdKExTJig==
dependencies:
- "@vue/runtime-core" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/runtime-core" "3.2.20"
+ "@vue/shared" "3.2.20"
csstype "^2.6.8"
-"@vue/server-renderer@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.19.tgz#870bcec9f7cdaee0c2187a169b6e636ab4362fb1"
- integrity sha512-A9FNT7fgQJXItwdzWREntAgWKVtKYuXHBKGev/H4+ByTu8vB7gQXGcim01QxaJshdNg4dYuH2tEBZXCNCNx+/w==
+"@vue/server-renderer@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.20.tgz#705e07ae9425132b2b6227d308a51a13f4d4ec81"
+ integrity sha512-viIbZGep9XabnrRcaxWIi00cOh1x21QYm2upIL5W0zqzTJ54VdTzpI+zi1osNp+VfRQDTHpV2U7H3Kn4ljYJvg==
dependencies:
- "@vue/compiler-ssr" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/compiler-ssr" "3.2.20"
+ "@vue/shared" "3.2.20"
-"@vue/shared@3.2.19":
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.19.tgz#111ec3da18337d86274446984c49925b1b2b2dd7"
- integrity sha512-Knqhx7WieLdVgwCAZgTVrDCXZ50uItuecLh9JdLC8O+a5ayaSyIQYveUK3hCRNC7ws5zalHmZwfdLMGaS8r4Ew==
+"@vue/shared@3.2.20":
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.20.tgz#53746961f731a8ea666e3316271e944238dc31db"
+ integrity sha512-FbpX+hD5BvXCQerEYO7jtAGHlhAkhTQ4KIV73kmLWNlawWhTiVuQxizgVb0BOkX5oG9cIRZ42EG++d/k/Efp0w==
"@webassemblyjs/ast@1.11.0":
version "1.11.0"
@@ -1655,7 +1648,7 @@ acorn-walk@^8.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.1.1.tgz#3ddab7f84e4a7e2313f6c414c5b7dac85f4e3ebc"
integrity sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==
-acorn@^7.1.1, acorn@^7.4.0:
+acorn@^7.1.1:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
@@ -1675,6 +1668,11 @@ acorn@^8.4.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c"
integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==
+acorn@^8.5.0:
+ version "8.5.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
+ integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
+
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -1714,16 +1712,6 @@ ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-ajv@^8.0.1:
- version "8.5.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.5.0.tgz#695528274bcb5afc865446aa275484049a18ae4b"
- integrity sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==
- dependencies:
- fast-deep-equal "^3.1.1"
- json-schema-traverse "^1.0.0"
- require-from-string "^2.0.2"
- uri-js "^4.2.2"
-
alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
@@ -2422,10 +2410,10 @@ builtin-modules@^1.1.1:
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-bull@3.29.2:
- version "3.29.2"
- resolved "https://registry.yarnpkg.com/bull/-/bull-3.29.2.tgz#30051fd14c7214b1e90c212585674f77fd982650"
- integrity sha512-zWHyza/ElwVvJUqIEDJdUhGKd1V9EHjituUL7sJAmJoxS9Z7QMhYcMOWcgbUlWPgtiKN1g9ZlOtFAoq7C4/SQw==
+bull@3.29.3:
+ version "3.29.3"
+ resolved "https://registry.yarnpkg.com/bull/-/bull-3.29.3.tgz#5b0059b172685b0d6f011d56214e1898ff3a7a0b"
+ integrity sha512-MOqV1dKLy1YQgP9m3lFolyMxaU+1+o4afzYYf0H4wNM+x/S0I1QPQfkgGlLiH00EyFrvSmeubeCYFP47rTfpjg==
dependencies:
cron-parser "^2.13.0"
debuglog "^1.0.0"
@@ -2497,10 +2485,10 @@ cache-content-type@^1.0.0:
mime-types "^2.1.18"
ylru "^1.2.0"
-cacheable-lookup@6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.0.2.tgz#8df03d6239c91bb9f6394700d7ba4a100abbad67"
- integrity sha512-9RJkUl1k/A1dFhaRfrEUdISvvou0WKx8LboMO0j1BpsqgAuolwZgwaEtn0dmFMk5HQxpFtHF1bHCnIQMywUpvw==
+cacheable-lookup@6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.0.3.tgz#61d6171f6818fab230666b11f7cf3f5a48df7818"
+ integrity sha512-xdwIK7MEC8NpRIt0dx2PL7pTRKaSmDb+zirzuM+cJTRWDfwfVu4XyASkODIU4XbjsyFHKo/tDOPSs64Z3yfFWg==
cacheable-lookup@^5.0.3:
version "5.0.3"
@@ -3325,10 +3313,10 @@ css-declaration-sorter@^6.0.3:
dependencies:
timsort "^0.3.0"
-css-loader@6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.3.0.tgz#334d3500ff0a0c14cfbd4b0670088dbb5b5c1530"
- integrity sha512-9NGvHOR+L6ps13Ilw/b216++Q8q+5RpJcVufCdW9S/9iCzs4KBDNa8qnA/n3FK/sSfWmH35PAIK/cfPi7LOSUg==
+css-loader@6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.4.0.tgz#01c57ea776024e18ca193428dcad3ff6b42a0130"
+ integrity sha512-Dlt6qfsxI/w1vU0r8qDd4BtMPxWqJeY5qQU7SmmZfvbpe6Xl18McO4GhyaMLns24Y2VNPiZwJPQ8JSbg4qvQLw==
dependencies:
icss-utils "^5.1.0"
postcss "^8.2.15"
@@ -4280,6 +4268,14 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1:
esrecurse "^4.3.0"
estraverse "^4.1.1"
+eslint-scope@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-6.0.0.tgz#9cf45b13c5ac8f3d4c50f46a5121f61b3e318978"
+ integrity sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
eslint-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
@@ -4287,7 +4283,14 @@ eslint-utils@^2.1.0:
dependencies:
eslint-visitor-keys "^1.1.0"
-eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
+eslint-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
+ integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+ dependencies:
+ eslint-visitor-keys "^2.0.0"
+
+eslint-visitor-keys@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
@@ -4297,37 +4300,41 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
-eslint@7.32.0:
- version "7.32.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
- integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
+eslint-visitor-keys@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186"
+ integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==
+
+eslint@8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.0.1.tgz#3610e7fe4a05c2154669515ca60835a76a19f700"
+ integrity sha512-LsgcwZgQ72vZ+SMp4K6pAnk2yFDWL7Ti4pJaRvsZ0Hsw2h8ZjUIW38a9AFn2cZXdBMlScMFYYgsSp4ttFI/0bA==
dependencies:
- "@babel/code-frame" "7.12.11"
- "@eslint/eslintrc" "^0.4.3"
- "@humanwhocodes/config-array" "^0.5.0"
+ "@eslint/eslintrc" "^1.0.3"
+ "@humanwhocodes/config-array" "^0.6.0"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
- debug "^4.0.1"
+ debug "^4.3.2"
doctrine "^3.0.0"
enquirer "^2.3.5"
escape-string-regexp "^4.0.0"
- eslint-scope "^5.1.1"
- eslint-utils "^2.1.0"
- eslint-visitor-keys "^2.0.0"
- espree "^7.3.1"
+ eslint-scope "^6.0.0"
+ eslint-utils "^3.0.0"
+ eslint-visitor-keys "^3.0.0"
+ espree "^9.0.0"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
file-entry-cache "^6.0.1"
functional-red-black-tree "^1.0.1"
- glob-parent "^5.1.2"
+ glob-parent "^6.0.1"
globals "^13.6.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
- js-yaml "^3.13.1"
+ js-yaml "^4.1.0"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
lodash.merge "^4.6.2"
@@ -4335,11 +4342,10 @@ eslint@7.32.0:
natural-compare "^1.4.0"
optionator "^0.9.1"
progress "^2.0.0"
- regexpp "^3.1.0"
+ regexpp "^3.2.0"
semver "^7.2.1"
strip-ansi "^6.0.0"
strip-json-comments "^3.1.0"
- table "^6.0.9"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@@ -4357,14 +4363,14 @@ espree@^6.2.1:
acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.1.0"
-espree@^7.3.0, espree@^7.3.1:
- version "7.3.1"
- resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
- integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
+espree@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.0.0.tgz#e90a2965698228502e771c7a58489b1a9d107090"
+ integrity sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==
dependencies:
- acorn "^7.4.0"
+ acorn "^8.5.0"
acorn-jsx "^5.3.1"
- eslint-visitor-keys "^1.3.0"
+ eslint-visitor-keys "^3.0.0"
esprima@^2.6.0:
version "2.7.3"
@@ -5043,12 +5049,12 @@ glob-parent@^5.1.0, glob-parent@~5.1.0:
dependencies:
is-glob "^4.0.1"
-glob-parent@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
- integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+glob-parent@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
dependencies:
- is-glob "^4.0.1"
+ is-glob "^4.0.3"
glob-stream@^6.1.0:
version "6.1.0"
@@ -5763,7 +5769,7 @@ ip-cidr@3.0.4:
ip-address "^7.1.0"
jsbn "^1.1.0"
-ip-regex@^4.3.0:
+ip-regex@^4.0.0, ip-regex@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
@@ -5773,6 +5779,11 @@ ip@^1.1.5:
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+ipaddr.js@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0"
+ integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==
+
is-absolute-url@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
@@ -5951,6 +5962,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
+is-glob@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
is-installed-globally@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
@@ -5959,6 +5977,13 @@ is-installed-globally@~0.4.0:
global-dirs "^3.0.0"
is-path-inside "^3.0.2"
+is-ip@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8"
+ integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==
+ dependencies:
+ ip-regex "^4.0.0"
+
is-lambda@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
@@ -6241,7 +6266,7 @@ js-yaml@4.0.0:
dependencies:
argparse "^2.0.1"
-js-yaml@4.1.0, js-yaml@^4.0.0:
+js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
@@ -6838,11 +6863,6 @@ lodash.bind@^4.1.4:
resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35"
integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=
-lodash.clonedeep@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
- integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
-
lodash.defaults@^4.0.1, lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
@@ -6923,11 +6943,6 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
-lodash.truncate@^4.4.2:
- version "4.4.2"
- resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
- integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
-
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -7560,10 +7575,10 @@ node-releases@^1.1.70, node-releases@^1.1.71:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb"
integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==
-nodemailer@6.6.5:
- version "6.6.5"
- resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.5.tgz#f9f6953cee5cfe82cbea152eeddacf7a0442049a"
- integrity sha512-C/v856DBijUzHcHIgGpQoTrfsH3suKIRAGliIzCstatM2cAa+MYX3LuyCrABiO/cdJTxgBBHXxV1ztiqUwst5A==
+nodemailer@6.7.0:
+ version "6.7.0"
+ resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.0.tgz#86614722c4e0c33d1b5b02aecb90d6d629932b0d"
+ integrity sha512-AtiTVUFHLiiDnMQ43zi0YgkzHOEWUkhDgPlBXrsDzJiJvB29Alo4OKxHQ0ugF3gRqRQIneCLtZU3yiUo7pItZw==
nofilter@^2.0.3:
version "2.0.3"
@@ -8398,10 +8413,10 @@ postcss-filter-plugins@^2.0.0:
dependencies:
postcss "^5.0.4"
-postcss-loader@6.1.1:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.1.1.tgz#58dd0a3accd9bc87cc52eff75244db578d11301a"
- integrity sha512-lBmJMvRh1D40dqpWKr9Rpygwxn8M74U9uaCSeYGNKLGInbk9mXBt1ultHf2dH9Ghk6Ue4UXlXWwGMH9QdUJ5ug==
+postcss-loader@6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.0.tgz#714370a3f567141cf4cadcdf9575f5234d186bc5"
+ integrity sha512-H9hv447QjQJVDbHj3OUdciyAXY3v5+UDduzEytAlZCVHCpNAAg/mCSwhYYqZr9BiGYhmYspU8QXxZwiHTLn3yA==
dependencies:
cosmiconfig "^7.0.0"
klona "^2.0.4"
@@ -8911,12 +8926,14 @@ prismjs@1.25.0:
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
-private-ip@2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/private-ip/-/private-ip-2.2.1.tgz#4fe167d04e12eca5c67cdcbd3224e86b38c79253"
- integrity sha512-jN1WT/br/VNW9xEcwHr6DjtOKxQ5qOIqmh7o+co2TWgq56pZJw99iO3UT1tWdfgsQiyK9FqG4ji3ykwpjFqITA==
+private-ip@2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/private-ip/-/private-ip-2.3.0.tgz#aa07bf623c60ea75ee5d140814f492648c001717"
+ integrity sha512-3lTFzg+Z1Q2VNQChw8AW2c5LM7getyUJ67SqeWtvnkUO4gihjbf5oIEK4+jAQ4v1sCqOVV7r+GzKrgowW/W3tw==
dependencies:
ip-regex "^4.3.0"
+ ipaddr.js "^2.0.1"
+ is-ip "^3.1.0"
netmask "^2.0.2"
probe-image-size@7.2.1:
@@ -9411,10 +9428,10 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
-regexpp@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
- integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
+regexpp@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
+ integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
remove-bom-buffer@^3.0.0:
version "3.0.0"
@@ -9739,18 +9756,18 @@ safe-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sass-loader@12.1.0:
- version "12.1.0"
- resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.1.0.tgz#b73324622231009da6fba61ab76013256380d201"
- integrity sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==
+sass-loader@12.2.0:
+ version "12.2.0"
+ resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.2.0.tgz#b370010fb0ababae2ef9c6c89e05d6c6debc6042"
+ integrity sha512-qducnp5vSV+8A8MZxuH6zV0MUg4MOVISScl2wDTCAn/2WJX+9Auxh92O/rnkdR2bvi5QxZBafnzkzRrWGZvm7w==
dependencies:
klona "^2.0.4"
neo-async "^2.6.2"
-sass@1.42.1:
- version "1.42.1"
- resolved "https://registry.yarnpkg.com/sass/-/sass-1.42.1.tgz#5ab17bebc1cb1881ad2e0c9a932c66ad64e441e2"
- integrity sha512-/zvGoN8B7dspKc5mC6HlaygyCBRvnyzzgD5khiaCfglWztY99cYoiTUksVx11NlnemrcfH5CEaCpsUKoW0cQqg==
+sass@1.43.2:
+ version "1.43.2"
+ resolved "https://registry.yarnpkg.com/sass/-/sass-1.43.2.tgz#c02501520c624ad6622529a8b3724eb08da82d65"
+ integrity sha512-DncYhjl3wBaPMMJR0kIUaH3sF536rVrOcqqVGmTZHQRRzj7LQlyGV7Mb8aCKFyILMr5VsPHwRYtyKpnKYlmQSQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
@@ -10620,28 +10637,16 @@ syslog-pro@1.0.0:
dependencies:
moment "^2.22.2"
-systeminformation@5.9.4:
- version "5.9.4"
- resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.9.4.tgz#1f0e29e0aa376dec8f69cc517eeefc5cdcda411a"
- integrity sha512-FOsiTn0CyJZoj9kIhla11ndsMzbbwwuriul81wpqIBt9IpbxHZ6P/oZCphIFgJrwqjTnme0Qp1HDzIkUD9Xr/g==
+systeminformation@5.9.7:
+ version "5.9.7"
+ resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.9.7.tgz#8a5041d3aa1518e962b17740e20a3c75ff390e6d"
+ integrity sha512-Vcmc8HaWPMFM4DoasuKN2lpvIwS2AqaoPuEGZc4HCT6tlRJH+IQ5GhA2BrUgjpBDJjFMj2Bti6qLOzP3T1arCw==
syuilo-password-strength@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/syuilo-password-strength/-/syuilo-password-strength-0.0.1.tgz#08f71a8f0ecb77db649f3d9a6424510d9d945f52"
integrity sha1-CPcajw7Ld9tknz2aZCRRDZ2UX1I=
-table@^6.0.9:
- version "6.7.1"
- resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
- integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==
- dependencies:
- ajv "^8.0.1"
- lodash.clonedeep "^4.5.0"
- lodash.truncate "^4.4.2"
- slice-ansi "^4.0.0"
- string-width "^4.2.0"
- strip-ansi "^6.0.0"
-
tapable@^2.1.1, tapable@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b"
@@ -10972,12 +10977,12 @@ ts-loader@9.2.6:
micromatch "^4.0.0"
semver "^7.3.4"
-ts-node@10.2.1:
- version "10.2.1"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.2.1.tgz#4cc93bea0a7aba2179497e65bb08ddfc198b3ab5"
- integrity sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==
+ts-node@10.3.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.3.0.tgz#a797f2ed3ff50c9a5d814ce400437cb0c1c048b4"
+ integrity sha512-RYIy3i8IgpFH45AX4fQHExrT8BxDeKTdC83QFJkNzkvt8uFB6QJ8XMyhynYiKMLxt9a7yuXaDBZNOYS3XjDcYw==
dependencies:
- "@cspotcode/source-map-support" "0.6.1"
+ "@cspotcode/source-map-support" "0.7.0"
"@tsconfig/node10" "^1.0.7"
"@tsconfig/node12" "^1.0.7"
"@tsconfig/node14" "^1.0.0"
@@ -11187,10 +11192,10 @@ typeorm@0.2.38:
yargs "^17.0.1"
zen-observable-ts "^1.0.0"
-typescript@4.4.3:
- version "4.4.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
- integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
+typescript@4.4.4:
+ version "4.4.4"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c"
+ integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.6"
@@ -11558,16 +11563,16 @@ vue-svg-loader@0.17.0-beta.2:
semver "^7.3.2"
svgo "^1.3.2"
-vue@3.2.19:
- version "3.2.19"
- resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.19.tgz#da2c80a6a0271c7097fee9e31692adfd9d569c8f"
- integrity sha512-6KAMdIfAtlK+qohTIUE4urwAv4A3YRuo8uAbByApUmiB0CziGAAPs6qVugN6oHPia8YIafHB/37K0O6KZ7sGmA==
+vue@3.2.20:
+ version "3.2.20"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.20.tgz#940f8aa8bf3e3be78243ca582bad41fcd45ae3e6"
+ integrity sha512-81JjEP4OGk9oO8+CU0h2nFPGgJBm9mNa3kdCX2k6FuRdrWrC+CNe+tOnuIeTg8EWwQuI+wwdra5Q7vSzp7p4Iw==
dependencies:
- "@vue/compiler-dom" "3.2.19"
- "@vue/compiler-sfc" "3.2.19"
- "@vue/runtime-dom" "3.2.19"
- "@vue/server-renderer" "3.2.19"
- "@vue/shared" "3.2.19"
+ "@vue/compiler-dom" "3.2.20"
+ "@vue/compiler-sfc" "3.2.20"
+ "@vue/runtime-dom" "3.2.20"
+ "@vue/server-renderer" "3.2.20"
+ "@vue/shared" "3.2.20"
vuedraggable@4.0.1:
version "4.0.1"
@@ -11679,10 +11684,10 @@ webpack-sources@^3.2.0:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d"
integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==
-webpack@5.58.0:
- version "5.58.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.58.0.tgz#9ec621cf8534f23c25e779e7c35dfde1211d5ccb"
- integrity sha512-xc2k5MLbR1iah24Z5xUm1nBh1PZXEdUnrX6YkTSOScq/VWbl5JCLREXJzGYqEAUbIO8tZI+Dzv82lGtnuUnVCQ==
+webpack@5.58.2:
+ version "5.58.2"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.58.2.tgz#6b4af12fc9bd5cbedc00dc0a2fc2b9592db16b44"
+ integrity sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==
dependencies:
"@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.50"