Compare commits
273 Commits
13.13.0-be
...
mkjs-n
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c454a44785 | ||
![]() |
41250d997b | ||
![]() |
a97d379c84 | ||
![]() |
535e778033 | ||
![]() |
726fdb9e93 | ||
![]() |
ae3ce71bb2 | ||
![]() |
106062fa23 | ||
![]() |
42990fe6b6 | ||
![]() |
dc787f7a76 | ||
![]() |
83a6902997 | ||
![]() |
84d3a06637 | ||
![]() |
60cddf87d8 | ||
![]() |
1c5606ca72 | ||
![]() |
02405287d1 | ||
![]() |
bd9c084a3a | ||
![]() |
cef5feaee2 | ||
![]() |
6157616b37 | ||
![]() |
af3258dc79 | ||
![]() |
734c41aba5 | ||
![]() |
fe16b16fc3 | ||
![]() |
a1327fa9e1 | ||
![]() |
f4cc9e3d2e | ||
![]() |
1b1f82a2e2 | ||
![]() |
d48172e9d1 | ||
![]() |
58a898dfe0 | ||
![]() |
d23ad8b511 | ||
![]() |
8099bc24e1 | ||
![]() |
ef354e94f2 | ||
![]() |
7bb8c71543 | ||
![]() |
a2c0573f84 | ||
![]() |
5d922e3084 | ||
![]() |
f0b5860b9c | ||
![]() |
fd4c43786a | ||
![]() |
60cc7f62e6 | ||
![]() |
dc27ba6f03 | ||
![]() |
3fe1c862f6 | ||
![]() |
33a2c0b59e | ||
![]() |
e8c5117b2d | ||
![]() |
e2261b63e9 | ||
![]() |
4d021f315f | ||
![]() |
bad25a804c | ||
![]() |
019199168e | ||
![]() |
8122cb3a86 | ||
![]() |
8c7bcdf998 | ||
![]() |
ab02fd3ec4 | ||
![]() |
028e7c00ae | ||
![]() |
27b6921d3c | ||
![]() |
3ec19e0b00 | ||
![]() |
f5dfb64a52 | ||
![]() |
fa7fd9ce25 | ||
![]() |
63971f1cd8 | ||
![]() |
b1313fbca8 | ||
![]() |
f1b0c54f6e | ||
![]() |
94c09f1441 | ||
![]() |
46222d0258 | ||
![]() |
c59a30ec09 | ||
![]() |
f3a16bcd6d | ||
![]() |
f69627939b | ||
![]() |
e8420ad90b | ||
![]() |
6182a1cb2c | ||
![]() |
308ab8f177 | ||
![]() |
359fbd78c1 | ||
![]() |
dd733ec1d0 | ||
![]() |
5e680500e5 | ||
![]() |
0465e74521 | ||
![]() |
34a32a8334 | ||
![]() |
3941c73db0 | ||
![]() |
703f3a8e37 | ||
![]() |
6032c2be1c | ||
![]() |
13870c63b0 | ||
![]() |
88083925ce | ||
![]() |
95b2148bfe | ||
![]() |
8ccf954065 | ||
![]() |
e456c6a9c1 | ||
![]() |
68c5426fd5 | ||
![]() |
29856a9129 | ||
![]() |
f4943bc5bb | ||
![]() |
aeb8955ca2 | ||
![]() |
981e6f996e | ||
![]() |
8263cc0094 | ||
![]() |
fa051a2a5f | ||
![]() |
ce252143c3 | ||
![]() |
259be258aa | ||
![]() |
2d5bb40ad0 | ||
![]() |
db7fb1c688 | ||
![]() |
6b0685a25c | ||
![]() |
618d07158a | ||
![]() |
a63a417fd4 | ||
![]() |
4443dba717 | ||
![]() |
565c502bbf | ||
![]() |
9e716fd813 | ||
![]() |
34e1b52b38 | ||
![]() |
8401117293 | ||
![]() |
ced5638b80 | ||
![]() |
b532ad8cd4 | ||
![]() |
b818f2308d | ||
![]() |
b697b2f651 | ||
![]() |
0571b83978 | ||
![]() |
b519ff1e10 | ||
![]() |
601eb65cfb | ||
![]() |
59f4bf2a74 | ||
![]() |
a5a9540eac | ||
![]() |
bb46030677 | ||
![]() |
9530cb01b9 | ||
![]() |
fd223a8538 | ||
![]() |
0cb3c7481c | ||
![]() |
4c52f3b286 | ||
![]() |
edc38fc2c7 | ||
![]() |
4a104af304 | ||
![]() |
a1b243bbda | ||
![]() |
6bd7a0d0aa | ||
![]() |
80bd84932c | ||
![]() |
7f28b7334c | ||
![]() |
669cfb1e29 | ||
![]() |
47fae30aba | ||
![]() |
64bbfc2107 | ||
![]() |
1e2178b717 | ||
![]() |
b5852f6053 | ||
![]() |
35b1f73b51 | ||
![]() |
f651ca4b48 | ||
![]() |
8bad11c559 | ||
![]() |
aead5305a7 | ||
![]() |
de9a5d515d | ||
![]() |
7f51ace0ff | ||
![]() |
586cfbe880 | ||
![]() |
f7f8845801 | ||
![]() |
93d111bfb6 | ||
![]() |
1f64b7c9ea | ||
![]() |
c4f434aa01 | ||
![]() |
4001c974a6 | ||
![]() |
2fc2f2d616 | ||
![]() |
f81479ad05 | ||
![]() |
db623dda22 | ||
![]() |
1177528c25 | ||
![]() |
a7abf941c0 | ||
![]() |
5230ec883e | ||
![]() |
482b00df77 | ||
![]() |
91d790bbb6 | ||
![]() |
40295ae57d | ||
![]() |
3857cd589f | ||
![]() |
9eaca966a4 | ||
![]() |
8bdf0dd135 | ||
![]() |
eedc8049db | ||
![]() |
23f272cc7d | ||
![]() |
15450b18e8 | ||
![]() |
50aeaf7498 | ||
![]() |
861bfa06a8 | ||
![]() |
3b30ee3130 | ||
![]() |
f6830885d7 | ||
![]() |
ff56511638 | ||
![]() |
337dd97b49 | ||
![]() |
146e89edd0 | ||
![]() |
cd82748889 | ||
![]() |
2c0b10b0ee | ||
![]() |
6c09361ec6 | ||
![]() |
3089a86c8e | ||
![]() |
ec2f05d4f7 | ||
![]() |
31a8129cb9 | ||
![]() |
8cc6c2c864 | ||
![]() |
a4de927df8 | ||
![]() |
a2c77a0944 | ||
![]() |
d8a564c6a0 | ||
![]() |
ff94b64c91 | ||
![]() |
1cc616b86c | ||
![]() |
6addf9002c | ||
![]() |
6dd219b6c7 | ||
![]() |
6198313c49 | ||
![]() |
90a22fe32f | ||
![]() |
3918473e29 | ||
![]() |
931cea75b6 | ||
![]() |
68a2aa3efd | ||
![]() |
dbeb1856ac | ||
![]() |
07bbadbbdc | ||
![]() |
78558eb666 | ||
![]() |
bc15dde742 | ||
![]() |
9135d2757e | ||
![]() |
a1c96d9bcb | ||
![]() |
94f25d9cdd | ||
![]() |
e1b4a0438e | ||
![]() |
93ea327660 | ||
![]() |
9ce6f99cad | ||
![]() |
d647df7f63 | ||
![]() |
654c93b0ce | ||
![]() |
8d36911f90 | ||
![]() |
84835be483 | ||
![]() |
35f90e94c9 | ||
![]() |
5268a55996 | ||
![]() |
53ad4b18e5 | ||
![]() |
54b6b79559 | ||
![]() |
b4cfa412b0 | ||
![]() |
dfdfc8fab4 | ||
![]() |
b14d3cdc32 | ||
![]() |
82a17ea427 | ||
![]() |
a57df6f2ca | ||
![]() |
41c353e24d | ||
![]() |
bca9c54923 | ||
![]() |
ce5faa8ff5 | ||
![]() |
0ef7a3db0f | ||
![]() |
c264b01658 | ||
![]() |
e07ed1b312 | ||
![]() |
c0bd1b82ab | ||
![]() |
d7fe783c46 | ||
![]() |
1b6ac7888b | ||
![]() |
86f4e206f4 | ||
![]() |
e689dcdd73 | ||
![]() |
810d065d21 | ||
![]() |
8adf2701d2 | ||
![]() |
11f41a6e8d | ||
![]() |
8d1569567f | ||
![]() |
23545bcbbb | ||
![]() |
aea6950b46 | ||
![]() |
d7d3f00488 | ||
![]() |
307bc2a38e | ||
![]() |
919af7b967 | ||
![]() |
359f0b21b0 | ||
![]() |
79f71acd42 | ||
![]() |
89480d9029 | ||
![]() |
0853b2fe42 | ||
![]() |
13fe20d47e | ||
![]() |
361ab296c7 | ||
![]() |
e76c1d8956 | ||
![]() |
0709ec5d82 | ||
![]() |
f7a0213af9 | ||
![]() |
9b27fffb0e | ||
![]() |
c0cbbe6072 | ||
![]() |
13fc093602 | ||
![]() |
ca29fdc795 | ||
![]() |
03a2501b45 | ||
![]() |
69ba41bd8d | ||
![]() |
5f2bbea6de | ||
![]() |
49dc995f1e | ||
![]() |
15ef1a082d | ||
![]() |
cdfab72b35 | ||
![]() |
37142d7495 | ||
![]() |
b6d04f5d5b | ||
![]() |
5e268f0611 | ||
![]() |
2afa664864 | ||
![]() |
64f4bb6a90 | ||
![]() |
00cc846729 | ||
![]() |
4f5d77391f | ||
![]() |
ac99cdce8b | ||
![]() |
3324f3fa15 | ||
![]() |
56a1e436f3 | ||
![]() |
ad6c5275ec | ||
![]() |
0e08c56bc7 | ||
![]() |
3e13bb4cd7 | ||
![]() |
d3ecb02644 | ||
![]() |
f3bc232419 | ||
![]() |
00b1fd2ee3 | ||
![]() |
44e819bf6a | ||
![]() |
49e32ebf2b | ||
![]() |
66447d13c1 | ||
![]() |
5bb2d71231 | ||
![]() |
32e489e536 | ||
![]() |
fc10a9026c | ||
![]() |
9699bac704 | ||
![]() |
d328a8cefc | ||
![]() |
34edf950ff | ||
![]() |
7d8fa48d47 | ||
![]() |
96e04738c0 | ||
![]() |
e4c36bbd7a | ||
![]() |
0ee1dab2bc | ||
![]() |
47e3792105 | ||
![]() |
0040aca841 | ||
![]() |
41a822c34c | ||
![]() |
55c217da73 | ||
![]() |
ff85376306 | ||
![]() |
ef15b9c0d3 | ||
![]() |
abefddb90e | ||
![]() |
3fcee7c4bd | ||
![]() |
d18750cb97 | ||
![]() |
6c53d1fdb7 | ||
![]() |
e9355bf918 |
24
.github/ISSUE_TEMPLATE/01_bug-report.md
vendored
24
.github/ISSUE_TEMPLATE/01_bug-report.md
vendored
@@ -39,8 +39,22 @@ Please include errors from the developer console and/or server log files if you
|
||||
<!-- Tell us where on the platform it happens -->
|
||||
<!-- DO NOT WRITE "latest". Please provide the specific version. -->
|
||||
|
||||
Misskey version:
|
||||
PostgreSQL version:
|
||||
Redis version:
|
||||
Your OS:
|
||||
Your browser:
|
||||
### 💻 Frontend
|
||||
* Model and OS of the device(s):
|
||||
<!-- Example: MacBook Pro (14inch, 2021), macOS Ventura 13.4 -->
|
||||
* Browser:
|
||||
<!-- Example: Chrome 113.0.5672.126 -->
|
||||
* Server URL:
|
||||
<!-- Example: misskey.io -->
|
||||
* Misskey:
|
||||
13.x.x
|
||||
|
||||
### 🛰 Backend (for server admin)
|
||||
<!-- If you are using a managed service, put that after the version. -->
|
||||
|
||||
* Installation Method or Hosting Service: <!-- Example: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment -->
|
||||
* Misskey: 13.x.x
|
||||
* Node: 18.x.x
|
||||
* PostgreSQL: 15.x.x
|
||||
* Redis: 7.x.x
|
||||
* OS and Architecture: <!-- Example: Ubuntu 22.04.2 LTS aarch64 -->
|
||||
|
40
CHANGELOG.md
40
CHANGELOG.md
@@ -12,6 +12,37 @@
|
||||
|
||||
-->
|
||||
|
||||
## 13.x.x (unreleased)
|
||||
|
||||
### General
|
||||
- identicon生成を無効にしてパフォーマンスを向上させることができるようになりました
|
||||
- サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました
|
||||
|
||||
### Client
|
||||
- Fix: サーバーメトリクスが90度傾いている
|
||||
- Fix: sparkle内にリンクを入れるとクリック不能になる問題の修正
|
||||
|
||||
## 13.13.2
|
||||
|
||||
### General
|
||||
- エラー時や項目が存在しないときなどのアイコン画像をサーバー管理者が設定できるように
|
||||
- ロールが付与されているユーザーリストを非公開にできるように
|
||||
- サーバーの負荷が非常に高いため、ユーザー統計表示機能を削除しました
|
||||
|
||||
### Client
|
||||
- Fix: タブがバックグラウンドでもstreamが切断されないように
|
||||
|
||||
### Server
|
||||
- Fix: キャッシュが溜まり続けないように
|
||||
|
||||
## 13.13.1
|
||||
|
||||
### Client
|
||||
- Fix: タブがアクティブな間はstreamが切断されないように
|
||||
|
||||
### Server
|
||||
- Fix: api/metaで`TypeError: JSON5.parse is not a function`エラーが発生する問題を修正
|
||||
|
||||
## 13.13.0
|
||||
|
||||
### General
|
||||
@@ -38,11 +69,17 @@
|
||||
- Fix: ロールタイムラインが無効でも投稿が流れてしまう問題の修正
|
||||
- Fix: ロールタイムラインにて全ての投稿が流れてしまう問題の修正
|
||||
- Fix: 「アクセストークンの管理」画面でアプリの情報が表示されない問題の修正
|
||||
- Fix: Firefoxにおける絵文字ピッカーのTabキーフォーカス問題の修正
|
||||
- Fix: フォローボタンがテーマのカラースキームによって視認性が悪くなる問題を修正
|
||||
- 新しいプロパティ `fgOnWhite` が追加されました
|
||||
|
||||
### Server
|
||||
- bullをbull-mqにアップグレードし、ジョブキューのパフォーマンスを改善
|
||||
- ストリーミングのパフォーマンスを改善
|
||||
- Fix: 無効化されたアンテナにアクセスがあった際に再度有効化するように
|
||||
- Fix: お知らせの画像URLを空にできない問題を修正
|
||||
- Fix: i/notificationsのsinceIdが機能しない問題を修正
|
||||
- Fix: pageのピン留めを解除することができない問題を修正
|
||||
|
||||
## 13.12.2
|
||||
|
||||
@@ -82,11 +119,12 @@ Meilisearchの設定に`index`が必要になりました。値はMisskeyサー
|
||||
## 13.12.0
|
||||
|
||||
### NOTE
|
||||
- Node.js 18.6.0以上が必要になりました
|
||||
- Node.js 18.16.0以上が必要になりました
|
||||
|
||||
### General
|
||||
- アカウントの引っ越し(フォロワー引き継ぎ)に対応
|
||||
- Meilisearchを全文検索に使用できるようになりました
|
||||
* 「フォロワーのみ」の投稿は検索結果に表示されません。
|
||||
- 新規登録前に簡潔なルールをユーザーに表示できる、サーバールール機能を追加
|
||||
- ユーザーへの自分用メモ機能
|
||||
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
|
||||
|
@@ -169,25 +169,20 @@ describe('After user signed in', () => {
|
||||
cy.get('[data-cy-user-setup-user-description] textarea').type('ほげ');
|
||||
// TODO: アイコン設定テスト
|
||||
|
||||
cy.get('[data-cy-user-setup-back]').click();
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
// プライバシー設定
|
||||
|
||||
cy.get('[data-cy-user-setup-back]').click();
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
// フォローはスキップ
|
||||
|
||||
cy.get('[data-cy-user-setup-back]').click();
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
// プッシュ通知設定はスキップ
|
||||
|
||||
cy.get('[data-cy-user-setup-back]').click();
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
cy.get('[data-cy-user-setup-back]').click();
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
});
|
||||
});
|
||||
|
@@ -21,6 +21,8 @@ import './commands'
|
||||
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
if ([
|
||||
'The source image cannot be decoded',
|
||||
|
||||
// Chrome
|
||||
'ResizeObserver loop limit exceeded',
|
||||
|
||||
|
@@ -267,8 +267,8 @@ start: "البداية"
|
||||
home: "الرئيسي"
|
||||
remoteUserCaution: "هذه المعلومات قد لا تكون مكتملة بما أن المستخدم من مثيل بعيد."
|
||||
activity: "النشاط"
|
||||
images: "الصور"
|
||||
image: "الصور"
|
||||
images: "صور"
|
||||
image: "صور"
|
||||
birthday: "تاريخ الميلاد"
|
||||
yearsOld: "{age} سنة"
|
||||
registeredDate: "انضم في"
|
||||
@@ -1331,7 +1331,7 @@ _pages:
|
||||
text: "نص"
|
||||
textarea: "حقل نصي"
|
||||
section: "قسم"
|
||||
image: "الصور"
|
||||
image: "صور"
|
||||
button: "زرّ"
|
||||
note: "ملاحظة مضمّنة"
|
||||
_note:
|
||||
|
@@ -991,7 +991,7 @@ postToTheChannel: "In Kanal senden"
|
||||
cannotBeChangedLater: "Kann später nicht mehr geändert werden."
|
||||
reactionAcceptance: "Reaktionsannahme"
|
||||
likeOnly: "Nur \"Gefällt mir\""
|
||||
likeOnlyForRemote: "Nur \"Gefällt mir\" für fremde Instanzen"
|
||||
likeOnlyForRemote: "Alle (Nur \"Gefällt mir\" für fremde Instanzen)"
|
||||
nonSensitiveOnly: "Keine Sensitiven"
|
||||
nonSensitiveOnlyForLocalLikeOnlyForRemote: "Keine Sensitiven (Nur \"Gefällt mir\" von fremden Instanzen)"
|
||||
rolesAssignedToMe: "Mir zugewiesene Rollen"
|
||||
@@ -1060,6 +1060,9 @@ cancelReactionConfirm: "Möchtest du deine Reaktion wirklich löschen?"
|
||||
changeReactionConfirm: "Möchtest du deine Reaktion wirklich ändern?"
|
||||
later: "Später"
|
||||
goToMisskey: "Zu Misskey"
|
||||
additionalEmojiDictionary: "Zusätzliche Emoji-Wörterbücher"
|
||||
installed: "Installiert"
|
||||
branding: "Branding"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "Dein Konto wurde erfolgreich erstellt!"
|
||||
letsStartAccountSetup: "Lass uns nun dein Konto einrichten."
|
||||
@@ -1091,7 +1094,7 @@ _accountMigration:
|
||||
migrationConfirm: "Dieses Konto wirklich zu {account} umziehen? Sobald der Umzug beginnt, kann er nicht rückgängig gemacht werden, und dieses Konto nicht wieder im ursprünglichen Zustand verwendet werden."
|
||||
movedAndCannotBeUndone: "\nDieses Konto wurde migriert.\nDiese Aktion ist unwiderruflich."
|
||||
postMigrationNote: "Dieses Konto wird 24 Stunden nach Abschluss der Migration allen Konten, denen es derzeit folgt, nicht mehr folgen.\n\nSowohl die Anzahl der Follower als auch die der Konten, denen dieses Konto folgt, wird dann auf Null gesetzt. Um zu vermeiden, dass Follower dieses Kontos dessen Beiträge, welche nur für Follower bestimmt sind, nicht mehr sehen können, werden sie diesem Konto jedoch weiterhin folgen."
|
||||
movedTo: "Umzugsziel:"
|
||||
movedTo: "Neues Konto:"
|
||||
_achievements:
|
||||
earnedAt: "Freigeschaltet am"
|
||||
_types:
|
||||
@@ -1345,7 +1348,7 @@ _role:
|
||||
condition: "Bedingung"
|
||||
isConditionalRole: "Dies ist eine konditionale Rolle."
|
||||
isPublic: "Öffentliche Rolle"
|
||||
descriptionOfIsPublic: "Ist dies aktiviert, so kann jeder die Liste der Benutzer, die dieser Rolle zugewiesen sind, einsehen. Zusätzlich wird diese Rolle im Profil zugewiesener Benutzer angezeigt."
|
||||
descriptionOfIsPublic: "Diese Rolle wird im Profil zugewiesener Benutzer angezeigt."
|
||||
options: "Optionen"
|
||||
policies: "Richtlinien"
|
||||
baseRole: "Rollenvorlage"
|
||||
@@ -1354,8 +1357,8 @@ _role:
|
||||
iconUrl: "Icon-URL"
|
||||
asBadge: "Als Abzeichen anzeigen"
|
||||
descriptionOfAsBadge: "Ist dies aktiviert, so wird das Icon dieser Rolle an der Seite der Namen von Benutzern mit dieser Rolle angezeigt."
|
||||
isExplorable: "Rollenchronik veröffentlichen"
|
||||
descriptionOfIsExplorable: "Ist dies aktiviert, so ist die Rollenchronik dieser Rolle frei zugänglich. Die Chronik von Rollen, welche nicht öffentlich sind, wird auch bei Aktivierung nicht veröffentlicht."
|
||||
isExplorable: "Benutzerliste veröffentlichen"
|
||||
descriptionOfIsExplorable: "Ist dies aktiviert, so ist die Chronik dieser Rolle, sowie eine Liste der Benutzer mit dieser Rolle, frei zugänglich."
|
||||
displayOrder: "Position"
|
||||
descriptionOfDisplayOrder: "Je höher die Nummer, desto höher die UI-Position."
|
||||
canEditMembersByModerator: "Moderatoren können Benutzern diese Rolle zuweisen"
|
||||
|
@@ -991,7 +991,7 @@ postToTheChannel: "Post to channel"
|
||||
cannotBeChangedLater: "This cannot be changed later."
|
||||
reactionAcceptance: "Reaction Acceptance"
|
||||
likeOnly: "Only likes"
|
||||
likeOnlyForRemote: "Only likes for remote instances"
|
||||
likeOnlyForRemote: "All (Only likes for remote instances)"
|
||||
nonSensitiveOnly: "Non-sensitive only"
|
||||
nonSensitiveOnlyForLocalLikeOnlyForRemote: "Non-sensitive only (Only likes from remote)"
|
||||
rolesAssignedToMe: "Roles assigned to me"
|
||||
@@ -1060,6 +1060,9 @@ cancelReactionConfirm: "Really delete your reaction?"
|
||||
changeReactionConfirm: "Really change your reaction?"
|
||||
later: "Later"
|
||||
goToMisskey: "To Misskey"
|
||||
additionalEmojiDictionary: "Additional emoji dictionaries"
|
||||
installed: "Installed"
|
||||
branding: "Branding"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "Your account was successfully created!"
|
||||
letsStartAccountSetup: "For starters, let's set up your profile."
|
||||
@@ -1091,7 +1094,7 @@ _accountMigration:
|
||||
migrationConfirm: "Really migrate this account to {account}? Once started, this process cannot be stopped or taken back, and you will not be able to use this account in its original state anymore."
|
||||
movedAndCannotBeUndone: "\nThis account has been migrated.\nMigration cannot be reversed."
|
||||
postMigrationNote: "This account will unfollow all accounts it is currently following 24 hours after migration finishes.\nBoth the number of follows and followers will then become zero. To avoid your followers from being unable to see followers only posts of this account, they will however continue following this account."
|
||||
movedTo: "Account to move to:"
|
||||
movedTo: "New account:"
|
||||
_achievements:
|
||||
earnedAt: "Unlocked at"
|
||||
_types:
|
||||
@@ -1345,7 +1348,7 @@ _role:
|
||||
condition: "Condition"
|
||||
isConditionalRole: "This is a conditional role."
|
||||
isPublic: "Public role"
|
||||
descriptionOfIsPublic: "Anyone will be able to view a list of users assigned to this role. In addition, this role will be displayed in the profiles of assigned users."
|
||||
descriptionOfIsPublic: "This role will be displayed in the profiles of assigned users."
|
||||
options: "Options"
|
||||
policies: "Policies"
|
||||
baseRole: "Role template"
|
||||
@@ -1354,8 +1357,8 @@ _role:
|
||||
iconUrl: "Icon URL"
|
||||
asBadge: "Show as badge"
|
||||
descriptionOfAsBadge: "This role's icon will be displayed next to the username of users with this role if turned on."
|
||||
isExplorable: "Role timeline is public"
|
||||
descriptionOfIsExplorable: "This role's timeline will become publicly accessible if enabled. Timelines of non-public roles will not be made public even if set."
|
||||
isExplorable: "Make role explorable"
|
||||
descriptionOfIsExplorable: "This role's timeline and the list of users with this will be made public if enabled."
|
||||
displayOrder: "Position"
|
||||
descriptionOfDisplayOrder: "The higher the number, the higher its UI position."
|
||||
canEditMembersByModerator: "Allow moderators to edit the list of members for this role"
|
||||
|
5
locales/index.d.ts
vendored
5
locales/index.d.ts
vendored
@@ -1063,6 +1063,11 @@ export interface Locale {
|
||||
"changeReactionConfirm": string;
|
||||
"later": string;
|
||||
"goToMisskey": string;
|
||||
"additionalEmojiDictionary": string;
|
||||
"installed": string;
|
||||
"branding": string;
|
||||
"enableServerMachineStats": string;
|
||||
"enableIdenticonGeneration": string;
|
||||
"_initialAccountSetting": {
|
||||
"accountCreated": string;
|
||||
"letsStartAccountSetup": string;
|
||||
|
@@ -1060,6 +1060,11 @@ cancelReactionConfirm: "リアクションを取り消しますか?"
|
||||
changeReactionConfirm: "リアクションを変更しますか?"
|
||||
later: "あとで"
|
||||
goToMisskey: "Misskeyへ"
|
||||
additionalEmojiDictionary: "絵文字の追加辞書"
|
||||
installed: "インストール済み"
|
||||
branding: "ブランディング"
|
||||
enableServerMachineStats: "サーバーのマシン情報を公開する"
|
||||
enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にする"
|
||||
|
||||
_initialAccountSetting:
|
||||
accountCreated: "アカウントの作成が完了しました!"
|
||||
@@ -1349,8 +1354,8 @@ _role:
|
||||
conditional: "コンディショナル"
|
||||
condition: "条件"
|
||||
isConditionalRole: "これはコンディショナルロールです。"
|
||||
isPublic: "ロールを公開"
|
||||
descriptionOfIsPublic: "ロールにアサインされたユーザーを誰でも見ることができます。また、ユーザーのプロフィールでこのロールが表示されます。"
|
||||
isPublic: "公開ロール"
|
||||
descriptionOfIsPublic: "ユーザーのプロフィールでこのロールが表示されます。"
|
||||
options: "オプション"
|
||||
policies: "ポリシー"
|
||||
baseRole: "ベースロール"
|
||||
@@ -1359,8 +1364,8 @@ _role:
|
||||
iconUrl: "アイコン画像のURL"
|
||||
asBadge: "バッジとして表示"
|
||||
descriptionOfAsBadge: "オンにすると、ユーザー名の横にロールのアイコンが表示されます。"
|
||||
isExplorable: "ロールタイムラインを公開"
|
||||
descriptionOfIsExplorable: "オンにすると、ロールのタイムラインを公開します。ロールの公開がオフの場合、タイムラインの公開はされません。"
|
||||
isExplorable: "ユーザーを見つけやすくする"
|
||||
descriptionOfIsExplorable: "オンにすると、「みつける」でメンバー一覧が公開されるほか、ロールのタイムラインが利用可能になります。"
|
||||
displayOrder: "表示順"
|
||||
descriptionOfDisplayOrder: "数値が大きいほどUI上で先頭に表示されます。"
|
||||
canEditMembersByModerator: "モデレーターのメンバー編集を許可"
|
||||
|
@@ -792,6 +792,7 @@ noMaintainerInformationWarning: "管理者情報が設定されてへんで"
|
||||
noBotProtectionWarning: "Botプロテクションが設定されてへんで。"
|
||||
configure: "設定する"
|
||||
postToGallery: "ギャラリーへ投稿"
|
||||
postToHashtag: "このハッシュタグで投稿"
|
||||
gallery: "ギャラリー"
|
||||
recentPosts: "最近の投稿"
|
||||
popularPosts: "人気の投稿"
|
||||
@@ -825,6 +826,7 @@ translatedFrom: "{x}から翻訳するで"
|
||||
accountDeletionInProgress: "アカウント削除しとるで待っとってなー"
|
||||
usernameInfo: "サーバー上であんたのアカウントをあんたやと分かるようにするための名前やで。アルファベット(a~z, A~Z)、数字(0~9)、それとアンダーバー(_)が使って考えてな。この名前は後から変更することはできへんからちゃんと考えるんやで。"
|
||||
aiChanMode: "藍モードやで"
|
||||
devMode: "開発者モード"
|
||||
keepCw: "CWを維持するで"
|
||||
pubSub: "Pub/Subのアカウント"
|
||||
lastCommunication: "直近の通信"
|
||||
@@ -834,6 +836,8 @@ breakFollow: "フォロワーを解除するで"
|
||||
breakFollowConfirm: "フォロワー解除してもええか?"
|
||||
itsOn: "オンになっとるよ"
|
||||
itsOff: "オフになってるで"
|
||||
on: "オン"
|
||||
off: "オフ"
|
||||
emailRequiredForSignup: "アカウント登録にメールアドレスを必須にするで"
|
||||
unread: "未読"
|
||||
filter: "フィルタ"
|
||||
@@ -988,6 +992,8 @@ cannotBeChangedLater: "後からは変えられへんで。"
|
||||
reactionAcceptance: "ツッコミの受け入れ"
|
||||
likeOnly: "いいねだけ"
|
||||
likeOnlyForRemote: "リモートからはいいねだけな"
|
||||
nonSensitiveOnly: "センシティブじゃないやつだけ"
|
||||
nonSensitiveOnlyForLocalLikeOnlyForRemote: "センシティブじゃないやつだけ (リモートはいいねだけ)"
|
||||
rolesAssignedToMe: "自分に割り当てられたロール"
|
||||
resetPasswordConfirm: "パスワード作り直すんでええな?"
|
||||
sensitiveWords: "けったいな単語"
|
||||
@@ -1045,10 +1051,17 @@ preventAiLearning: "生成AIの学習に使わんといて"
|
||||
preventAiLearningDescription: "他の文章生成AIとか画像生成AIに、投稿したノートとか画像なんかを勝手に使わんように頼むで。具体的にはnoaiフラグをHTMLレスポンスに含めるんやけど、これ聞いてくれるんはAIの気分次第やから、使われる可能性もちょっとはあるな。"
|
||||
options: "オプション"
|
||||
specifyUser: "ユーザー指定"
|
||||
failedToPreviewUrl: "プレビューできへん"
|
||||
update: "更新"
|
||||
rolesThatCanBeUsedThisEmojiAsReaction: "ツッコミとして使えるロール"
|
||||
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ロールが一個も指定されてへんかったら、誰でもツッコミとして使えるで。"
|
||||
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "ロールは公開ロールじゃないとアカンで。"
|
||||
cancelReactionConfirm: "ツッコむんをやっぱやめるか?"
|
||||
changeReactionConfirm: "ツッコミを別のに変えるか?"
|
||||
later: "あとで"
|
||||
goToMisskey: "Misskeyへ"
|
||||
additionalEmojiDictionary: "絵文字の追加辞書"
|
||||
installed: "インストール済み"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "アカウント作り終わったで。"
|
||||
letsStartAccountSetup: "アカウントの初期設定をしよか。"
|
||||
@@ -1063,6 +1076,7 @@ _initialAccountSetting:
|
||||
haveFun: "{name}、楽しんでな~"
|
||||
ifYouNeedLearnMore: "{name}(Misskey)の使い方とかをよー知りたいんやったら{link}をみてな。"
|
||||
skipAreYouSure: "初期設定飛ばすか?"
|
||||
laterAreYouSure: "初期設定あとでやり直すん?"
|
||||
_serverRules:
|
||||
description: "新規登録前に見せる、サーバーの簡潔なルールを設定すんで。内容は使うための決め事の要約とすることを推奨するわ。"
|
||||
_accountMigration:
|
||||
|
@@ -870,7 +870,7 @@ instanceDefaultLightTheme: "서버 기본 라이트 테마"
|
||||
instanceDefaultDarkTheme: "서버 기본 다크 테마"
|
||||
instanceDefaultThemeDescription: "객체 형식의 테마 코드를 입력해 주세요."
|
||||
mutePeriod: "뮤트할 기간"
|
||||
period: "투표 기한"
|
||||
period: "기간"
|
||||
indefinitely: "무기한"
|
||||
tenMinutes: "10분"
|
||||
oneHour: "1시간"
|
||||
@@ -1060,12 +1060,14 @@ cancelReactionConfirm: "리액션을 취소하시겠습니까?"
|
||||
changeReactionConfirm: "리액션을 변경하시겠습니까?"
|
||||
later: "나중에"
|
||||
goToMisskey: "Misskey로"
|
||||
additionalEmojiDictionary: "이모지 추가 사전"
|
||||
installed: "설치됨"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "계정 생성이 완료되었습니다!"
|
||||
letsStartAccountSetup: "계정의 초기 설정을 진행합니다."
|
||||
letsFillYourProfile: "우선 나의 프로필을 설정해 보아요."
|
||||
profileSetting: "프로필 설정"
|
||||
privacySetting: "\n프라이버시 설정"
|
||||
privacySetting: "프라이버시 설정"
|
||||
theseSettingsCanEditLater: "이 설정들은 나중에도 변경할 수 있습니다."
|
||||
youCanEditMoreSettingsInSettingsPageLater: "이 외에도 '설정' 페이지에서 다양한 설정을 나의 입맛에 맞게 조절할 수 있습니다. 꼭 확인해 보세요!"
|
||||
followUsers: "관심사가 맞는 유저를 팔로우하여 타임라인을 가꾸어 봅시다."
|
||||
@@ -1073,19 +1075,19 @@ _initialAccountSetting:
|
||||
initialAccountSettingCompleted: "초기 설정을 모두 마쳤습니다!"
|
||||
haveFun: "{name}와 함께 즐거운 시간 보내세요!"
|
||||
ifYouNeedLearnMore: "{name}(Misskey)의 사용 방법에 대해 자세히 알아보려면 {link}를 참고해 주세요."
|
||||
skipAreYouSure: "초기 설정을 넘기시겠습니까?"
|
||||
laterAreYouSure: "초기 설정을 나중에 다시 진행하시겠습니까?"
|
||||
skipAreYouSure: "초기 설정을 중단하시겠습니까?"
|
||||
laterAreYouSure: "초기 설정을 나중에 진행하시겠습니까?"
|
||||
_serverRules:
|
||||
description: "회원 가입 이전에 간단하게 표시할 서버 규칙입니다. 이용 약관의 요약으로 구성하는 것을 추천합니다."
|
||||
_accountMigration:
|
||||
moveFrom: "다른 계정에서 이 계정으로 이사"
|
||||
moveFromSub: "다른 계정에 대한 별칭을 생성"
|
||||
moveFromLabel: "기존 계정:"
|
||||
moveFromLabel: "기존 계정 #{n}"
|
||||
moveFromDescription: "다른 계정에서 이 계정으로 팔로워를 가져오려면, 우선 여기에서 별칭을 지정해야 합니다. 반드시 이사하기 전에 지정해야 합니다! 기존 계정을 다음과 같은 형식으로 입력해 주십시오: @person@instance.com"
|
||||
moveTo: "이 계정에서 다른 계정으로 이사"
|
||||
moveToLabel: "이사할 계정:"
|
||||
moveCannotBeUndone: "한 번 이사하면, 두 번 다시 되돌릴 수 없습니다."
|
||||
moveAccountDescription: "이 작업은 취소할 수 없습니다. 먼저 이사할 계정에서 이 계정에 대한 별칭을 지정하였는지 다시 한 번 확인해 주십시오. 별칭을 지정한 다음, 이사할 계정을 다음과 같은 형식으로 입력해 주십시오: @person@instance.com"
|
||||
moveAccountDescription: "새 계정으로 이전합니다.\n ・팔로워가 새 계정을 자동으로 팔로우 합니다\n ・이 계정에서 팔로우는 모두 해제됩니다\n ・이 계정으로는 노트 작성 등을 할 수 없게 됩니다\n\n팔로워는 자동으로 이전되지만, 팔로우는 수동으로 진행해야 합니다. 이전하기 전에 이 계정에서 팔로우를 내보내고, 이전 후에는 즉시 이전한 계정에서 가져오기를 진행하십시오.\n리스트・뮤트・차단에 대해서도 마찬가지이므로 수동으로 이전해야 합니다.\n\n(이 설명은 이 서버(Misskey v13.12.0 이후)의 사양입니다. Mastodon 등의 다른 ActivityPub 소프트웨어에서는 작동이 다를 수 있습니다.)"
|
||||
moveAccountHowTo: "계정을 이사하려면 우선 이사갈 계정에서 이 계정에 대한 별칭을 지정해야 합니다.\n별칭을 작성한 다음, 이사갈 계정을 다음과 같이 입력하십시오:\n@username@server.example.com"
|
||||
startMigration: "이사하기"
|
||||
migrationConfirm: "정말로 이 계정을 {account} 으로 이전하시겠습니까? 한 번 이전한 다음에는 취소할 수 없으며, 두 번 다시 원래 상태로 복구할 수 없습니다.\n이사할 계정에서 계정 별칭을 지정하였는지 다시 한 번 확인하십시오."
|
||||
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
_lang_: "Norsk Bokmål"
|
||||
headlineMisskey: "Et nettverk forbundet med notes"
|
||||
introMisskey: "Velkommen! Misskey er en desentralisert mikrobloggtjeneste med åpen kildekode.\nOpprett \"notes\" for å dele tankene dine med alle rundt deg. 📡\nMed \"reaksjoner\" kan du også raskt gi uttrykk for hva du synes om alles notes. 👍\nLa oss utforske en ny verden! 🚀"
|
||||
headlineMisskey: "Et nettverk forbundet med Notes"
|
||||
introMisskey: "Velkommen! Misskey er en desentralisert mikrobloggtjeneste med åpen kildekode.\nOpprett \"Notes\" for å dele tankene dine med alle rundt deg. 📡\nMed \"reaksjoner\" kan du også raskt gi uttrykk for hva du synes om alles Notes. 👍\nLa oss utforske en ny verden! 🚀"
|
||||
monthAndDay: "{day}-{month}"
|
||||
search: "Søk"
|
||||
notifications: "Varsler"
|
||||
@@ -15,7 +15,7 @@ cancel: "Avbryt"
|
||||
noThankYou: "Ikke nå"
|
||||
enterUsername: "Skriv inn brukernavn"
|
||||
renotedBy: "Renotes av {user}"
|
||||
noNotes: "Ingen notes"
|
||||
noNotes: "Ingen Notes"
|
||||
noNotifications: "Ingen varsler"
|
||||
instance: "Server"
|
||||
settings: "Innstillinger"
|
||||
@@ -25,7 +25,7 @@ otherSettings: "Andre innstillinger"
|
||||
openInWindow: "Åpne i vindu"
|
||||
profile: "Profil"
|
||||
timeline: "Tidslinje"
|
||||
noAccountDescription: "Denne brukeren har ikke skrevet sin bio ennå."
|
||||
noAccountDescription: "Denne brukeren har ikke skrevet sin biografi ennå."
|
||||
login: "Logg inn"
|
||||
loggingIn: "Logget inn"
|
||||
logout: "Logg ut"
|
||||
@@ -46,7 +46,7 @@ copyContent: "Kopier innhold"
|
||||
copyLink: "Kopier lenke"
|
||||
delete: "Slett"
|
||||
deleteAndEdit: "Slett og rediger"
|
||||
deleteAndEditConfirm: "Er du sikker på at du vil slette denne noten og redigere den? Du vil miste alle reaksjoner, renotes og svar på den."
|
||||
deleteAndEditConfirm: "Er du sikker på at du vil slette denne Noten og redigere den? Du vil miste alle reaksjoner, Renotes og svar på den."
|
||||
addToList: "Legg til i liste"
|
||||
sendMessage: "Send en melding"
|
||||
copyRSS: "Kopier RSS"
|
||||
@@ -81,6 +81,7 @@ pageLoadError: "Kunne ikke hente side."
|
||||
serverIsDead: "Denne serveren svarer ikke. Vennligst vent en stund og prøv igjen."
|
||||
enterListName: "Skriv inn et navn på listen"
|
||||
privacy: "Personvern"
|
||||
defaultNoteVisibility: "Standard synlighet"
|
||||
follow: "Følg"
|
||||
followRequest: "Følgeforespørsel"
|
||||
followRequests: "Følgeforespørsel"
|
||||
@@ -90,9 +91,11 @@ enterEmoji: "Skriv inn en emoji"
|
||||
renote: "Renote"
|
||||
renoted: "Renotet."
|
||||
cantRenote: "Dette innlegget kan ikke renotes."
|
||||
cantReRenote: "En renote kan ikke renotes."
|
||||
cantReRenote: "En Renote kan ikke renotes."
|
||||
quote: "Sitat"
|
||||
pinnedNote: "Festet note"
|
||||
inChannelRenote: "Renote kun for kanal"
|
||||
inChannelQuote: "Sitat kun for kanal"
|
||||
pinnedNote: "Festet Note"
|
||||
pinned: "Fest til profil"
|
||||
you: "Du"
|
||||
clickToShow: "Klikk for å vise"
|
||||
@@ -101,13 +104,13 @@ reaction: "Reaksjon"
|
||||
reactions: "Reaksjoner"
|
||||
reactionSetting: "Reaksjoner som vises i reaksjonsvelgeren"
|
||||
reactionSettingDescription2: "Dra for å endre rekkefølgen, klikk for å slette, trykk \"+\" for å legge til."
|
||||
rememberNoteVisibility: "Husk innstillingene for synlighet av notes"
|
||||
rememberNoteVisibility: "Husk innstillingene for synlighet av Notes"
|
||||
attachCancel: "Fjern vedlegg"
|
||||
enterFileName: "Skriv inn filnavn"
|
||||
mute: "Skjul"
|
||||
unmute: "Vis"
|
||||
renoteMute: "Skjul renotes"
|
||||
renoteUnmute: "Vis renotes"
|
||||
renoteMute: "Skjul Renotes"
|
||||
renoteUnmute: "Vis Renotes"
|
||||
block: "Blokker"
|
||||
unblock: "Opphev blokkering"
|
||||
suspend: "Suspender"
|
||||
@@ -145,14 +148,18 @@ instances: "Servere"
|
||||
registeredAt: "Registrerte seg"
|
||||
latestRequestReceivedAt: "Siste forespørsel mottatt"
|
||||
latestStatus: "Siste status"
|
||||
charts: "Diagrammer"
|
||||
perHour: "Per time"
|
||||
perDay: "Per dag"
|
||||
stopActivityDelivery: "Slutt å sende aktiviteter"
|
||||
blockThisInstance: "Blokker denne serveren"
|
||||
operations: "Operasjoner"
|
||||
software: "Programvare"
|
||||
version: "Versjon"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} fil(er)"
|
||||
network: "Nettverk"
|
||||
instanceInfo: "Serverinformasjon"
|
||||
statistics: "Statistikk"
|
||||
clearQueue: "Tøm kø"
|
||||
clearQueueConfirmTitle: "Er du sikker på at du vil tømme køen?"
|
||||
@@ -163,10 +170,12 @@ mutedUsers: "Skjulte brukere"
|
||||
blockedUsers: "Blokkerte brukere"
|
||||
noUsers: "Det er ingen brukere"
|
||||
editProfile: "Rediger profil"
|
||||
noteDeleteConfirm: "Er du sikker på at du vil slette denne noten?"
|
||||
noteDeleteConfirm: "Er du sikker på at du vil slette denne Noten?"
|
||||
pinLimitExceeded: "Du kan ikke feste flere."
|
||||
intro: "Installasjonen av Misskey er ferdig! Vennligst opprett en administratorkonto."
|
||||
done: "Ferdig"
|
||||
default: "Standard"
|
||||
defaultValueIs: "Standard: {value}"
|
||||
noCustomEmojis: "Det er ingen emoji"
|
||||
noJobs: "Det er ingen jobber"
|
||||
blocked: "Blokkert"
|
||||
@@ -175,10 +184,13 @@ all: "Alle"
|
||||
notResponding: "Svarer ikke"
|
||||
changePassword: "Endre passord"
|
||||
security: "Sikkerhet"
|
||||
retypedNotMatch: "Inngangene stemmer ikke overens."
|
||||
currentPassword: "Nåværende passord"
|
||||
newPassword: "Nytt passord"
|
||||
newPasswordRetype: "Nytt passord (gjenta)"
|
||||
attachFile: "Legg ved filer"
|
||||
more: "Mer!"
|
||||
noSuchUser: "Bruker ikke funnet"
|
||||
announcements: "Kunngjøringer"
|
||||
remove: "Slett"
|
||||
removed: "Vellykket slettet"
|
||||
@@ -188,18 +200,28 @@ saved: "Lagret"
|
||||
upload: "Laste opp"
|
||||
keepOriginalUploading: "Behold originalbildet"
|
||||
fromUrl: "Fra URL"
|
||||
uploadFromUrl: "Last opp fra en URL"
|
||||
uploadFromUrlDescription: "URL til filen du vil laste opp"
|
||||
explore: "Utforsk"
|
||||
messageRead: "Lest"
|
||||
agree: "Jeg godtar"
|
||||
nUsersRead: "lest av {n}"
|
||||
agreeTo: "Jeg godtar {0}"
|
||||
agree: "Godta"
|
||||
agreeBelow: "Jeg godtar følgende"
|
||||
basicNotesBeforeCreateAccount: "Viktige merknader"
|
||||
termsOfService: "Vilkår for bruk"
|
||||
home: "Hjem"
|
||||
activity: "Aktivitet"
|
||||
images: "Bilder"
|
||||
image: "Bilder"
|
||||
image: "Bilde"
|
||||
birthday: "Bursdag"
|
||||
yearsOld: "{age} år gammel"
|
||||
theme: "Temaer"
|
||||
light: "Lys"
|
||||
dark: "Mørk"
|
||||
lightThemes: "Lyse temaer"
|
||||
darkThemes: "Mørke temaer"
|
||||
syncDeviceDarkMode: "Synkroniser mørkmodus med enhetens innstillinger"
|
||||
fileName: "Filnavn"
|
||||
selectFile: "Velg en fil"
|
||||
selectFiles: "Velg filer"
|
||||
@@ -213,6 +235,9 @@ deleteFolder: "Slett denne mappen"
|
||||
addFile: "Legg til en fil"
|
||||
emptyFolder: "Denne mappen er tom"
|
||||
unableToDelete: "Kan ikke slette"
|
||||
inputNewFileName: "Skriv inn et nytt filnavn"
|
||||
inputNewDescription: "Skriv inn ny bildetekst"
|
||||
inputNewFolderName: "Skriv inn et nytt mappenavn"
|
||||
circularReferenceFolder: "Målmappen er en undermappe til mappen du ønsker å flytte."
|
||||
hasChildFilesOrFolders: "Siden denne mappen ikke er tom, kan den ikke slettes."
|
||||
copyUrl: "Kopier URL"
|
||||
@@ -226,7 +251,7 @@ instanceName: "Servernavn"
|
||||
instanceDescription: "Serverbeskrivelse"
|
||||
thisYear: "År"
|
||||
thisMonth: "Måned"
|
||||
today: "Dag"
|
||||
today: "I dag"
|
||||
dayX: "{day}"
|
||||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
@@ -242,21 +267,32 @@ basicInfo: "Grunnleggende informasjon"
|
||||
pinnedUsers: "Festede brukrere"
|
||||
pinnedUsersDescription: "Liste over brukernavn atskilt med linjeskift som skal festes i \"Utforsk\" fanen."
|
||||
pinnedPages: "Festede sider"
|
||||
pinnedNotes: "Festet note"
|
||||
pinnedNotes: "Festet Note"
|
||||
hcaptcha: "hCaptcha"
|
||||
enableHcaptcha: "Aktiver hCaptcha"
|
||||
recaptcha: "reCAPTCHA"
|
||||
enableRecaptcha: "Aktiver reCAPTCHA"
|
||||
turnstile: "Turnstile"
|
||||
enableTurnstile: "Aktiver Turnstile"
|
||||
antennas: "Antenner"
|
||||
name: "Navn"
|
||||
antennaSource: "Antennekilde"
|
||||
notifyAntenna: "Varsle om nye Notes"
|
||||
withFileAntenna: "Bare Notes med filer"
|
||||
notesAndReplies: "Notes og svar"
|
||||
popularUsers: "Populære brukere"
|
||||
exploreUsersCount: "Det finnes {count} brukere"
|
||||
exploreFediverse: "Utforsk Fediverse"
|
||||
userList: "Lister"
|
||||
about: "Infomasjon"
|
||||
about: "Informasjon"
|
||||
aboutMisskey: "Om Misskey"
|
||||
newPasswordIs: "Det nye passordet er \"{password}\"."
|
||||
share: "Del"
|
||||
notFound: "Ikke funnet"
|
||||
markAsReadAllNotifications: "Merk alle varsler som lest"
|
||||
markAsReadAllUnreadNotes: "Merk alle Notes som lest"
|
||||
help: "Hjelp"
|
||||
inputMessageHere: "Skriv inn melding her"
|
||||
close: "Lukk"
|
||||
invites: "Inviter"
|
||||
members: "Medlemmer"
|
||||
@@ -264,6 +300,10 @@ title: "Tittel"
|
||||
text: "Tekst"
|
||||
next: "Neste"
|
||||
retype: "Gjenta"
|
||||
quoteAttached: "Sitat"
|
||||
noMessagesYet: "Ingen meldinger ennå"
|
||||
newMessageExists: "Det er nye meldinger"
|
||||
onlyOneFileCanBeAttached: "Du kan bare legge ved én fil i en melding"
|
||||
invitations: "Inviter"
|
||||
available: "Tilgjengelig"
|
||||
unavailable: "Utilgjengelig"
|
||||
@@ -286,7 +326,7 @@ objectStorageRegion: "Region"
|
||||
objectStorageUseSSL: "Bruk SSL"
|
||||
objectStorageUseProxy: "Bruk Proxy"
|
||||
deleteAll: "Slett alt"
|
||||
newNoteRecived: "Det er nye notes"
|
||||
newNoteRecived: "Det er nye Notes"
|
||||
listen: "Lytt"
|
||||
none: "Ingen"
|
||||
volume: "Volum"
|
||||
@@ -339,6 +379,7 @@ developer: "Utvikler"
|
||||
makeExplorable: "Gjør konto synlig i \"Utforsk\""
|
||||
makeExplorableDescription: "Hvis du slår av dette, vises ikke kontoen din i \"Utforsk\" delen."
|
||||
left: "Venstre"
|
||||
nNotes: "{n} Notes"
|
||||
saveAs: "Lagre som"
|
||||
value: "Verdi"
|
||||
deleteConfirm: "Vil du slette?"
|
||||
@@ -424,6 +465,26 @@ _initialAccountSetting:
|
||||
theseSettingsCanEditLater: "Du kan endre disse innstillingene senere."
|
||||
_achievements:
|
||||
_types:
|
||||
_notes10:
|
||||
title: "Noen Notes"
|
||||
_notes100:
|
||||
title: "Mange Notes"
|
||||
_notes500:
|
||||
title: "Dekket i Notes"
|
||||
_notes1000:
|
||||
title: "Et fjell av Notes"
|
||||
_notes5000:
|
||||
title: "Overfylte Notes"
|
||||
_notes10000:
|
||||
title: "Super Notes"
|
||||
_notes20000:
|
||||
title: "Trenger... mer... Notes..."
|
||||
_notes30000:
|
||||
title: "Notes Notes Notes!"
|
||||
_notes40000:
|
||||
title: "Note fabrikk"
|
||||
_notes50000:
|
||||
title: "Planet av Notes"
|
||||
_notes100000:
|
||||
flavor: "Du har jammen mye å si."
|
||||
_noteFavorited1:
|
||||
@@ -542,6 +603,7 @@ _time:
|
||||
day: "Dager"
|
||||
_timelineTutorial:
|
||||
title: "Hvordan bruke Misskey"
|
||||
step2_2: "Hva med å skrive en selvpresentasjon, eller bare \"Hei {name}!\" hvis du ikke har lyst?"
|
||||
_2fa:
|
||||
renewTOTPCancel: "Avbryt"
|
||||
_weekday:
|
||||
@@ -554,6 +616,7 @@ _weekday:
|
||||
saturday: "Lørdag"
|
||||
_widgets:
|
||||
profile: "Profil"
|
||||
instanceInfo: "Serverinformasjon"
|
||||
notifications: "Varsler"
|
||||
timeline: "Tidslinje"
|
||||
calendar: "Kalender"
|
||||
@@ -589,6 +652,7 @@ _postForm:
|
||||
_profile:
|
||||
name: "Navn"
|
||||
username: "Brukernavn"
|
||||
description: "Biografi"
|
||||
metadataContent: "Innhold"
|
||||
_exportOrImport:
|
||||
followingList: "Følg"
|
||||
@@ -630,12 +694,14 @@ _pages:
|
||||
button: "Knapp"
|
||||
_notification:
|
||||
youWereFollowed: "fulgte deg"
|
||||
unreadAntennaNote: "Antenne {name}"
|
||||
achievementEarned: "Prestasjon låst opp"
|
||||
_types:
|
||||
follow: "Følg"
|
||||
follow: "Nye følgere"
|
||||
reply: "Svar"
|
||||
renote: "Renote"
|
||||
quote: "Sitat"
|
||||
reaction: "Reaksjon"
|
||||
renote: "Renotes"
|
||||
quote: "Sitater"
|
||||
reaction: "Reaksjoner"
|
||||
_actions:
|
||||
reply: "Svar"
|
||||
renote: "Renote"
|
||||
@@ -650,6 +716,7 @@ _deck:
|
||||
_columns:
|
||||
notifications: "Varsler"
|
||||
tl: "Tidslinje"
|
||||
antenna: "Antenner"
|
||||
list: "Lister"
|
||||
channel: "Kanaler"
|
||||
direct: "Direkte"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
_lang_: "Русский"
|
||||
headlineMisskey: "Сеть, сплетённая из заметок"
|
||||
introMisskey: "Добро пожаловать! Misskey — это децентрализованный сервис микроблогов с открытым исходным кодом.\nПишите «заметки» — делитесь со всеми происходящим вокруг или рассказывайте о себе 📡\nСтавьте «реакции» — выражайте свои чувства и эмоции от заметок других 👍\nОткройте для себя новый мир 🚀"
|
||||
poweredByMisskeyDescription: "{name} – один из инстансов (также называемый экземпляром Misskey), использующий платформу с открытым исходным кодом <b>Misskey</b>."
|
||||
poweredByMisskeyDescription: "{name} – сервис на платформе с открытым исходным кодом <b>Misskey</b>, называемый инстансом Misskey."
|
||||
monthAndDay: "{day}.{month}"
|
||||
search: "Поиск"
|
||||
notifications: "Уведомления"
|
||||
@@ -649,8 +649,8 @@ abuseReported: "Жалоба отправлена. Большое спасибо
|
||||
reporter: "Сообщивший"
|
||||
reporteeOrigin: "О ком сообщено"
|
||||
reporterOrigin: "Кто сообщил"
|
||||
forwardReport: "Перенаправление отчета на инстант."
|
||||
forwardReportIsAnonymous: "Удаленный инстант не сможет увидеть вашу информацию и будет отображаться как анонимная системная учетная запись."
|
||||
forwardReport: "Отправить жалобу на инстанс автора."
|
||||
forwardReportIsAnonymous: "Жалоба на удалённый инстанс будет отправлена анонимно. Вместо ваших данных у получателя будет отображена системная учётная запись."
|
||||
send: "Отправить"
|
||||
abuseMarkAsResolved: "Отметить жалобу как решённую"
|
||||
openInNewTab: "Открыть в новой вкладке"
|
||||
@@ -823,6 +823,7 @@ translatedFrom: "Перевод. Язык оригинала — {x}"
|
||||
accountDeletionInProgress: "В настоящее время выполняется удаление учетной записи"
|
||||
usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере. Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания (_). Имена пользователей не могут быть изменены позже."
|
||||
aiChanMode: "Режим Ай"
|
||||
devMode: "Режим разработчика"
|
||||
keepCw: "Сохраняйте Предупреждения о содержимом"
|
||||
pubSub: "Учётные записи Pub/Sub"
|
||||
lastCommunication: "Последнее сообщение"
|
||||
@@ -914,8 +915,8 @@ cannotUploadBecauseInappropriate: "Файл не может быть загру
|
||||
cannotUploadBecauseNoFreeSpace: "Файл не может быть загружен, так как не осталось места на диске"
|
||||
cannotUploadBecauseExceedsFileSizeLimit: "Файл не может быть загружен, так как он превышает лимит размера файла."
|
||||
beta: "Бета"
|
||||
enableAutoSensitive: "Автоматическое определение NSFW"
|
||||
enableAutoSensitiveDescription: "Если доступно, используйте машинное обучение для автоматической установки флага NSFW на носителе. Даже если эта функция отключена, она может быть установлена автоматически в зависимости от инстанта."
|
||||
enableAutoSensitive: "Автоматическое определение содержимого не для всех"
|
||||
enableAutoSensitiveDescription: "Позволяет определять наличие содержимого не для всех при помощи искусственного интеллекта там, где это возможно. Даже если эту опцию отключить, она всё равно может быть включена на весь инстанс."
|
||||
activeEmailValidationDescription: "Если включено, будет проводиться более строгая проверка адреса электронной почты, в том числе на то, что он действительный и не временный. Если же отключено, то проверяется только корректность написания адреса."
|
||||
navbar: "Панель навигации"
|
||||
shuffle: "Перемешать"
|
||||
@@ -1006,6 +1007,7 @@ noteIdOrUrl: "ID или ссылка на заметку"
|
||||
video: "Видео"
|
||||
videos: "Видео"
|
||||
dataSaver: "Экономия трафика"
|
||||
renotesList: "Репосты"
|
||||
horizontal: "Сбоку"
|
||||
youFollowing: "Подписки"
|
||||
options: "Настройки ролей"
|
||||
@@ -1180,6 +1182,9 @@ _achievements:
|
||||
_client30min:
|
||||
title: "Перерыв на обед"
|
||||
description: "Прошло 30 минут с момента запуска клиента"
|
||||
_client60min:
|
||||
title: "Не наглядеться на Misskey"
|
||||
description: "Misskey был открыт 60 минут подряд"
|
||||
_noteDeletedWithin1min:
|
||||
title: "Ой, нет!"
|
||||
description: "Заметка удалена через минуту после публикации"
|
||||
@@ -1282,6 +1287,7 @@ _role:
|
||||
canInvite: "Может создавать пригласительные коды"
|
||||
canManageCustomEmojis: "Управлять пользовательскими эмодзи"
|
||||
driveCapacity: "Доступное пространство на «диске»"
|
||||
alwaysMarkNsfw: "Всегда отмечать файлы как «не для всех»"
|
||||
pinMax: "Доступное количество закреплённых заметок"
|
||||
antennaMax: "Доступное количество антенн"
|
||||
wordMuteMax: "Доступное количество знаков в списке скрытия слов"
|
||||
@@ -1309,7 +1315,7 @@ _sensitiveMediaDetection:
|
||||
description: "Машинное обучение может быть использовано для автоматического обнаружения чувствительных медиа для модерации. Нагрузка на сервер увеличивается незначительно."
|
||||
sensitivity: "Чувствительность обнаружения"
|
||||
sensitivityDescription: "Более низкая чувствительность уменьшает количество ложных срабатываний (false positives). Повышение чувствительности уменьшает утечку при обнаружении (ложноотрицательные результаты)."
|
||||
setSensitiveFlagAutomatically: "Установить флаг NSFW"
|
||||
setSensitiveFlagAutomatically: "Обозначить как не для всех"
|
||||
setSensitiveFlagAutomaticallyDescription: "Даже если этот параметр отключен, результат оценки сохраняется внутри системы."
|
||||
analyzeVideos: "Анализировать видео?"
|
||||
analyzeVideosDescription: "Анализируйте видео в дополнение к неподвижным изображениям. Нагрузка на сервер немного увеличивается."
|
||||
@@ -1528,6 +1534,16 @@ _time:
|
||||
minute: "мин"
|
||||
hour: "ч"
|
||||
day: "сут"
|
||||
_timelineTutorial:
|
||||
title: "Как пользоваться Misskey"
|
||||
step1_1: "Это лицо Misskey, так называемая лента. Ваш инстанс, {name}, покажет тут все опубликованные на нём заметки в хронологическом порядке."
|
||||
step1_2: "Здесь есть несколько лент. К примеру «персональная» лента отображает заметки тех, на кого вы подписаны. А «местная» — заметки тех, кого приютил {name}."
|
||||
step2_1: "Что ж, теперь самое время опубликовать заметку. Если нажать вверху страницы на изображение карандаша, появится форма для текста."
|
||||
step2_2: "Почему бы не написать немного о себе? Ну, или хотя бы «Привет, {name}»?"
|
||||
step3_1: "Справились с первой заметкой?"
|
||||
step3_2: "Отлично, теперь она должна появиться в вашей ленте."
|
||||
step4_1: "А ещё здесь можно делиться своими реакциями на заметки."
|
||||
step4_2: "Отмечайте реакции, нажимая на символ «+» под заметкой и выбирая значок по душе."
|
||||
_2fa:
|
||||
alreadyRegistered: "Двухфакторная аутентификация уже настроена."
|
||||
registerTOTP: "Начните настраивать приложение-аутентификатор"
|
||||
@@ -1868,6 +1884,9 @@ _deck:
|
||||
_dialog:
|
||||
charactersExceeded: "Превышено максимальное количество символов! У вас {current} / из {max}"
|
||||
charactersBelow: "Это ниже минимального количества символов! У вас {current} / из {min}"
|
||||
_disabledTimeline:
|
||||
title: "Лента отключена"
|
||||
description: "Ваша текущая роль не позволяет пользоваться этой лентой."
|
||||
_webhookSettings:
|
||||
name: "Название"
|
||||
active: "Вкл."
|
||||
|
@@ -1,6 +1,7 @@
|
||||
---
|
||||
_lang_: "Türkçe"
|
||||
introMisskey: "Açık kaynaklı bir dağıtılmış mikroblog hizmeti olan Misskey'e hoş geldiniz.\nMisskey, neler olup bittiğini paylaşmak ve herkese sizden bahsetmek için \"notlar\" oluşturmanıza olanak tanıyan, açık kaynaklı, dağıtılmış bir mikroblog hizmetidir.\nHerkesin notlarına kendi tepkilerinizi hızlıca eklemek için \"Tepkiler\" özelliğini de kullanabilirsiniz👍.\nYeni bir dünyayı keşfedin🚀."
|
||||
poweredByMisskeyDescription: "name}Açık kaynak bir platform\n<b>Misskey</b>Dünya'nın en sunucularında biri。"
|
||||
monthAndDay: "{month}Ay {day}Gün"
|
||||
search: "Arama"
|
||||
notifications: "Bildirim"
|
||||
@@ -13,7 +14,9 @@ cancel: "İptal"
|
||||
enterUsername: "Kullanıcı adınızı giriniz"
|
||||
noNotes: "Notlar mevcut değil."
|
||||
noNotifications: "Bildirim bulunmuyor"
|
||||
instance: "Sunucu"
|
||||
settings: "Ayarlar"
|
||||
notificationSettings: "Bildirim Ayarları"
|
||||
basicSettings: "Temel Ayarlar"
|
||||
otherSettings: "Diğer Ayarlar"
|
||||
openInWindow: "Bir pencere ile aç"
|
||||
@@ -21,9 +24,11 @@ profile: "Profil"
|
||||
timeline: "Zaman çizelgesi"
|
||||
noAccountDescription: "Bu kullanıcı henüz biyografisini yazmadı"
|
||||
login: "Giriş Yap "
|
||||
loggingIn: "Oturum aç"
|
||||
logout: "Çıkış Yap"
|
||||
signup: "Kayıt Ol"
|
||||
uploading: "Yükleniyor"
|
||||
save: "Kaydet"
|
||||
users: "Kullanıcı"
|
||||
addUser: "Kullanıcı Ekle"
|
||||
favorite: "Favoriler"
|
||||
@@ -31,6 +36,7 @@ favorites: "Favoriler"
|
||||
unfavorite: "Favorilerden Kaldır"
|
||||
favorited: "Favorilerime eklendi."
|
||||
alreadyFavorited: "Zaten favorilerinizde kayıtlı."
|
||||
cantFavorite: "Favorilere kayıt yapılamadı"
|
||||
pin: "Sabitlenmiş"
|
||||
unpin: "Sabitlemeyi kaldır"
|
||||
copyContent: "İçeriği kopyala"
|
||||
@@ -40,23 +46,88 @@ deleteAndEdit: "Sil ve yeniden düzenle"
|
||||
deleteAndEditConfirm: "Bu notu silip yeniden düzenlemek istiyor musunuz? Bu nota ilişkin tüm Tepkiler, Yeniden Notlar ve Yanıtlar da silinecektir."
|
||||
addToList: "Listeye ekle"
|
||||
sendMessage: "Mesaj Gönder"
|
||||
copyRSS: "RSSKopyala"
|
||||
copyUsername: "Kullanıcı Adını Kopyala"
|
||||
copyUserId: "KullanıcıyıKopyala"
|
||||
copyNoteId: "Kimlik notunu kopyala"
|
||||
searchUser: "Kullanıcıları ara"
|
||||
reply: "yanıt"
|
||||
loadMore: "Devamını yükle"
|
||||
showMore: "Devamını yükle"
|
||||
lists: "Listeler"
|
||||
noLists: "Liste yok"
|
||||
note: "not"
|
||||
notes: "notlar"
|
||||
following: "takipçi"
|
||||
followers: "takipçi"
|
||||
followsYou: "seni takip ediyor"
|
||||
createList: "Liste oluştur"
|
||||
manageLists: "Yönetici Listeleri"
|
||||
error: "hata"
|
||||
follow: "takipçi"
|
||||
followRequest: "Takip isteği"
|
||||
followRequests: "Takip istekleri"
|
||||
unfollow: "takip etmeyi bırak"
|
||||
followRequestPending: "Bekleyen Takip Etme Talebi"
|
||||
enterEmoji: "Emoji Giriniz"
|
||||
renote: "vazgeçme"
|
||||
unrenote: "not alma"
|
||||
renoted: "yeniden adlandırılmış"
|
||||
cantRenote: "Ayrılamama"
|
||||
cantReRenote: "not alabilirmiyim"
|
||||
quote: "alıntı"
|
||||
pinnedNote: "Sabitlenen"
|
||||
pinned: "Sabitlenmiş"
|
||||
you: "sen"
|
||||
unmute: "sesi aç"
|
||||
renoteMute: "sesi kapat"
|
||||
renoteUnmute: "sesi açmayı iptal et"
|
||||
block: "engelle"
|
||||
unblock: "engellemeyi kaldır"
|
||||
suspend: "askıya al"
|
||||
unsuspend: "askıya alma"
|
||||
blockConfirm: "Onayı engelle"
|
||||
unblockConfirm: "engellemeyi kaldır onayla"
|
||||
selectChannel: "Kanal seç"
|
||||
flagAsBot: "Bot olarak işaretle"
|
||||
instances: "Sunucu"
|
||||
remove: "Sil"
|
||||
pinnedNotes: "Sabitlenen"
|
||||
userList: "Listeler"
|
||||
smtpUser: "Kullanıcı Adı"
|
||||
smtpPass: "Şifre"
|
||||
user: "Kullanıcı"
|
||||
searchByGoogle: "Arama"
|
||||
_theme:
|
||||
keys:
|
||||
renote: "vazgeçme"
|
||||
_sfx:
|
||||
note: "notlar"
|
||||
notification: "Bildirim"
|
||||
_widgets:
|
||||
profile: "Profil"
|
||||
notifications: "Bildirim"
|
||||
timeline: "Zaman çizelgesi"
|
||||
_cw:
|
||||
show: "Devamını yükle"
|
||||
_visibility:
|
||||
followers: "takipçi"
|
||||
_profile:
|
||||
username: "Kullanıcı Adı"
|
||||
_exportOrImport:
|
||||
followingList: "takipçi"
|
||||
blockingList: "engelle"
|
||||
userLists: "Listeler"
|
||||
_notification:
|
||||
_types:
|
||||
follow: "takipçi"
|
||||
renote: "vazgeçme"
|
||||
quote: "alıntı"
|
||||
_actions:
|
||||
reply: "yanıt"
|
||||
renote: "vazgeçme"
|
||||
_deck:
|
||||
_columns:
|
||||
notifications: "Bildirim"
|
||||
tl: "Zaman çizelgesi"
|
||||
list: "Listeler"
|
||||
|
@@ -52,6 +52,8 @@ addToList: "添加至列表"
|
||||
sendMessage: "发送"
|
||||
copyRSS: "复制RSS"
|
||||
copyUsername: "复制用户名"
|
||||
copyUserId: "复制用户ID"
|
||||
copyNoteId: "复制帖子ID"
|
||||
searchUser: "搜索用户"
|
||||
reply: "回复"
|
||||
loadMore: "查看更多"
|
||||
@@ -790,6 +792,7 @@ noMaintainerInformationWarning: "管理人员信息未设置。"
|
||||
noBotProtectionWarning: "Bot保护未设置。"
|
||||
configure: "设置"
|
||||
postToGallery: "发送到图库"
|
||||
postToHashtag: "投稿到这个标签"
|
||||
gallery: "图库"
|
||||
recentPosts: "最新发布"
|
||||
popularPosts: "热门投稿"
|
||||
@@ -823,6 +826,7 @@ translatedFrom: "从 {x} 翻译"
|
||||
accountDeletionInProgress: "正在删除账户"
|
||||
usernameInfo: "在服务器上唯一标识您的帐户的名称。您可以使用字母 (a ~ z, A ~ Z)、数字 (0 ~ 9) 和下划线 (_)。用户名以后不能更改。"
|
||||
aiChanMode: "小蓝模式"
|
||||
devMode: "开发者模式"
|
||||
keepCw: "回复时维持隐藏内容"
|
||||
pubSub: "Pub/Sub账户"
|
||||
lastCommunication: "最近通信"
|
||||
@@ -832,6 +836,8 @@ breakFollow: "移除关注者"
|
||||
breakFollowConfirm: "你想取消关注吗?"
|
||||
itsOn: "已开启"
|
||||
itsOff: "已关闭"
|
||||
on: "开启"
|
||||
off: "关闭"
|
||||
emailRequiredForSignup: "注册账户需要电子邮件地址"
|
||||
unread: "未读"
|
||||
filter: "筛选"
|
||||
@@ -986,6 +992,8 @@ cannotBeChangedLater: "之后不能再更改。"
|
||||
reactionAcceptance: "接受表情回应"
|
||||
likeOnly: "仅点赞"
|
||||
likeOnlyForRemote: "远程仅点赞"
|
||||
nonSensitiveOnly: "仅限非敏感内容"
|
||||
nonSensitiveOnlyForLocalLikeOnlyForRemote: "仅限非敏感内容(远程仅点赞)"
|
||||
rolesAssignedToMe: "指派给自己的角色"
|
||||
resetPasswordConfirm: "确定重置密码?"
|
||||
sensitiveWords: "敏感词"
|
||||
@@ -1043,6 +1051,17 @@ preventAiLearning: "拒绝接受生成式AI的学习"
|
||||
preventAiLearningDescription: "要求文章生成AI或图像生成AI不能够以发布的帖子和图像等内容作为学习对象。这是通过在HTML响应中包含noai标志来实现的,这不能完全阻止AI学习你的发布内容,并不是所有AI都会遵守这类请求。"
|
||||
options: "选项"
|
||||
specifyUser: "用户指定"
|
||||
failedToPreviewUrl: "无法预览"
|
||||
update: "更新"
|
||||
rolesThatCanBeUsedThisEmojiAsReaction: "可以使用表情作为回应的角色"
|
||||
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "在没有指定角色的情况下,任何人都可以使用表情作为回应。"
|
||||
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "角色必须是公开的。"
|
||||
cancelReactionConfirm: "要取消回应吗?"
|
||||
changeReactionConfirm: "要更改回应吗?"
|
||||
later: "一会再说"
|
||||
goToMisskey: "去往Misskey"
|
||||
additionalEmojiDictionary: "表情符号追加字典"
|
||||
installed: "已安装"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "账户创建完成了!"
|
||||
letsStartAccountSetup: "来进行帐户的初始设置吧。"
|
||||
@@ -1057,6 +1076,7 @@ _initialAccountSetting:
|
||||
haveFun: "希望{name}在这里玩得开心!"
|
||||
ifYouNeedLearnMore: "关于{name}(Misskey)的使用方法,详见{link}。"
|
||||
skipAreYouSure: "要跳过初始设置吗?"
|
||||
laterAreYouSure: "要稍后再进行初始设定吗?"
|
||||
_serverRules:
|
||||
description: "在新用户注册前显示服务器的简单规则。推荐显示服务条款的主要内容。"
|
||||
_accountMigration:
|
||||
|
@@ -1060,6 +1060,9 @@ cancelReactionConfirm: "要取消做出的反應嗎?"
|
||||
changeReactionConfirm: "要變更做出的反應嗎?"
|
||||
later: "稍後再說"
|
||||
goToMisskey: "往Misskey"
|
||||
additionalEmojiDictionary: "表情符號的附加辭典"
|
||||
installed: "已安裝"
|
||||
branding: "品牌宣傳"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "帳戶已建立完成!"
|
||||
letsStartAccountSetup: "來進行帳戶的初始設定吧。"
|
||||
|
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"version": "13.13.0-beta.6",
|
||||
"version": "13.13.2",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -51,16 +51,16 @@
|
||||
"gulp-replace": "1.1.4",
|
||||
"gulp-terser": "2.1.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"typescript": "5.0.4"
|
||||
"typescript": "5.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/gulp": "4.0.10",
|
||||
"@types/gulp-rename": "2.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.5",
|
||||
"@typescript-eslint/parser": "5.59.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "12.13.0",
|
||||
"eslint": "8.40.0",
|
||||
"cypress": "12.15.0",
|
||||
"eslint": "8.43.0",
|
||||
"start-server-and-test": "2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@@ -17,7 +17,7 @@
|
||||
"paths": {
|
||||
"@/*": ["*"]
|
||||
},
|
||||
"target": "es2021"
|
||||
"target": "es2022"
|
||||
},
|
||||
"minify": false
|
||||
}
|
||||
|
BIN
packages/backend/assets/avatar.png
Normal file
BIN
packages/backend/assets/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
17
packages/backend/migration/1685973839966-errorImageUrl.js
Normal file
17
packages/backend/migration/1685973839966-errorImageUrl.js
Normal file
@@ -0,0 +1,17 @@
|
||||
export class ErrorImageUrl1685973839966 {
|
||||
name = 'ErrorImageUrl1685973839966'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "errorImageUrl"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "serverErrorImageUrl" character varying(1024)`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "notFoundImageUrl" character varying(1024)`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "infoImageUrl" character varying(1024)`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "infoImageUrl"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "notFoundImageUrl"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "serverErrorImageUrl"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "errorImageUrl" character varying(1024) DEFAULT 'https://xn--931a.moe/aiart/yubitun.png'`);
|
||||
}
|
||||
}
|
13
packages/backend/migration/1688280713783-add-meta-options.js
Normal file
13
packages/backend/migration/1688280713783-add-meta-options.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export class AddMetaOptions1688280713783 {
|
||||
name = 'AddMetaOptions1688280713783'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "enableServerMachineStats" boolean NOT NULL DEFAULT false`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "enableIdenticonGeneration" boolean NOT NULL DEFAULT true`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableIdenticonGeneration"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableServerMachineStats"`);
|
||||
}
|
||||
}
|
@@ -54,33 +54,33 @@
|
||||
"@aws-sdk/client-s3": "3.321.1",
|
||||
"@aws-sdk/lib-storage": "3.321.1",
|
||||
"@aws-sdk/node-http-handler": "3.321.1",
|
||||
"@bull-board/api": "5.2.0",
|
||||
"@bull-board/fastify": "5.2.0",
|
||||
"@bull-board/ui": "5.2.0",
|
||||
"@bull-board/api": "5.5.3",
|
||||
"@bull-board/fastify": "5.5.3",
|
||||
"@bull-board/ui": "5.5.3",
|
||||
"@discordapp/twemoji": "14.1.2",
|
||||
"@fastify/accepts": "4.1.0",
|
||||
"@fastify/accepts": "4.2.0",
|
||||
"@fastify/cookie": "8.3.0",
|
||||
"@fastify/cors": "8.2.1",
|
||||
"@fastify/http-proxy": "9.1.0",
|
||||
"@fastify/multipart": "7.6.0",
|
||||
"@fastify/static": "6.10.1",
|
||||
"@fastify/cors": "8.3.0",
|
||||
"@fastify/http-proxy": "9.2.1",
|
||||
"@fastify/multipart": "7.7.0",
|
||||
"@fastify/static": "6.10.2",
|
||||
"@fastify/view": "7.4.1",
|
||||
"@nestjs/common": "9.4.2",
|
||||
"@nestjs/core": "9.4.2",
|
||||
"@nestjs/testing": "9.4.2",
|
||||
"@nestjs/common": "10.0.3",
|
||||
"@nestjs/core": "10.0.3",
|
||||
"@nestjs/testing": "10.0.3",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sinonjs/fake-timers": "10.0.2",
|
||||
"@sinonjs/fake-timers": "10.3.0",
|
||||
"@swc/cli": "0.1.62",
|
||||
"@swc/core": "1.3.59",
|
||||
"@swc/core": "1.3.66",
|
||||
"accepts": "1.3.8",
|
||||
"ajv": "8.12.0",
|
||||
"archiver": "5.3.1",
|
||||
"autwh": "0.1.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "2.0.5",
|
||||
"bullmq": "3.14.1",
|
||||
"cacheable-lookup": "6.1.0",
|
||||
"cbor": "8.1.0",
|
||||
"bullmq": "4.1.0",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"cbor": "9.0.0",
|
||||
"chalk": "5.2.0",
|
||||
"chalk-template": "0.4.0",
|
||||
"chokidar": "3.5.3",
|
||||
@@ -90,37 +90,37 @@
|
||||
"date-fns": "2.30.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"escape-regexp": "0.0.1",
|
||||
"fastify": "4.17.0",
|
||||
"fastify": "4.18.0",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "18.4.0",
|
||||
"file-type": "18.5.0",
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"form-data": "4.0.0",
|
||||
"got": "12.6.0",
|
||||
"happy-dom": "9.19.2",
|
||||
"got": "13.0.0",
|
||||
"happy-dom": "9.20.3",
|
||||
"hpagent": "1.2.0",
|
||||
"ioredis": "5.3.2",
|
||||
"ip-cidr": "3.1.0",
|
||||
"ipaddr.js": "2.1.0",
|
||||
"is-svg": "4.3.2",
|
||||
"js-yaml": "4.1.0",
|
||||
"jsdom": "21.1.1",
|
||||
"jsdom": "22.1.0",
|
||||
"json5": "2.2.3",
|
||||
"jsonld": "8.1.1",
|
||||
"jsonld": "8.2.0",
|
||||
"jsrsasign": "10.8.6",
|
||||
"meilisearch": "0.32.4",
|
||||
"meilisearch": "0.33.0",
|
||||
"mfm-js": "0.23.3",
|
||||
"mime-types": "2.1.35",
|
||||
"misskey-js": "workspace:*",
|
||||
"ms": "3.0.0-canary.1",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "3.3.1",
|
||||
"nodemailer": "6.9.2",
|
||||
"nodemailer": "6.9.3",
|
||||
"nsfwjs": "2.4.2",
|
||||
"oauth": "0.10.0",
|
||||
"os-utils": "0.0.14",
|
||||
"otpauth": "9.1.2",
|
||||
"parse5": "7.1.2",
|
||||
"pg": "8.11.0",
|
||||
"private-ip": "3.0.0",
|
||||
"probe-image-size": "7.2.3",
|
||||
"promise-limit": "2.7.0",
|
||||
"pug": "3.0.2",
|
||||
@@ -129,36 +129,34 @@
|
||||
"qrcode": "1.5.3",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"re2": "1.18.0",
|
||||
"re2": "1.19.1",
|
||||
"redis-lock": "0.1.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rename": "1.0.4",
|
||||
"rndstr": "1.0.0",
|
||||
"rss-parser": "3.13.0",
|
||||
"rxjs": "7.8.1",
|
||||
"s-age": "1.1.2",
|
||||
"sanitize-html": "2.10.0",
|
||||
"seedrandom": "3.0.5",
|
||||
"semver": "7.5.1",
|
||||
"sanitize-html": "2.11.0",
|
||||
"semver": "7.5.3",
|
||||
"sharp": "0.32.1",
|
||||
"sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
|
||||
"slacc": "0.0.9",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"summaly": "github:misskey-dev/summaly",
|
||||
"systeminformation": "5.17.12",
|
||||
"systeminformation": "5.18.4",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tmp": "0.2.1",
|
||||
"tsc-alias": "1.8.6",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"twemoji-parser": "14.0.0",
|
||||
"typeorm": "0.3.16",
|
||||
"typescript": "5.0.4",
|
||||
"typeorm": "0.3.17",
|
||||
"typescript": "5.1.3",
|
||||
"ulid": "2.3.0",
|
||||
"unzipper": "0.10.11",
|
||||
"unzipper": "0.10.14",
|
||||
"uuid": "9.0.0",
|
||||
"vary": "1.1.2",
|
||||
"web-push": "3.6.1",
|
||||
"web-push": "3.6.3",
|
||||
"ws": "8.13.0",
|
||||
"xev": "3.0.2"
|
||||
},
|
||||
@@ -173,17 +171,18 @@
|
||||
"@types/content-disposition": "0.5.5",
|
||||
"@types/escape-regexp": "0.0.1",
|
||||
"@types/fluent-ffmpeg": "2.1.21",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/js-yaml": "4.0.5",
|
||||
"@types/jsdom": "21.1.1",
|
||||
"@types/jsonld": "1.5.8",
|
||||
"@types/jsonld": "1.5.9",
|
||||
"@types/jsrsasign": "10.5.8",
|
||||
"@types/mime-types": "2.1.1",
|
||||
"@types/node": "20.2.3",
|
||||
"@types/ms": "^0.7.31",
|
||||
"@types/node": "20.3.1",
|
||||
"@types/node-fetch": "3.0.3",
|
||||
"@types/nodemailer": "6.4.8",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/pg": "8.10.1",
|
||||
"@types/pg": "8.10.2",
|
||||
"@types/pug": "2.0.6",
|
||||
"@types/punycode": "2.1.0",
|
||||
"@types/qrcode": "1.5.0",
|
||||
@@ -198,19 +197,20 @@
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@types/tmp": "0.2.3",
|
||||
"@types/unzipper": "0.10.6",
|
||||
"@types/uuid": "9.0.1",
|
||||
"@types/uuid": "9.0.2",
|
||||
"@types/vary": "1.1.0",
|
||||
"@types/web-push": "3.3.2",
|
||||
"@types/websocket": "1.0.5",
|
||||
"@types/ws": "8.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.5",
|
||||
"@typescript-eslint/parser": "5.59.5",
|
||||
"@types/ws": "8.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"aws-sdk-client-mock": "2.1.1",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "8.40.0",
|
||||
"eslint": "8.43.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"execa": "6.1.0",
|
||||
"jest": "29.5.0",
|
||||
"jest-mock": "29.5.0"
|
||||
"jest-mock": "29.5.0",
|
||||
"schema-type": "github:misskey-dev/schema-type"
|
||||
}
|
||||
}
|
||||
|
@@ -4,83 +4,7 @@ import type { User } from '@/models/entities/User.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { NotificationService } from '@/core/NotificationService.js';
|
||||
|
||||
export const ACHIEVEMENT_TYPES = [
|
||||
'notes1',
|
||||
'notes10',
|
||||
'notes100',
|
||||
'notes500',
|
||||
'notes1000',
|
||||
'notes5000',
|
||||
'notes10000',
|
||||
'notes20000',
|
||||
'notes30000',
|
||||
'notes40000',
|
||||
'notes50000',
|
||||
'notes60000',
|
||||
'notes70000',
|
||||
'notes80000',
|
||||
'notes90000',
|
||||
'notes100000',
|
||||
'login3',
|
||||
'login7',
|
||||
'login15',
|
||||
'login30',
|
||||
'login60',
|
||||
'login100',
|
||||
'login200',
|
||||
'login300',
|
||||
'login400',
|
||||
'login500',
|
||||
'login600',
|
||||
'login700',
|
||||
'login800',
|
||||
'login900',
|
||||
'login1000',
|
||||
'passedSinceAccountCreated1',
|
||||
'passedSinceAccountCreated2',
|
||||
'passedSinceAccountCreated3',
|
||||
'loggedInOnBirthday',
|
||||
'loggedInOnNewYearsDay',
|
||||
'noteClipped1',
|
||||
'noteFavorited1',
|
||||
'myNoteFavorited1',
|
||||
'profileFilled',
|
||||
'markedAsCat',
|
||||
'following1',
|
||||
'following10',
|
||||
'following50',
|
||||
'following100',
|
||||
'following300',
|
||||
'followers1',
|
||||
'followers10',
|
||||
'followers50',
|
||||
'followers100',
|
||||
'followers300',
|
||||
'followers500',
|
||||
'followers1000',
|
||||
'collectAchievements30',
|
||||
'viewAchievements3min',
|
||||
'iLoveMisskey',
|
||||
'foundTreasure',
|
||||
'client30min',
|
||||
'client60min',
|
||||
'noteDeletedWithin1min',
|
||||
'postedAtLateNight',
|
||||
'postedAt0min0sec',
|
||||
'selfQuote',
|
||||
'htl20npm',
|
||||
'viewInstanceChart',
|
||||
'outputHelloWorldOnScratchpad',
|
||||
'open3windows',
|
||||
'driveFolderCircularReference',
|
||||
'reactWithoutRead',
|
||||
'clickedClickHere',
|
||||
'justPlainLucky',
|
||||
'setNameToSyuilo',
|
||||
'cookieClicked',
|
||||
'brainDiver',
|
||||
] as const;
|
||||
import { ACHIEVEMENT_TYPES } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class AchievementService {
|
||||
|
@@ -10,7 +10,7 @@ import { isUserRelated } from '@/misc/is-user-related.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { PushNotificationService } from '@/core/PushNotificationService.js';
|
||||
import * as Acct from '@/misc/acct.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { MutingsRepository, NotesRepository, AntennasRepository, UserListJoiningsRepository } from '@/models/index.js';
|
||||
import { UtilityService } from '@/core/UtilityService.js';
|
||||
|
@@ -168,6 +168,17 @@ export class CacheService implements OnApplicationShutdown {
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.redisForSub.off('message', this.onMessage);
|
||||
this.userByIdCache.dispose();
|
||||
this.localUserByNativeTokenCache.dispose();
|
||||
this.localUserByIdCache.dispose();
|
||||
this.uriPersonCache.dispose();
|
||||
this.userProfileCache.dispose();
|
||||
this.userMutingsCache.dispose();
|
||||
this.userBlockingCache.dispose();
|
||||
this.userBlockedCache.dispose();
|
||||
this.renoteMutingsCache.dispose();
|
||||
this.userFollowingsCache.dispose();
|
||||
this.userFollowingChannelsCache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||
import { DataSource, In, IsNull } from 'typeorm';
|
||||
import * as Redis from 'ioredis';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
@@ -18,7 +18,7 @@ import type { Serialized } from '@/server/api/stream/types.js';
|
||||
const parseEmojiStrRegexp = /^(\w+)(?:@([\w.-]+))?$/;
|
||||
|
||||
@Injectable()
|
||||
export class CustomEmojiService {
|
||||
export class CustomEmojiService implements OnApplicationShutdown {
|
||||
private cache: MemoryKVCache<Emoji | null>;
|
||||
public localEmojisCache: RedisSingleCache<Map<string, Emoji>>;
|
||||
|
||||
@@ -349,4 +349,14 @@ export class CustomEmojiService {
|
||||
this.cache.set(`${emoji.name} ${emoji.host}`, emoji);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.cache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onApplicationShutdown(signal?: string | undefined): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,7 @@ import * as fs from 'node:fs';
|
||||
import * as stream from 'node:stream';
|
||||
import * as util from 'node:util';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import IPCIDR from 'ip-cidr';
|
||||
import PrivateIp from 'private-ip';
|
||||
import ipaddr from 'ipaddr.js';
|
||||
import chalk from 'chalk';
|
||||
import got, * as Got from 'got';
|
||||
import { parse } from 'content-disposition';
|
||||
@@ -123,15 +122,15 @@ export class DownloadService {
|
||||
public async downloadTextFile(url: string): Promise<string> {
|
||||
// Create temp file
|
||||
const [path, cleanup] = await createTemp();
|
||||
|
||||
|
||||
this.logger.info(`text file: Temp file is ${path}`);
|
||||
|
||||
|
||||
try {
|
||||
// write content at URL to temp file
|
||||
await this.downloadUrl(url, path);
|
||||
|
||||
|
||||
const text = await util.promisify(fs.readFile)(path, 'utf8');
|
||||
|
||||
|
||||
return text;
|
||||
} finally {
|
||||
cleanup();
|
||||
@@ -140,13 +139,14 @@ export class DownloadService {
|
||||
|
||||
@bindThis
|
||||
private isPrivateIp(ip: string): boolean {
|
||||
const parsedIp = ipaddr.parse(ip);
|
||||
|
||||
for (const net of this.config.allowedPrivateNetworks ?? []) {
|
||||
const cidr = new IPCIDR(net);
|
||||
if (cidr.contains(ip)) {
|
||||
if (parsedIp.match(ipaddr.parseCIDR(net))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return PrivateIp(ip) ?? false;
|
||||
return parsedIp.range() !== 'unicast';
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||
import * as Redis from 'ioredis';
|
||||
import type { InstancesRepository } from '@/models/index.js';
|
||||
import type { Instance } from '@/models/entities/Instance.js';
|
||||
@@ -9,7 +9,7 @@ import { UtilityService } from '@/core/UtilityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
@Injectable()
|
||||
export class FederatedInstanceService {
|
||||
export class FederatedInstanceService implements OnApplicationShutdown {
|
||||
public federatedInstanceCache: RedisKVCache<Instance | null>;
|
||||
|
||||
constructor(
|
||||
@@ -77,4 +77,14 @@ export class FederatedInstanceService {
|
||||
|
||||
this.federatedInstanceCache.set(result.host, result);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.federatedInstanceCache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onApplicationShutdown(signal?: string | undefined): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
@@ -16,11 +16,11 @@ import type {
|
||||
UserListStreamTypes,
|
||||
RoleTimelineStreamTypes,
|
||||
} from '@/server/api/stream/types.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { Role } from '@/models';
|
||||
import { Role } from '@/models/index.js';
|
||||
|
||||
@Injectable()
|
||||
export class GlobalEventService {
|
||||
|
@@ -5,7 +5,7 @@ import type { Config } from '@/config.js';
|
||||
import { genAid, parseAid } from '@/misc/id/aid.js';
|
||||
import { genMeid, parseMeid } from '@/misc/id/meid.js';
|
||||
import { genMeidg, parseMeidg } from '@/misc/id/meidg.js';
|
||||
import { genObjectId } from '@/misc/id/object-id.js';
|
||||
import { genObjectId, parseObjectId } from '@/misc/id/object-id.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { parseUlid } from '@/misc/id/ulid.js';
|
||||
|
||||
@@ -38,7 +38,7 @@ export class IdService {
|
||||
public parse(id: string): { date: Date; } {
|
||||
switch (this.method) {
|
||||
case 'aid': return parseAid(id);
|
||||
case 'objectid':
|
||||
case 'objectid': return parseObjectId(id);
|
||||
case 'meid': return parseMeid(id);
|
||||
case 'meidg': return parseMeidg(id);
|
||||
case 'ulid': return parseUlid(id);
|
||||
|
@@ -3,7 +3,7 @@ import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import Logger from '@/logger.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { KEYWORD } from 'color-convert/conversions';
|
||||
import type { KEYWORD } from 'color-convert/conversions.js';
|
||||
|
||||
@Injectable()
|
||||
export class LoggerService {
|
||||
|
@@ -3,7 +3,7 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||
import { In } from 'typeorm';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Note } from '@/models/entities/Note.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||
import push from 'web-push';
|
||||
import * as Redis from 'ioredis';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { Packed } from '@/misc/json-schema';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { getNoteSummary } from '@/misc/get-note-summary.js';
|
||||
import type { SwSubscription, SwSubscriptionsRepository } from '@/models/index.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
@@ -42,7 +42,7 @@ function truncateBody<T extends keyof PushNotificationsTypes>(type: T, body: Pus
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PushNotificationService {
|
||||
export class PushNotificationService implements OnApplicationShutdown {
|
||||
private subscriptionsCache: RedisKVCache<SwSubscription[]>;
|
||||
|
||||
constructor(
|
||||
@@ -115,4 +115,14 @@ export class PushNotificationService {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.subscriptionsCache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onApplicationShutdown(signal?: string | undefined): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
@@ -400,11 +400,11 @@ export class QueueService {
|
||||
this.deliverQueue.once('cleaned', (jobs, status) => {
|
||||
//deliverLogger.succ(`Cleaned ${jobs.length} ${status} jobs`);
|
||||
});
|
||||
this.deliverQueue.clean(0, Infinity, 'delayed');
|
||||
this.deliverQueue.clean(0, 0, 'delayed');
|
||||
|
||||
this.inboxQueue.once('cleaned', (jobs, status) => {
|
||||
//inboxLogger.succ(`Cleaned ${jobs.length} ${status} jobs`);
|
||||
});
|
||||
this.inboxQueue.clean(0, Infinity, 'delayed');
|
||||
this.inboxQueue.clean(0, 0, 'delayed');
|
||||
}
|
||||
}
|
||||
|
@@ -8,12 +8,12 @@ import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
import type { RoleCondFormulaValue } from '@/models/entities/Role.js';
|
||||
import type { RoleCondFormulaValue } from 'misskey-js/built/schemas/role.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { StreamMessages } from '@/server/api/stream/types.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import type { Packed } from '@/misc/json-schema';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||
|
||||
export type RolePolicies = {
|
||||
@@ -435,6 +435,7 @@ export class RoleService implements OnApplicationShutdown {
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.redisForSub.off('message', this.onMessage);
|
||||
this.roleAssignmentByUserIdCache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
@@ -107,7 +107,10 @@ export class UserBlockingService implements OnModuleInit {
|
||||
if (this.userEntityService.isLocalUser(followee)) {
|
||||
this.userEntityService.pack(followee, followee, {
|
||||
detail: true,
|
||||
}).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed));
|
||||
}).then(packed => {
|
||||
this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed);
|
||||
return packed; // somehow this is needed by typescript
|
||||
});
|
||||
}
|
||||
|
||||
if (this.userEntityService.isLocalUser(follower) && !silent) {
|
||||
@@ -122,6 +125,8 @@ export class UserBlockingService implements OnModuleInit {
|
||||
user: packed,
|
||||
});
|
||||
}
|
||||
|
||||
return packed; // somehow this is needed by typescript
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@ import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import InstanceChart from '@/core/chart/charts/instance.js';
|
||||
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
|
||||
import { WebhookService } from '@/core/WebhookService.js';
|
||||
@@ -267,7 +267,7 @@ export class UserFollowingService implements OnModuleInit {
|
||||
this.userEntityService.pack(followee.id, follower, {
|
||||
detail: true,
|
||||
}).then(async packed => {
|
||||
this.globalEventService.publishMainStream(follower.id, 'follow', packed as Packed<'UserDetailedNotMe'>);
|
||||
this.globalEventService.publishMainStream(follower.id, 'follow', packed);
|
||||
|
||||
const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('follow'));
|
||||
for (const webhook of webhooks) {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||
import * as Redis from 'ioredis';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { UserKeypairsRepository } from '@/models/index.js';
|
||||
@@ -8,7 +8,7 @@ import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
@Injectable()
|
||||
export class UserKeypairService {
|
||||
export class UserKeypairService implements OnApplicationShutdown {
|
||||
private cache: RedisKVCache<UserKeypair>;
|
||||
|
||||
constructor(
|
||||
@@ -31,4 +31,14 @@ export class UserKeypairService {
|
||||
public async getUserKeypair(userId: User['id']): Promise<UserKeypair> {
|
||||
return await this.cache.fetch(userId);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.cache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onApplicationShutdown(signal?: string | undefined): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||
import escapeRegexp from 'escape-regexp';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js';
|
||||
@@ -30,7 +30,7 @@ export type UriParseResult = {
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class ApDbResolverService {
|
||||
export class ApDbResolverService implements OnApplicationShutdown {
|
||||
private publicKeyCache: MemoryKVCache<UserPublickey | null>;
|
||||
private publicKeyByUserIdCache: MemoryKVCache<UserPublickey | null>;
|
||||
|
||||
@@ -162,4 +162,15 @@ export class ApDbResolverService {
|
||||
key,
|
||||
};
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.publicKeyCache.dispose();
|
||||
this.publicKeyByUserIdCache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onApplicationShutdown(signal?: string | undefined): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'activeUsers';
|
||||
|
||||
export const schema = {
|
||||
'readWrite': { intersection: ['read', 'write'] },
|
||||
'read': { uniqueIncrement: true },
|
||||
'write': { uniqueIncrement: true },
|
||||
'registeredWithinWeek': { uniqueIncrement: true },
|
||||
'registeredWithinMonth': { uniqueIncrement: true },
|
||||
'registeredWithinYear': { uniqueIncrement: true },
|
||||
'registeredOutsideWeek': { uniqueIncrement: true },
|
||||
'registeredOutsideMonth': { uniqueIncrement: true },
|
||||
'registeredOutsideYear': { uniqueIncrement: true },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'activeUsers' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,11 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'apRequest';
|
||||
|
||||
export const schema = {
|
||||
'deliverFailed': { },
|
||||
'deliverSucceeded': { },
|
||||
'inboxReceived': { },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'apRequest' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,16 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'drive';
|
||||
|
||||
export const schema = {
|
||||
'local.incCount': {},
|
||||
'local.incSize': {}, // in kilobyte
|
||||
'local.decCount': {},
|
||||
'local.decSize': {}, // in kilobyte
|
||||
'remote.incCount': {},
|
||||
'remote.incSize': {}, // in kilobyte
|
||||
'remote.decCount': {},
|
||||
'remote.decSize': {}, // in kilobyte
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'drive' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,16 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'federation';
|
||||
|
||||
export const schema = {
|
||||
'deliveredInstances': { uniqueIncrement: true, range: 'small' },
|
||||
'inboxInstances': { uniqueIncrement: true, range: 'small' },
|
||||
'stalled': { uniqueIncrement: true, range: 'small' },
|
||||
'sub': { accumulate: true, range: 'small' },
|
||||
'pub': { accumulate: true, range: 'small' },
|
||||
'pubsub': { accumulate: true, range: 'small' },
|
||||
'subActive': { accumulate: true, range: 'small' },
|
||||
'pubActive': { accumulate: true, range: 'small' },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'federation' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,32 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'instance';
|
||||
|
||||
export const schema = {
|
||||
'requests.failed': { range: 'small' },
|
||||
'requests.succeeded': { range: 'small' },
|
||||
'requests.received': { range: 'small' },
|
||||
'notes.total': { accumulate: true },
|
||||
'notes.inc': {},
|
||||
'notes.dec': {},
|
||||
'notes.diffs.normal': {},
|
||||
'notes.diffs.reply': {},
|
||||
'notes.diffs.renote': {},
|
||||
'notes.diffs.withFile': {},
|
||||
'users.total': { accumulate: true },
|
||||
'users.inc': { range: 'small' },
|
||||
'users.dec': { range: 'small' },
|
||||
'following.total': { accumulate: true },
|
||||
'following.inc': { range: 'small' },
|
||||
'following.dec': { range: 'small' },
|
||||
'followers.total': { accumulate: true },
|
||||
'followers.inc': { range: 'small' },
|
||||
'followers.dec': { range: 'small' },
|
||||
'drive.totalFiles': { accumulate: true },
|
||||
'drive.incFiles': {},
|
||||
'drive.decFiles': {},
|
||||
'drive.incUsage': {}, // in kilobyte
|
||||
'drive.decUsage': {}, // in kilobyte
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'instance' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,22 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'notes';
|
||||
|
||||
export const schema = {
|
||||
'local.total': { accumulate: true },
|
||||
'local.inc': {},
|
||||
'local.dec': {},
|
||||
'local.diffs.normal': {},
|
||||
'local.diffs.reply': {},
|
||||
'local.diffs.renote': {},
|
||||
'local.diffs.withFile': {},
|
||||
'remote.total': { accumulate: true },
|
||||
'remote.inc': {},
|
||||
'remote.dec': {},
|
||||
'remote.diffs.normal': {},
|
||||
'remote.diffs.reply': {},
|
||||
'remote.diffs.renote': {},
|
||||
'remote.diffs.withFile': {},
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'notes' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,14 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'perUserDrive';
|
||||
|
||||
export const schema = {
|
||||
'totalCount': { accumulate: true },
|
||||
'totalSize': { accumulate: true }, // in kilobyte
|
||||
'incCount': { range: 'small' },
|
||||
'incSize': {}, // in kilobyte
|
||||
'decCount': { range: 'small' },
|
||||
'decSize': {}, // in kilobyte
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'perUserDrive' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,20 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'perUserFollowing';
|
||||
|
||||
export const schema = {
|
||||
'local.followings.total': { accumulate: true },
|
||||
'local.followings.inc': { range: 'small' },
|
||||
'local.followings.dec': { range: 'small' },
|
||||
'local.followers.total': { accumulate: true },
|
||||
'local.followers.inc': { range: 'small' },
|
||||
'local.followers.dec': { range: 'small' },
|
||||
'remote.followings.total': { accumulate: true },
|
||||
'remote.followings.inc': { range: 'small' },
|
||||
'remote.followings.dec': { range: 'small' },
|
||||
'remote.followers.total': { accumulate: true },
|
||||
'remote.followers.inc': { range: 'small' },
|
||||
'remote.followers.dec': { range: 'small' },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'perUserFollowing' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,15 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'perUserNotes';
|
||||
|
||||
export const schema = {
|
||||
'total': { accumulate: true },
|
||||
'inc': { range: 'small' },
|
||||
'dec': { range: 'small' },
|
||||
'diffs.normal': { range: 'small' },
|
||||
'diffs.reply': { range: 'small' },
|
||||
'diffs.renote': { range: 'small' },
|
||||
'diffs.withFile': { range: 'small' },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'perUserNotes' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,12 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'perUserPv';
|
||||
|
||||
export const schema = {
|
||||
'upv.user': { uniqueIncrement: true, range: 'small' },
|
||||
'pv.user': { range: 'small' },
|
||||
'upv.visitor': { uniqueIncrement: true, range: 'small' },
|
||||
'pv.visitor': { range: 'small' },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'perUserPv' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,10 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
export const name = 'perUserReaction';
|
||||
|
||||
export const schema = {
|
||||
'local.count': { range: 'small' },
|
||||
'remote.count': { range: 'small' },
|
||||
} as const;
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'perUserReactions' as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,11 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'testGrouped';
|
||||
|
||||
export const schema = {
|
||||
'foo.total': { accumulate: true },
|
||||
'foo.inc': {},
|
||||
'foo.dec': {},
|
||||
} as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||
|
@@ -1,11 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'testIntersection';
|
||||
|
||||
export const schema = {
|
||||
'a': { uniqueIncrement: true },
|
||||
'b': { uniqueIncrement: true },
|
||||
'aAndB': { intersection: ['a', 'b'] },
|
||||
} as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'testUnique';
|
||||
|
||||
export const schema = {
|
||||
'foo': { uniqueIncrement: true },
|
||||
} as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,11 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'test';
|
||||
|
||||
export const schema = {
|
||||
'foo.total': { accumulate: true },
|
||||
'foo.inc': {},
|
||||
'foo.dec': {},
|
||||
} as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -1,14 +1,7 @@
|
||||
import Chart from '../../core.js';
|
||||
|
||||
import { chartsSchemas } from 'misskey-js/built/schemas/charts.js';
|
||||
export const name = 'users';
|
||||
|
||||
export const schema = {
|
||||
'local.total': { accumulate: true },
|
||||
'local.inc': { range: 'small' },
|
||||
'local.dec': { range: 'small' },
|
||||
'remote.total': { accumulate: true },
|
||||
'remote.inc': { range: 'small' },
|
||||
'remote.dec': { range: 'small' },
|
||||
} as const;
|
||||
export const schema = chartsSchemas[name];
|
||||
|
||||
export const entity = Chart.schemaToEntity(name, schema);
|
||||
|
@@ -10,22 +10,12 @@ import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/misc
|
||||
import type Logger from '@/logger.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Repository, DataSource } from 'typeorm';
|
||||
import type { ChartSchema as Schema, ChartResult, Unflatten } from 'misskey-js/built/schemas';
|
||||
|
||||
const COLUMN_PREFIX = '___' as const;
|
||||
const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const;
|
||||
const COLUMN_DELIMITER = '_' as const;
|
||||
|
||||
type Schema = Record<string, {
|
||||
uniqueIncrement?: boolean;
|
||||
|
||||
intersection?: string[] | ReadonlyArray<string>;
|
||||
|
||||
range?: 'big' | 'small' | 'medium';
|
||||
|
||||
// previousな値を引き継ぐかどうか
|
||||
accumulate?: boolean;
|
||||
}>;
|
||||
|
||||
type KeyToColumnName<T extends string> = T extends `${infer R1}.${infer R2}` ? `${R1}${typeof COLUMN_DELIMITER}${KeyToColumnName<R2>}` : T;
|
||||
|
||||
type Columns<S extends Schema> = {
|
||||
@@ -64,47 +54,6 @@ export type KVs<S extends Schema> = {
|
||||
[K in keyof S]: number;
|
||||
};
|
||||
|
||||
type ChartResult<T extends Schema> = {
|
||||
[P in keyof T]: number[];
|
||||
};
|
||||
|
||||
type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
|
||||
|
||||
type UnflattenSingleton<K extends string, V> = K extends `${infer A}.${infer B}`
|
||||
? { [_ in A]: UnflattenSingleton<B, V>; }
|
||||
: { [_ in K]: V; };
|
||||
|
||||
type Unflatten<T extends Record<string, any>> = UnionToIntersection<
|
||||
{
|
||||
[K in Extract<keyof T, string>]: UnflattenSingleton<K, T[K]>;
|
||||
}[Extract<keyof T, string>]
|
||||
>;
|
||||
|
||||
type ToJsonSchema<S> = {
|
||||
type: 'object';
|
||||
properties: {
|
||||
[K in keyof S]: S[K] extends number[] ? { type: 'array'; items: { type: 'number'; }; } : ToJsonSchema<S[K]>;
|
||||
},
|
||||
required: (keyof S)[];
|
||||
};
|
||||
|
||||
export function getJsonSchema<S extends Schema>(schema: S): ToJsonSchema<Unflatten<ChartResult<S>>> {
|
||||
const jsonSchema = {
|
||||
type: 'object',
|
||||
properties: {} as Record<string, unknown>,
|
||||
required: [],
|
||||
};
|
||||
|
||||
for (const k in schema) {
|
||||
jsonSchema.properties[k] = {
|
||||
type: 'array',
|
||||
items: { type: 'number' },
|
||||
};
|
||||
}
|
||||
|
||||
return jsonSchema as ToJsonSchema<Unflatten<ChartResult<S>>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 様々なチャートの管理を司るクラス
|
||||
*/
|
||||
|
@@ -5,6 +5,7 @@ import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { AbuseUserReport } from '@/models/entities/AbuseUserReport.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class AbuseUserReportEntityService {
|
||||
@@ -19,7 +20,7 @@ export class AbuseUserReportEntityService {
|
||||
@bindThis
|
||||
public async pack(
|
||||
src: AbuseUserReport['id'] | AbuseUserReport,
|
||||
) {
|
||||
): Promise<Packed<'AbuseUserReport'>> {
|
||||
const report = typeof src === 'object' ? src : await this.abuseUserReportsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return await awaitAll({
|
||||
@@ -46,7 +47,7 @@ export class AbuseUserReportEntityService {
|
||||
@bindThis
|
||||
public packMany(
|
||||
reports: any[],
|
||||
) {
|
||||
): Promise<Packed<'AbuseUserReport'>[]> {
|
||||
return Promise.all(reports.map(x => this.pack(x)));
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { AntennasRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Antenna } from '@/models/entities/Antenna.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { AccessTokensRepository, AppsRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { App } from '@/models/entities/App.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -6,6 +6,7 @@ import type { AuthSession } from '@/models/entities/AuthSession.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import { AppEntityService } from './AppEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class AuthSessionEntityService {
|
||||
@@ -21,7 +22,7 @@ export class AuthSessionEntityService {
|
||||
public async pack(
|
||||
src: AuthSession['id'] | AuthSession,
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'AuthSession'>> {
|
||||
const session = typeof src === 'object' ? src : await this.authSessionsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return await awaitAll({
|
||||
|
@@ -2,11 +2,12 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { BlockingsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Blocking } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import type { Serialized } from 'schema-type';
|
||||
|
||||
@Injectable()
|
||||
export class BlockingEntityService {
|
||||
@@ -39,7 +40,7 @@ export class BlockingEntityService {
|
||||
public packMany(
|
||||
blockings: any[],
|
||||
me: { id: User['id'] },
|
||||
) {
|
||||
): Promise<Packed<'Blocking'>[]> {
|
||||
return Promise.all(blockings.map(x => this.pack(x, me)));
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, NoteUnreadsRepository, NotesRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Channel } from '@/models/entities/Channel.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { ClipFavoritesRepository, ClipsRepository, User } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Clip } from '@/models/entities/Clip.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
@@ -47,7 +46,7 @@ export class ClipEntityService {
|
||||
public packMany(
|
||||
clips: Clip[],
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'Clip'>[]> {
|
||||
return Promise.all(clips.map(x => this.pack(x, me)));
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import { DataSource, In } from 'typeorm';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { NotesRepository, DriveFilesRepository } from '@/models/index.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { DriveFile } from '@/models/entities/DriveFile.js';
|
||||
@@ -265,11 +265,11 @@ export class DriveFileEntityService {
|
||||
public async packManyByIdsMap(
|
||||
fileIds: DriveFile['id'][],
|
||||
options?: PackOptions,
|
||||
): Promise<Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>> {
|
||||
): Promise<Map<Packed<'DriveFile'>>['id'], Serialized<Packed<'DriveFile'> | null>> {
|
||||
if (fileIds.length === 0) return new Map();
|
||||
const files = await this.driveFilesRepository.findBy({ id: In(fileIds) });
|
||||
const packedFiles = await this.packMany(files, options);
|
||||
const map = new Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>(packedFiles.map(f => [f.id, f]));
|
||||
const map = new Map<Packed<'DriveFile'>>['id'], Serialized<Packed<'DriveFile'> | null>(packedFiles.map(f => [f.id, f]));
|
||||
for (const id of fileIds) {
|
||||
if (!map.has(id)) map.set(id, null);
|
||||
}
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { DriveFilesRepository, DriveFoldersRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { DriveFolder } from '@/models/entities/DriveFolder.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { EmojisRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Emoji } from '@/models/entities/Emoji.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Flash } from '@/models/entities/Flash.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { FlashLikesRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { FlashLike } from '@/models/entities/FlashLike.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { FollowRequestsRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { FollowRequest } from '@/models/entities/FollowRequest.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { Packed } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class FollowRequestEntityService {
|
||||
@@ -21,7 +21,7 @@ export class FollowRequestEntityService {
|
||||
public async pack(
|
||||
src: FollowRequest['id'] | FollowRequest,
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'FollowRequest'>> {
|
||||
const request = typeof src === 'object' ? src : await this.followRequestsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return {
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { FollowingsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Following } from '@/models/entities/Following.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { GalleryLikesRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { GalleryLike } from '@/models/entities/GalleryLike.js';
|
||||
import { GalleryPostEntityService } from './GalleryPostEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { GalleryPost } from '@/models/entities/GalleryPost.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { HashtagsRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Hashtag } from '@/models/entities/Hashtag.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { InstancesRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Instance } from '@/models/entities/Instance.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -2,10 +2,10 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { ModerationLogsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { ModerationLog } from '@/models/entities/ModerationLog.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class ModerationLogEntityService {
|
||||
@@ -20,7 +20,7 @@ export class ModerationLogEntityService {
|
||||
@bindThis
|
||||
public async pack(
|
||||
src: ModerationLog['id'] | ModerationLog,
|
||||
) {
|
||||
): Promise<Packed<'ModerationLog'>> {
|
||||
const log = typeof src === 'object' ? src : await this.moderationLogsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return await awaitAll({
|
||||
@@ -38,8 +38,7 @@ export class ModerationLogEntityService {
|
||||
@bindThis
|
||||
public packMany(
|
||||
reports: any[],
|
||||
) {
|
||||
): Promise<Packed<'ModerationLog'>[]> {
|
||||
return Promise.all(reports.map(x => this.pack(x)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { MutingsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Muting } from '@/models/entities/Muting.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -3,7 +3,7 @@ import { DataSource, In } from 'typeorm';
|
||||
import * as mfm from 'mfm-js';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { nyaize } from '@/misc/nyaize.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { NoteFavoritesRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { NoteFavorite } from '@/models/entities/NoteFavorite.js';
|
||||
import { NoteEntityService } from './NoteEntityService.js';
|
||||
@@ -21,7 +21,7 @@ export class NoteFavoriteEntityService {
|
||||
public async pack(
|
||||
src: NoteFavorite['id'] | NoteFavorite,
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'NoteFavorite'>> {
|
||||
const favorite = typeof src === 'object' ? src : await this.noteFavoritesRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return {
|
||||
|
@@ -1,10 +1,9 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { NoteReactionsRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { OnModuleInit } from '@nestjs/common';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { NoteReaction } from '@/models/entities/NoteReaction.js';
|
||||
import type { ReactionService } from '../ReactionService.js';
|
||||
|
@@ -6,10 +6,10 @@ import type { AccessTokensRepository, FollowRequestsRepository, NoteReactionsRep
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Notification } from '@/models/entities/Notification.js';
|
||||
import type { Note } from '@/models/entities/Note.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { isNotNull } from '@/misc/is-not-null.js';
|
||||
import { notificationTypes } from '@/types.js';
|
||||
import { notificationTypes } from 'misskey-js';
|
||||
import type { OnModuleInit } from '@nestjs/common';
|
||||
import type { CustomEmojiService } from '../CustomEmojiService.js';
|
||||
import type { UserEntityService } from './UserEntityService.js';
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { DriveFilesRepository, PagesRepository, PageLikesRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Page } from '@/models/entities/Page.js';
|
||||
import type { DriveFile } from '@/models/entities/DriveFile.js';
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { PageLikesRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { PageLike } from '@/models/entities/PageLike.js';
|
||||
import { PageEntityService } from './PageEntityService.js';
|
||||
|
@@ -2,8 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { RenoteMutingsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { RenoteMuting } from '@/models/entities/RenoteMuting.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@@ -8,6 +8,7 @@ import type { Role } from '@/models/entities/Role.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class RoleEntityService {
|
||||
@@ -26,7 +27,7 @@ export class RoleEntityService {
|
||||
public async pack(
|
||||
src: Role['id'] | Role,
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'Role'>> {
|
||||
const role = typeof src === 'object' ? src : await this.rolesRepository.findOneByOrFail({ id: src });
|
||||
|
||||
const assignedCount = await this.roleAssignmentsRepository.createQueryBuilder('assign')
|
||||
@@ -37,7 +38,7 @@ export class RoleEntityService {
|
||||
}))
|
||||
.getCount();
|
||||
|
||||
const policies = { ...role.policies };
|
||||
const policies: { [x: string]: Packed<'RolePolicy'> } = { ...role.policies };
|
||||
for (const [k, v] of Object.entries(DEFAULT_POLICIES)) {
|
||||
if (policies[k] == null) policies[k] = {
|
||||
useDefault: true,
|
||||
@@ -72,8 +73,7 @@ export class RoleEntityService {
|
||||
public packMany(
|
||||
roles: any[],
|
||||
me: { id: User['id'] },
|
||||
) {
|
||||
): Promise<Packed<'Role'>[]> {
|
||||
return Promise.all(roles.map(x => this.pack(x, me)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { SigninsRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Signin } from '@/models/entities/Signin.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
@@ -19,8 +19,10 @@ export class SigninEntityService {
|
||||
@bindThis
|
||||
public async pack(
|
||||
src: Signin,
|
||||
) {
|
||||
return src;
|
||||
): Promise<Packed<'SignIn'>> {
|
||||
return {
|
||||
...src,
|
||||
createdAt: src.createdAt.toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { In, Not } from 'typeorm';
|
||||
import * as Redis from 'ioredis';
|
||||
import Ajv from 'ajv';
|
||||
import _Ajv from 'ajv';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { Promiseable } from '@/misc/prelude/await-all.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js';
|
||||
@@ -28,9 +28,10 @@ type IsMeAndIsUserDetailed<ExpectsMe extends boolean | null, Detailed extends bo
|
||||
Detailed extends true ?
|
||||
ExpectsMe extends true ? Packed<'MeDetailed'> :
|
||||
ExpectsMe extends false ? Packed<'UserDetailedNotMe'> :
|
||||
Packed<'UserDetailed'> :
|
||||
(Packed<'MeDetailed'> | Packed<'UserDetailedNotMe'>) :
|
||||
Packed<'UserLite'>;
|
||||
|
||||
const Ajv = _Ajv.default;
|
||||
const ajv = new Ajv();
|
||||
|
||||
function isLocalUser(user: User): user is LocalUser;
|
||||
@@ -290,7 +291,7 @@ export class UserEntityService implements OnModuleInit {
|
||||
return `${this.config.url}/users/${userId}`;
|
||||
}
|
||||
|
||||
public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>(
|
||||
public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false, R = IsMeAndIsUserDetailed<ExpectsMe, D>>(
|
||||
src: User['id'] | User,
|
||||
me?: { id: User['id']; } | null | undefined,
|
||||
options?: {
|
||||
@@ -298,7 +299,7 @@ export class UserEntityService implements OnModuleInit {
|
||||
includeSecrets?: boolean,
|
||||
userProfile?: UserProfile,
|
||||
},
|
||||
): Promise<IsMeAndIsUserDetailed<ExpectsMe, D>> {
|
||||
): Promise<R> {
|
||||
const opts = Object.assign({
|
||||
detail: false,
|
||||
includeSecrets: false,
|
||||
@@ -498,19 +499,19 @@ export class UserEntityService implements OnModuleInit {
|
||||
isMuted: relation.isMuted,
|
||||
isRenoteMuted: relation.isRenoteMuted,
|
||||
} : {}),
|
||||
} as Promiseable<Packed<'User'>> as Promiseable<IsMeAndIsUserDetailed<ExpectsMe, D>>;
|
||||
} as Promiseable<R>;
|
||||
|
||||
return await awaitAll(packed);
|
||||
}
|
||||
|
||||
public packMany<D extends boolean = false>(
|
||||
public packMany<D extends boolean = false, R = IsUserDetailed<D>>(
|
||||
users: (User['id'] | User)[],
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
options?: {
|
||||
detail?: D,
|
||||
includeSecrets?: boolean,
|
||||
},
|
||||
): Promise<IsUserDetailed<D>[]> {
|
||||
return Promise.all(users.map(u => this.pack(u, me, options)));
|
||||
): Promise<R[]> {
|
||||
return Promise.all(users.map(u => this.pack<null, D, R>(u, me, options)));
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { UserListJoiningsRepository, UserListsRepository } from '@/models/index.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
import type { UserList } from '@/models/entities/UserList.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
@@ -39,4 +38,3 @@ export class UserListEntityService {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ import si from 'systeminformation';
|
||||
import Xev from 'xev';
|
||||
import * as osUtils from 'os-utils';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||
|
||||
const ev = new Xev();
|
||||
@@ -14,9 +15,10 @@ const round = (num: number) => Math.round(num * 10) / 10;
|
||||
|
||||
@Injectable()
|
||||
export class ServerStatsService implements OnApplicationShutdown {
|
||||
private intervalId: NodeJS.Timer;
|
||||
private intervalId: NodeJS.Timer | null = null;
|
||||
|
||||
constructor(
|
||||
private metaService: MetaService,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -24,7 +26,9 @@ export class ServerStatsService implements OnApplicationShutdown {
|
||||
* Report server stats regularly
|
||||
*/
|
||||
@bindThis
|
||||
public start(): void {
|
||||
public async start(): Promise<void> {
|
||||
if (!(await this.metaService.fetch(true)).enableServerMachineStats) return;
|
||||
|
||||
const log = [] as any[];
|
||||
|
||||
ev.on('requestServerStatsLog', x => {
|
||||
@@ -64,7 +68,9 @@ export class ServerStatsService implements OnApplicationShutdown {
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
clearInterval(this.intervalId);
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
@@ -4,7 +4,7 @@ import { default as convertColor } from 'color-convert';
|
||||
import { format as dateFormat } from 'date-fns';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { envOption } from './env.js';
|
||||
import type { KEYWORD } from 'color-convert/conversions';
|
||||
import type { KEYWORD } from 'color-convert/conversions.js';
|
||||
|
||||
type Context = {
|
||||
name: string;
|
||||
|
@@ -83,6 +83,16 @@ export class RedisKVCache<T> {
|
||||
|
||||
// TODO: イベント発行して他プロセスのメモリキャッシュも更新できるようにする
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public gc() {
|
||||
this.memoryCache.gc();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose() {
|
||||
this.memoryCache.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class RedisSingleCache<T> {
|
||||
@@ -174,10 +184,15 @@ export class RedisSingleCache<T> {
|
||||
export class MemoryKVCache<T> {
|
||||
public cache: Map<string, { date: number; value: T; }>;
|
||||
private lifetime: number;
|
||||
private gcIntervalHandle: NodeJS.Timer;
|
||||
|
||||
constructor(lifetime: MemoryKVCache<never>['lifetime']) {
|
||||
this.cache = new Map();
|
||||
this.lifetime = lifetime;
|
||||
|
||||
this.gcIntervalHandle = setInterval(() => {
|
||||
this.gc();
|
||||
}, 1000 * 60 * 3);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -200,7 +215,7 @@ export class MemoryKVCache<T> {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public delete(key: string) {
|
||||
public delete(key: string): void {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
|
||||
@@ -255,6 +270,21 @@ export class MemoryKVCache<T> {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public gc(): void {
|
||||
const now = Date.now();
|
||||
for (const [key, { date }] of this.cache.entries()) {
|
||||
if ((now - date) > this.lifetime) {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
clearInterval(this.gcIntervalHandle);
|
||||
}
|
||||
}
|
||||
|
||||
export class MemorySingleCache<T> {
|
||||
|
@@ -1,3 +1,3 @@
|
||||
import { secureRndstr } from '@/misc/secure-rndstr.js';
|
||||
|
||||
export default () => secureRndstr(16, true);
|
||||
export default () => secureRndstr(16);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import IPCIDR from 'ip-cidr';
|
||||
|
||||
export function getIpHash(ip: string) {
|
||||
export function getIpHash(ip: string): string {
|
||||
try {
|
||||
// because a single person may control many IPv6 addresses,
|
||||
// only a /64 subnet prefix of any IP will be taken into account.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { Packed } from './json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
|
||||
/**
|
||||
* 投稿を表す文字列を取得します。
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { Packed } from './json-schema.js';
|
||||
import type { Packed } from 'misskey-js';
|
||||
|
||||
export function isInstanceMuted(note: Packed<'Note'>, mutedInstances: Set<string>): boolean {
|
||||
if (mutedInstances.has(note.user.host ?? '')) return true;
|
||||
|
@@ -1,185 +0,0 @@
|
||||
import {
|
||||
packedUserLiteSchema,
|
||||
packedUserDetailedNotMeOnlySchema,
|
||||
packedMeDetailedOnlySchema,
|
||||
packedUserDetailedNotMeSchema,
|
||||
packedMeDetailedSchema,
|
||||
packedUserDetailedSchema,
|
||||
packedUserSchema,
|
||||
} from '@/models/json-schema/user.js';
|
||||
import { packedNoteSchema } from '@/models/json-schema/note.js';
|
||||
import { packedUserListSchema } from '@/models/json-schema/user-list.js';
|
||||
import { packedAppSchema } from '@/models/json-schema/app.js';
|
||||
import { packedNotificationSchema } from '@/models/json-schema/notification.js';
|
||||
import { packedDriveFileSchema } from '@/models/json-schema/drive-file.js';
|
||||
import { packedDriveFolderSchema } from '@/models/json-schema/drive-folder.js';
|
||||
import { packedFollowingSchema } from '@/models/json-schema/following.js';
|
||||
import { packedMutingSchema } from '@/models/json-schema/muting.js';
|
||||
import { packedRenoteMutingSchema } from '@/models/json-schema/renote-muting.js';
|
||||
import { packedBlockingSchema } from '@/models/json-schema/blocking.js';
|
||||
import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js';
|
||||
import { packedHashtagSchema } from '@/models/json-schema/hashtag.js';
|
||||
import { packedPageSchema } from '@/models/json-schema/page.js';
|
||||
import { packedNoteFavoriteSchema } from '@/models/json-schema/note-favorite.js';
|
||||
import { packedChannelSchema } from '@/models/json-schema/channel.js';
|
||||
import { packedAntennaSchema } from '@/models/json-schema/antenna.js';
|
||||
import { packedClipSchema } from '@/models/json-schema/clip.js';
|
||||
import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js';
|
||||
import { packedQueueCountSchema } from '@/models/json-schema/queue.js';
|
||||
import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.js';
|
||||
import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/json-schema/emoji.js';
|
||||
import { packedFlashSchema } from '@/models/json-schema/flash.js';
|
||||
|
||||
export const refs = {
|
||||
UserLite: packedUserLiteSchema,
|
||||
UserDetailedNotMeOnly: packedUserDetailedNotMeOnlySchema,
|
||||
MeDetailedOnly: packedMeDetailedOnlySchema,
|
||||
UserDetailedNotMe: packedUserDetailedNotMeSchema,
|
||||
MeDetailed: packedMeDetailedSchema,
|
||||
UserDetailed: packedUserDetailedSchema,
|
||||
User: packedUserSchema,
|
||||
|
||||
UserList: packedUserListSchema,
|
||||
App: packedAppSchema,
|
||||
Note: packedNoteSchema,
|
||||
NoteReaction: packedNoteReactionSchema,
|
||||
NoteFavorite: packedNoteFavoriteSchema,
|
||||
Notification: packedNotificationSchema,
|
||||
DriveFile: packedDriveFileSchema,
|
||||
DriveFolder: packedDriveFolderSchema,
|
||||
Following: packedFollowingSchema,
|
||||
Muting: packedMutingSchema,
|
||||
RenoteMuting: packedRenoteMutingSchema,
|
||||
Blocking: packedBlockingSchema,
|
||||
Hashtag: packedHashtagSchema,
|
||||
Page: packedPageSchema,
|
||||
Channel: packedChannelSchema,
|
||||
QueueCount: packedQueueCountSchema,
|
||||
Antenna: packedAntennaSchema,
|
||||
Clip: packedClipSchema,
|
||||
FederationInstance: packedFederationInstanceSchema,
|
||||
GalleryPost: packedGalleryPostSchema,
|
||||
EmojiSimple: packedEmojiSimpleSchema,
|
||||
EmojiDetailed: packedEmojiDetailedSchema,
|
||||
Flash: packedFlashSchema,
|
||||
};
|
||||
|
||||
export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;
|
||||
|
||||
type TypeStringef = 'null' | 'boolean' | 'integer' | 'number' | 'string' | 'array' | 'object' | 'any';
|
||||
type StringDefToType<T extends TypeStringef> =
|
||||
T extends 'null' ? null :
|
||||
T extends 'boolean' ? boolean :
|
||||
T extends 'integer' ? number :
|
||||
T extends 'number' ? number :
|
||||
T extends 'string' ? string | Date :
|
||||
T extends 'array' ? ReadonlyArray<any> :
|
||||
T extends 'object' ? Record<string, any> :
|
||||
any;
|
||||
|
||||
// https://swagger.io/specification/?sbsearch=optional#schema-object
|
||||
type OfSchema = {
|
||||
readonly anyOf?: ReadonlyArray<Schema>;
|
||||
readonly oneOf?: ReadonlyArray<Schema>;
|
||||
readonly allOf?: ReadonlyArray<Schema>;
|
||||
}
|
||||
|
||||
export interface Schema extends OfSchema {
|
||||
readonly type?: TypeStringef;
|
||||
readonly nullable?: boolean;
|
||||
readonly optional?: boolean;
|
||||
readonly items?: Schema;
|
||||
readonly properties?: Obj;
|
||||
readonly required?: ReadonlyArray<Extract<keyof NonNullable<this['properties']>, string>>;
|
||||
readonly description?: string;
|
||||
readonly example?: any;
|
||||
readonly format?: string;
|
||||
readonly ref?: keyof typeof refs;
|
||||
readonly enum?: ReadonlyArray<string | null>;
|
||||
readonly default?: (this['type'] extends TypeStringef ? StringDefToType<this['type']> : any) | null;
|
||||
readonly maxLength?: number;
|
||||
readonly minLength?: number;
|
||||
readonly maximum?: number;
|
||||
readonly minimum?: number;
|
||||
readonly pattern?: string;
|
||||
}
|
||||
|
||||
type RequiredPropertyNames<s extends Obj> = {
|
||||
[K in keyof s]:
|
||||
// K is not optional
|
||||
s[K]['optional'] extends false ? K :
|
||||
// K has default value
|
||||
s[K]['default'] extends null | string | number | boolean | Record<string, unknown> ? K :
|
||||
never
|
||||
}[keyof s];
|
||||
|
||||
export type Obj = Record<string, Schema>;
|
||||
|
||||
// https://github.com/misskey-dev/misskey/issues/8535
|
||||
// To avoid excessive stack depth error,
|
||||
// deceive TypeScript with UnionToIntersection (or more precisely, `infer` expression within it).
|
||||
export type ObjType<s extends Obj, RequiredProps extends ReadonlyArray<keyof s>> =
|
||||
UnionToIntersection<
|
||||
{ -readonly [R in RequiredPropertyNames<s>]-?: SchemaType<s[R]> } &
|
||||
{ -readonly [R in RequiredProps[number]]-?: SchemaType<s[R]> } &
|
||||
{ -readonly [P in keyof s]?: SchemaType<s[P]> }
|
||||
>;
|
||||
|
||||
type NullOrUndefined<p extends Schema, T> =
|
||||
| (p['nullable'] extends true ? null : never)
|
||||
| (p['optional'] extends true ? undefined : never)
|
||||
| T;
|
||||
|
||||
// https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection
|
||||
// Get intersection from union
|
||||
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||
type PartialIntersection<T> = Partial<UnionToIntersection<T>>;
|
||||
|
||||
// https://github.com/misskey-dev/misskey/pull/8144#discussion_r785287552
|
||||
// To get union, we use `Foo extends any ? Hoge<Foo> : never`
|
||||
type UnionSchemaType<a extends readonly any[], X extends Schema = a[number]> = X extends any ? SchemaType<X> : never;
|
||||
//type UnionObjectSchemaType<a extends readonly any[], X extends Schema = a[number]> = X extends any ? ObjectSchemaType<X> : never;
|
||||
type UnionObjType<s extends Obj, a extends readonly any[], X extends ReadonlyArray<keyof s> = a[number]> = X extends any ? ObjType<s, X> : never;
|
||||
type ArrayUnion<T> = T extends any ? Array<T> : never;
|
||||
|
||||
type ObjectSchemaTypeDef<p extends Schema> =
|
||||
p['ref'] extends keyof typeof refs ? Packed<p['ref']> :
|
||||
p['properties'] extends NonNullable<Obj> ?
|
||||
p['anyOf'] extends ReadonlyArray<Schema> ? p['anyOf'][number]['required'] extends ReadonlyArray<keyof p['properties']> ?
|
||||
UnionObjType<p['properties'], NonNullable<p['anyOf'][number]['required']>> & ObjType<p['properties'], NonNullable<p['required']>>
|
||||
: never
|
||||
: ObjType<p['properties'], NonNullable<p['required']>>
|
||||
:
|
||||
p['anyOf'] extends ReadonlyArray<Schema> ? never : // see CONTRIBUTING.md
|
||||
p['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<p['allOf']>> :
|
||||
any
|
||||
|
||||
type ObjectSchemaType<p extends Schema> = NullOrUndefined<p, ObjectSchemaTypeDef<p>>;
|
||||
|
||||
export type SchemaTypeDef<p extends Schema> =
|
||||
p['type'] extends 'null' ? null :
|
||||
p['type'] extends 'integer' ? number :
|
||||
p['type'] extends 'number' ? number :
|
||||
p['type'] extends 'string' ? (
|
||||
p['enum'] extends readonly (string | null)[] ?
|
||||
p['enum'][number] :
|
||||
p['format'] extends 'date-time' ? string : // Dateにする??
|
||||
string
|
||||
) :
|
||||
p['type'] extends 'boolean' ? boolean :
|
||||
p['type'] extends 'object' ? ObjectSchemaTypeDef<p> :
|
||||
p['type'] extends 'array' ? (
|
||||
p['items'] extends OfSchema ? (
|
||||
p['items']['anyOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<NonNullable<p['items']['anyOf']>>[] :
|
||||
p['items']['oneOf'] extends ReadonlyArray<Schema> ? ArrayUnion<UnionSchemaType<NonNullable<p['items']['oneOf']>>> :
|
||||
p['items']['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<NonNullable<p['items']['allOf']>>>[] :
|
||||
never
|
||||
) :
|
||||
p['items'] extends NonNullable<Schema> ? SchemaTypeDef<p['items']>[] :
|
||||
any[]
|
||||
) :
|
||||
p['anyOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<p['anyOf']> & PartialIntersection<UnionSchemaType<p['anyOf']>> :
|
||||
p['oneOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<p['oneOf']> :
|
||||
any;
|
||||
|
||||
export type SchemaType<p extends Schema> = NullOrUndefined<p, SchemaTypeDef<p>>;
|
@@ -1,10 +1,9 @@
|
||||
import * as crypto from 'node:crypto';
|
||||
|
||||
const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||
export const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||
const LU_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
export function secureRndstr(length = 32, useLU = true): string {
|
||||
const chars = useLU ? LU_CHARS : L_CHARS;
|
||||
export function secureRndstr(length = 32, { chars = LU_CHARS } = {}): string {
|
||||
const chars_len = chars.length;
|
||||
|
||||
let str = '';
|
||||
|
@@ -101,13 +101,25 @@ export class Meta {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public errorImageUrl: string | null;
|
||||
public iconUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public iconUrl: string | null;
|
||||
public serverErrorImageUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public notFoundImageUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public infoImageUrl: string | null;
|
||||
|
||||
@Column('boolean', {
|
||||
default: true,
|
||||
@@ -401,6 +413,16 @@ export class Meta {
|
||||
})
|
||||
public enableChartsForFederatedInstances: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public enableServerMachineStats: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: true,
|
||||
})
|
||||
public enableIdenticonGeneration: boolean;
|
||||
|
||||
@Column('jsonb', {
|
||||
default: { },
|
||||
})
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||
import { id } from '../id.js';
|
||||
import { mutedNoteReasons } from '../../types.js';
|
||||
import { mutedNoteReasons } from 'misskey-js';
|
||||
import { Note } from './Note.js';
|
||||
import { User } from './User.js';
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm';
|
||||
import { id } from '../id.js';
|
||||
import { noteVisibilities } from '../../types.js';
|
||||
import { noteVisibilities } from 'misskey-js';
|
||||
import { User } from './User.js';
|
||||
import { Channel } from './Channel.js';
|
||||
import type { DriveFile } from './DriveFile.js';
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { notificationTypes } from '@/types.js';
|
||||
import { ACHIEVEMENT_TYPES, notificationTypes } from 'misskey-js';
|
||||
import { User } from './User.js';
|
||||
import { Note } from './Note.js';
|
||||
import { FollowRequest } from './FollowRequest.js';
|
||||
@@ -39,7 +39,7 @@ export type Notification = {
|
||||
|
||||
choice: number | null;
|
||||
|
||||
achievement: string | null;
|
||||
achievement: typeof ACHIEVEMENT_TYPES[number] | null;
|
||||
|
||||
/**
|
||||
* アプリ通知のbody
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user