Compare commits

...

137 Commits

Author SHA1 Message Date
syuilo
d078f78602 Merge branch 'develop' 2019-07-05 02:13:02 +09:00
syuilo
a5c6145237 11.24.0 2019-07-05 02:12:45 +09:00
syuilo
50df9f7dff Update node version 2019-07-05 02:12:23 +09:00
syuilo
7b33522d97 New Crowdin translations (#5082)
* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Korean)
2019-07-05 02:09:59 +09:00
syuilo
d3edf03125 Fix errors 2019-07-05 02:00:54 +09:00
Acid Chicken (硫酸鶏)
d5cd38b459 Create partial type definition for 'jsrsasign' (#5092)
* Create partial type definition for 'jsrsasign'

* Update comments

* Add jsrsasign dependency

* Make some params of Signature class optional

* Make init argument of Signature.init optional
2019-07-05 01:54:16 +09:00
syuilo
2c76d410ab Resolve #1867 2019-07-04 22:59:52 +09:00
syuilo
dfd991a6c6 テストメールは管理者アドレスに送信するように 2019-07-04 21:08:47 +09:00
syuilo
16b81fff38 Resolve #3431 2019-07-04 21:07:02 +09:00
syuilo
f379a721f1 Fix bug 2019-07-04 20:52:21 +09:00
syuilo
194a958d40 Update CHANGELOG.md 2019-07-04 20:40:02 +09:00
syuilo
327ffd3498 Resolve #4321 2019-07-04 20:39:33 +09:00
syuilo
40276d7f1a テストページ廃止 2019-07-04 20:26:12 +09:00
syuilo
9254f95679 Update CHANGELOG.md 2019-07-04 15:14:13 +09:00
syuilo
2e1a9dffbe Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-07-04 14:45:33 +09:00
syuilo
ead5a6a258 APNG support 2019-07-04 14:45:28 +09:00
MeiMei
97002400a8 アバターファイル選択でimage以外は表示しないように (#5098) 2019-07-04 14:31:30 +09:00
syuilo
5e7a4e4752 Fix MIME 2019-07-03 23:43:09 +09:00
syuilo
2c955858a0 Add note 2019-07-03 20:31:52 +09:00
syuilo
a0e56504de Update package.json 2019-07-03 20:31:38 +09:00
Satsuki Yanagi
d46e9f5abe Update ESLint 🚀 (#5097) 2019-07-03 20:20:02 +09:00
Mary
fd94b817ab Implement Webauthn 🎉 (#5088)
* Implement Webauthn 🎉

* Share hexifyAB

* Move hr inside template and add AttestationChallenges janitor daemon

* Apply suggestions from code review

Co-Authored-By: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* Add newline at the end of file

* Fix stray newline in promise chain

* Ignore var in try{}catch(){} block

Co-Authored-By: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* Add missing comma

* Add missing semicolon

* Support more attestation formats

* add support for more key types and linter pass

* Refactor

* Refactor

* credentialId --> id

* Fix

* Improve readability

* Add indexes

* fixes for credentialId->id

* Avoid changing store state

* Fix syntax error and code style

* Remove unused import

* Refactor of getkey API

* Create 1561706992953-webauthn.ts

* Update ja-JP.yml

* Add type annotations

* Fix code style

* Specify depedency version

* Fix code style

* Fix janitor daemon and login requesting 2FA regardless of status
2019-07-03 20:18:07 +09:00
syuilo
f17e229c1e Resolve #5072 2019-07-03 03:58:45 +09:00
syuilo
96e23b0e5b MFMで連続したスペースがひとつに纏まるのを修正 2019-07-02 20:52:37 +09:00
syuilo
014b945ea6 Fix test 2019-07-02 20:08:30 +09:00
syuilo
76693138d3 Fix MFM parsing: Ignore parent [] of URL 2019-07-02 20:05:52 +09:00
syuilo
10677b57d4 Update dependencies 🚀 2019-07-02 19:20:34 +09:00
syuilo
5f0ac0f46a Fix #5073 2019-07-02 19:17:14 +09:00
syuilo
7ffe559525 Resolve #5085 2019-07-02 18:32:24 +09:00
Acid Chicken (硫酸鶏)
919e3e2fed Update README.md [AUTOGEN] (#5094) 2019-07-02 15:37:24 +09:00
syuilo
03e999875a リモートファイルの削除が重い問題を修正 2019-07-01 21:12:14 +09:00
syuilo
ed0070c470 Set job concurrency to reduce performance issue 2019-07-01 20:37:26 +09:00
syuilo
d764316708 Simplify log domain 2019-07-01 03:25:31 +09:00
syuilo
06b1203ef9 Create 1561873850023-ChartIndexes.ts 2019-06-30 14:51:57 +09:00
syuilo
b2cf74e878 Create accept-migration.ts 2019-06-30 04:49:30 +09:00
syuilo
21064f7859 Add initial migration 2019-06-29 23:19:21 +09:00
syuilo
bb2d76ffa3 Fix #4926 2019-06-29 23:12:00 +09:00
syuilo
763b70e01b Revert "Update ormconfig.ts"
This reverts commit 5a349eb376.
2019-06-29 15:58:04 +09:00
syuilo
5a349eb376 Update ormconfig.ts 2019-06-29 15:31:54 +09:00
MeiMei
0141affe05 Fix: AP object / actor type (#5086)
* attributedToがArrayの場合などに対応

* attachment以外で来るDocument系のObjectに対応

* Renote, Reply 対応

* 表示をいい感じに

* fix type

* revert as const

* Fix Note / Question type

* attributedToのtypeで複合配列を想定する
2019-06-28 18:54:09 +09:00
syuilo
a8379e3bc9 Use as const
#5089
2019-06-28 16:38:48 +09:00
syuilo
952789cc1e Use as const
#5089
2019-06-27 18:04:09 +09:00
syuilo
0500600cdd Merge branch 'develop' 2019-06-25 01:27:51 +09:00
syuilo
6b897e562a 11.23.1 2019-06-25 01:27:33 +09:00
syuilo
f74bc309b1 Fix bug 2019-06-25 01:24:01 +09:00
syuilo
bc83963ac7 English nyaize 2019-06-24 22:20:13 +09:00
syuilo
94715e6153 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-06-23 16:12:37 +09:00
syuilo
31a5247b9c 🎨 2019-06-23 16:12:11 +09:00
syuilo
ac9f77752d New translations ja-JP.yml (Chinese Simplified) (#5081) 2019-06-23 01:53:21 +09:00
syuilo
73ac2632c2 Merge branch 'develop' 2019-06-23 00:22:33 +09:00
syuilo
20f11a6701 11.23.0 2019-06-23 00:21:58 +09:00
syuilo
9bdc67c1f6 New Crowdin translations (#5065)
* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)
2019-06-23 00:21:04 +09:00
syuilo
bb4ca7b31a Resolve #5010 2019-06-23 00:06:39 +09:00
syuilo
89f16668e6 Fix #4519 2019-06-22 04:17:02 +09:00
syuilo
8409b59dea Improve usability 2019-06-22 04:09:53 +09:00
MeiMei
1707002d43 Block all activities from suspended users (#5076) 2019-06-21 15:42:07 +09:00
MeiMei
16b03fc157 Improve url-preview (#5077)
* url-previewリクエスト時にハッシュは除く

* ハッシュだけ違うプレビューカードは表示しない

*  url-previewをユーザーロケールで出し分けるように

* Fix code style
2019-06-21 15:41:02 +09:00
syuilo
fa0023e541 Fix bug 2019-06-21 15:11:56 +09:00
syuilo
aec5911821 Improve sync 2019-06-21 15:08:17 +09:00
syuilo
26f4c038f3 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-06-21 13:06:55 +09:00
syuilo
6136f6f33a デッキの状態を同期できるように 2019-06-21 13:06:47 +09:00
MeiMei
2b8d0225cc Enable ServiceWorker (#5075) 2019-06-21 11:50:38 +09:00
syuilo
18184441f1 ホームのカスタマイズ情報を複数のデバイス間で同期できるように 2019-06-21 01:50:01 +09:00
syuilo
bd83939993 Provide Redis version 2019-06-20 22:55:57 +09:00
syuilo
2c1932faa7 Add psql version to info page 2019-06-20 22:52:35 +09:00
syuilo
33d79420eb Fix code style 2019-06-19 17:47:24 +09:00
syuilo
80d8af84dd Merge branch 'develop' 2019-06-18 19:16:41 +09:00
syuilo
aac519bf80 11.22.0 2019-06-18 19:15:55 +09:00
syuilo
d64dffbdda Add index 2019-06-18 17:11:28 +09:00
syuilo
4015ccef2f Add chart indices 2019-06-18 17:10:28 +09:00
syuilo
b6f985abaf Update summaly to 2.3.0 2019-06-18 16:58:32 +09:00
syuilo
2dac8d3d1f Update db.vue 2019-06-18 16:53:14 +09:00
syuilo
4f284e1bc0 Resolve #5063 2019-06-18 16:49:58 +09:00
syuilo
b0280355e8 Better request interval 2019-06-18 16:17:20 +09:00
syuilo
048d88b784 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-06-18 15:56:31 +09:00
syuilo
bb52ebdc3e Provide version of postgresql 2019-06-18 15:56:03 +09:00
Satsuki Yanagi
5f2fda85ba Resolve #5069 (#5070) 2019-06-18 15:42:08 +09:00
syuilo
1331f0b953 Use WHATWG API
> New application code should use the WHATWG API.
2019-06-18 15:27:13 +09:00
syuilo
736fdabc1d Fix #2637 2019-06-18 15:19:19 +09:00
syuilo
7096c0ca49 Add note 2019-06-18 14:04:41 +09:00
syuilo
1a984de8e8 Better error handling 2019-06-18 13:58:59 +09:00
syuilo
285d0d13f9 Fix MFM URL parsing 2019-06-17 20:15:19 +09:00
syuilo
63c659bc8f Fix MFM strike parsing 2019-06-16 21:42:57 +09:00
syuilo
af60b45ee7 Fix MFM italic parsing 2019-06-16 21:30:51 +09:00
syuilo
e7effd606d Fix test 2019-06-16 21:30:26 +09:00
syuilo
5042d23bc4 Simplify test 2019-06-16 21:29:31 +09:00
syuilo
b134467bd3 Add some MFM tests 2019-06-16 21:26:43 +09:00
syuilo
5cc1aab530 Merge branch 'develop' 2019-06-16 16:09:04 +09:00
syuilo
49d57ce049 11.21.0 2019-06-16 16:08:36 +09:00
syuilo
f1feceaf1a Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-06-16 16:08:29 +09:00
syuilo
1204e1c5e4 Update dependencies 🚀 2019-06-16 16:07:57 +09:00
syuilo
96cf4c30cf New Crowdin translations (#5053)
* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (French)
2019-06-16 16:06:00 +09:00
MeiMei
a3853611ad Fix: オートコンプリートにアニメーション停止が効かない (#5061) 2019-06-16 16:04:27 +09:00
MeiMei
ef7eaaabfa Support Unicode 12.0 Emoji (#5062) 2019-06-16 14:24:37 +09:00
MeiMei
a4a96710b0 閉鎖しているホストにはAP deliverしないように (#5057)
* 閉鎖しているホストにはAP deliverしないように

* fix case
2019-06-15 17:09:59 +09:00
syuilo
6d08909b2f Refactor 2019-06-15 17:06:03 +09:00
syuilo
2615368b1e Resolve #365 2019-06-15 00:07:41 +09:00
Aya Morisawa
2bd03ca725 Use halfwidth space instead of fullwidth space in code (#5054) 2019-06-14 22:54:19 +09:00
MeiMei
67dda01fcb image以外はproxyしないように (#5051) 2019-06-14 12:14:23 +09:00
syuilo
e9dc54c4d9 サムネイル生成でエラーになってもファイルのアップロードを失敗しないように
#5050
2019-06-13 22:59:15 +09:00
syuilo
fde9fc2891 Make url preview log warn 2019-06-13 22:35:37 +09:00
syuilo
6e59798e82 Merge branch 'develop' 2019-06-13 18:22:49 +09:00
syuilo
5e3cc0a3c6 11.20.4 2019-06-13 18:22:31 +09:00
syuilo
cfb35324d0 Fix bug 2019-06-13 18:15:35 +09:00
syuilo
9bfbc12afa Add indexes 2019-06-13 15:30:51 +09:00
MeiMei
b41cddaf5a Fix: #5035 (#5048) 2019-06-12 13:47:58 +09:00
Satsuki Yanagi
1432a7193d 設定でPostgreSQLのクエリー結果のキャッシュを無効できるように (#5046) 2019-06-11 20:49:08 +09:00
Acid Chicken (硫酸鶏)
20630cb3a0 Update README.md [AUTOGEN] (#5044) 2019-06-11 16:57:52 +09:00
syuilo
2eb02ae581 Merge branch 'develop' 2019-06-10 23:11:22 +09:00
syuilo
801f9027aa 11.20.3 2019-06-10 23:11:04 +09:00
syuilo
802739a2df Fix bug 2019-06-10 23:09:36 +09:00
syuilo
95b1e1a21d Merge branch 'develop' 2019-06-10 11:44:01 +09:00
syuilo
b8060a522a 11.20.2 2019-06-10 11:43:45 +09:00
syuilo
fe2191a491 New Crowdin translations (#5040)
* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)
2019-06-10 11:42:06 +09:00
syuilo
2891f52817 Merge branch 'riamu' into develop 2019-06-10 11:41:07 +09:00
Satsuki Yanagi
5bdc44c672 ✌️ (#5041)
related #5020
2019-06-10 01:02:33 +09:00
syuilo
65d359b57a Fix #5020 2019-06-09 23:07:32 +09:00
syuilo
7b6e717e23 Merge branch 'develop' 2019-06-07 20:47:56 +09:00
syuilo
2820f6a621 11.20.1 2019-06-07 20:47:14 +09:00
syuilo
6f96e05fec New Crowdin translations (#4979)
* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)
2019-06-07 20:43:34 +09:00
syuilo
4c2c762b87 Fix #5036 2019-06-07 20:40:05 +09:00
syuilo
81fadfa4ff Fix bug 2019-06-07 20:34:05 +09:00
syuilo
c227641d50 Update dependencies 🚀 2019-06-07 20:29:13 +09:00
syuilo
dacc713f99 Fix #5021 2019-06-07 20:24:07 +09:00
syuilo
a1f794ee05 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-06-07 20:11:38 +09:00
syuilo
8b2098fc89 Fix bug 2019-06-07 20:11:23 +09:00
Acid Chicken (硫酸鶏)
4436852de0 Deny 'private' in note visibility (#5031)
Fixes #5028
2019-06-06 19:45:25 +09:00
Acid Chicken (硫酸鶏)
a8ff1e19dc Add resolutions for polluted packages
for yarn users: Just `yarn install` then vulnerabilities are fixed!
for npm users: Wait for support of 'resolutions' from npm.
2019-06-04 23:06:30 +09:00
Acid Chicken (硫酸鶏)
d559aa8e6d Update README.md [AUTOGEN] (#5025) 2019-06-04 18:19:16 +09:00
Aya Morisawa
83fedcff3b Add missing semicolon (#5030) 2019-06-04 18:03:56 +09:00
Acid Chicken (硫酸鶏)
9969cf8816 Update README.md [AUTOGEN] (#5017) 2019-06-02 10:13:11 +09:00
Acid Chicken (硫酸鶏)
dee48fff12 Update README.md [AUTOGEN] (#5013) 2019-06-01 20:38:46 +09:00
syuilo
aff80199e5 Fix bug 2019-05-29 12:22:47 +09:00
Acid Chicken (硫酸鶏)
b9f1a55190 Update README.md [AUTOGEN] (#5003) 2019-05-27 23:44:44 +09:00
Acid Chicken (硫酸鶏)
07d5bce61a Update README.md [AUTOGEN] (#5001) 2019-05-27 23:15:46 +09:00
Aya Morisawa
834edd216c Fix #4894 (#5000) 2019-05-27 20:04:01 +09:00
Acid Chicken (硫酸鶏)
155da0c6a3 Avoid roma-ji naming 2019-04-10 20:30:00 +09:00
250 changed files with 5799 additions and 2214 deletions

View File

@@ -8,6 +8,9 @@
# Final accessible URL seen by a user.
url: https://example.tld/
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# URL SETTINGS AFTER THAT!
# ┌───────────────────────┐
#───┘ Port and TLS settings └───────────────────────────────────
@@ -62,6 +65,9 @@ db:
user: example-misskey-user
pass: example-misskey-pass
# Whether disable Caching queries
#disableCache: true
# Extra Connection options
#extra:
# ssl: true

View File

@@ -1,23 +1,23 @@
{
"parserOptions": {
"parser": "typescript-eslint-parser"
"parser": "@typescript-eslint/parser"
},
"extends": [
"eslint:recommended",
"plugin:vue/recommended"
],
"rules": {
"vue/require-v-for-key": false,
"vue/max-attributes-per-line": false,
"vue/html-indent": false,
"vue/html-self-closing": false,
"vue/no-unused-vars": false,
"vue/attributes-order": false,
"vue/require-prop-types": false,
"vue/require-default-prop": false,
"vue/html-closing-bracket-spacing": false,
"vue/singleline-html-element-content-newline": false,
"vue/no-v-html": false,
"vue/require-v-for-key": 0,
"vue/max-attributes-per-line": 0,
"vue/html-indent": 0,
"vue/html-self-closing": 0,
"vue/no-unused-vars": 0,
"vue/attributes-order": 0,
"vue/require-prop-types": 0,
"vue/require-default-prop": 0,
"vue/html-closing-bracket-spacing": 0,
"vue/singleline-html-element-content-newline": 0,
"vue/no-v-html": 0,
"no-console": 0,
"no-unused-vars": 0,
"no-empty": 0

View File

@@ -17,6 +17,102 @@ npm i -g ts-node
npm run migrate
```
11.24.0 (2019/07/05)
--------------------
注意: このアップデート後に、`node built/tools/accept-migration Init 1000000000000`してください。
### ✨Improvements
* WebAuthnサポート
* APNGサポート
* アバターファイル選択でimage以外は表示しないように
* データベース手動バキューム機能
* メールサーバー設定が正しいか確認できるように
* ピン止めの上限に達したときエラーを表示するように
* AP: attributedTo, to, cc が Array や Object のパターンに対応
* AP: object type が Audio, Document, Image, Page, Video のパターンに対応
* フォロー解除時に確認ダイアログを表示するように
* ユーザー入力ダイアログで、入力時にユーザーの存在を確認するように
### 🐛Fixes
* 自分のインスタンスのルートURIへのリンクが無になる問題を修正
* リモートファイルの削除が重い問題を修正
* 投稿などの連続したスペースがひとつに纏まるのを修正
* MFMのパース修正
* マイグレーション時にエラーが出る問題を修正
11.23.1 (2019/06/25)
--------------------
### 🐛Fixes
* クライアントの設定がリセットされることがある問題を修正
11.23.0 (2019/06/23)
--------------------
### ✨Improvements
* ホーム/デッキのカスタマイズ情報を複数のデバイスで同期できるように
* ホーム/デッキのカスタマイズ情報の複数プリセット切り替え
* サーバー情報にRedisのバージョンを追加
* ServiceWorker有効化
* MisskeyPagesでリストの要素数を取得する関数を追加
* URLプレビューでハッシュだけ違うプレビューカードは表示しないように
* URLプレビューをユーザーロケールで出し分けるように
* リモートの凍結されたアカウントからのアクティビティはすべて無視するように
### 🐛Fixes
* フォロー解除してもフォローボタンがフォロー中のままになる問題を修正
11.22.0 (2019/06/18)
--------------------
### ✨Improvements
* 管理画面でデータベースの各テーブルのレコード数やサイズを確認できるように
* サーバー情報にPostgreSQLのバージョンを追加
### 🐛Fixes
* リモートファイルのダウンロードに失敗することがある問題を修正
* アンケートの期間を日時指定で選択すると日時がUTCになってしまう問題を修正
* MFMのパースを修正
11.21.0 (2019/06/16)
--------------------
### ✨Improvements
* Unicode 12.0 の絵文字に対応
* 閉鎖しているホストにはAP deliverしないように
* image以外はproxyしないように
### 🐛Fixes
* サムネイル生成でエラーになるとファイルのアップロードに失敗する問題を修正
* オートコンプリートにアニメーション停止が効かない問題を修正
11.20.4 (2019/06/13)
--------------------
### 🐛Fixes
* 検索結果がループする問題を修正
* 設定でPostgreSQLのクエリー結果のキャッシュを無効できるように
* 「投稿内の動きのあるテキストを無効にする」だけ反応しない問題を修正
* 特定の操作のデータベースのパフォーマンス調整
11.20.3 (2019/06/10)
--------------------
### 🐛Fixes
* 絵文字サジェストが動作しなくなっていた問題を修正
11.20.2 (2019/06/10)
--------------------
### 🐛Fixes
* Redisにパスワードを設定している場合接続できない問題を修正
* i18n
* など
11.20.1 (2019/06/07)
--------------------
### 🐛Fixes
* リモートファイルのキャッシュをすべて削除するときの動作を修正
* ストリームのハッシュタグチャンネルが死んでいる問題を修正
* Pagesから他の同一インスタンス内のPagesのページへのリンクができない問題を修正
* /api/notes/create 公開範囲private を渡すとタイムアウトする問題を修正
* パスワードの確認が完了しなくてもユーザー登録できる問題を修正
* 依存関係の更新
* i18n
11.20.0 (2019/05/27)
--------------------
### ✨Improvements
@@ -515,10 +611,9 @@ mongodb:
3. migration ブランチに切り替え
4. `npm i`
5. `npm run build`
6. `npm run init`
7. `npm run migrate`
8. master ブランチに戻す
9. enjoy
6. `npm run migrate`
7. master ブランチに戻す
8. enjoy
10.100.0
----------

View File

@@ -219,8 +219,6 @@ const user = await Users.findOne(userId).then(ensure);
```
### Migration作成方法
コードの変更をした後、`ormconfig.json``npm run ormconfig`で生成)を用意し、
```
npm i -g ts-node
ts-node ./node_modules/typeorm/cli.js migration:generate -n 変更の名前

View File

@@ -1,4 +1,4 @@
FROM node:12.1-alpine AS base
FROM node:12.5-alpine AS base
ENV NODE_ENV=production

View File

@@ -106,22 +106,24 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5888816/36da0f7c15954df0ab13f9abdf227f66/1.jpeg?token-time=2145916800&token-hash=at8QpJXJ8C0zINY_NmoMKv-MhXVoUK-YzTgaJPJzJYU%3D" alt="Hiroshi Seki" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/776209" alt="Denshi" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1.jpe?token-time=2145916800&token-hash=bqwLTk0Wo0hUJJ8J5y7ii05bLzz-_CDA7Bo0Mp4RFU0%3D" alt="ne_moni" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/4.jpe?token-time=2145916800&token-hash=zEyJqVM7u9d8Ri-65fJYSJcWF1jBH1nJ5a3taRzrTmw%3D" alt="Melilot" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
<td><a href="https://www.patreon.com/weepjp">weepjp</a></td>
<td><a href="https://www.patreon.com/user?u=19045173">kiritan</a></td>
<td><a href="https://www.patreon.com/user?u=776209">Denshi</a></td>
<td><a href="https://www.patreon.com/user?u=557245">mkatze</a></td>
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
</tr></table>
<table><tr>
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1.png?token-time=2145916800&token-hash=FMV7cPKBD1TU2WTbl1jg6AcdKSvTb2BSFcDhgc-EO8w%3D" alt="gutfuckllc" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/12718187" alt="Peter G." width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1.jpe?token-time=2145916800&token-hash=UQRWf01TwHDV4Cls1K0YAOAjM29ssif7hLVq0ESQ0hs%3D" alt="nemu" width="100"></td>
@@ -130,8 +132,8 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61</a></td>
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
@@ -143,7 +145,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1.jpe?token-time=2145916800&token-hash=CPxGQhKIlEaa6WUcgbyHixyKEhakiw9RFdOhsIJBQ_o%3D" alt="takimura" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4.jpe?token-time=2145916800&token-hash=UslrPVM-8TXOe8AapuNiaFYjcIJgPNcU-fKpGbfGJNI%3D" alt="Damillora" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/83884b38afc74d4cbe83c30a13b10edd/1.png?token-time=2145916800&token-hash=R5Tog8RWg0rguRoCIoir3lThokrdPvs8Utfikhc0nhY%3D" alt="Atsuko Tominaga" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td>
@@ -151,11 +152,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/10789744/97175095d8f04c0f86225ff47cb98d40/1.jpeg?token-time=2145916800&token-hash=l4AoMR7Nj7K4yAHrkrk2hAoggPkbSPm12m1nmbe9Pb8%3D" alt="Naoki Hirayama" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
<td><a href="https://www.patreon.com/user?u=16900731">Atsuko Tominaga</a></td>
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
@@ -163,19 +162,20 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/Corset">CG</a></td>
<td><a href="https://www.patreon.com/hekovic">Hekovic</a></td>
<td><a href="https://www.patreon.com/spinlock">Naoki Hirayama</a></td>
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1.jpeg?token-time=2145916800&token-hash=d8jBQLMOHD87KtXs5C9fk1o58DMF73pQ-dYH3uZJPBE%3D" alt="Gargron" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table>
**Last updated:** Sun, 19 May 2019 02:37:06 UTC
**Last updated:** Mon, 01 Jul 2019 21:44:06 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright

View File

@@ -93,6 +93,25 @@ common:
empty-timeline-info:
follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose"
explore: "Najít uživatele"
post-form:
attach-location-information: "Přidat informace o lokaci"
hide-contents: "Schovat obsah"
reply-placeholder: "Odpovědět na tento příspěvek"
quote-placeholder: "Citovat tento příspěvek"
submit: "Odeslat"
reply: "Odpovědět"
renote: "Renotovat"
attach-media-from-local: "Uplodovat soubor z vašeho zařízení"
insert-a-kao: "v('ω')v"
create-poll: "Vytvořit anketu"
text-remain: "zbývá ještě {} znaků"
recent-tags: "Nejnovější"
visibility: "Viditelnost"
geolocation-alert: "Vaše zařízení nedalo k dispozici lokaci"
error: "Chyba"
enter-username: "Zadejte své uživatelské jméno"
add-visible-user: "Přidat uživatele"
username-prompt: "Zadejte své uživatelské jméno"
weekday-short:
sunday: "Ne"
monday: "Po"
@@ -241,6 +260,7 @@ common:
disable-via-mobile: "Neoznačovat příspěvky jako „z mobilu“"
load-raw-images: "Zobrazovat obrázky v původní kvalitě"
load-remote-media: "Zobrazovat média ze vzdáleného serveru"
sync: "Synchronizace"
search: "Hledání"
delete: "Odstranit"
loading: "Načítám..."
@@ -251,7 +271,7 @@ common:
my-token-regenerated: "Váš token byl regenerován, proto budete odhlášen/a."
hide-password: "Skrýt heslo"
show-password: "Zobrazit heslo"
enter-username: "Zadejte uživatelské jméno"
enter-username: "Zadejte své uživatelské jméno"
do-not-use-in-production: "Tohle je vývojářský build. Nepoužívejte v produkci."
user-suspended: "Tomuto uživateli byl pozastaven účet."
is-remote-user: "Informace o tomto uživateli nemusí být kompletní."
@@ -308,7 +328,10 @@ auth/views/form.vue:
accept: "Povolit přístup"
auth/views/index.vue:
loading: "Načítám..."
denied-paragraph: "Tato aplikace nebude mít přístup k Vašemu účtu."
already-authorized: "Tato aplikace byla již autorizována."
callback-url: "Zpátky do aplikace."
please-go-back: "Prosím vraťte se zpátky do aplikace."
error: "Taková relace neexistuje."
sign-in: "Prosím přihlaste se."
common/views/pages/explore.vue:
@@ -358,23 +381,30 @@ common/views/components/games/reversi/reversi.room.vue:
waiting-for-both: "Připravuji"
cancel: "Zrušit"
ready: "Připraveno"
cancel-ready: "Pokračovat v přípravě"
common/views/components/connect-failed.vue:
title: "Nelze se připojit k serveru"
description: "Nastal problém s Vaším připojením k internetu, nebo server není dostupný nebo zrovna probíhá údržba. Prosím {zkuste to znova} za pár minut."
thanks: "Děkujeme že jste použili Misskey."
common/views/components/connect-failed.troubleshooter.vue:
title: "Poradce při potížích"
network: "Síťové připojení"
checking-network: "Prověřit síťové připojení"
internet: "Připojení k internetu"
checking-internet: "Ověřuji připojení k internetu."
server: "Připojení k serveru"
checking-server: "Spojuji se se serverem"
no-network-desc: "Ujistěte se že jste připojeni k Internetu."
no-internet: "Nejste připojeni k internetu"
no-internet-desc: "Jste připojen k síti, ale zdá se že stále chybí připojení k Internetu. Prosím zkontrolujte Vaše připojení k Internetu."
no-server: "Nelze se připojit k serveru Misskey"
success: "Úspěšně se podařilo spojit s Misskey serverem"
flush: "Vyčistit mezipaměť"
common/views/components/media-banner.vue:
sensitive: "Choulostivý obsah"
click-to-show: "Klikněte pro zobrazení"
common/views/components/theme.vue:
theme: "Vzhled"
light-theme: "Motiv pro použití ve světlém vzhledu"
dark-theme: "Motiv pro použití v tmavém vzhledu"
light-themes: "Světlý vzhled"
@@ -385,6 +415,7 @@ common/views/components/theme.vue:
installed: "\"{}\" byl nainstalován"
create-a-theme: "Vytvořit motiv"
save-created-theme: "Uložit motiv"
primary-color: "Základní barva"
text-color: "Barva textu"
base-theme: "Základní vzhled"
base-theme-light: "Světlý"
@@ -392,8 +423,10 @@ common/views/components/theme.vue:
find-more-theme: "Najít další vzhledy"
theme-name: "Jméno vzhledu"
preview-created-theme: "Náhled"
invalid-theme: "Vzhled není validní"
already-installed: "Tento vzhled je již nainstalován."
saved: "Uloženo"
manage-themes: "Správa vzhledů"
builtin-themes: "Standardní vzhledy"
my-themes: "Moje vzhledy"
installed-themes: "Nainstalované vzhledy"
@@ -404,6 +437,7 @@ common/views/components/theme.vue:
desc: "Popis"
export: "Exportovat"
import: "Importovat"
import-by-code: "nebo zkopírujte kód"
theme-name-required: "Jméno vzhledu je povinné"
common/views/components/cw-button.vue:
hide: "Skrýt"
@@ -416,6 +450,7 @@ common/views/components/messaging.vue:
you: "Vy"
no-history: "Žádná historie"
user: "Uživatel"
group: "Skupina"
common/views/components/messaging-room.vue:
new-message: "Máte novou zprávu"
common/views/components/messaging-room.form.vue:
@@ -433,6 +468,7 @@ common/views/components/nav.vue:
repository: "Úložiště"
develop: "Vývojáři"
feedback: "Zpětná vazba"
tos: "Podmínky užívání"
common/views/components/note-menu.vue:
mention: "Zmínění"
detail: "Více"
@@ -476,10 +512,13 @@ common/views/components/poll-editor.vue:
remove: "Odstranit tuto možnost"
add: "+ Přidat možnost"
destroy: "Zahodit dotazník"
multiple: "Více odpovědí je povoleno"
expiration: "Termín"
infinite: "Nekonečne"
at: "Výběr data a času"
no-more: "Více už přidat nemůžete"
deadline-date: "Termín ukončení"
deadline-time: "Doba trvání"
interval: "Trvání"
second: "Sekunda"
minute: "Minuta"
@@ -487,6 +526,7 @@ common/views/components/poll-editor.vue:
day: "Ne"
common/views/components/reaction-picker.vue:
choose-reaction: "Vyberte svoji reakci"
input-reaction-placeholder: "nebo vložte Emoji"
common/views/components/emoji-picker.vue:
custom-emoji: "Emoji"
people: "Lidé"
@@ -500,6 +540,7 @@ common/views/components/emoji-picker.vue:
common/views/components/signin.vue:
username: "Přezdívka"
password: "Heslo"
token: "Token"
signing-in: "Přihlašování..."
or: "Nebo"
signin-with-twitter: "Přihlásit se pomocí účtu Twitter"
@@ -527,6 +568,7 @@ common/views/components/signup.vue:
password-matched: "OK"
password-not-matched: "Neshodují se"
recaptcha: "Potvrzení"
tos: "Podmínky užívání"
create: "Vytvořit účet"
some-error: "Pokus o vytvoření účtu selhal. Prosím zkuste to znovu."
common/views/components/special-message.vue:
@@ -565,6 +607,7 @@ common/views/components/visibility-chooser.vue:
home: "Domů"
specified-desc: "Poslat pouze zmíněným uživatelům"
local-public: "Veřejná (pouze místní)"
local-public-desc: "Nepublikovat na vzdálených serverech"
local-home: "Domovská (pouze místní)"
local-followers: "Pro sledující (pouze místní)"
common/views/components/trends.vue:
@@ -574,6 +617,8 @@ common/views/components/language-settings.vue:
title: "Zobrazit jazyky"
pick-language: "Zvolte jazyk"
recommended: "Doporučené"
auto: "Automaticky"
specify-language: "Vyberte jazyk"
info: "Pro aktivování změn musíte znovu načíst stránky."
common/views/components/profile-editor.vue:
title: "Profil"
@@ -600,6 +645,7 @@ common/views/components/profile-editor.vue:
email-not-verified: "Váš email není potvrzen. Prosím zkontrolujte si svou schránku."
export: "Exportovat"
import: "Importovat"
export-and-import: "Import / Export"
export-targets:
following-list: "Seznam sledujících"
mute-list: "Seznam ztlumených uživatelů"
@@ -618,15 +664,32 @@ common/views/components/user-list-editor.vue:
deleted: "Smazáno"
add-user: "Přidat uživatele"
common/views/components/user-group-editor.vue:
users: "Členové"
rename: "Přejmenovat skupinu"
delete: "Odstranit skupinu"
transfer: "Přesunout skupinu"
transfer-are-you-sure: "Jste si jistí že chcete přidat @$2 do skupiny: $1?"
transferred: "Skupina přesunuta"
remove-user: "Odebrat uživatele z této skupiny"
delete-are-you-sure: "Jste si jistí že chcete smazat skupinu \"$1\"?"
deleted: "Smazáno"
invite: "Pozvat"
invited: "Pozvánka byla úspěšně odeslána"
common/views/components/user-lists.vue:
user-lists: "Seznamy"
create-list: "Vytvořit seznam"
list-name: "Název seznamu"
common/views/components/user-groups.vue:
user-groups: "Skupiny"
create-group: "Vytvořit skupinu"
group-name: "Název skupiny"
owned-groups: "Moje skupiny"
invites: "Pozvat"
reject-invite: "Odmítnout"
common/views/widgets/broadcast.vue:
fetching: "Načítám"
no-broadcasts: "Žádná nová oznámení"
have-a-nice-day: "Přejeme Vám příjemný den!"
next: "Další"
common/views/widgets/calendar.vue:
year: "Rok {}"
@@ -653,6 +716,12 @@ common/views/widgets/slideshow.vue:
no-image: "V této složce nebyly nalezeny žádné fotky."
common/views/pages/not-found.vue:
page-not-found: "Stránka nenalezena"
common/views/pages/follow.vue:
following: "Sledování"
follow: "Sledovat"
common/views/pages/follow-requests.vue:
accept: "Přijmout"
reject: "Odmítnout"
desktop:
banner: "Baner"
avatar-crop-title: "Vyberte část, která se zobrazí jako avatar"
@@ -755,27 +824,11 @@ desktop/views/components/notes.vue:
error: "Načítání selhalo."
retry: "Opakovat"
desktop/views/components/post-form.vue:
add-visible-user: "+Přidat uživatele"
attach-location-information: "Přidat informace o lokaci"
hide-contents: "Schovat obsah"
reply-placeholder: "Odpovědět na tento příspěvěk"
quote-placeholder: "Citovat tento příspěvek"
submit: "Příspěvek"
reply: "Odpovědět"
renote: "Renotovat"
posted: "Odesláno!"
replied: "Odpověděno!"
reposted: "Renotováno!"
note-failed: "Nepodařilo se přidat příspěvek"
renote-failed: "Renotování neuspělo"
insert-a-kao: "v('ω')v"
create-poll: "Vytvořit anketu"
text-remain: "{0} znaků zbývá"
recent-tags: "Nejnovější"
visibility: "Viditelnost"
geolocation-alert: "Vaše zařízení nepodporuje lokační službu"
error: "Chyba"
enter-username: "Zadejte své uživatelské jméno..."
desktop/views/components/post-form-window.vue:
note: "Nový příspěvek"
reply: "Odpovědět"
@@ -794,6 +847,7 @@ desktop/views/components/renote-form-window.vue:
desktop/views/components/settings.2fa.vue:
detail: "Více…"
url: "https://www.google.cz/landing/2step/"
token: "Token"
common/views/components/media-image.vue:
click-to-show: "Klikněte pro zobrazení"
common/views/components/api-settings.vue:
@@ -850,6 +904,7 @@ desktop/views/components/ui.header.vue:
desktop/views/components/ui.header.account.vue:
profile: "Váš profil"
lists: "Seznamy"
groups: "Skupiny"
admin: "Administrace"
desktop/views/components/ui.header.nav.vue:
game: "Hry"
@@ -884,6 +939,11 @@ admin/views/dashboard.vue:
instances: "Instance"
this-instance: "Tato instance"
federated: "Z fedivesmíru"
admin/views/logs.vue:
logs: "Logy"
levels:
info: "Informace"
error: "Chyba"
admin/views/abuse.vue:
details: "Popis"
remove-report: "Odstranit"
@@ -927,6 +987,7 @@ admin/views/instance.vue:
smtp-auth: "Provést SMTP autentikaci"
smtp-user: "SMTP uživatel"
smtp-pass: "SMTP heslo"
test-email: "Test"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "Povolit ServiceWorker"
vapid-publickey: "VAPID veřejný klíč"
@@ -1026,6 +1087,7 @@ admin/views/federation.vue:
host: "Hostitel"
notes: "Poznámky"
users: "Uživatelé"
following: "Sledování"
caught-at: "Vytvořeno"
status: "Status"
latest-request-received-at: "Poslední požadavek přijat"
@@ -1045,6 +1107,7 @@ admin/views/federation.vue:
hour: "za hodinu"
day: "za den"
blocked-hosts: "Blokován"
save: "Uložit"
desktop/views/pages/welcome.vue:
about: "O Misskey"
timeline: "Časová osa"
@@ -1083,6 +1146,8 @@ desktop/views/pages/user/user.photos.vue:
no-photos: "Žádné obrázky"
desktop/views/pages/user/user.header.vue:
posts: "Poznámky"
following: "Sledovaní"
followers: "Sledující"
month: "Po"
day: "Ne"
desktop/views/widgets/notifications.vue:
@@ -1111,6 +1176,7 @@ mobile/views/components/drive.file-detail.vue:
mobile/views/components/media-video.vue:
click-to-show: "Klikněte pro zobrazení"
common/views/components/follow-button.vue:
following: "Sledování"
follow-processing: "Zpracovávám"
mobile/views/components/note.vue:
private: "Tento příspěvek je soukromý"
@@ -1130,15 +1196,6 @@ mobile/views/components/note-sub.vue:
admin: "admin"
bot: "bot"
cat: "kočka"
mobile/views/components/post-form.vue:
add-visible-user: "Přidat uživatele"
submit: "Příspěvek"
reply: "Odpovědět"
renote: "Renotovat"
reply-placeholder: "Odpovědět na tento příspěvěk"
geolocation-alert: "Vaše zařízení nepodporuje lokační službu"
error: "Chyba"
username-prompt: "Zadejte uživatelské jméno"
mobile/views/components/sub-note-content.vue:
private: "Tento příspěvek je soukromý"
deleted: "Tento příspěvek byl odstraněn"
@@ -1151,6 +1208,7 @@ mobile/views/components/ui.nav.vue:
notifications: "Oznámení"
search: "Vyhledávání"
user-lists: "Seznamy"
user-groups: "Skupiny"
widgets: "Widgety"
game: "Hry"
admin: "Administrace"
@@ -1244,5 +1302,7 @@ pages:
arg2: "Seznamy"
_pick:
arg1: "Seznamy"
_listLen:
arg1: "Seznamy"
types:
array: "Seznamy"

View File

@@ -95,6 +95,14 @@ common:
empty-timeline-info:
follow-users-to-make-your-timeline: "Følgende brugere vil få vist deres poster på tidslinjen."
explore: "Find brugere"
post-form:
submit: "Post"
reply: "Svar"
renote: "Gen-postering"
error: "Fejl"
enter-username: "Angiv brugernavn"
add-visible-user: "Tilføj en bruger"
username-prompt: "Angiv brugernavn"
weekday-short:
sunday: "Søn"
monday: "Man"
@@ -918,34 +926,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "Der er ingen notifikationer!"
desktop/views/components/post-form.vue:
add-visible-user: "+Tilføj bruger"
attach-location-information: "Vedhæft oplysninger om placering"
hide-contents: "Skjul indhold"
reply-placeholder: "Svar på denne post"
quote-placeholder: "Citer denne post"
submit: "Post"
reply: "Svar"
renote: "Gen-postering"
posted: "Afsendt!"
replied: "Besvaret!"
reposted: "Gen-posteret!"
note-failed: "Fejl under afsendelse"
reply-failed: "Fejl under besvarelse"
renote-failed: "Fejl under gen-postering"
posting: "Afsender"
attach-media-from-local: "Vedhæft medie fra din enhed"
attach-media-from-drive: "Vedhæft medie fra dit drev"
insert-a-kao: "v('ω')v"
create-poll: "Opret en afstemning"
text-remain: "Der mangler {} tegn"
recent-tags: "Seneste"
local-only-message: "Denne post vil kun blive offentliggjort lokalt"
click-to-tagging: "Klik for at tagge"
visibility: "Synlighed"
geolocation-alert: "Din enhed giver ikke mulighed for at benytte placeringstjenester"
error: "Fejl"
enter-username: "Angiv brugernavn"
annotations: "Kommentarer til posten (frivillige)"
desktop/views/components/post-form-window.vue:
note: "Ny post"
reply: "Svar"
@@ -1106,6 +1092,13 @@ admin/views/dashboard.vue:
admin/views/queue.vue:
title: "Kø"
remove-all-jobs: "Ryd alle job køer"
queue: "Kø"
state: "Sorter efter"
admin/views/logs.vue:
logs: "Logs"
levels:
info: "Information"
error: "Fejl"
admin/views/abuse.vue:
title: "Misbrug"
target: "Mål"
@@ -1202,6 +1195,7 @@ admin/views/instance.vue:
smtp-auth: "Udfør autentifikation af SMTP"
smtp-user: "SMTP bruger"
smtp-pass: "SMTP adgangskode"
test-email: "Test"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "Aktiver ServiceWorker"
serviceworker-info: "Skal være aktiveret for at give push notifikationer."
@@ -1402,6 +1396,7 @@ admin/views/federation.vue:
day: "pr. dag"
blocked-hosts: "Bloker"
blocked-hosts-info: "Beskrivelse af værterne du vil blokere, adskilt af linjeskift."
save: "Gem"
desktop/views/pages/welcome.vue:
about: "Mere info..."
timeline: "Tidslinje"
@@ -1533,17 +1528,6 @@ mobile/views/components/note-sub.vue:
cat: "cat"
mobile/views/components/notifications.vue:
empty: "Der er ingen notifikationer!"
mobile/views/components/post-form.vue:
add-visible-user: "Tilføj en bruger"
submit: "Post"
reply: "Svar"
renote: "Gen-postering"
quote-placeholder: "Citer denne post... (valgfrit)"
reply-placeholder: "Svar på denne post"
cw-placeholder: "Kommentar til indholdet (valgfrit)"
geolocation-alert: "Din enhed giver ikke mulighed for at benytte placeringstjenester"
error: "Fejl"
username-prompt: "Angiv brugernavn"
mobile/views/components/sub-note-content.vue:
private: "Posten er privat"
deleted: "Posten er blevet fjernet"
@@ -1778,8 +1762,7 @@ pages:
_divide:
arg1: "A"
arg2: "B"
remind: "÷ Tomo"
_remind:
_mod:
arg1: "A"
arg2: "B"
eq: "A og B er ens"
@@ -1862,6 +1845,8 @@ pages:
_pick:
arg1: "Lister"
arg2: "Position"
_listLen:
arg1: "Lister"
number: "Tal"
stringToNumber: "Tekst til tal"
_stringToNumber:

View File

@@ -95,6 +95,11 @@ common:
empty-timeline-info:
follow-users-to-make-your-timeline: "Beiträge von Benutzern, denen du folgst, werden in der Zeitleiste angezeigt."
explore: "Benutzer finden"
post-form:
reply: "Antworten"
renote: "Anmerkung"
enter-username: "Bitte gib einen Benutzernamen ein"
username-prompt: "Bitte gib einen Benutzernamen ein"
weekday-short:
sunday: "So"
monday: "Mo"
@@ -684,7 +689,7 @@ desktop/views/components/note-detail.vue:
add-reaction: "Reaktion hinzufügen"
desktop/views/components/note.vue:
reply: "Antworten"
renote: "Anmerken"
renote: "Anmerkung"
detail: "Details"
private: "Dieser Beitrag ist privat"
deleted: "Dieser Beitrag wurde entfernt"
@@ -694,27 +699,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "Keine Benachrichtigungen"
desktop/views/components/post-form.vue:
add-visible-user: "+Nutzer hinzufügen"
hide-contents: "Inhalt verstecken"
reply-placeholder: "Antworte auf diese Anmerkung..."
quote-placeholder: "Zitiere diese Anmerkung..."
submit: "Abschicken"
reply: "Antworten"
renote: "Anmerken"
posted: "Gepostet!"
replied: "Geantwortet!"
reposted: "Weitergesagt!"
note-failed: "Anmerkung fehlgeschlagen"
reply-failed: "Antwort fehlgeschlagen"
renote-failed: "Anmerkung fehlgeschlagen"
posting: "Posting"
attach-media-from-local: "Medien von deinem PC hinzufügen"
attach-media-from-drive: "Medien von deinem Speicher hinzufügen"
create-poll: "Eine Abstimmung erstellen"
text-remain: "{} Zeichen verbleibend"
visibility: "Sichtbarkeit"
error: "Fehler"
enter-username: "Bitte gib einen Benutzernamen ein..."
desktop/views/components/post-form-window.vue:
note: "Neuer Beitrag"
reply: "Antworten"
@@ -785,6 +775,7 @@ admin/views/instance.vue:
invite: "Einladen"
save: "Speichern"
saved: "Gespeichert"
test-email: "Test"
admin/views/charts.vue:
drive: "Drive"
admin/views/drive.vue:
@@ -807,6 +798,7 @@ admin/views/announcements.vue:
saved: "Gespeichert"
admin/views/federation.vue:
status: "Status"
save: "Speichern"
desktop/views/pages/note.vue:
prev: "Vorheriger Kommentar"
next: "Nächster Kommentar"
@@ -851,10 +843,6 @@ mobile/views/components/note-detail.vue:
location: "Ort"
mobile/views/components/notifications.vue:
empty: "Keine Benachrichtigungen"
mobile/views/components/post-form.vue:
reply: "Antworten"
renote: "Anmerken"
reply-placeholder: "Antworte auf diese Anmerkung..."
mobile/views/components/sub-note-content.vue:
private: "Dieser Beitrag ist privat"
deleted: "Dieser Beitrag wurde entfernt"
@@ -942,5 +930,7 @@ pages:
arg2: "Listen"
_pick:
arg1: "Listen"
_listLen:
arg1: "Listen"
types:
array: "Listen"

View File

@@ -95,6 +95,33 @@ common:
empty-timeline-info:
follow-users-to-make-your-timeline: "Following users will show their posts in your timeline."
explore: "Find users"
post-form:
attach-location-information: "Attach location information"
hide-contents: "Hide contents"
reply-placeholder: "Reply to this post..."
quote-placeholder: "Quote this Post..."
option-quote-placeholder: "Quote this post... (optional)"
quote-attached: "Quoted"
quote-question: "Do you want to append a quote?"
submit: "Post"
reply: "Reply"
renote: "Renote"
posting: "Posting"
attach-media-from-local: "Attach media from your device"
attach-media-from-drive: "Attach media from your Drive"
insert-a-kao: "v('ω')v"
create-poll: "Create a poll"
text-remain: "{} characters remaining"
recent-tags: "Recent"
local-only-message: "This post will only be published locally"
click-to-tagging: "Click to tagging"
visibility: "Visibility"
geolocation-alert: "Your device does not provide location services"
error: "Error"
enter-username: "Please enter username"
add-visible-user: "Add a user"
cw-placeholder: "Comments for the post (optional)"
username-prompt: "Please enter username"
weekday-short:
sunday: "S"
monday: "M"
@@ -243,6 +270,9 @@ common:
disable-via-mobile: "Don't mark the post as 'from mobile'"
load-raw-images: "Show attached images in original quality"
load-remote-media: "Show media from a remote server"
sync: "Sync"
home-profile: "Home profile"
deck-profile: "Deck profile"
search: "Search"
delete: "Delete"
loading: "Loading"
@@ -253,7 +283,7 @@ common:
my-token-regenerated: "Your token has been regenerated, so you will be signed out."
hide-password: "Hide Password"
show-password: "Show Password"
enter-username: "Enter user name"
enter-username: "Please enter username"
do-not-use-in-production: "This is a development build. Do not use in production."
user-suspended: "This user has been suspended."
is-remote-user: "The information about this user may not be entirely complete."
@@ -319,7 +349,7 @@ auth/views/index.vue:
error: "Session does not exist."
sign-in: "Please sign in."
common/views/pages/explore.vue:
pinned-users: "Higlighted users"
pinned-users: "Pinned users"
popular-users: "Popular users"
recently-updated-users: "Recently active users"
recently-registered-users: "Users who joined recently"
@@ -493,6 +523,7 @@ common/views/components/note-menu.vue:
delete: "Delete"
delete-confirm: "Are you sure you want to delete this post?"
remote: "Show original note"
pin-limit-exceeded: "You can't pin any more posts."
common/views/components/user-menu.vue:
mention: "Mention"
mute: "Mute"
@@ -571,6 +602,8 @@ common/views/components/signin.vue:
signin-with-github: "Sign in with GitHub"
signin-with-discord: "Sign in with Discord"
login-failed: "Logging in has failed. Make sure you have entered the correct username and password."
tap-key: "Click on the Security Key to log in"
enter-2fa-code: "Enter your verification code"
common/views/components/signup.vue:
invitation-code: "Invitation code"
invitation-info: "If you do not have an invitation code, please contact an <a href=\"{}\">administrator</a>."
@@ -708,7 +741,9 @@ common/views/components/user-group-editor.vue:
delete: "Delete group"
transfer: "transfer group"
transfer-are-you-sure: "Are you sure you want to add @$2 to the group $1?"
transferred: "Group transferred"
remove-user: "Remove a user from this group"
delete-are-you-sure: "Are you sure to delete group \"$1\"?"
deleted: "Deleted"
invite: "Invite"
invited: "The invitation was successfully sent"
@@ -717,7 +752,7 @@ common/views/components/user-lists.vue:
create-list: "Create a list"
list-name: "List name"
common/views/components/user-groups.vue:
user-groups: "Group"
user-groups: "Groups"
create-group: "Create a group"
group-name: "Group name"
owned-groups: "My groups"
@@ -920,34 +955,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "No notifications!"
desktop/views/components/post-form.vue:
add-visible-user: "+Add a user"
attach-location-information: "Attach location information"
hide-contents: "Hide contents"
reply-placeholder: "Reply to this post..."
quote-placeholder: "Quote this Post..."
submit: "Post"
reply: "Reply"
renote: "Renote"
posted: "Posted!"
replied: "Replied!"
reposted: "Renoted!"
note-failed: "Failed to post"
reply-failed: "Failed to reply"
renote-failed: "Failed to Renote"
posting: "Posting"
attach-media-from-local: "Attach media from your device"
attach-media-from-drive: "Attach media from your Drive"
insert-a-kao: "v('ω')v"
create-poll: "Create a poll"
text-remain: "{} characters remaining"
recent-tags: "Recent"
local-only-message: "This post will only be published locally"
click-to-tagging: "Click to tagging"
visibility: "Visibility"
geolocation-alert: "Your device does not provide location services."
error: "Error"
enter-username: "Please enter a username..."
annotations: "Annotations for the post (optional)"
desktop/views/components/post-form-window.vue:
note: "New Post"
reply: "Reply"
@@ -974,7 +987,7 @@ desktop/views/components/settings.2fa.vue:
url: "https://www.google.com/landing/2step/"
caution: "If you lose access to your registered device, you won't be able to connect to Misskey anymore!"
register: "Register a device"
already-registered: "This device is already registered"
already-registered: "Your account is currently registered to an authenticator application"
unregister: "Unregister"
unregistered: "Two-factor authentication has been disabled."
enter-password: "Enter the password"
@@ -987,6 +1000,15 @@ desktop/views/components/settings.2fa.vue:
success: "Settings saved!"
failed: "Failed to setup. Please ensure that the token is correct."
info: "From the next time you sign in to Misskey, the token displayed on your device will be necessary too, as well as the password."
totp-header: "Authenticator App"
security-key-header: "Security Key"
security-key: "For additional security, you can log in to your account using a hardware Security Key that supports FIDO2. When you then sign in, you'll need the registered Security Key, or an authenticator app with you."
last-used: "Last used:"
activate-key: "Click to activate the Security Key"
security-key-name: "Name the Key"
register-security-key: "Complete Key registration"
something-went-wrong: "Wow! There was a problem registering the Key:"
key-unregistered: "The Key has been deleted"
common/views/components/media-image.vue:
sensitive: "NSFW"
click-to-show: "Click to show"
@@ -1061,7 +1083,7 @@ desktop/views/components/ui.header.vue:
desktop/views/components/ui.header.account.vue:
profile: "Your profile"
lists: "Lists"
groups: "Group"
groups: "Groups"
follow-requests: "Follow requests"
admin: "Admin"
desktop/views/components/ui.header.nav.vue:
@@ -1096,7 +1118,13 @@ admin/views/index.vue:
abuse: "Abuse"
queue: "Job Queue"
logs: "Logs"
db: "Database"
back-to-misskey: "Back to Misskey"
admin/views/db.vue:
tables: "Tables"
vacuum: "Vacuum"
vacuum-info: "Tidies up the database. Keeps the data intact and reduces disk usage. This is usually done automatically and periodically."
vacuum-exclamation: "Vacuuming can overload the database for a while, and cause users not to be able to participate in interactions."
admin/views/dashboard.vue:
dashboard: "Dashboard"
accounts: "Accounts"
@@ -1108,6 +1136,32 @@ admin/views/dashboard.vue:
admin/views/queue.vue:
title: "Queue"
remove-all-jobs: "Clear all queued jobs"
jobs: "Jobs"
queue: "Queue"
domains:
deliver: "Delivers"
inbox: "Received"
db: "Database"
objectStorage: "Object Storage"
state: "Sort"
states:
active: "Running"
delayed: "Scheduled"
waiting: "Queued"
result-is-truncated: "Result is truncated"
other-queues: "Other queues"
admin/views/logs.vue:
logs: "Logs"
domain: "Domain"
level: "Level"
levels:
all: "All"
info: "Information"
success: "Success"
warning: "Warning"
error: "Error"
debug: "Debug"
delete-all: "Remove All"
admin/views/abuse.vue:
title: "Abuse"
target: "Target"
@@ -1132,13 +1186,21 @@ admin/views/instance.vue:
maintainer-name: "Administrator name"
maintainer-email: "Contact Administrator"
advanced-config: "Other settings"
note-and-tl: "Notes and timelines"
drive-config: "Drive settings"
use-object-storage: "Use Object Storage"
object-storage-base-url: "URL"
object-storage-bucket: "Bucket Name"
object-storage-prefix: "Prefix"
object-storage-endpoint: "Endpoint"
object-storage-region: "Region"
object-storage-port: "Port"
object-storage-access-key: "Access Key"
object-storage-secret-key: "Secret Key"
object-storage-use-ssl: "Use SSL"
object-storage-s3-info: "If you are going to use Amazon S3 as Object Storage, Please refer {0} to configure 'Endpoint' and 'Region'."
object-storage-s3-info-here: "here"
object-storage-gcs-info: "If you are going to use Google Cloud Storage as Object Storage, Set the 'Endpoint' as storage.googleapis.com, and keep the 'Region' is blank."
cache-remote-files: "Cache remote files"
cache-remote-files-desc: "Without this parameter, all remote files are linked to their host server directly. This will be an effective solution to save your server storage, however make remote files invisible to users who set direct-link disabled, since no thumbnail will be generated, increase traffic. It is recommended that this parameter set enabled."
local-drive-capacity-mb: "Volume of Drive per user"
@@ -1146,9 +1208,14 @@ admin/views/instance.vue:
mb: "In megabytes"
recaptcha-config: "the reCAPTCHA settings"
recaptcha-info: "reCAPTCHA token is required. Please get it on https://www.google.com/recaptcha/intro/"
recaptcha-info2: "v3 is not supported. Please use v2."
enable-recaptcha: "enable reCAPTCHA"
recaptcha-site-key: "Site key"
recaptcha-secret-key: "Secret Key"
recaptcha-preview: "Preview"
hidden-tags: "Hidden hashtags"
hidden-tags-info: "List up the hashtags delimited by line breaks that you want exclude from statistics."
external-service-integration-config: "Connect an external service"
twitter-integration-config: "Settings of connecting to Twitter"
twitter-integration-info: "The callback URL is set on {url}."
enable-twitter-integration: "Enable connection to Twitter"
@@ -1179,7 +1246,8 @@ admin/views/instance.vue:
invite: "Invite"
save: "Save"
saved: "Saved"
pinned-users: "Higlighted user"
pinned-users: "Pinned user"
pinned-users-info: "List up the users delimited by line breaks that you want to show as 'Pinned Users'."
email-config: "Email server settings"
email-config-info: "Used to confirm email and password reset etc."
enable-email: "Enable email delivery"
@@ -1191,6 +1259,7 @@ admin/views/instance.vue:
smtp-auth: "Perform SMTP authentication"
smtp-user: "SMTP User"
smtp-pass: "SMTP Password"
test-email: "Test"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "Enable ServiceWorker"
serviceworker-info: "Must be enabled for push notifications."
@@ -1245,6 +1314,9 @@ admin/views/drive.vue:
unmark-as-sensitive: "Unmark as 'sensitive'"
marked-as-sensitive: "Set a sensitive content notice"
unmarked-as-sensitive: "Remove the sensitive content notice"
clean-remote-files: "Clear the remote files cache"
clean-remote-files-are-you-sure: "Are you sure you want to remove all cached files from remote?"
clean-up: "Clean up"
admin/views/users.vue:
operation: "Operations"
username-or-userid: "Username or user ID"
@@ -1390,6 +1462,8 @@ admin/views/federation.vue:
hour: "Hourly"
day: "Daily"
blocked-hosts: "Blocking"
blocked-hosts-info: "List up the hosts delimited by line breaks that you want to block."
save: "Save"
desktop/views/pages/welcome.vue:
about: "More details..."
timeline: "Timeline"
@@ -1521,17 +1595,6 @@ mobile/views/components/note-sub.vue:
cat: "cat"
mobile/views/components/notifications.vue:
empty: "No notifications"
mobile/views/components/post-form.vue:
add-visible-user: "Add a user"
submit: "Post"
reply: "Reply"
renote: "Renote"
quote-placeholder: "Quote this post... (optional)"
reply-placeholder: "Reply to this note..."
cw-placeholder: "Comments for the post (optional)"
geolocation-alert: "Your device does not provide location services."
error: "Error"
username-prompt: "Enter user name"
mobile/views/components/sub-note-content.vue:
private: "This post is private"
deleted: "This post has been deleted"
@@ -1546,7 +1609,7 @@ mobile/views/components/ui.nav.vue:
follow-requests: "Follow requests"
search: "Search"
user-lists: "Lists"
user-groups: "Group"
user-groups: "Groups"
widgets: "Widgets"
game: "Games"
admin: "Admin"
@@ -1695,6 +1758,10 @@ pages:
inspector: "Inspector"
content: "Page block"
variables: "Variables"
variables-info: "You can make your page more dynamic by using variables. If you write down <b>{ variable name }</b> in the text, you can embed the value of the variable there. For example, if the source text is <b>Hello { thing } world!</b> and the value of variable 'thing' is <b> ai </b>, that text becomes to <b>Hello ai world!</b>."
variables-info2: "Because the evaluation(=calculating) of variables are performed from top to bottom, the variable cannot refer another variable which exists on later line. For example, when defining three variables <b>A</b>, <b>B</b> and <b>C</b>, variable <b>C</b> <i>can</i> refer the variable <b>A</b> and <b>B</b> in its expression, but variable <b>A</b> <i>cannot</i> refer the variable <b>B</b> or <b>C</b> in its expression."
variables-info3: "If you want to get some input from the user, place a 'User Input' block on the page and set the variable name as which you want to store that input in 'variable name' (variables are created automatically). You can use that variable to perform actions in response to user's input."
variables-info4: "Function allows make your processing logic as group in a reusable way. To create a function, create a variable of type 'Function'. A function can have a slot (Argument) whose value is available as a variable in the function. There are also functions that take functions as arguments in the AiScript standard (called the higher-order function.). In addition to the predefined functions, you can also set them in the slots of such higher-order functions on the fly."
more-details: "Description"
title: "Title"
url: "Page URL"
@@ -1792,6 +1859,7 @@ pages:
strReverse: "Flip text"
_strReverse:
arg1: "Text"
join: "Text Concatenation"
_join:
arg1: "Lists"
arg2: "Separator"
@@ -1811,7 +1879,8 @@ pages:
_divide:
arg1: "A"
arg2: "B"
_remind:
mod: "÷ Remaindering"
_mod:
arg1: "A"
arg2: "B"
eq: "A and B are equal"
@@ -1874,21 +1943,29 @@ pages:
dailyRandomPick: "Choose at random from the list (Daily for each user)"
_dailyRandomPick:
arg1: "Lists"
seedRandom: "Random (Seed)"
_seedRandom:
arg1: "Seed"
arg2: "Probability"
seedRannum: "Random number (Seed)"
_seedRannum:
arg1: "Seed"
arg2: "Minimum"
arg3: "Maximum"
seedRandomPick: "Randomly selected from list (Seed)"
_seedRandomPick:
arg1: "Seed"
arg2: "Lists"
DRPWPM: "Randomly selected from weighted list (Daily updated per user)"
_DRPWPM:
arg1: "List of text"
pick: "Select from list"
_pick:
arg1: "Lists"
arg2: "Position"
listLen: "Get length of list"
_listLen:
arg1: "Lists"
number: "Number"
stringToNumber: "Text to number"
_stringToNumber:
@@ -1903,8 +1980,13 @@ pages:
fn: "Function"
_fn:
slots: "Slots"
slots-info: "Please delimit each slot with a line break"
arg1: "Output"
for: "Repeat"
_for:
arg1: "Count"
arg2: "Action"
typeError: "Slot {slot} accepts \"{expect}\" type, but It actually contains \"{actual}\" type!"
thereIsEmptySlot: "Slot {slot} is empty!"
types:
string: "Text"

View File

@@ -80,6 +80,11 @@ common:
"read:notifications": "Ver notificaciones"
"read:reactions": "Ver reacciones"
"write:votes": "Vota"
post-form:
reply: "Responder"
renote: "Volver a publicar"
enter-username: "Ingresar nombre de usuario"
username-prompt: "Ingresar nombre de usuario"
weekday-short:
sunday: "domingo"
monday: "lunes"
@@ -202,6 +207,7 @@ common:
my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado."
hide-password: "Ocultar contraseña"
show-password: "Mostrar contraseña"
enter-username: "Ingresar nombre de usuario"
do-not-use-in-production: "Esto está en desarrollo, no usarlo para producción."
user-suspended: "Este usuario ha sido suspendido"
is-remote-user: "La información sobre este usuario puede no estar completa"
@@ -766,7 +772,7 @@ desktop/views/components/note-detail.vue:
add-reaction: "Agregar una reacción"
desktop/views/components/note.vue:
reply: "Responder"
renote: "Republicar"
renote: "Volver a publicar"
add-reaction: "Reacción"
detail: "Detalles"
private: "Esta publicación es privada"
@@ -777,32 +783,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "No hay notificaciones"
desktop/views/components/post-form.vue:
add-visible-user: "+Agregar usuario"
attach-location-information: "Agregar localización"
hide-contents: "Esconder contenidos"
reply-placeholder: "Responder a esta nota..."
quote-placeholder: "Citar esta nota..."
submit: "Publicar"
reply: "Responder"
renote: "Republicar"
posted: "¡Publicado!"
replied: "¡Respondido!"
reposted: "¡Republicado!"
note-failed: "Error al publicar nota"
reply-failed: "Error al responder"
renote-failed: "Error al republicar"
posting: "Publicando"
attach-media-from-local: "Agregar medios de tu dispositivo"
attach-media-from-drive: "Adjunta multimedia desde tu Disco"
create-poll: "Crea una encuesta"
text-remain: "quedan {} caracteres"
recent-tags: "Reciente"
click-to-tagging: "Click para etiquetar"
visibility: "Visibilidad"
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
error: "Error"
enter-username: "Por favor escribe un nombre de usuario..."
annotations: "Anotaciones a la publicación (opcional)"
desktop/views/components/post-form-window.vue:
note: "Nota nueva"
reply: "Responder"
@@ -921,6 +907,9 @@ admin/views/dashboard.vue:
admin/views/queue.vue:
title: "Cola"
remove-all-jobs: "Limpiar todos los trabajos pendientes"
queue: "Cola"
admin/views/logs.vue:
logs: "Registros"
admin/views/abuse.vue:
title: "Abuso"
target: "Destinatario"
@@ -950,6 +939,7 @@ admin/views/instance.vue:
smtp-port: "Puerto SMTP"
smtp-user: "Usuario SMTP"
smtp-pass: "Contraseña SMTP"
test-email: "Prueba"
admin/views/charts.vue:
title: "Gráficos"
per-day: "Por día"
@@ -1000,6 +990,7 @@ admin/views/federation.vue:
hour: "Por hora"
day: "Por día"
blocked-hosts: "Bloquear"
save: "Guardar"
desktop/views/pages/selectdrive.vue:
cancel: "Cancelar"
desktop/views/pages/user-list.users.vue:
@@ -1052,11 +1043,6 @@ mobile/views/components/note-detail.vue:
location: "Localización"
mobile/views/components/notifications.vue:
empty: "No hay notificaciones"
mobile/views/components/post-form.vue:
reply: "Responder"
renote: "Republicar"
reply-placeholder: "Responder a esta nota..."
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
mobile/views/components/sub-note-content.vue:
private: "Esta publicación es privada"
deleted: "Esta publicación ha sido removida"
@@ -1124,5 +1110,7 @@ pages:
arg2: "Listas"
_pick:
arg1: "Listas"
_listLen:
arg1: "Listas"
types:
array: "Listas"

View File

@@ -12,7 +12,7 @@ common:
rich-contents: "Notes"
rich-contents-desc: "Partagez vos idées, les événements et les sujets qui vous tiennent à cœur ainsi que tout autre chose que vous souhaitez partager avec les autres. Si vous le désirez, vous pouvez décorer vos messages en utilisant une syntaxe différente ou en y joignant des sondages et des fichiers, tels que les photos ou les vidéos que vous aimez."
reaction: "Réactions"
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateurs. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateur·rice·s. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
ui: "Interface"
ui-desc: "Aucune interface graphique ne peut plaire à tout le monde. Par conséquent, Misskey possède une interface utilisateur hautement personnalisable selon vos goûts. Vous pouvez rendre votre page d'accueil originale en modifiant la mise en page de votre fil et en déplaçant les widgets que vous pouvez facilement ajuster pour vous approprier cet espace."
drive: "Drive"
@@ -78,8 +78,10 @@ common:
"write:drive": "Écrire sur le Drive"
"read:favorites": "Afficher les favoris"
"write:favorites": "Écrire des favoris"
"read:following": "Voir les informations de l'abonné"
"read:messaging": "Lire les conversations"
"write:messaging": "Utiliser la messagerie"
"read:mutes": "Voir les comptes masqués"
"write:notes": "Créer ou supprimer des publications"
"read:notifications": "Afficher les notifications"
"write:notifications": "Gérer vos notifications"
@@ -87,8 +89,34 @@ common:
"write:reactions": "Gérer vos réactions"
"write:votes": "Vote"
empty-timeline-info:
follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil."
explore: "Trouver des utilisateurs"
follow-users-to-make-your-timeline: "Les utilisateur·rice·s suivant·e·s afficheront leurs publications sur votre fil."
explore: "Trouver des utilisateur·rice·s"
post-form:
attach-location-information: "Joindre des informations de localisation"
hide-contents: "Masquer les contenus"
reply-placeholder: "Répondre à cette note …"
quote-placeholder: "Citer cette note …"
option-quote-placeholder: "Citer ce billet ... (Facultatif)"
quote-attached: "Cité"
submit: "Publication"
reply: "Répondre"
renote: "Republier"
posting: "Publication …"
attach-media-from-local: "Joindre un média depuis votre appareil"
attach-media-from-drive: "Joindre un média depuis votre Drive"
insert-a-kao: "v('ω')v"
create-poll: "Créer un sondage"
text-remain: "{} caractères restants"
recent-tags: "Récent"
local-only-message: "Ce message sera publié uniquement sur le fil local"
click-to-tagging: "Cliquer pour taguer"
visibility: "Visibilité"
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
error: "Erreur"
enter-username: "Saisir un nom d'utilisateur"
add-visible-user: "Ajouter un utilisateur"
cw-placeholder: "Commenter le contenu (optionnel)"
username-prompt: "Saisir un nom d'utilisateur"
weekday-short:
sunday: "D"
monday: "L"
@@ -120,13 +148,13 @@ common:
public: "Public"
home: "Principal"
home-desc: "Publier sur le fil principal uniquement"
followers: "Abonnés"
followers-desc: "Publier à vos abonnés uniquement"
followers: "Abonné·e·s"
followers-desc: "Publier à vos abonné·e·s uniquement"
specified: "Direct"
specified-desc: "Publier uniquement aux utilisateurs mentionnés"
specified-desc: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
local-public: "Local (Public)"
local-home: "Accueil (local uniquement)"
local-followers: "Local (Abonnés)"
local-followers: "Abonné·e·s (Local uniquement)"
note-placeholders:
a: "Que faites-vous maintenant ?"
b: "Quoi de neuf ?"
@@ -156,6 +184,7 @@ common:
web-search-engine: "Moteur de recherche Web"
web-search-engine-desc: "Exemple: https://www.google.com/?#q={{query}}"
keep-cw: "Maintenir l'avertissement de contenu"
keep-cw-desc: "Lorsque vous répondez à un message, le même avertissement de contenu est reprit par défaut dans la réponse, le même que celui qui a été défini dans le message original."
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
use-avatar-reversi-stones: "Utiliser lavatar comme pion dans Reversi"
@@ -198,9 +227,11 @@ common:
delete-wallpaper: "Supprimer le fond d'écran"
post-form-on-timeline: "Afficher le champs de saisie en haut du fil"
show-clock-on-header: "Afficher l'horloge sur le coté supérieur droit"
show-reply-target: "Afficher les réponses"
timeline: "Fil dactualité"
show-my-renotes: "Afficher mes republications dans le fil"
show-renoted-my-notes: "Afficher les partages de mes propres notes sur le fil"
show-local-renotes: "Afficher les partages locaux sur les fils"
remain-deleted-note: "Continuer à afficher les notes supprimées"
sound: "Son"
enable-sounds: "Activer les sons"
@@ -234,6 +265,7 @@ common:
disable-via-mobile: "Enlever la mention publié via 'mobile'"
load-raw-images: "Afficher les photos jointes dans leur qualité originale"
load-remote-media: "Afficher les médias depuis le serveur distant"
sync: "Synchroniser"
search: "Recherche"
delete: "Supprimer"
loading: "Chargement en cours…"
@@ -283,7 +315,7 @@ common:
version: "Version"
broadcast: "Diffusion"
notifications: "Notifications"
users: "Utilisateurs recommandés"
users: "Utilisateur·rice·s recommandé·e·s"
polls: "Sondages"
post-form: "Champs de publication"
server: "Infos sur le serveur"
@@ -310,13 +342,14 @@ auth/views/index.vue:
error: "La session nexiste pas."
sign-in: "Veuillez vous connecter"
common/views/pages/explore.vue:
popular-users: "Utilisateurs populaires"
recently-updated-users: "Utilisateurs actifs récemment"
pinned-users: "Utilisateur·rice·s épinglé·e·s"
popular-users: "Utilisateur·rice·s populaires"
recently-updated-users: "Utilisateur·rice·s actif·ve·s récemment"
recently-registered-users: "Les nouveaux inscrits"
popular-tags: "Mots-clés populaires"
federated: "Du Fédiverse"
explore: "Explorer {host}"
users-info: "Actuellement, {users} utilisateurs se sont inscrit ici"
users-info: "Actuellement, {users} utilisateur·rice·s se sont inscrit ici"
common/views/components/url-preview.vue:
enable-player: "Activer la lecture"
disable-player: "Fermer le lecteur"
@@ -441,6 +474,7 @@ common/views/components/messaging.vue:
user: "Utilisateur·rice·s"
group: "Groupe"
start-with-user: "Initier une discussion avec un·e utilisateur·rice"
start-with-group: "Démarrer un groupe et converser"
select-group: "Sélectionner un groupe"
common/views/components/messaging-room.vue:
not-talked-user: "Vous n'avez pas encore discuté avec cet·te utilisateur·rice"
@@ -532,6 +566,7 @@ common/views/components/poll-editor.vue:
day: "D"
common/views/components/reaction-picker.vue:
choose-reaction: "Choisissez votre réaction"
input-reaction-placeholder: "ou insérez un émoji"
common/views/components/emoji-picker.vue:
custom-emoji: "Émoji personnalisé"
people: "Personnes"
@@ -573,6 +608,7 @@ common/views/components/signup.vue:
password-matched: "OK"
password-not-matched: "Les mots de passe ne correspondent pas."
recaptcha: "Vérifier"
agree-to: "Accepter {0}."
tos: "Conditions d'utilisation"
create: "Créer un compte"
some-error: "La création du compte a échoué. Veuillez réessayer."
@@ -618,13 +654,13 @@ common/views/components/visibility-chooser.vue:
followers: "Abonné·e·s"
followers-desc: "Publier à vos abonné·e·s uniquement"
specified: "Direct"
specified-desc: "Publier uniquement aux utilisateurs mentionnés"
specified-desc: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
local-public: "Local (Public)"
local-public-desc: "Ne pas publier pour les distants"
local-home: "Accueil (local uniquement)"
local-followers: "Local (Abonnés)"
local-followers: "Abonné·e·s (Local uniquement)"
common/views/components/trends.vue:
count: "{} utilisateurs mentionnés"
count: "{} utilisateur·rice·s mentionné·e·s"
empty: "Aucune tendance"
common/views/components/language-settings.vue:
title: "Langue "
@@ -683,8 +719,13 @@ common/views/components/user-list-editor.vue:
deleted: "Supprimé"
add-user: "Ajouter un utilisateur"
common/views/components/user-group-editor.vue:
users: "Membres"
rename: "Renommer le groupe"
delete: "Supprimer le groupe"
transfer: "Transférer de groupe"
transferred: "Groupe transféré"
remove-user: "Enlever un utilisateur de ce groupe"
delete-are-you-sure: "Désirez-vous vraiment supprimer le groupe $1 ?"
deleted: "Supprimé"
invite: "Inviter"
invited: "Invitation envoyée avec succès"
@@ -858,7 +899,7 @@ desktop/views/components/media-video.vue:
sensitive: "Le contenu est NSFW"
click-to-show: "Cliquer pour afficher"
desktop/views/components/followers-window.vue:
followers: "{} abonné·e·s"
followers: "Abonné·e·s de {}"
desktop/views/components/followers.vue:
empty: "Il semble que vous navez pas encore dabonné·e·s."
desktop/views/components/following-window.vue:
@@ -895,34 +936,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "Aucune de notification !"
desktop/views/components/post-form.vue:
add-visible-user: "+Ajouter un·e utilisateur·rice"
attach-location-information: "Attacher des informations de localisation"
hide-contents: "Masquer les contenus"
reply-placeholder: "Répondre à cette note …"
quote-placeholder: "Citer cette note …"
submit: "Publier"
reply: "Répondre"
renote: "Republier"
posted: "Publié !"
replied: "Répondu !"
reposted: "Reposté !"
note-failed: "La note à échoué"
reply-failed: "La réponse a échoué"
renote-failed: "Échec lors de la republication"
posting: "Publication …"
attach-media-from-local: "Joindre un média depuis votre appareil"
attach-media-from-drive: "Joindre un média depuis votre Drive"
insert-a-kao: "v('ω')v"
create-poll: "Créer un sondage"
text-remain: "{} caractères restants"
recent-tags: "Récent"
local-only-message: "Ce message sera publié uniquement sur le fil local"
click-to-tagging: "Cliquer pour taguer"
visibility: "Visibilité"
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
error: "Erreur"
enter-username: "Saisir un nom d'utilisateur …"
annotations: "Commenter le contenu (optionnel)"
desktop/views/components/post-form-window.vue:
note: "Nouvelle note"
reply: "Répondre"
@@ -1071,7 +1090,10 @@ admin/views/index.vue:
abuse: "Abus"
queue: "File dattente"
logs: "Journaux"
db: "Base de données"
back-to-misskey: "Retour vers Misskey"
admin/views/db.vue:
tables: "Tables"
admin/views/dashboard.vue:
dashboard: "Tableau de bord"
accounts: "Comptes"
@@ -1083,6 +1105,30 @@ admin/views/dashboard.vue:
admin/views/queue.vue:
title: "File d'attente"
remove-all-jobs: "Enlever toutes les tâches en attente"
jobs: "Tâches"
queue: "File d'attente"
domains:
deliver: "Délivrées"
inbox: "Reçues"
db: "Base de données"
state: "État"
states:
active: "en cours"
delayed: "Programmé"
waiting: "En file d'attente"
other-queues: "Autres files dattente"
admin/views/logs.vue:
logs: "Journaux"
domain: "Domaine"
level: "Niveau"
levels:
all: "Tous"
info: "Informations"
success: "Succès"
warning: "Avertissement"
error: "Erreur"
debug: "Débogage"
delete-all: "Effacer tout"
admin/views/abuse.vue:
title: "Abus"
target: "Cible"
@@ -1106,9 +1152,12 @@ admin/views/instance.vue:
maintainer-name: "Nom de ladministrateur"
maintainer-email: "Contact administratif"
advanced-config: "Autres réglages"
note-and-tl: "Notes et fils"
drive-config: "Paramètres du lecteur"
object-storage-base-url: "URL"
object-storage-prefix: "Préfixe"
object-storage-endpoint: "Point de terminaison"
object-storage-region: "Région"
object-storage-port: "Port"
object-storage-access-key: "Clé d'accès"
object-storage-secret-key: "Clé secrète"
@@ -1120,10 +1169,13 @@ admin/views/instance.vue:
mb: "en mégaoctets"
recaptcha-config: "Paramètres de reCAPTCHA"
recaptcha-info: "Si activé, un jeton reCAPTCHA est requis. Vous pouvez en obtenir un sur https://www.google.com/recaptcha/intro/"
recaptcha-info2: "v3 n'est pas supportée. Veuillez utiliser v2."
enable-recaptcha: "Activation de reCAPTCHA"
recaptcha-site-key: "Clé du site"
recaptcha-secret-key: "Clé secrète"
recaptcha-preview: "Prévisualisation"
hidden-tags: "Tags cachés"
external-service-integration-config: "Services connectés"
twitter-integration-config: "Paramètres de connexion à Twitter"
twitter-integration-info: "L'URL de callback est {url}."
enable-twitter-integration: "Activer la connexion à Twitter"
@@ -1148,9 +1200,12 @@ admin/views/instance.vue:
disable-local-timeline: "Désactiver le fil local"
disable-global-timeline: "Désactiver le fil global"
disabling-timelines-info: "Même si vous désactivez ces fils, l'administrateur et les modérateurs peuvent continuer à les utiliser."
enable-emoji-reaction: "Activer les pictogrammes dans les réactions"
use-star-for-reaction-fallback: "Utiliser une étoile si une réaction est inconnue"
invite: "Inviter"
save: "Sauvegarder"
saved: "Enregistré"
pinned-users: "Utilisateur·rice épinglé·e"
email-config: "Paramètres du serveur de messagerie"
email-config-info: "Utilisé pour confirmer votre adresse de courrier électronique et la réinitialisation de votre mot de passe."
enable-email: "Activation de la distribution du courrier"
@@ -1162,6 +1217,7 @@ admin/views/instance.vue:
smtp-auth: "Effectuer une authentification SMTP"
smtp-user: "Utilisateur SMTP"
smtp-pass: "Mot de passe SMTP"
test-email: "Test"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "Activer ServiceWorker"
serviceworker-info: "Devrait être activé pour les notifications push."
@@ -1174,7 +1230,7 @@ admin/views/charts.vue:
per-hour: "par heure"
federation: "Fédération"
notes: "Publications"
users: "Utilisateurs"
users: "Utilisateur·rice·s"
drive: "Lecteur"
network: "Réseau"
charts:
@@ -1184,8 +1240,8 @@ admin/views/charts.vue:
local-notes: "Nombre des publications : augmentation/diminution (Local)"
remote-notes: "Nombre de publications : augmentation/diminution (distants)"
notes-total: "Total des notes"
users: "Nombre dutilisateurs : augmentation/diminution"
users-total: "Nombre total des utilisateurs"
users: "Nombre dutilisateur·rice·s : augmentation/diminution"
users-total: "Nombre total des utilisateur·rice·s"
active-users: "Utilisateur·rice·s actif·ve·s"
drive: "Capacité utilisée comme stockage : augmentation/diminution"
drive-total: "Utilisation totale du lecteur"
@@ -1216,6 +1272,8 @@ admin/views/drive.vue:
unmark-as-sensitive: "Ne pas marquer comme sensible"
marked-as-sensitive: "Marqué comme sensible"
unmarked-as-sensitive: "Marqué comme non sensible"
clean-remote-files: "Nettoyer le cache des fichiers distants"
clean-up: "Nettoyage"
admin/views/users.vue:
operation: "Actions"
username-or-userid: "Nom dutilisateur·rice ou ID utilisateur"
@@ -1235,6 +1293,7 @@ admin/views/users.vue:
unmake-silence: "Enlever la sourdine"
update-remote-user: "Mettre à jour les informations de lutilisateur·rice distant·e"
remote-user-updated: "Les informations de lutilisateur·rice distant·e ont étés mis à jour"
delete-all-files: "Supprimer tous les fichiers"
users:
title: "Utilisateur·rice·s"
sort:
@@ -1309,6 +1368,7 @@ admin/views/federation.vue:
latest-request-sent-at: "Dernière requête envoyée"
latest-request-received-at: "Dernière requête reçue"
remove-all-following-info: "Se désabonner de tous les comptes de {host}. Exécutez cette commande si l'instance n'existe plus."
delete-all-files: "Supprimer tous les fichiers"
block: "Bloquer"
marked-as-closed: "Marquées comme fermées"
lookup: "Recherche"
@@ -1321,7 +1381,7 @@ admin/views/federation.vue:
lastCommunicatedAtAsc: "La date et l'heure des interactions plus anciennes"
lastCommunicatedAtDesc: "La date et l'heure des nouvelles interactions"
notesDesc: "Description des notes"
usersAsc: "Peu d'abonnés"
usersAsc: "Peu d'abonné·e·s"
followingAsc: "Les moins suivies"
followingDesc: "Ayant le plus d'abonné·e·s"
followersAsc: "Ayant le moins d'abonné·e·s"
@@ -1336,7 +1396,7 @@ admin/views/federation.vue:
charts: "Graphs"
chart-srcs:
requests: "Requêtes"
users: "Nombre dutilisateurs·trices : augmentation/diminution"
users: "Nombre dutilisateur·trice·s : augmentation/diminution"
users-total: "Nombre total des utilisateur·rice·s"
notes: "Augmentation/diminution du nombre des notes"
notes-total: "Nombre total des notes"
@@ -1348,6 +1408,7 @@ admin/views/federation.vue:
hour: "Par heure"
day: "Par jour"
blocked-hosts: "En cours blocage"
save: "Enregistrer"
desktop/views/pages/welcome.vue:
about: "à propos"
timeline: "Fil dactualité"
@@ -1377,7 +1438,7 @@ desktop/views/pages/user-list.users.vue:
desktop/views/pages/user/user.followers-you-know.vue:
title: "Abonné·e·s que vous connaissez"
loading: "Chargement en cours"
no-users: "Aucun abonné connu"
no-users: "Aucun·e abonné·e connu·e"
desktop/views/pages/user/user.friends.vue:
title: "Mentions fréquentes"
loading: "Chargement en cours"
@@ -1430,8 +1491,10 @@ mobile/views/components/drive.vue:
nothing-in-drive: "Rien"
folder-is-empty: "Ce dossier est vide"
folder-name: "Nom du dossier"
here-is-root: "Actuellement, vous êtes dans la racine et non pas dans un dossier."
url-prompt: "URL du fichier que vous souhaitez téléverser"
uploading: "Envoi demandé. Le téléversement pourrait prendre un certain temps avant de s'achever."
folder-name-cannot-empty: "Le nom du dossier ne peut être laissé vide."
mobile/views/components/drive-file-chooser.vue:
select-file: "Choisissez un fichier"
mobile/views/components/drive-folder-chooser.vue:
@@ -1476,17 +1539,6 @@ mobile/views/components/note-sub.vue:
cat: "chat"
mobile/views/components/notifications.vue:
empty: "Aucune de notification !"
mobile/views/components/post-form.vue:
add-visible-user: "Ajouter un·e utilisateur·rice"
submit: "Publier"
reply: "Répondre"
renote: "Republier"
quote-placeholder: "Citer ce billet ... (Facultatif)"
reply-placeholder: "Répondre à cette note"
cw-placeholder: "Commenter le contenu (optionnel)"
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
error: "Erreur"
username-prompt: "Saisir un nom d'utilisateur"
mobile/views/components/sub-note-content.vue:
private: "cette publication est privée"
deleted: "cette publication a été supprimée"
@@ -1589,7 +1641,7 @@ deck:
remove: "Supprimer la colonne"
add-column: "Ajouter une colonne"
rename: "Renommer"
stack-left: "Vers la gauche"
stack-left: "Empiler à gauche"
pop-right: "Vers la droite"
disabled-timeline:
title: "Le fil été désactivé"
@@ -1601,7 +1653,7 @@ deck/deck.user-column.vue:
follows-you: "Vous suit"
posts: "Notes"
following: "Suit"
followers: "Abonnés"
followers: "Abonné·e·s"
images: "Images"
activity: "Activité"
timeline: "Fil dactualité"
@@ -1617,23 +1669,34 @@ dev/views/apps.vue:
app-missing: "Aucune application"
dev/views/new-app.vue:
new-app: "Nouvelle application"
new-app-info: "Vous pouvez aussi créer une application avec l'API. (app/create)"
create-app: "Création dune application"
app-name: "Nom de lapplication"
app-name-placeholder: "p. ex. Misskey pour iOS"
app-name-desc: "Le nom de votre application"
app-overview: "Description courte de lapplication"
app-overview-placeholder: "p. ex. Misskey pour iOS"
app-overview-desc: "Brève description introductive à votre application."
callback-url: "LUrl de callback (facultatif)"
callback-url-placeholder: "p. ex. https://votre.app.example.com/callback.php"
callback-url-desc: "Vous pouvez définir lURL de redirection lorsque lutilisateur sest authentifié via formulaire dauthentification."
authority: "Autorisations "
authority-desc: "Sont accessibles via lAPI, uniquement les fonctionnalités demandées ici."
authority-warning: "Vous pouvez le changer même après avoir créé l'application, mais si vous attribuez une nouvelle permission, toutes les clés utilisateur associées seront dès lors invalides."
pages:
new-page: "Créer une page"
edit-page: "Modifier une page"
read-page: "Voir la source"
page-created: "Page a été créée !"
page-updated: "A mis à jour la page"
are-you-sure-delete: "Confirmez-vous la suppression de cette page ?"
page-deleted: "La page a bien été supprimée."
edit-this-page: "Éditer cette page"
view-source: "Afficher la source"
view-page: "Afficher la page"
like: "Bien"
liked-pages: "Pages favorites"
my-pages: "Mes pages"
inspector: "Inspecteur"
content: "Bloc de page"
variables: "Variables"
@@ -1645,6 +1708,8 @@ pages:
font: "Police de caractères"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
set-eye-catching-image: "Définir une image attirante"
remove-eye-catching-image: "Supprimer une image attirante"
choose-block: "Ajouter un bloc"
select-type: "Choisir un type"
enter-variable-name: "Veuillez choisir un nom de variable"
@@ -1707,9 +1772,11 @@ pages:
random: "Aléatoire"
value: "Valeur"
fn: "Fonction"
text: "Actions texte"
list: "Listes"
blocks:
text: "Texte"
textList: "Liste de texte"
strLen: "Longueur du texte"
_strLen:
arg1: "Texte"
@@ -1742,7 +1809,7 @@ pages:
_divide:
arg1: "A"
arg2: "B"
_remind:
_mod:
arg1: "A"
arg2: "B"
eq: "A et B sont équivalents"
@@ -1753,21 +1820,27 @@ pages:
_notEq:
arg1: "A"
arg2: "B"
and: "A et B"
_and:
arg1: "A"
arg2: "B"
or: "A ou B"
_or:
arg1: "A"
arg2: "B"
lt: "A est plus petit que B"
_lt:
arg1: "A"
arg2: "B"
gt: "A est supérieur à B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "A est plus petit ou égal à B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: "A est supérieur ou égal à B"
_gtEq:
arg1: "A"
arg2: "B"
@@ -1779,6 +1852,13 @@ pages:
_not:
arg1: "négation"
random: "Aléatoire"
_random:
arg1: "Probabilité"
rannum: "Nombre aléatoire"
_rannum:
arg1: "Minimum"
arg2: "Maximum"
randomPick: "Choisir aléatoirement depuis la liste"
_randomPick:
arg1: "Listes"
_dailyRandom:
@@ -1801,6 +1881,8 @@ pages:
_pick:
arg1: "Listes"
arg2: "Position"
_listLen:
arg1: "Listes"
number: "Numérique"
stringToNumber: "Chaîne en chiffres"
_stringToNumber:
@@ -1816,10 +1898,14 @@ pages:
slots: "Emplacement"
arg1: "Sortie"
for: "Répéter"
_for:
arg1: "Compter"
arg2: "Action"
thereIsEmptySlot: "Slot {slot} est vide !"
types:
string: "Texte"
number: "Numérique"
boolean: "Marqueur"
array: "Listes"
stringArray: "Liste de texte"
emptySlot: "Slot vide"

View File

@@ -36,6 +36,7 @@ common:
signout: "ログアウト"
reload-to-apply-the-setting: "この設定を反映するにはページをリロードする必要があります。今すぐリロードしますか?"
fetching-as-ap-object: "連合に照会中"
unfollow-confirm: "{name}さんをフォロー解除しますか?"
got-it: "わかった"
customization-tips:
@@ -282,6 +283,9 @@ common:
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する"
sync: "同期"
home-profile: "ホームのプロファイル"
deck-profile: "デッキのプロファイル"
search: "検索"
delete: "削除"
@@ -558,6 +562,7 @@ common/views/components/note-menu.vue:
delete: "削除"
delete-confirm: "この投稿を削除しますか?"
remote: "投稿元で見る"
pin-limit-exceeded: "これ以上ピン留めできません。"
common/views/components/user-menu.vue:
mention: "メンション"
@@ -642,6 +647,8 @@ common/views/components/signin.vue:
signin-with-github: "GitHubでログイン"
signin-with-discord: "Discordでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
tap-key: "セキュリティキーをクリックしてログイン"
enter-2fa-code: "認証コードを入力してください"
common/views/components/signup.vue:
invitation-code: "招待コード"
@@ -1096,6 +1103,15 @@ desktop/views/components/settings.2fa.vue:
success: "設定が完了しました!"
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
totp-header: "認証アプリ"
security-key-header: "セキュリティキー"
security-key: "セキュリティを強化するために、FIDO2をサポートするハードウェアセキュリティキーを使用してアカウントにログインできます。 サインインの際は、登録されたセキュリティキーまたは認証アプリが必要になります。"
last-used: "最後の使用:"
activate-key: "クリックしてセキュリティキーをアクティベートしてください"
security-key-name: "キー名"
register-security-key: "キーの登録を完了"
something-went-wrong: "わー! キーを登録する際に問題が発生しました:"
key-unregistered: "キーが削除されました"
common/views/components/media-image.vue:
sensitive: "閲覧注意"
@@ -1226,8 +1242,15 @@ admin/views/index.vue:
abuse: "スパム報告"
queue: "ジョブキュー"
logs: "ログ"
db: "データベース"
back-to-misskey: "Misskeyに戻る"
admin/views/db.vue:
tables: "テーブル"
vacuum: "バキューム"
vacuum-info: "データベースの掃除を行います。データはそのままで、ディスク使用量を減らします。通常この操作は自動で定期的に行われます。"
vacuum-exclamation: "バキュームを行うと、しばらくの間データベースの負荷が高くなり、ユーザーの操作を受け付けなくなる場合があります。"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
accounts: "アカウント"
@@ -1366,6 +1389,7 @@ admin/views/instance.vue:
smtp-auth: "SMTP認証を行う"
smtp-user: "SMTPユーザー"
smtp-pass: "SMTPパスワード"
test-email: "テスト"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "ServiceWorkerを有効にする"
serviceworker-info: "プッシュ通知を行うには有効する必要があります。"
@@ -2060,8 +2084,8 @@ pages:
_divide:
arg1: "A"
arg2: "B"
remind: "÷ 割った余り"
_remind:
mod: "÷ 割った余り"
_mod:
arg1: "A"
arg2: "B"
eq: "AとBが同じ"
@@ -2144,6 +2168,9 @@ pages:
_pick:
arg1: "リスト"
arg2: "位置"
listLen: "リストの長さを取得"
_listLen:
arg1: "リスト"
number: "数値"
stringToNumber: "テキストを数値に"
_stringToNumber:

View File

@@ -62,6 +62,14 @@ common:
favorites: "お気に入り"
permissions:
"write:votes": "投票するで"
post-form:
submit: "投稿"
reply: "返す"
renote: "Renote"
error: "エラー"
enter-username: "ユーザー名を入力してや"
add-visible-user: "ユーザー増やす"
username-prompt: "ユーザー名を入力してや"
weekday-short:
sunday: "日"
monday: "月"
@@ -670,33 +678,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "あらへん!"
desktop/views/components/post-form.vue:
add-visible-user: "+ユーザー増やす"
attach-location-information: "いる場所くっつけるで"
hide-contents: "内容を隠す"
reply-placeholder: "この投稿への返信..."
quote-placeholder: "この投稿を引用..."
submit: "投稿"
reply: "返信"
renote: "Renote"
posted: "投稿したで!"
replied: "返信したで!"
reposted: "Renoteしたで"
note-failed: "投稿に失敗したで"
reply-failed: "返信に失敗したで"
renote-failed: "Renoteでけへん"
posting: "投稿中"
attach-media-from-local: "PCからメディア持ってくる"
attach-media-from-drive: "ドライブからメディア持ってくる"
create-poll: "アンケートを作成"
text-remain: "残り{}文字"
recent-tags: "最近のタグ"
local-only-message: "この投稿はローカルだけ公開されるで"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
error: "エラー"
enter-username: "ユーザー名を入力してや"
annotations: "もっと教えてな(別にええけど)"
desktop/views/components/post-form-window.vue:
note: "新規投稿"
reply: "返す"
@@ -845,6 +832,10 @@ admin/views/dashboard.vue:
instances: "インスタンス"
this-instance: "ワイのインスタンス"
federated: "連合"
admin/views/logs.vue:
levels:
info: "情報"
error: "エラー"
admin/views/abuse.vue:
details: "もっと"
remove-report: "削除"
@@ -991,6 +982,7 @@ admin/views/federation.vue:
hour: "1時間ごと"
day: "1日ごと"
blocked-hosts: "ブロック"
save: "保存"
desktop/views/pages/welcome.vue:
about: "もうちょい……"
timeline: "タイムライン"
@@ -1114,17 +1106,6 @@ mobile/views/components/note-sub.vue:
cat: "cat"
mobile/views/components/notifications.vue:
empty: "あらへん!"
mobile/views/components/post-form.vue:
add-visible-user: "ユーザー増やす"
submit: "投稿"
reply: "返す"
renote: "Renote"
quote-placeholder: "この投稿を持ってくる(オプション)"
reply-placeholder: "この投稿への返信..."
cw-placeholder: "内容への注釈 (オプション)"
geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
error: "エラー"
username-prompt: "ユーザー名を入力してや"
mobile/views/components/sub-note-content.vue:
private: "この投稿は見せられへんわ"
deleted: "この投稿なんか無くなってもうたわ"
@@ -1273,5 +1254,7 @@ pages:
arg2: "リスト"
_pick:
arg1: "リスト"
_listLen:
arg1: "リスト"
types:
array: "リスト"

View File

@@ -4,7 +4,7 @@ meta:
common:
misskey: "연합우주의 ⭐"
about-title: "연합우주의 ⭐."
about: "Misskey를 찾아주셔서 감사합니다. Misskey는 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse(다양한 SNS로 구성되는 우주)에 존재하 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까."
about: "Misskey를 발견해주셔서 감사합니다! Misskey는 지구에서 태어난 <b>분산 마이크로 블로그 SNS</b> 입니다. Fediverse (다양한 SNS가 함께하는 우주)에 존재하고 있어서, 다른 SNS와 서로 연결되어 있습니다. 번잡한 도시에서 벗어나 새로운 인터넷에 빠져보지 않으시겠어요?"
intro:
title: "Misskey란?"
about: "Misskey는 오픈소스 <b>분산형 마이크로블로그 SNS</b>입니다. 다양하고 폭넓게 커스터마이징할 수 있는 UI, 글에 대한 리액션, 파일을 관리할 수 있는 드라이브 등의 선진적인 기능을 갖추고 있습니다. 더하여 Fediverse라고 부르는 네트워크에 연결할 수 있어 다른 SNS와도 주고받을 수 있습니다. 예를 들자면, 당신이 무언가를 게시하면, 해당 게시물은 Misskey 뿐만 아니라 다른 SNS에도 전해집니다. 살짝 어떤 행성에서 다른 행성으로 전파를 발신하고 있는 모습을 상상해주세요."
@@ -35,6 +35,7 @@ common:
signout: "로그아웃"
reload-to-apply-the-setting: "이 설정을 적용하려면 페이지를 새로고침해야 합니다. 바로 새로고침하시겠습니까?"
fetching-as-ap-object: "연합에서 조회 중"
unfollow-confirm: "{name} 님을 팔로우 해제하시겠습니까?"
got-it: "알겠습니다"
customization-tips:
title: "커스터마이징 도움말"
@@ -95,6 +96,33 @@ common:
empty-timeline-info:
follow-users-to-make-your-timeline: "사용자를 팔로우하면 글이 타임라인에 표시됩니다."
explore: "사용자 탐색"
post-form:
attach-location-information: "위치 정보를 첨부합니다"
hide-contents: "내용 숨기기"
reply-placeholder: "이 글에 답글..."
quote-placeholder: "이 글을 인용..."
option-quote-placeholder: "이 글을 인용... (옵션)"
quote-attached: "인용함"
quote-question: "인용해서 작성하시겠습니까?"
submit: "글쓰기"
reply: "답글 달기"
renote: "리노트"
posting: "게시중"
attach-media-from-local: "PC에서 미디어 첨부"
attach-media-from-drive: "드라이브에서 미디어 첨부"
insert-a-kao: "v('ω')v"
create-poll: "투표 만들기"
text-remain: "{}문자 남음"
recent-tags: "최근"
local-only-message: "이 글은 로컬에만 공개되어 있습니다"
click-to-tagging: "클릭하여 태그 넣기"
visibility: "공개 범위"
geolocation-alert: "사용 중이신 장치에서는 위치 정보를 사용할 수 없습니다"
error: "오류"
enter-username: "사용자명을 입력해주세요"
add-visible-user: "사용자 추가"
cw-placeholder: "내용에 대한 주석 (옵션)"
username-prompt: "사용자명을 입력해주세요"
weekday-short:
sunday: "일"
monday: "월"
@@ -243,6 +271,9 @@ common:
disable-via-mobile: "작성하는 글에 \"모바일에서 작성함\" 을 붙이지 않음"
load-raw-images: "첨부 이미지를 고품질로 표시"
load-remote-media: "원격 서버의 미디어를 표시"
sync: "동기화"
home-profile: "홈 프로필"
deck-profile: "덱 프로필"
search: "검색"
delete: "삭제"
loading: "로드 중"
@@ -253,13 +284,13 @@ common:
my-token-regenerated: "당신의 토큰이 업데이트되었으므로 로그아웃합니다."
hide-password: "비밀번호 숨기기"
show-password: "비밀번호 표시"
enter-username: "사용자명을 입력하여 주십시오"
enter-username: "사용자명을 입력해주세요"
do-not-use-in-production: "이것은 개발 빌드입니다. 프로덕션 환경에서 사용하지 마십시오."
user-suspended: "이 사용자는 정지된 상태입니다."
is-remote-user: "이 사용자 정보는 정확하지 않을 수 있습니다."
is-remote-post: "이 글 정보는 복사본입니다."
view-on-remote: "정확한 정보 보기"
renoted-by: "{user}이(가) 리노트"
renoted-by: "{user}이 리노트"
no-notes: "글이 없습니다"
turn-on-darkmode: "어둠에 삼켜져라"
turn-off-darkmode: "빛이 있으라"
@@ -493,6 +524,7 @@ common/views/components/note-menu.vue:
delete: "삭제"
delete-confirm: "이 글을 삭제하시겠습니까?"
remote: "글 원본 보기"
pin-limit-exceeded: "더 이상 고정할 수 없습니다."
common/views/components/user-menu.vue:
mention: "멘션"
mute: "뮤트"
@@ -571,6 +603,8 @@ common/views/components/signin.vue:
signin-with-github: "GitHub으로 로그인"
signin-with-discord: "Discord로 로그인"
login-failed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
tap-key: "보안 키를 클릭하여 로그인"
enter-2fa-code: "인증 코드를 입력하여 주십시오"
common/views/components/signup.vue:
invitation-code: "초대 코드"
invitation-info: "초대 코드가 없으신 분은 <a href=\"{}\">관리자</a>에게 연락하시기 바랍니다."
@@ -922,34 +956,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "비었습니다!"
desktop/views/components/post-form.vue:
add-visible-user: "+사용자 추가"
attach-location-information: "위치정보를 첨부하기"
hide-contents: "내용 숨기기"
reply-placeholder: "이 글에 답글..."
quote-placeholder: "이 글을 인용..."
submit: "글쓰기"
reply: "답글 달기"
renote: "리노트"
posted: "게시하였습니다!"
replied: "답글을 달았습니다!"
reposted: "리노트 하였습니다!"
note-failed: "게시에 실패하였습니다"
reply-failed: "답글을 달지 못했습니다"
renote-failed: "리노트에 실패하였습니다"
posting: "게시중"
attach-media-from-local: "PC에서 미디어 첨부"
attach-media-from-drive: "드라이브에서 미디어 첨부"
insert-a-kao: "v('ω')v"
create-poll: "투표 만들기"
text-remain: "{}문자 남음"
recent-tags: "최근"
local-only-message: "이 글은 로컬에만 공개되어 있습니다"
click-to-tagging: "클릭하여 태그 넣기"
visibility: "공개설정"
geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
error: "오류"
enter-username: "사용자명을 입력해주세요"
annotations: "내용 주석 (선택적)"
desktop/views/components/post-form-window.vue:
note: "새 글"
reply: "답글 달기"
@@ -989,6 +1001,15 @@ desktop/views/components/settings.2fa.vue:
success: "설정이 완료되었습니다!"
failed: "설정에 실패했습니다. 토큰이 잘못되었는지 확인해주십시오."
info: "다음 로그인부터는 이와 동일하게 비밀번호에 더해 장치에 표시된 토큰을 입력합니다."
totp-header: "인증 앱"
security-key-header: "보안 키"
security-key: "보안을 강화하려면 FIDO2를 지원하는 하드웨어 보안 키를 사용하여 계정에 로그인할 수 있습니다. 로그인 시 등록하였던 보안 키 또는 인증 앱이 필요하게 됩니다."
last-used: "마지막 사용:"
activate-key: "클릭하여 보안 키를 활성화하여 주십시오"
security-key-name: "키 이름"
register-security-key: "키 등록 완료"
something-went-wrong: "으악! 키를 등록하는 도중 문제가 발생하였습니다:"
key-unregistered: "키가 등록되어 있지 않습니다"
common/views/components/media-image.vue:
sensitive: "열람주의"
click-to-show: "클릭하여 보기"
@@ -1098,7 +1119,13 @@ admin/views/index.vue:
abuse: "스팸 신고"
queue: "작업 대기열"
logs: "로그"
db: "데이터베이스"
back-to-misskey: "Misskey로 돌아가기"
admin/views/db.vue:
tables: "테이블"
vacuum: "청소"
vacuum-info: "데이터베이스를 청소합니다. 데이터는 그대로인 채로 데이터의 사용량을 줄입니다. 일반적으로 이 작업은 자동으로 정기적으로 수행됩니다."
vacuum-exclamation: "청소를 수행하면 한동안 데이터베이스의 부하가 높아져 사용자 조작을 처리하지 못 할 수 있습니다."
admin/views/dashboard.vue:
dashboard: "대시보드"
accounts: "계정"
@@ -1110,6 +1137,32 @@ admin/views/dashboard.vue:
admin/views/queue.vue:
title: "큐"
remove-all-jobs: "모든 작업 제거"
jobs: "작업"
queue: "큐"
domains:
deliver: "전송"
inbox: "수신"
db: "데이터베이스"
objectStorage: "오브젝트 스토리지"
state: "상태"
states:
active: "처리중"
delayed: "지연됨"
waiting: "대기열에 있음"
result-is-truncated: "결과는 생략되었습니다"
other-queues: "기타 큐"
admin/views/logs.vue:
logs: "로그"
domain: "도메인"
level: "수준"
levels:
all: "전체"
info: "정보"
success: "성공"
warning: "경고"
error: "오류"
debug: "디버그"
delete-all: "모두 삭제"
admin/views/abuse.vue:
title: "스팸 신고"
target: "대상"
@@ -1207,6 +1260,7 @@ admin/views/instance.vue:
smtp-auth: "SMTP 인증 수행"
smtp-user: "SMTP 사용자"
smtp-pass: "SMTP 비밀번호"
test-email: "테스트"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "ServiceWorker 사용"
serviceworker-info: "푸시알림을 수행하려면 사용해야 합니다."
@@ -1261,6 +1315,9 @@ admin/views/drive.vue:
unmark-as-sensitive: "열람주의 해제"
marked-as-sensitive: "열람주의로 설정하였습니다"
unmarked-as-sensitive: "열람주의를 제거하였습니다"
clean-remote-files: "리모트 파일 캐시를 삭제"
clean-remote-files-are-you-sure: "정말 모든 리모트 파일의 캐시를 삭제하시겠습니까?"
clean-up: "청소"
admin/views/users.vue:
operation: "작업"
username-or-userid: "사용자명 혹은 사용자 ID"
@@ -1407,6 +1464,7 @@ admin/views/federation.vue:
day: "1일마다"
blocked-hosts: "차단"
blocked-hosts-info: "차단할 호스트를 줄바꿈으로 구분하여 기술합니다."
save: "저장"
desktop/views/pages/welcome.vue:
about: "자세히..."
timeline: "타임라인"
@@ -1538,17 +1596,6 @@ mobile/views/components/note-sub.vue:
cat: "cat"
mobile/views/components/notifications.vue:
empty: "없습니다!"
mobile/views/components/post-form.vue:
add-visible-user: "사용자 추가"
submit: "글쓰기"
reply: "답글 달기"
renote: "리노트"
quote-placeholder: "이 글을 인용... (선택적)"
reply-placeholder: "이 글에 답글..."
cw-placeholder: "내용 주석 (선택적)"
geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
error: "오류"
username-prompt: "사용자명을 입력하여 주십시오"
mobile/views/components/sub-note-content.vue:
private: "이 글은 비공개입니다"
deleted: "이 글은 삭제되었습니다"
@@ -1833,8 +1880,8 @@ pages:
_divide:
arg1: "A"
arg2: "B"
remind: "÷ 나눈 나머지"
_remind:
mod: "÷ 나눈 나머지"
_mod:
arg1: "A"
arg2: "B"
eq: "A와 B가 동일"
@@ -1917,6 +1964,9 @@ pages:
_pick:
arg1: "리스트"
arg2: "위치"
listLen: "리스트의 길이 가져오기"
_listLen:
arg1: "리스트"
number: "수치"
stringToNumber: "텍스트를 수치로"
_stringToNumber:

View File

@@ -25,6 +25,10 @@ common:
favorites: "Deze notitie toevoegen aan favorieten"
permissions:
"write:votes": "Stemmen"
post-form:
submit: "Bericht"
reply: "Beantwoorden"
add-visible-user: "Gebruiker toevoegen"
weekday-short:
sunday: "Z"
monday: "M"
@@ -325,21 +329,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "Geen meldingen"
desktop/views/components/post-form.vue:
reply-placeholder: "Deze notitie beantwoorden..."
quote-placeholder: "Deze notitie citeren..."
submit: "Bericht"
reply: "Beantwoorden"
posted: "Geplaatst!"
replied: "Beantwoord!"
reposted: "Hergeplaatst!"
note-failed: "Noteren mislukt"
reply-failed: "Beantwoorden mislukt"
renote-failed: "Renote mislukt"
posting: "Bezig met plaatsen"
attach-media-from-local: "Media bijvoegen van je computer"
attach-media-from-drive: "Media bijvoegen uit je Drive"
create-poll: "Peiling creëren"
text-remain: "{} resterende tekens"
desktop/views/components/post-form-window.vue:
note: "Nieuwe notitie"
reply: "Beantwoorden"
@@ -538,11 +533,6 @@ mobile/views/components/note-detail.vue:
location: "Locatie"
mobile/views/components/notifications.vue:
empty: "Geen meldingen"
mobile/views/components/post-form.vue:
add-visible-user: "Gebruiker toevoegen"
submit: "Plaatsen"
reply: "Antwoord"
reply-placeholder: "Deze notitie beantwoorden..."
mobile/views/components/sub-note-content.vue:
private: "(dit bericht is privé)"
media-count: "{} media"
@@ -633,5 +623,7 @@ pages:
arg2: "Lijsten"
_pick:
arg1: "Lijsten"
_listLen:
arg1: "Lijsten"
types:
array: "Lijsten"

View File

@@ -39,6 +39,10 @@ common:
favorites: "Merket som favoritt"
permissions:
"write:votes": "Stem"
post-form:
submit: "Innlegg"
reply: "Svar"
error: "Feil"
weekday-short:
sunday: "S"
monday: "M"
@@ -261,13 +265,6 @@ desktop/views/components/note.vue:
detail: "Detaljer"
desktop/views/components/notes.vue:
retry: "Prøv på nytt"
desktop/views/components/post-form.vue:
submit: "Send"
reply: "Svar"
posting: "Publiserer"
recent-tags: "Nylig"
visibility: "Synlighet"
error: "Feil"
desktop/views/components/post-form-window.vue:
note: "Nytt innlegg"
reply: "Svar"
@@ -328,6 +325,10 @@ admin/views/index.vue:
admin/views/dashboard.vue:
notes: "Innlegg"
drive: "Disk"
admin/views/logs.vue:
levels:
info: "Informasjon"
error: "Feil"
admin/views/abuse.vue:
details: "Detaljer"
remove-report: "Slett"
@@ -366,6 +367,7 @@ admin/views/federation.vue:
status: "Status"
states:
all: "Alle"
save: "Lagre"
desktop/views/pages/welcome.vue:
announcements: "Kunngjøringer"
info: "Informasjon"
@@ -437,10 +439,6 @@ mobile/views/components/note-sub.vue:
admin: "admin"
bot: "bot"
cat: "katt"
mobile/views/components/post-form.vue:
submit: "Send"
reply: "Svar"
error: "Feil"
mobile/views/components/ui.header.vue:
adjective: "Mr."
mobile/views/components/ui.nav.vue:
@@ -505,5 +503,7 @@ pages:
arg2: "Lister"
_pick:
arg1: "Lister"
_listLen:
arg1: "Lister"
types:
array: "Lister"

View File

@@ -65,9 +65,29 @@ common:
favorites: "Moje ulubione"
permissions:
"read:drive": "Wyświetl dysk"
"read:messaging": "Zobacz konwersację"
"write:votes": "Zagłosuj"
empty-timeline-info:
explore: "Poznaj"
post-form:
hide-contents: "Ukryj zawartość"
reply-placeholder: "Odpowiedź na ten wpis…"
quote-placeholder: "Zacytuj ten wpis…"
quote-attached: "Z cytatem"
submit: "Wpis"
reply: "Odpowiedz"
renote: "Udostępnij"
posting: "Wysyłanie"
attach-media-from-local: "Załącz zawartość multimedialną z komputera"
attach-media-from-drive: "Załącz zawartość multimedialną z dysku"
create-poll: "Utwórz ankietę"
text-remain: "pozostałe znaki: {}"
recent-tags: "Ostatnie"
visibility: "Widoczność"
error: "Błąd"
enter-username: "Wprowadź nazwę użytkownika"
add-visible-user: "Dodaj użytkownika"
username-prompt: "Wprowadź nazwę użytkownika"
weekday-short:
sunday: "N"
monday: "Pn"
@@ -218,6 +238,9 @@ auth/views/index.vue:
please-go-back: "Wróć do aplikacji."
error: "Sesja nie istnieje."
sign-in: "Proszę zalogować się."
common/views/pages/explore.vue:
popular-users: "Popularni użytkownicy"
popular-tags: "Popularne tagi"
common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "Oczekiwanie na {}"
@@ -701,33 +724,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "Brak powiadomień"
desktop/views/components/post-form.vue:
add-visible-user: "+Dodaj użytkownika"
attach-location-information: "Załącz informacje o lokalizacji"
hide-contents: "Ukryj zawartość"
reply-placeholder: "Odpowiedz na ten wpis…"
quote-placeholder: "Zacytuj ten wpis…"
submit: "Wyślij"
reply: "Odpowiedz"
renote: "Udostępnienie"
posted: "Opublikowano!"
replied: "Odpowiedziano!"
reposted: "Udostępniono!"
note-failed: "Nie udało się wysłać"
reply-failed: "Nie udało się odpowiedzieć"
renote-failed: "Nie udało się udostępnić"
posting: "Wysyłanie"
attach-media-from-local: "Załącz zawartość multimedialną z komputera"
attach-media-from-drive: "Załącz zawartość multimedialną z dysku"
insert-a-kao: "v('ω')v"
create-poll: "Utwórz ankietę"
text-remain: "pozostałe znaki: {}"
recent-tags: "Ostatnie"
click-to-tagging: "Naciśnij aby oznaczyć"
visibility: "Widoczność"
geolocation-alert: "Twoje urządzenie nie obsługuje geolokalizacji."
error: "Bład"
enter-username: "Wprowadź nazwę użytkownika…"
annotations: "Treść ostrzeżenia (opcjonalnie)"
desktop/views/components/post-form-window.vue:
note: "Nowy wpis"
reply: "Odpowiedz"
@@ -862,6 +864,10 @@ admin/views/dashboard.vue:
notes: "Wpisy"
drive: "Dysk"
instances: "Instancja"
admin/views/logs.vue:
levels:
info: "Informacje"
error: "Błąd"
admin/views/abuse.vue:
details: "Szczegóły"
remove-report: "Usuń"
@@ -876,6 +882,7 @@ admin/views/instance.vue:
save: "Zapisz"
saved: "Zapisano"
email: "Adres e-mail"
test-email: "Test"
admin/views/charts.vue:
notes: "Wpisy"
users: "Użytkownicy"
@@ -950,6 +957,7 @@ admin/views/federation.vue:
chart-srcs:
requests: "Żądania"
blocked-hosts: "Zablokuj"
save: "Zapisz"
desktop/views/pages/welcome.vue:
about: "O Misskey"
timeline: "Oś czasu"
@@ -1072,17 +1080,6 @@ mobile/views/components/note-sub.vue:
cat: "kot"
mobile/views/components/notifications.vue:
empty: "Brak powiadomień"
mobile/views/components/post-form.vue:
add-visible-user: "Dodaj użytkownika"
submit: "Wyślij"
reply: "Odpowiedz"
renote: "Udostępnij"
quote-placeholder: "Zacytuj ten wpis… (nieobowiązkowe)"
reply-placeholder: "Odpowiedź na ten wpis…"
cw-placeholder: "Treść ostrzeżenia (opcjonalnie)"
geolocation-alert: "Twoje urządzenie nie obsługuje geolokalizacji."
error: "Błąd"
username-prompt: "Wprowadź nazwę użytkownika"
mobile/views/components/sub-note-content.vue:
private: "ten wpis jest prywatny"
deleted: "ten wpis został usunięty"
@@ -1225,5 +1222,7 @@ pages:
arg2: "Listy"
_pick:
arg1: "Listy"
_listLen:
arg1: "Listy"
types:
array: "Listy"

View File

@@ -45,6 +45,9 @@ common:
trash: "Lixo"
timeline: "Linha do tempo"
followers: "Seguidores"
post-form:
enter-username: "Digite o nome de usuário."
username-prompt: "Digite o nome de usuário."
weekday-short:
sunday: "Dom"
monday: "Seg"
@@ -89,6 +92,7 @@ common:
update-available-title: "Atualização disponível"
update-available: "Uma nova versão de Misskey está disponível ({newer}). A versão atual é {current}. Recarregue a página para atualizar."
my-token-regenerated: "Seu token foi recriado, portanto você foi deslogado."
enter-username: "Digite o nome de usuário."
reversi:
drawn: "Empatado"
my-turn: "Seu turno"

View File

@@ -26,6 +26,13 @@ common:
do-not-copy-paste: "Пожалуйста, не вводите и не вставляйте сюда код. Аккаунту может угрожать опасность."
load-more: "Загрузить больше"
enter-password: "Пожалуйста, введите ваш пароль"
2fa: "Двухфакторная аутентификация"
customize-home: "Настройка домашней страницы"
dark-mode: "Тёмная тема"
signin: "Войти"
signup: "Регистрация"
signout: "Выйти"
reload-to-apply-the-setting: "Вам необходимо перезагрузить страницу, чтобы применить настройки. Вы хотите перезагрузить сейчас?"
customization-tips:
title: "Советы по настройке"
gotit: "Понятно!"
@@ -51,7 +58,14 @@ common:
month-and-day: "{day}.{month}"
trash: "Мусорное ведро"
drive: "Drive"
pages: "Страницы"
messaging: "Чат"
timeline: "Лента"
followers: "Подписчики"
favorites: "Избранное"
post-form:
reply: "Ответить"
create-poll: "Создать опрос"
weekday-short:
sunday: "Вс"
monday: "Пн"

View File

@@ -95,6 +95,33 @@ common:
empty-timeline-info:
follow-users-to-make-your-timeline: "关注其他用户时,帖子将显示在时间线中。"
explore: "查找用户"
post-form:
attach-location-information: "添加位置信息"
hide-contents: "隐藏内容"
reply-placeholder: "回复此贴..."
quote-placeholder: "引用此帖…"
option-quote-placeholder: "引用此帖…(可选)"
quote-attached: "已引用"
quote-question: "是否将其作为引用附上?"
submit: "帖子"
reply: "回复"
renote: "转推"
posting: "发送中"
attach-media-from-local: "从PC中添加媒体文件"
attach-media-from-drive: "从网盘中添加媒体文件"
insert-a-kao: "v('ω')v"
create-poll: "创建一个投票"
text-remain: "还剩{}个字符"
recent-tags: "最近"
local-only-message: "这篇文章只会在本地发布"
click-to-tagging: "点击添加标签"
visibility: "可见性"
geolocation-alert: "您的设备不支持定位服务"
error: "错误"
enter-username: "输入用户名"
add-visible-user: "添加用户"
cw-placeholder: "评论帖子(可选)"
username-prompt: "输入用户名"
weekday-short:
sunday: "日"
monday: "一"
@@ -243,6 +270,9 @@ common:
disable-via-mobile: "不要将帖子标记为“来自手机”"
load-raw-images: "以原始质量显示附加图像"
load-remote-media: "显示来自远程服务器的媒体"
sync: "同步"
home-profile: "定制首页数据"
deck-profile: "定制Deck数据"
search: "搜索"
delete: "删除"
loading: "正在加载中"
@@ -253,7 +283,7 @@ common:
my-token-regenerated: "您的 Token 已被重置, 您将自动登出。"
hide-password: "隐藏密码"
show-password: "显示密码"
enter-username: "输入用户名"
enter-username: "输入用户名"
do-not-use-in-production: "这是一个开发者测试版. 请勿在生产环境中使用."
user-suspended: "该用户已被冻结。"
is-remote-user: "此用户信息可能不准确。"
@@ -550,6 +580,7 @@ common/views/components/poll-editor.vue:
day: "日"
common/views/components/reaction-picker.vue:
choose-reaction: "选择回应"
input-reaction-placeholder: "表情符号输入"
common/views/components/emoji-picker.vue:
custom-emoji: "自定义表情符号"
people: "人"
@@ -831,7 +862,7 @@ desktop/views/components/crop-window.vue:
cancel: "取消"
ok: "确定"
desktop/views/components/drive-window.vue:
used: "使用"
used: "使用"
desktop/views/components/drive.file.vue:
avatar: "头像"
banner: "背景"
@@ -921,34 +952,12 @@ desktop/views/components/notes.vue:
desktop/views/components/notifications.vue:
empty: "没有通知哦!"
desktop/views/components/post-form.vue:
add-visible-user: "+添加用户"
attach-location-information: "添加位置信息"
hide-contents: "隐藏内容"
reply-placeholder: "回复这个帖子"
quote-placeholder: "引用这个帖子…"
submit: "投稿"
reply: "回复"
renote: "转推"
posted: "已发送投稿!"
replied: "已回复!"
reposted: "已转推!"
note-failed: "发帖失败"
reply-failed: "回复失败"
renote-failed: "转推失败"
posting: "发送中"
attach-media-from-local: "从设备中添加媒体文件"
attach-media-from-drive: "从网盘中添加媒体文件"
insert-a-kao: "v('ω')v"
create-poll: "创建一个投票"
text-remain: "还剩{}字"
recent-tags: "最近"
local-only-message: "这篇文章只会在本地发表"
click-to-tagging: "点击添加标签"
visibility: "可见性"
geolocation-alert: "您的设备不提供位置服务"
error: "错误"
enter-username: "请填写一个用户名"
annotations: "注释帖子(可选)"
desktop/views/components/post-form-window.vue:
note: "新建帖子"
reply: "回复"
@@ -1010,7 +1019,7 @@ desktop/views/components/settings.apps.vue:
no-apps: "没有已连接的应用程序"
common/views/components/drive-settings.vue:
max: "容量"
in-use: "正在使用"
in-use: "使用"
stats: "统计"
common/views/components/mute-and-block.vue:
mute-and-block: "屏蔽/拉黑"
@@ -1097,7 +1106,10 @@ admin/views/index.vue:
abuse: "举报垃圾信息"
queue: "作业队列"
logs: "登录"
db: "数据库"
back-to-misskey: "返回 Misskey"
admin/views/db.vue:
tables: "表格"
admin/views/dashboard.vue:
dashboard: "Dashboard"
accounts: "账户"
@@ -1109,6 +1121,32 @@ admin/views/dashboard.vue:
admin/views/queue.vue:
title: "队列"
remove-all-jobs: "清除所有作业"
jobs: "任务"
queue: "队列"
domains:
deliver: "交付"
inbox: "收件箱"
db: "数据库"
objectStorage: "对象存储"
state: "状态"
states:
active: "处理中"
delayed: "已预订"
waiting: "队列等待中"
result-is-truncated: "结果已省略"
other-queues: "其他队列"
admin/views/logs.vue:
logs: "登录"
domain: "域"
level: "级别"
levels:
all: "所有"
info: "信息"
success: "成功"
warning: "警告"
error: "错误"
debug: "调试"
delete-all: "全部删除"
admin/views/abuse.vue:
title: "举报垃圾信息"
target: "目标"
@@ -1206,6 +1244,7 @@ admin/views/instance.vue:
smtp-auth: "SMTP身份验证"
smtp-user: "SMTP 用户名"
smtp-pass: "SMTP 密码"
test-email: "测试"
serviceworker-config: "ServiceWorker"
enable-serviceworker: "启用ServiceWorker"
serviceworker-info: "您需要启用推送通知"
@@ -1260,6 +1299,9 @@ admin/views/drive.vue:
unmark-as-sensitive: "取消标记为“敏感”"
marked-as-sensitive: "标记为“敏感”"
unmarked-as-sensitive: "取消标记为“敏感”"
clean-remote-files: "删除远程文件缓存"
clean-remote-files-are-you-sure: "确定要删除所有远程文件缓存吗?"
clean-up: "清除缓存"
admin/views/users.vue:
operation: "操作"
username-or-userid: "用户名或用户ID"
@@ -1406,6 +1448,7 @@ admin/views/federation.vue:
day: "每天"
blocked-hosts: "拉黑"
blocked-hosts-info: "描述您要阻止的主机,以换行符分隔。"
save: "保存"
desktop/views/pages/welcome.vue:
about: "更多信息..."
timeline: "时间线"
@@ -1482,7 +1525,7 @@ desktop/views/widgets/users.vue:
refresh: "更多"
no-one: "不是!"
mobile/views/components/drive.vue:
used: "使用"
used: "使用"
folder-count: "文件夹"
count-separator: ""
file-count: "文件"
@@ -1537,17 +1580,6 @@ mobile/views/components/note-sub.vue:
cat: "cat"
mobile/views/components/notifications.vue:
empty: "没有通知哦!"
mobile/views/components/post-form.vue:
add-visible-user: "添加用户"
submit: "帖子"
reply: "回复"
renote: "转推"
quote-placeholder: "引用这个帖子t... (可选)"
reply-placeholder: "回复这个帖子"
cw-placeholder: "评论帖子(可选)"
geolocation-alert: "您的设备不提供位置服务"
error: "错误"
username-prompt: "请输入用户名"
mobile/views/components/sub-note-content.vue:
private: "私密帖子"
deleted: "帖子已删除"
@@ -1832,8 +1864,8 @@ pages:
_divide:
arg1: "A"
arg2: "B"
remind: "÷ 取模"
_remind:
mod: "÷ 取模"
_mod:
arg1: "A"
arg2: "B"
eq: "A和B相等"
@@ -1916,6 +1948,9 @@ pages:
_pick:
arg1: "列表"
arg2: "位置"
listLen: "获取列表长度"
_listLen:
arg1: "列表"
number: "数值"
stringToNumber: "文本到数字"
_stringToNumber:

View File

@@ -0,0 +1,485 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class Init1000000000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`CREATE TYPE "log_level_enum" AS ENUM('error', 'warning', 'info', 'success', 'debug')`);
await queryRunner.query(`CREATE TABLE "log" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "domain" character varying(64) array NOT NULL DEFAULT '{}'::varchar[], "level" "log_level_enum" NOT NULL, "worker" character varying(8) NOT NULL, "machine" character varying(128) NOT NULL, "message" character varying(1024) NOT NULL, "data" jsonb NOT NULL DEFAULT '{}', CONSTRAINT "PK_350604cbdf991d5930d9e618fbd" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_8e4eb51a35d81b64dda28eed0a" ON "log" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_8cb40cfc8f3c28261e6f887b03" ON "log" ("domain") `);
await queryRunner.query(`CREATE INDEX "IDX_584b536b49e53ac81beb39a177" ON "log" ("level") `);
await queryRunner.query(`CREATE TABLE "drive_folder" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(128) NOT NULL, "userId" character varying(32), "parentId" character varying(32), CONSTRAINT "PK_7a0c089191f5ebdc214e0af808a" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_02878d441ceae15ce060b73daf" ON "drive_folder" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_f4fc06e49c0171c85f1c48060d" ON "drive_folder" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_00ceffb0cdc238b3233294f08f" ON "drive_folder" ("parentId") `);
await queryRunner.query(`CREATE TABLE "drive_file" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32), "userHost" character varying(128), "md5" character varying(32) NOT NULL, "name" character varying(256) NOT NULL, "type" character varying(128) NOT NULL, "size" integer NOT NULL, "comment" character varying(512), "properties" jsonb NOT NULL DEFAULT '{}', "storedInternal" boolean NOT NULL, "url" character varying(512) NOT NULL, "thumbnailUrl" character varying(512), "webpublicUrl" character varying(512), "accessKey" character varying(256), "thumbnailAccessKey" character varying(256), "webpublicAccessKey" character varying(256), "uri" character varying(512), "src" character varying(512), "folderId" character varying(32), "isSensitive" boolean NOT NULL DEFAULT false, "isLink" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_43ddaaaf18c9e68029b7cbb032e" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_c8dfad3b72196dd1d6b5db168a" ON "drive_file" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_860fa6f6c7df5bb887249fba22" ON "drive_file" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_92779627994ac79277f070c91e" ON "drive_file" ("userHost") `);
await queryRunner.query(`CREATE INDEX "IDX_37bb9a1b4585f8a3beb24c62d6" ON "drive_file" ("md5") `);
await queryRunner.query(`CREATE INDEX "IDX_a40b8df8c989d7db937ea27cf6" ON "drive_file" ("type") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_d85a184c2540d2deba33daf642" ON "drive_file" ("accessKey") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_e74022ce9a074b3866f70e0d27" ON "drive_file" ("thumbnailAccessKey") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c55b2b7c284d9fef98026fc88e" ON "drive_file" ("webpublicAccessKey") `);
await queryRunner.query(`CREATE INDEX "IDX_e5848eac4940934e23dbc17581" ON "drive_file" ("uri") `);
await queryRunner.query(`CREATE INDEX "IDX_bb90d1956dafc4068c28aa7560" ON "drive_file" ("folderId") `);
await queryRunner.query(`CREATE TABLE "user" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE, "lastFetchedAt" TIMESTAMP WITH TIME ZONE, "username" character varying(128) NOT NULL, "usernameLower" character varying(128) NOT NULL, "name" character varying(128), "followersCount" integer NOT NULL DEFAULT 0, "followingCount" integer NOT NULL DEFAULT 0, "notesCount" integer NOT NULL DEFAULT 0, "avatarId" character varying(32), "bannerId" character varying(32), "tags" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "avatarUrl" character varying(512), "bannerUrl" character varying(512), "avatarColor" character varying(32), "bannerColor" character varying(32), "isSuspended" boolean NOT NULL DEFAULT false, "isSilenced" boolean NOT NULL DEFAULT false, "isLocked" boolean NOT NULL DEFAULT false, "isBot" boolean NOT NULL DEFAULT false, "isCat" boolean NOT NULL DEFAULT false, "isAdmin" boolean NOT NULL DEFAULT false, "isModerator" boolean NOT NULL DEFAULT false, "isVerified" boolean NOT NULL DEFAULT false, "emojis" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "host" character varying(128), "inbox" character varying(512), "sharedInbox" character varying(512), "featured" character varying(512), "uri" character varying(512), "token" character(16), CONSTRAINT "UQ_a854e557b1b14814750c7c7b0c9" UNIQUE ("token"), CONSTRAINT "REL_58f5c71eaab331645112cf8cfa" UNIQUE ("avatarId"), CONSTRAINT "REL_afc64b53f8db3707ceb34eb28e" UNIQUE ("bannerId"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_e11e649824a45d8ed01d597fd9" ON "user" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_80ca6e6ef65fb9ef34ea8c90f4" ON "user" ("updatedAt") `);
await queryRunner.query(`CREATE INDEX "IDX_a27b942a0d6dcff90e3ee9b5e8" ON "user" ("usernameLower") `);
await queryRunner.query(`CREATE INDEX "IDX_fa99d777623947a5b05f394cae" ON "user" ("tags") `);
await queryRunner.query(`CREATE INDEX "IDX_3252a5df8d5bbd16b281f7799e" ON "user" ("host") `);
await queryRunner.query(`CREATE INDEX "IDX_be623adaa4c566baf5d29ce0c8" ON "user" ("uri") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a854e557b1b14814750c7c7b0c" ON "user" ("token") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5deb01ae162d1d70b80d064c27" ON "user" ("usernameLower", "host") `);
await queryRunner.query(`CREATE TABLE "app" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32), "secret" character varying(64) NOT NULL, "name" character varying(128) NOT NULL, "description" character varying(512) NOT NULL, "permission" character varying(64) array NOT NULL, "callbackUrl" character varying(512), CONSTRAINT "PK_9478629fc093d229df09e560aea" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_048a757923ed8b157e9895da53" ON "app" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_3f5b0899ef90527a3462d7c2cb" ON "app" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_f49922d511d666848f250663c4" ON "app" ("secret") `);
await queryRunner.query(`CREATE TABLE "access_token" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "token" character varying(128) NOT NULL, "hash" character varying(128) NOT NULL, "userId" character varying(32) NOT NULL, "appId" character varying(32) NOT NULL, CONSTRAINT "PK_f20f028607b2603deabd8182d12" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_70ba8f6af34bc924fc9e12adb8" ON "access_token" ("token") `);
await queryRunner.query(`CREATE INDEX "IDX_64c327441248bae40f7d92f34f" ON "access_token" ("hash") `);
await queryRunner.query(`CREATE INDEX "IDX_9949557d0e1b2c19e5344c171e" ON "access_token" ("userId") `);
await queryRunner.query(`CREATE TYPE "note_visibility_enum" AS ENUM('public', 'home', 'followers', 'specified')`);
await queryRunner.query(`CREATE TABLE "note" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "replyId" character varying(32), "renoteId" character varying(32), "text" text, "name" character varying(256), "cw" character varying(512), "appId" character varying(32), "userId" character varying(32) NOT NULL, "viaMobile" boolean NOT NULL DEFAULT false, "localOnly" boolean NOT NULL DEFAULT false, "renoteCount" smallint NOT NULL DEFAULT 0, "repliesCount" smallint NOT NULL DEFAULT 0, "reactions" jsonb NOT NULL DEFAULT '{}', "visibility" "note_visibility_enum" NOT NULL, "uri" character varying(512), "score" integer NOT NULL DEFAULT 0, "fileIds" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], "attachedFileTypes" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "visibleUserIds" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], "mentions" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], "mentionedRemoteUsers" text NOT NULL DEFAULT '[]', "emojis" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "tags" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "hasPoll" boolean NOT NULL DEFAULT false, "geo" jsonb DEFAULT null, "userHost" character varying(128), "replyUserId" character varying(32), "replyUserHost" character varying(128), "renoteUserId" character varying(32), "renoteUserHost" character varying(128), CONSTRAINT "PK_96d0c172a4fba276b1bbed43058" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_e7c0567f5261063592f022e9b5" ON "note" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_17cb3553c700a4985dff5a30ff" ON "note" ("replyId") `);
await queryRunner.query(`CREATE INDEX "IDX_52ccc804d7c69037d558bac4c9" ON "note" ("renoteId") `);
await queryRunner.query(`CREATE INDEX "IDX_5b87d9d19127bd5d92026017a7" ON "note" ("userId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_153536c67d05e9adb24e99fc2b" ON "note" ("uri") `);
await queryRunner.query(`CREATE INDEX "IDX_51c063b6a133a9cb87145450f5" ON "note" ("fileIds") `);
await queryRunner.query(`CREATE INDEX "IDX_25dfc71b0369b003a4cd434d0b" ON "note" ("attachedFileTypes") `);
await queryRunner.query(`CREATE INDEX "IDX_796a8c03959361f97dc2be1d5c" ON "note" ("visibleUserIds") `);
await queryRunner.query(`CREATE INDEX "IDX_54ebcb6d27222913b908d56fd8" ON "note" ("mentions") `);
await queryRunner.query(`CREATE INDEX "IDX_88937d94d7443d9a99a76fa5c0" ON "note" ("tags") `);
await queryRunner.query(`CREATE INDEX "IDX_7125a826ab192eb27e11d358a5" ON "note" ("userHost") `);
await queryRunner.query(`CREATE TABLE "poll_vote" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "choice" integer NOT NULL, CONSTRAINT "PK_fd002d371201c472490ba89c6a0" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_0fb627e1c2f753262a74f0562d" ON "poll_vote" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_66d2bd2ee31d14bcc23069a89f" ON "poll_vote" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_aecfbd5ef60374918e63ee95fa" ON "poll_vote" ("noteId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_50bd7164c5b78f1f4a42c4d21f" ON "poll_vote" ("userId", "noteId", "choice") `);
await queryRunner.query(`CREATE TABLE "note_reaction" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "reaction" character varying(128) NOT NULL, CONSTRAINT "PK_767ec729b108799b587a3fcc9cf" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_01f4581f114e0ebd2bbb876f0b" ON "note_reaction" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_13761f64257f40c5636d0ff95e" ON "note_reaction" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_45145e4953780f3cd5656f0ea6" ON "note_reaction" ("noteId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_ad0c221b25672daf2df320a817" ON "note_reaction" ("userId", "noteId") `);
await queryRunner.query(`CREATE TABLE "note_watching" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "noteUserId" character varying(32) NOT NULL, CONSTRAINT "PK_49286fdb23725945a74aa27d757" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_318cdf42a9cfc11f479bd802bb" ON "note_watching" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_b0134ec406e8d09a540f818288" ON "note_watching" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_03e7028ab8388a3f5e3ce2a861" ON "note_watching" ("noteId") `);
await queryRunner.query(`CREATE INDEX "IDX_44499765eec6b5489d72c4253b" ON "note_watching" ("noteUserId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a42c93c69989ce1d09959df4cf" ON "note_watching" ("userId", "noteId") `);
await queryRunner.query(`CREATE TABLE "note_unread" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "noteUserId" character varying(32) NOT NULL, "isSpecified" boolean NOT NULL, CONSTRAINT "PK_1904eda61a784f57e6e51fa9c1f" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_56b0166d34ddae49d8ef7610bb" ON "note_unread" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_e637cba4dc4410218c4251260e" ON "note_unread" ("noteId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_d908433a4953cc13216cd9c274" ON "note_unread" ("userId", "noteId") `);
await queryRunner.query(`CREATE TABLE "notification" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "notifieeId" character varying(32) NOT NULL, "notifierId" character varying(32) NOT NULL, "type" character varying(32) NOT NULL, "isRead" boolean NOT NULL DEFAULT false, "noteId" character varying(32), "reaction" character varying(128), "choice" integer, CONSTRAINT "PK_705b6c7cdf9b2c2ff7ac7872cb7" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_b11a5e627c41d4dc3170f1d370" ON "notification" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_3c601b70a1066d2c8b517094cb" ON "notification" ("notifieeId") `);
await queryRunner.query(`CREATE TABLE "meta" ("id" character varying(32) NOT NULL, "name" character varying(128), "description" character varying(1024), "maintainerName" character varying(128), "maintainerEmail" character varying(128), "announcements" jsonb NOT NULL DEFAULT '[]', "disableRegistration" boolean NOT NULL DEFAULT false, "disableLocalTimeline" boolean NOT NULL DEFAULT false, "disableGlobalTimeline" boolean NOT NULL DEFAULT false, "enableEmojiReaction" boolean NOT NULL DEFAULT true, "useStarForReactionFallback" boolean NOT NULL DEFAULT false, "langs" character varying(64) array NOT NULL DEFAULT '{}'::varchar[], "hiddenTags" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "blockedHosts" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "mascotImageUrl" character varying(512) DEFAULT '/assets/ai.png', "bannerUrl" character varying(512), "errorImageUrl" character varying(512) DEFAULT 'https://xn--931a.moe/aiart/yubitun.png', "iconUrl" character varying(512), "cacheRemoteFiles" boolean NOT NULL DEFAULT true, "proxyAccount" character varying(128), "enableRecaptcha" boolean NOT NULL DEFAULT false, "recaptchaSiteKey" character varying(64), "recaptchaSecretKey" character varying(64), "localDriveCapacityMb" integer NOT NULL DEFAULT 1024, "remoteDriveCapacityMb" integer NOT NULL DEFAULT 32, "maxNoteTextLength" integer NOT NULL DEFAULT 500, "summalyProxy" character varying(128), "enableEmail" boolean NOT NULL DEFAULT false, "email" character varying(128), "smtpSecure" boolean NOT NULL DEFAULT false, "smtpHost" character varying(128), "smtpPort" integer, "smtpUser" character varying(128), "smtpPass" character varying(128), "enableServiceWorker" boolean NOT NULL DEFAULT false, "swPublicKey" character varying(128), "swPrivateKey" character varying(128), "enableTwitterIntegration" boolean NOT NULL DEFAULT false, "twitterConsumerKey" character varying(128), "twitterConsumerSecret" character varying(128), "enableGithubIntegration" boolean NOT NULL DEFAULT false, "githubClientId" character varying(128), "githubClientSecret" character varying(128), "enableDiscordIntegration" boolean NOT NULL DEFAULT false, "discordClientId" character varying(128), "discordClientSecret" character varying(128), CONSTRAINT "PK_c4c17a6c2bd7651338b60fc590b" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TABLE "following" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "followeeId" character varying(32) NOT NULL, "followerId" character varying(32) NOT NULL, "followerHost" character varying(128), "followerInbox" character varying(512), "followerSharedInbox" character varying(512), "followeeHost" character varying(128), "followeeInbox" character varying(512), "followeeSharedInbox" character varying(512), CONSTRAINT "PK_c76c6e044bdf76ecf8bfb82a645" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_582f8fab771a9040a12961f3e7" ON "following" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_24e0042143a18157b234df186c" ON "following" ("followeeId") `);
await queryRunner.query(`CREATE INDEX "IDX_6516c5a6f3c015b4eed39978be" ON "following" ("followerId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_307be5f1d1252e0388662acb96" ON "following" ("followerId", "followeeId") `);
await queryRunner.query(`CREATE TABLE "instance" ("id" character varying(32) NOT NULL, "caughtAt" TIMESTAMP WITH TIME ZONE NOT NULL, "host" character varying(128) NOT NULL, "system" character varying(64), "usersCount" integer NOT NULL DEFAULT 0, "notesCount" integer NOT NULL DEFAULT 0, "followingCount" integer NOT NULL DEFAULT 0, "followersCount" integer NOT NULL DEFAULT 0, "driveUsage" integer NOT NULL DEFAULT 0, "driveFiles" integer NOT NULL DEFAULT 0, "latestRequestSentAt" TIMESTAMP WITH TIME ZONE, "latestStatus" integer, "latestRequestReceivedAt" TIMESTAMP WITH TIME ZONE, "lastCommunicatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "isNotResponding" boolean NOT NULL DEFAULT false, "isMarkedAsClosed" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_eaf60e4a0c399c9935413e06474" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_2cd3b2a6b4cf0b910b260afe08" ON "instance" ("caughtAt") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_8d5afc98982185799b160e10eb" ON "instance" ("host") `);
await queryRunner.query(`CREATE TABLE "muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_2e92d06c8b5c602eeb27ca9ba48" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_f86d57fbca33c7a4e6897490cc" ON "muting" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_ec96b4fed9dae517e0dbbe0675" ON "muting" ("muteeId") `);
await queryRunner.query(`CREATE INDEX "IDX_93060675b4a79a577f31d260c6" ON "muting" ("muterId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_1eb9d9824a630321a29fd3b290" ON "muting" ("muterId", "muteeId") `);
await queryRunner.query(`CREATE TABLE "sw_subscription" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "endpoint" character varying(512) NOT NULL, "auth" character varying(256) NOT NULL, "publickey" character varying(128) NOT NULL, CONSTRAINT "PK_e8f763631530051b95eb6279b91" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_97754ca6f2baff9b4abb7f853d" ON "sw_subscription" ("userId") `);
await queryRunner.query(`CREATE TABLE "blocking" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "blockeeId" character varying(32) NOT NULL, "blockerId" character varying(32) NOT NULL, CONSTRAINT "PK_e5d9a541cc1965ee7e048ea09dd" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_b9a354f7941c1e779f3b33aea6" ON "blocking" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_2cd4a2743a99671308f5417759" ON "blocking" ("blockeeId") `);
await queryRunner.query(`CREATE INDEX "IDX_0627125f1a8a42c9a1929edb55" ON "blocking" ("blockerId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_98a1bc5cb30dfd159de056549f" ON "blocking" ("blockerId", "blockeeId") `);
await queryRunner.query(`CREATE TABLE "user_list" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, CONSTRAINT "PK_87bab75775fd9b1ff822b656402" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_b7fcefbdd1c18dce86687531f9" ON "user_list" ("userId") `);
await queryRunner.query(`CREATE TABLE "user_list_joining" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "userListId" character varying(32) NOT NULL, CONSTRAINT "PK_11abb3768da1c5f8de101c9df45" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_d844bfc6f3f523a05189076efa" ON "user_list_joining" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_605472305f26818cc93d1baaa7" ON "user_list_joining" ("userListId") `);
await queryRunner.query(`CREATE TABLE "hashtag" ("id" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, "mentionedUserIds" character varying(32) array NOT NULL, "mentionedUsersCount" integer NOT NULL DEFAULT 0, "mentionedLocalUserIds" character varying(32) array NOT NULL, "mentionedLocalUsersCount" integer NOT NULL DEFAULT 0, "mentionedRemoteUserIds" character varying(32) array NOT NULL, "mentionedRemoteUsersCount" integer NOT NULL DEFAULT 0, "attachedUserIds" character varying(32) array NOT NULL, "attachedUsersCount" integer NOT NULL DEFAULT 0, "attachedLocalUserIds" character varying(32) array NOT NULL, "attachedLocalUsersCount" integer NOT NULL DEFAULT 0, "attachedRemoteUserIds" character varying(32) array NOT NULL, "attachedRemoteUsersCount" integer NOT NULL DEFAULT 0, CONSTRAINT "PK_cb36eb8af8412bfa978f1165d78" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_347fec870eafea7b26c8a73bac" ON "hashtag" ("name") `);
await queryRunner.query(`CREATE INDEX "IDX_2710a55f826ee236ea1a62698f" ON "hashtag" ("mentionedUsersCount") `);
await queryRunner.query(`CREATE INDEX "IDX_0e206cec573f1edff4a3062923" ON "hashtag" ("mentionedLocalUsersCount") `);
await queryRunner.query(`CREATE INDEX "IDX_4c02d38a976c3ae132228c6fce" ON "hashtag" ("mentionedRemoteUsersCount") `);
await queryRunner.query(`CREATE INDEX "IDX_d57f9030cd3af7f63ffb1c267c" ON "hashtag" ("attachedUsersCount") `);
await queryRunner.query(`CREATE INDEX "IDX_0c44bf4f680964145f2a68a341" ON "hashtag" ("attachedLocalUsersCount") `);
await queryRunner.query(`CREATE INDEX "IDX_0b03cbcd7e6a7ce068efa8ecc2" ON "hashtag" ("attachedRemoteUsersCount") `);
await queryRunner.query(`CREATE TABLE "note_favorite" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, CONSTRAINT "PK_af0da35a60b9fa4463a62082b36" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_47f4b1892f5d6ba8efb3057d81" ON "note_favorite" ("userId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0f4fb9ad355f3effff221ef245" ON "note_favorite" ("userId", "noteId") `);
await queryRunner.query(`CREATE TABLE "abuse_user_report" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "reporterId" character varying(32) NOT NULL, "comment" character varying(512) NOT NULL, CONSTRAINT "PK_87873f5f5cc5c321a1306b2d18c" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_db2098070b2b5a523c58181f74" ON "abuse_user_report" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_d049123c413e68ca52abe73420" ON "abuse_user_report" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_04cc96756f89d0b7f9473e8cdf" ON "abuse_user_report" ("reporterId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5cd442c3b2e74fdd99dae20243" ON "abuse_user_report" ("userId", "reporterId") `);
await queryRunner.query(`CREATE TABLE "registration_ticket" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "code" character varying(64) NOT NULL, CONSTRAINT "PK_f11696b6fafcf3662d4292734f8" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0ff69e8dfa9fe31bb4a4660f59" ON "registration_ticket" ("code") `);
await queryRunner.query(`CREATE TABLE "messaging_message" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "recipientId" character varying(32) NOT NULL, "text" character varying(4096), "isRead" boolean NOT NULL DEFAULT false, "fileId" character varying(32), CONSTRAINT "PK_db398fd79dc95d0eb8c30456eaa" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_e21cd3646e52ef9c94aaf17c2e" ON "messaging_message" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_5377c307783fce2b6d352e1203" ON "messaging_message" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_cac14a4e3944454a5ce7daa514" ON "messaging_message" ("recipientId") `);
await queryRunner.query(`CREATE TABLE "signin" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "ip" character varying(128) NOT NULL, "headers" jsonb NOT NULL, "success" boolean NOT NULL, CONSTRAINT "PK_9e96ddc025712616fc492b3b588" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_2c308dbdc50d94dc625670055f" ON "signin" ("userId") `);
await queryRunner.query(`CREATE TABLE "auth_session" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "token" character varying(128) NOT NULL, "userId" character varying(32), "appId" character varying(32) NOT NULL, CONSTRAINT "PK_19354ed146424a728c1112a8cbf" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_62cb09e1129f6ec024ef66e183" ON "auth_session" ("token") `);
await queryRunner.query(`CREATE TABLE "follow_request" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "followeeId" character varying(32) NOT NULL, "followerId" character varying(32) NOT NULL, "requestId" character varying(128), "followerHost" character varying(128), "followerInbox" character varying(512), "followerSharedInbox" character varying(512), "followeeHost" character varying(128), "followeeInbox" character varying(512), "followeeSharedInbox" character varying(512), CONSTRAINT "PK_53a9aa3725f7a3deb150b39dbfc" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_12c01c0d1a79f77d9f6c15fadd" ON "follow_request" ("followeeId") `);
await queryRunner.query(`CREATE INDEX "IDX_a7fd92dd6dc519e6fb435dd108" ON "follow_request" ("followerId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_d54a512b822fac7ed52800f6b4" ON "follow_request" ("followerId", "followeeId") `);
await queryRunner.query(`CREATE TABLE "emoji" ("id" character varying(32) NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE, "name" character varying(128) NOT NULL, "host" character varying(128), "url" character varying(512) NOT NULL, "uri" character varying(512), "type" character varying(64), "aliases" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], CONSTRAINT "PK_df74ce05e24999ee01ea0bc50a3" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_b37dafc86e9af007e3295c2781" ON "emoji" ("name") `);
await queryRunner.query(`CREATE INDEX "IDX_5900e907bb46516ddf2871327c" ON "emoji" ("host") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_4f4d35e1256c84ae3d1f0eab10" ON "emoji" ("name", "host") `);
await queryRunner.query(`CREATE TABLE "reversi_game" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "startedAt" TIMESTAMP WITH TIME ZONE, "user1Id" character varying(32) NOT NULL, "user2Id" character varying(32) NOT NULL, "user1Accepted" boolean NOT NULL DEFAULT false, "user2Accepted" boolean NOT NULL DEFAULT false, "black" integer, "isStarted" boolean NOT NULL DEFAULT false, "isEnded" boolean NOT NULL DEFAULT false, "winnerId" character varying(32), "surrendered" character varying(32), "logs" jsonb NOT NULL DEFAULT '[]', "map" character varying(64) array NOT NULL, "bw" character varying(32) NOT NULL, "isLlotheo" boolean NOT NULL DEFAULT false, "canPutEverywhere" boolean NOT NULL DEFAULT false, "loopedBoard" boolean NOT NULL DEFAULT false, "form1" jsonb DEFAULT null, "form2" jsonb DEFAULT null, "crc32" character varying(32), CONSTRAINT "PK_76b30eeba71b1193ad7c5311c3f" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_b46ec40746efceac604142be1c" ON "reversi_game" ("createdAt") `);
await queryRunner.query(`CREATE TABLE "reversi_matching" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "parentId" character varying(32) NOT NULL, "childId" character varying(32) NOT NULL, CONSTRAINT "PK_880bd0afbab232f21c8b9d146cf" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_b604d92d6c7aec38627f6eaf16" ON "reversi_matching" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_3b25402709dd9882048c2bbade" ON "reversi_matching" ("parentId") `);
await queryRunner.query(`CREATE INDEX "IDX_e247b23a3c9b45f89ec1299d06" ON "reversi_matching" ("childId") `);
await queryRunner.query(`CREATE TABLE "user_note_pining" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, CONSTRAINT "PK_a6a2dad4ae000abce2ea9d9b103" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_bfbc6f79ba4007b4ce5097f08d" ON "user_note_pining" ("userId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_410cd649884b501c02d6e72738" ON "user_note_pining" ("userId", "noteId") `);
await queryRunner.query(`CREATE TYPE "poll_notevisibility_enum" AS ENUM('public', 'home', 'followers', 'specified')`);
await queryRunner.query(`CREATE TABLE "poll" ("noteId" character varying(32) NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE, "multiple" boolean NOT NULL, "choices" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "votes" integer array NOT NULL, "noteVisibility" "poll_notevisibility_enum" NOT NULL, "userId" character varying(32) NOT NULL, "userHost" character varying(128), CONSTRAINT "REL_da851e06d0dfe2ef397d8b1bf1" UNIQUE ("noteId"), CONSTRAINT "PK_da851e06d0dfe2ef397d8b1bf1b" PRIMARY KEY ("noteId"))`);
await queryRunner.query(`CREATE INDEX "IDX_0610ebcfcfb4a18441a9bcdab2" ON "poll" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_7fa20a12319c7f6dc3aed98c0a" ON "poll" ("userHost") `);
await queryRunner.query(`CREATE TABLE "user_keypair" ("userId" character varying(32) NOT NULL, "publicKey" character varying(4096) NOT NULL, "privateKey" character varying(4096) NOT NULL, CONSTRAINT "REL_f4853eb41ab722fe05f81cedeb" UNIQUE ("userId"), CONSTRAINT "PK_f4853eb41ab722fe05f81cedeb6" PRIMARY KEY ("userId"))`);
await queryRunner.query(`CREATE TABLE "user_publickey" ("userId" character varying(32) NOT NULL, "keyId" character varying(256) NOT NULL, "keyPem" character varying(4096) NOT NULL, CONSTRAINT "REL_10c146e4b39b443ede016f6736" UNIQUE ("userId"), CONSTRAINT "PK_10c146e4b39b443ede016f6736d" PRIMARY KEY ("userId"))`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_171e64971c780ebd23fae140bb" ON "user_publickey" ("keyId") `);
await queryRunner.query(`CREATE TABLE "user_profile" ("userId" character varying(32) NOT NULL, "location" character varying(128), "birthday" character(10), "description" character varying(1024), "fields" jsonb NOT NULL DEFAULT '[]', "url" character varying(512), "email" character varying(128), "emailVerifyCode" character varying(128), "emailVerified" boolean NOT NULL DEFAULT false, "twoFactorTempSecret" character varying(128), "twoFactorSecret" character varying(128), "twoFactorEnabled" boolean NOT NULL DEFAULT false, "password" character varying(128), "clientData" jsonb NOT NULL DEFAULT '{}', "autoWatch" boolean NOT NULL DEFAULT false, "autoAcceptFollowed" boolean NOT NULL DEFAULT false, "alwaysMarkNsfw" boolean NOT NULL DEFAULT false, "carefulBot" boolean NOT NULL DEFAULT false, "twitter" boolean NOT NULL DEFAULT false, "twitterAccessToken" character varying(64) DEFAULT null, "twitterAccessTokenSecret" character varying(64) DEFAULT null, "twitterUserId" character varying(64) DEFAULT null, "twitterScreenName" character varying(64) DEFAULT null, "github" boolean NOT NULL DEFAULT false, "githubAccessToken" character varying(64) DEFAULT null, "githubId" integer DEFAULT null, "githubLogin" character varying(64) DEFAULT null, "discord" boolean NOT NULL DEFAULT false, "discordAccessToken" character varying(64) DEFAULT null, "discordRefreshToken" character varying(64) DEFAULT null, "discordExpiresDate" integer DEFAULT null, "discordId" character varying(64) DEFAULT null, "discordUsername" character varying(64) DEFAULT null, "discordDiscriminator" character varying(64) DEFAULT null, "userHost" character varying(128), CONSTRAINT "REL_51cb79b5555effaf7d69ba1cff" UNIQUE ("userId"), CONSTRAINT "PK_51cb79b5555effaf7d69ba1cff9" PRIMARY KEY ("userId"))`);
await queryRunner.query(`CREATE INDEX "IDX_dce530b98e454793dac5ec2f5a" ON "user_profile" ("userHost") `);
await queryRunner.query(`CREATE TYPE "__chart__active_users_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__active_users" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__active_users_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_count" bigint NOT NULL, "___remote_count" bigint NOT NULL, CONSTRAINT "PK_317237a9f733b970604a11e314f" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__drive_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__drive" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__drive_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_totalCount" bigint NOT NULL, "___local_totalSize" bigint NOT NULL, "___local_incCount" bigint NOT NULL, "___local_incSize" bigint NOT NULL, "___local_decCount" bigint NOT NULL, "___local_decSize" bigint NOT NULL, "___remote_totalCount" bigint NOT NULL, "___remote_totalSize" bigint NOT NULL, "___remote_incCount" bigint NOT NULL, "___remote_incSize" bigint NOT NULL, "___remote_decCount" bigint NOT NULL, "___remote_decSize" bigint NOT NULL, CONSTRAINT "PK_f96bc548a765cd4b3b354221ce7" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__federation_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__federation" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__federation_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___instance_total" bigint NOT NULL, "___instance_inc" bigint NOT NULL, "___instance_dec" bigint NOT NULL, CONSTRAINT "PK_b39dcd31a0fe1a7757e348e85fd" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__hashtag_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__hashtag" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__hashtag_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_count" bigint NOT NULL, "___remote_count" bigint NOT NULL, CONSTRAINT "PK_c32f1ea2b44a5d2f7881e37f8f9" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__instance_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__instance" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__instance_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___requests_failed" bigint NOT NULL, "___requests_succeeded" bigint NOT NULL, "___requests_received" bigint NOT NULL, "___notes_total" bigint NOT NULL, "___notes_inc" bigint NOT NULL, "___notes_dec" bigint NOT NULL, "___notes_diffs_normal" bigint NOT NULL, "___notes_diffs_reply" bigint NOT NULL, "___notes_diffs_renote" bigint NOT NULL, "___users_total" bigint NOT NULL, "___users_inc" bigint NOT NULL, "___users_dec" bigint NOT NULL, "___following_total" bigint NOT NULL, "___following_inc" bigint NOT NULL, "___following_dec" bigint NOT NULL, "___followers_total" bigint NOT NULL, "___followers_inc" bigint NOT NULL, "___followers_dec" bigint NOT NULL, "___drive_totalFiles" bigint NOT NULL, "___drive_totalUsage" bigint NOT NULL, "___drive_incFiles" bigint NOT NULL, "___drive_incUsage" bigint NOT NULL, "___drive_decFiles" bigint NOT NULL, "___drive_decUsage" bigint NOT NULL, CONSTRAINT "PK_1267c67c7c2d47b4903975f2c00" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__network_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__network" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__network_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___incomingRequests" bigint NOT NULL, "___outgoingRequests" bigint NOT NULL, "___totalTime" bigint NOT NULL, "___incomingBytes" bigint NOT NULL, "___outgoingBytes" bigint NOT NULL, CONSTRAINT "PK_bc4290c2e27fad14ef0c1ca93f3" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__notes_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__notes" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__notes_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_total" bigint NOT NULL, "___local_inc" bigint NOT NULL, "___local_dec" bigint NOT NULL, "___local_diffs_normal" bigint NOT NULL, "___local_diffs_reply" bigint NOT NULL, "___local_diffs_renote" bigint NOT NULL, "___remote_total" bigint NOT NULL, "___remote_inc" bigint NOT NULL, "___remote_dec" bigint NOT NULL, "___remote_diffs_normal" bigint NOT NULL, "___remote_diffs_reply" bigint NOT NULL, "___remote_diffs_renote" bigint NOT NULL, CONSTRAINT "PK_0aec823fa85c7f901bdb3863b14" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__per_user_drive_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__per_user_drive" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__per_user_drive_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___totalCount" bigint NOT NULL, "___totalSize" bigint NOT NULL, "___incCount" bigint NOT NULL, "___incSize" bigint NOT NULL, "___decCount" bigint NOT NULL, "___decSize" bigint NOT NULL, CONSTRAINT "PK_d0ef23d24d666e1a44a0cd3d208" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__per_user_following_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__per_user_following" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__per_user_following_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_followings_total" bigint NOT NULL, "___local_followings_inc" bigint NOT NULL, "___local_followings_dec" bigint NOT NULL, "___local_followers_total" bigint NOT NULL, "___local_followers_inc" bigint NOT NULL, "___local_followers_dec" bigint NOT NULL, "___remote_followings_total" bigint NOT NULL, "___remote_followings_inc" bigint NOT NULL, "___remote_followings_dec" bigint NOT NULL, "___remote_followers_total" bigint NOT NULL, "___remote_followers_inc" bigint NOT NULL, "___remote_followers_dec" bigint NOT NULL, CONSTRAINT "PK_85bb1b540363a29c2fec83bd907" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__per_user_notes_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__per_user_notes" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__per_user_notes_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___total" bigint NOT NULL, "___inc" bigint NOT NULL, "___dec" bigint NOT NULL, "___diffs_normal" bigint NOT NULL, "___diffs_reply" bigint NOT NULL, "___diffs_renote" bigint NOT NULL, CONSTRAINT "PK_334acf6e915af2f29edc11b8e50" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__per_user_reaction_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__per_user_reaction" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__per_user_reaction_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_count" bigint NOT NULL, "___remote_count" bigint NOT NULL, CONSTRAINT "PK_984f54dae441e65b633e8d27a7f" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__test_grouped_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__test_grouped" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__test_grouped_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___foo_total" bigint NOT NULL, "___foo_inc" bigint NOT NULL, "___foo_dec" bigint NOT NULL, CONSTRAINT "PK_f4a2b175d308695af30d4293272" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__test_unique_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__test_unique" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__test_unique_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___foo" bigint NOT NULL, CONSTRAINT "PK_409bac9c97cc612d8500012319d" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__test_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__test" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__test_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___foo_total" bigint NOT NULL, "___foo_inc" bigint NOT NULL, "___foo_dec" bigint NOT NULL, CONSTRAINT "PK_b4bc31dffbd1b785276a3ecfc1e" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TYPE "__chart__users_span_enum" AS ENUM('hour', 'day')`);
await queryRunner.query(`CREATE TABLE "__chart__users" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "group" character varying(128), "span" "__chart__users_span_enum" NOT NULL, "unique" jsonb NOT NULL DEFAULT '{}', "___local_total" bigint NOT NULL, "___local_inc" bigint NOT NULL, "___local_dec" bigint NOT NULL, "___remote_total" bigint NOT NULL, "___remote_inc" bigint NOT NULL, "___remote_dec" bigint NOT NULL, CONSTRAINT "PK_4dfcf2c78d03524b9eb2c99d328" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "drive_folder" ADD CONSTRAINT "FK_f4fc06e49c0171c85f1c48060d2" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "drive_folder" ADD CONSTRAINT "FK_00ceffb0cdc238b3233294f08f2" FOREIGN KEY ("parentId") REFERENCES "drive_folder"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "drive_file" ADD CONSTRAINT "FK_860fa6f6c7df5bb887249fba22e" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "drive_file" ADD CONSTRAINT "FK_bb90d1956dafc4068c28aa7560a" FOREIGN KEY ("folderId") REFERENCES "drive_folder"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user" ADD CONSTRAINT "FK_58f5c71eaab331645112cf8cfa5" FOREIGN KEY ("avatarId") REFERENCES "drive_file"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user" ADD CONSTRAINT "FK_afc64b53f8db3707ceb34eb28e2" FOREIGN KEY ("bannerId") REFERENCES "drive_file"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "app" ADD CONSTRAINT "FK_3f5b0899ef90527a3462d7c2cb3" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "access_token" ADD CONSTRAINT "FK_9949557d0e1b2c19e5344c171e9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "access_token" ADD CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560" FOREIGN KEY ("appId") REFERENCES "app"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_17cb3553c700a4985dff5a30ff5" FOREIGN KEY ("replyId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_52ccc804d7c69037d558bac4c96" FOREIGN KEY ("renoteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_ec5c201576192ba8904c345c5cc" FOREIGN KEY ("appId") REFERENCES "app"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_5b87d9d19127bd5d92026017a7b" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "poll_vote" ADD CONSTRAINT "FK_66d2bd2ee31d14bcc23069a89f8" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "poll_vote" ADD CONSTRAINT "FK_aecfbd5ef60374918e63ee95fa7" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_reaction" ADD CONSTRAINT "FK_13761f64257f40c5636d0ff95ee" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_reaction" ADD CONSTRAINT "FK_45145e4953780f3cd5656f0ea6a" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_watching" ADD CONSTRAINT "FK_b0134ec406e8d09a540f8182888" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_watching" ADD CONSTRAINT "FK_03e7028ab8388a3f5e3ce2a8619" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_unread" ADD CONSTRAINT "FK_56b0166d34ddae49d8ef7610bb9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_unread" ADD CONSTRAINT "FK_e637cba4dc4410218c4251260e4" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_3c601b70a1066d2c8b517094cb9" FOREIGN KEY ("notifieeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710" FOREIGN KEY ("notifierId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_769cb6b73a1efe22ddf733ac453" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "following" ADD CONSTRAINT "FK_24e0042143a18157b234df186c3" FOREIGN KEY ("followeeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "following" ADD CONSTRAINT "FK_6516c5a6f3c015b4eed39978be5" FOREIGN KEY ("followerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "muting" ADD CONSTRAINT "FK_ec96b4fed9dae517e0dbbe0675c" FOREIGN KEY ("muteeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "muting" ADD CONSTRAINT "FK_93060675b4a79a577f31d260c67" FOREIGN KEY ("muterId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "sw_subscription" ADD CONSTRAINT "FK_97754ca6f2baff9b4abb7f853dd" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "blocking" ADD CONSTRAINT "FK_2cd4a2743a99671308f5417759e" FOREIGN KEY ("blockeeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "blocking" ADD CONSTRAINT "FK_0627125f1a8a42c9a1929edb552" FOREIGN KEY ("blockerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_list" ADD CONSTRAINT "FK_b7fcefbdd1c18dce86687531f99" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_list_joining" ADD CONSTRAINT "FK_d844bfc6f3f523a05189076efaa" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_list_joining" ADD CONSTRAINT "FK_605472305f26818cc93d1baaa74" FOREIGN KEY ("userListId") REFERENCES "user_list"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_favorite" ADD CONSTRAINT "FK_47f4b1892f5d6ba8efb3057d81a" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "note_favorite" ADD CONSTRAINT "FK_0e00498f180193423c992bc4370" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_d049123c413e68ca52abe734203" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_04cc96756f89d0b7f9473e8cdf3" FOREIGN KEY ("reporterId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "messaging_message" ADD CONSTRAINT "FK_5377c307783fce2b6d352e1203b" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "messaging_message" ADD CONSTRAINT "FK_cac14a4e3944454a5ce7daa5142" FOREIGN KEY ("recipientId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "messaging_message" ADD CONSTRAINT "FK_535def119223ac05ad3fa9ef64b" FOREIGN KEY ("fileId") REFERENCES "drive_file"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "signin" ADD CONSTRAINT "FK_2c308dbdc50d94dc625670055f7" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "auth_session" ADD CONSTRAINT "FK_c072b729d71697f959bde66ade0" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "auth_session" ADD CONSTRAINT "FK_dbe037d4bddd17b03a1dc778dee" FOREIGN KEY ("appId") REFERENCES "app"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "follow_request" ADD CONSTRAINT "FK_12c01c0d1a79f77d9f6c15fadd2" FOREIGN KEY ("followeeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "follow_request" ADD CONSTRAINT "FK_a7fd92dd6dc519e6fb435dd108f" FOREIGN KEY ("followerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "reversi_game" ADD CONSTRAINT "FK_f7467510c60a45ce5aca6292743" FOREIGN KEY ("user1Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "reversi_game" ADD CONSTRAINT "FK_6649a4e8c5d5cf32fb03b5da9f6" FOREIGN KEY ("user2Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "reversi_matching" ADD CONSTRAINT "FK_3b25402709dd9882048c2bbade0" FOREIGN KEY ("parentId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "reversi_matching" ADD CONSTRAINT "FK_e247b23a3c9b45f89ec1299d066" FOREIGN KEY ("childId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_note_pining" ADD CONSTRAINT "FK_bfbc6f79ba4007b4ce5097f08d6" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_note_pining" ADD CONSTRAINT "FK_68881008f7c3588ad7ecae471cf" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "FK_10c146e4b39b443ede016f6736d" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9"`);
await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "FK_10c146e4b39b443ede016f6736d"`);
await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6"`);
await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b"`);
await queryRunner.query(`ALTER TABLE "user_note_pining" DROP CONSTRAINT "FK_68881008f7c3588ad7ecae471cf"`);
await queryRunner.query(`ALTER TABLE "user_note_pining" DROP CONSTRAINT "FK_bfbc6f79ba4007b4ce5097f08d6"`);
await queryRunner.query(`ALTER TABLE "reversi_matching" DROP CONSTRAINT "FK_e247b23a3c9b45f89ec1299d066"`);
await queryRunner.query(`ALTER TABLE "reversi_matching" DROP CONSTRAINT "FK_3b25402709dd9882048c2bbade0"`);
await queryRunner.query(`ALTER TABLE "reversi_game" DROP CONSTRAINT "FK_6649a4e8c5d5cf32fb03b5da9f6"`);
await queryRunner.query(`ALTER TABLE "reversi_game" DROP CONSTRAINT "FK_f7467510c60a45ce5aca6292743"`);
await queryRunner.query(`ALTER TABLE "follow_request" DROP CONSTRAINT "FK_a7fd92dd6dc519e6fb435dd108f"`);
await queryRunner.query(`ALTER TABLE "follow_request" DROP CONSTRAINT "FK_12c01c0d1a79f77d9f6c15fadd2"`);
await queryRunner.query(`ALTER TABLE "auth_session" DROP CONSTRAINT "FK_dbe037d4bddd17b03a1dc778dee"`);
await queryRunner.query(`ALTER TABLE "auth_session" DROP CONSTRAINT "FK_c072b729d71697f959bde66ade0"`);
await queryRunner.query(`ALTER TABLE "signin" DROP CONSTRAINT "FK_2c308dbdc50d94dc625670055f7"`);
await queryRunner.query(`ALTER TABLE "messaging_message" DROP CONSTRAINT "FK_535def119223ac05ad3fa9ef64b"`);
await queryRunner.query(`ALTER TABLE "messaging_message" DROP CONSTRAINT "FK_cac14a4e3944454a5ce7daa5142"`);
await queryRunner.query(`ALTER TABLE "messaging_message" DROP CONSTRAINT "FK_5377c307783fce2b6d352e1203b"`);
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_04cc96756f89d0b7f9473e8cdf3"`);
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_d049123c413e68ca52abe734203"`);
await queryRunner.query(`ALTER TABLE "note_favorite" DROP CONSTRAINT "FK_0e00498f180193423c992bc4370"`);
await queryRunner.query(`ALTER TABLE "note_favorite" DROP CONSTRAINT "FK_47f4b1892f5d6ba8efb3057d81a"`);
await queryRunner.query(`ALTER TABLE "user_list_joining" DROP CONSTRAINT "FK_605472305f26818cc93d1baaa74"`);
await queryRunner.query(`ALTER TABLE "user_list_joining" DROP CONSTRAINT "FK_d844bfc6f3f523a05189076efaa"`);
await queryRunner.query(`ALTER TABLE "user_list" DROP CONSTRAINT "FK_b7fcefbdd1c18dce86687531f99"`);
await queryRunner.query(`ALTER TABLE "blocking" DROP CONSTRAINT "FK_0627125f1a8a42c9a1929edb552"`);
await queryRunner.query(`ALTER TABLE "blocking" DROP CONSTRAINT "FK_2cd4a2743a99671308f5417759e"`);
await queryRunner.query(`ALTER TABLE "sw_subscription" DROP CONSTRAINT "FK_97754ca6f2baff9b4abb7f853dd"`);
await queryRunner.query(`ALTER TABLE "muting" DROP CONSTRAINT "FK_93060675b4a79a577f31d260c67"`);
await queryRunner.query(`ALTER TABLE "muting" DROP CONSTRAINT "FK_ec96b4fed9dae517e0dbbe0675c"`);
await queryRunner.query(`ALTER TABLE "following" DROP CONSTRAINT "FK_6516c5a6f3c015b4eed39978be5"`);
await queryRunner.query(`ALTER TABLE "following" DROP CONSTRAINT "FK_24e0042143a18157b234df186c3"`);
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_769cb6b73a1efe22ddf733ac453"`);
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710"`);
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_3c601b70a1066d2c8b517094cb9"`);
await queryRunner.query(`ALTER TABLE "note_unread" DROP CONSTRAINT "FK_e637cba4dc4410218c4251260e4"`);
await queryRunner.query(`ALTER TABLE "note_unread" DROP CONSTRAINT "FK_56b0166d34ddae49d8ef7610bb9"`);
await queryRunner.query(`ALTER TABLE "note_watching" DROP CONSTRAINT "FK_03e7028ab8388a3f5e3ce2a8619"`);
await queryRunner.query(`ALTER TABLE "note_watching" DROP CONSTRAINT "FK_b0134ec406e8d09a540f8182888"`);
await queryRunner.query(`ALTER TABLE "note_reaction" DROP CONSTRAINT "FK_45145e4953780f3cd5656f0ea6a"`);
await queryRunner.query(`ALTER TABLE "note_reaction" DROP CONSTRAINT "FK_13761f64257f40c5636d0ff95ee"`);
await queryRunner.query(`ALTER TABLE "poll_vote" DROP CONSTRAINT "FK_aecfbd5ef60374918e63ee95fa7"`);
await queryRunner.query(`ALTER TABLE "poll_vote" DROP CONSTRAINT "FK_66d2bd2ee31d14bcc23069a89f8"`);
await queryRunner.query(`ALTER TABLE "note" DROP CONSTRAINT "FK_5b87d9d19127bd5d92026017a7b"`);
await queryRunner.query(`ALTER TABLE "note" DROP CONSTRAINT "FK_ec5c201576192ba8904c345c5cc"`);
await queryRunner.query(`ALTER TABLE "note" DROP CONSTRAINT "FK_52ccc804d7c69037d558bac4c96"`);
await queryRunner.query(`ALTER TABLE "note" DROP CONSTRAINT "FK_17cb3553c700a4985dff5a30ff5"`);
await queryRunner.query(`ALTER TABLE "access_token" DROP CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560"`);
await queryRunner.query(`ALTER TABLE "access_token" DROP CONSTRAINT "FK_9949557d0e1b2c19e5344c171e9"`);
await queryRunner.query(`ALTER TABLE "app" DROP CONSTRAINT "FK_3f5b0899ef90527a3462d7c2cb3"`);
await queryRunner.query(`ALTER TABLE "user" DROP CONSTRAINT "FK_afc64b53f8db3707ceb34eb28e2"`);
await queryRunner.query(`ALTER TABLE "user" DROP CONSTRAINT "FK_58f5c71eaab331645112cf8cfa5"`);
await queryRunner.query(`ALTER TABLE "drive_file" DROP CONSTRAINT "FK_bb90d1956dafc4068c28aa7560a"`);
await queryRunner.query(`ALTER TABLE "drive_file" DROP CONSTRAINT "FK_860fa6f6c7df5bb887249fba22e"`);
await queryRunner.query(`ALTER TABLE "drive_folder" DROP CONSTRAINT "FK_00ceffb0cdc238b3233294f08f2"`);
await queryRunner.query(`ALTER TABLE "drive_folder" DROP CONSTRAINT "FK_f4fc06e49c0171c85f1c48060d2"`);
await queryRunner.query(`DROP TABLE "__chart__users"`);
await queryRunner.query(`DROP TYPE "__chart__users_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__test"`);
await queryRunner.query(`DROP TYPE "__chart__test_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__test_unique"`);
await queryRunner.query(`DROP TYPE "__chart__test_unique_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__test_grouped"`);
await queryRunner.query(`DROP TYPE "__chart__test_grouped_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__per_user_reaction"`);
await queryRunner.query(`DROP TYPE "__chart__per_user_reaction_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__per_user_notes"`);
await queryRunner.query(`DROP TYPE "__chart__per_user_notes_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__per_user_following"`);
await queryRunner.query(`DROP TYPE "__chart__per_user_following_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__per_user_drive"`);
await queryRunner.query(`DROP TYPE "__chart__per_user_drive_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__notes"`);
await queryRunner.query(`DROP TYPE "__chart__notes_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__network"`);
await queryRunner.query(`DROP TYPE "__chart__network_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__instance"`);
await queryRunner.query(`DROP TYPE "__chart__instance_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__hashtag"`);
await queryRunner.query(`DROP TYPE "__chart__hashtag_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__federation"`);
await queryRunner.query(`DROP TYPE "__chart__federation_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__drive"`);
await queryRunner.query(`DROP TYPE "__chart__drive_span_enum"`);
await queryRunner.query(`DROP TABLE "__chart__active_users"`);
await queryRunner.query(`DROP TYPE "__chart__active_users_span_enum"`);
await queryRunner.query(`DROP INDEX "IDX_dce530b98e454793dac5ec2f5a"`);
await queryRunner.query(`DROP TABLE "user_profile"`);
await queryRunner.query(`DROP INDEX "IDX_171e64971c780ebd23fae140bb"`);
await queryRunner.query(`DROP TABLE "user_publickey"`);
await queryRunner.query(`DROP TABLE "user_keypair"`);
await queryRunner.query(`DROP INDEX "IDX_7fa20a12319c7f6dc3aed98c0a"`);
await queryRunner.query(`DROP INDEX "IDX_0610ebcfcfb4a18441a9bcdab2"`);
await queryRunner.query(`DROP TABLE "poll"`);
await queryRunner.query(`DROP TYPE "poll_notevisibility_enum"`);
await queryRunner.query(`DROP INDEX "IDX_410cd649884b501c02d6e72738"`);
await queryRunner.query(`DROP INDEX "IDX_bfbc6f79ba4007b4ce5097f08d"`);
await queryRunner.query(`DROP TABLE "user_note_pining"`);
await queryRunner.query(`DROP INDEX "IDX_e247b23a3c9b45f89ec1299d06"`);
await queryRunner.query(`DROP INDEX "IDX_3b25402709dd9882048c2bbade"`);
await queryRunner.query(`DROP INDEX "IDX_b604d92d6c7aec38627f6eaf16"`);
await queryRunner.query(`DROP TABLE "reversi_matching"`);
await queryRunner.query(`DROP INDEX "IDX_b46ec40746efceac604142be1c"`);
await queryRunner.query(`DROP TABLE "reversi_game"`);
await queryRunner.query(`DROP INDEX "IDX_4f4d35e1256c84ae3d1f0eab10"`);
await queryRunner.query(`DROP INDEX "IDX_5900e907bb46516ddf2871327c"`);
await queryRunner.query(`DROP INDEX "IDX_b37dafc86e9af007e3295c2781"`);
await queryRunner.query(`DROP TABLE "emoji"`);
await queryRunner.query(`DROP INDEX "IDX_d54a512b822fac7ed52800f6b4"`);
await queryRunner.query(`DROP INDEX "IDX_a7fd92dd6dc519e6fb435dd108"`);
await queryRunner.query(`DROP INDEX "IDX_12c01c0d1a79f77d9f6c15fadd"`);
await queryRunner.query(`DROP TABLE "follow_request"`);
await queryRunner.query(`DROP INDEX "IDX_62cb09e1129f6ec024ef66e183"`);
await queryRunner.query(`DROP TABLE "auth_session"`);
await queryRunner.query(`DROP INDEX "IDX_2c308dbdc50d94dc625670055f"`);
await queryRunner.query(`DROP TABLE "signin"`);
await queryRunner.query(`DROP INDEX "IDX_cac14a4e3944454a5ce7daa514"`);
await queryRunner.query(`DROP INDEX "IDX_5377c307783fce2b6d352e1203"`);
await queryRunner.query(`DROP INDEX "IDX_e21cd3646e52ef9c94aaf17c2e"`);
await queryRunner.query(`DROP TABLE "messaging_message"`);
await queryRunner.query(`DROP INDEX "IDX_0ff69e8dfa9fe31bb4a4660f59"`);
await queryRunner.query(`DROP TABLE "registration_ticket"`);
await queryRunner.query(`DROP INDEX "IDX_5cd442c3b2e74fdd99dae20243"`);
await queryRunner.query(`DROP INDEX "IDX_04cc96756f89d0b7f9473e8cdf"`);
await queryRunner.query(`DROP INDEX "IDX_d049123c413e68ca52abe73420"`);
await queryRunner.query(`DROP INDEX "IDX_db2098070b2b5a523c58181f74"`);
await queryRunner.query(`DROP TABLE "abuse_user_report"`);
await queryRunner.query(`DROP INDEX "IDX_0f4fb9ad355f3effff221ef245"`);
await queryRunner.query(`DROP INDEX "IDX_47f4b1892f5d6ba8efb3057d81"`);
await queryRunner.query(`DROP TABLE "note_favorite"`);
await queryRunner.query(`DROP INDEX "IDX_0b03cbcd7e6a7ce068efa8ecc2"`);
await queryRunner.query(`DROP INDEX "IDX_0c44bf4f680964145f2a68a341"`);
await queryRunner.query(`DROP INDEX "IDX_d57f9030cd3af7f63ffb1c267c"`);
await queryRunner.query(`DROP INDEX "IDX_4c02d38a976c3ae132228c6fce"`);
await queryRunner.query(`DROP INDEX "IDX_0e206cec573f1edff4a3062923"`);
await queryRunner.query(`DROP INDEX "IDX_2710a55f826ee236ea1a62698f"`);
await queryRunner.query(`DROP INDEX "IDX_347fec870eafea7b26c8a73bac"`);
await queryRunner.query(`DROP TABLE "hashtag"`);
await queryRunner.query(`DROP INDEX "IDX_605472305f26818cc93d1baaa7"`);
await queryRunner.query(`DROP INDEX "IDX_d844bfc6f3f523a05189076efa"`);
await queryRunner.query(`DROP TABLE "user_list_joining"`);
await queryRunner.query(`DROP INDEX "IDX_b7fcefbdd1c18dce86687531f9"`);
await queryRunner.query(`DROP TABLE "user_list"`);
await queryRunner.query(`DROP INDEX "IDX_98a1bc5cb30dfd159de056549f"`);
await queryRunner.query(`DROP INDEX "IDX_0627125f1a8a42c9a1929edb55"`);
await queryRunner.query(`DROP INDEX "IDX_2cd4a2743a99671308f5417759"`);
await queryRunner.query(`DROP INDEX "IDX_b9a354f7941c1e779f3b33aea6"`);
await queryRunner.query(`DROP TABLE "blocking"`);
await queryRunner.query(`DROP INDEX "IDX_97754ca6f2baff9b4abb7f853d"`);
await queryRunner.query(`DROP TABLE "sw_subscription"`);
await queryRunner.query(`DROP INDEX "IDX_1eb9d9824a630321a29fd3b290"`);
await queryRunner.query(`DROP INDEX "IDX_93060675b4a79a577f31d260c6"`);
await queryRunner.query(`DROP INDEX "IDX_ec96b4fed9dae517e0dbbe0675"`);
await queryRunner.query(`DROP INDEX "IDX_f86d57fbca33c7a4e6897490cc"`);
await queryRunner.query(`DROP TABLE "muting"`);
await queryRunner.query(`DROP INDEX "IDX_8d5afc98982185799b160e10eb"`);
await queryRunner.query(`DROP INDEX "IDX_2cd3b2a6b4cf0b910b260afe08"`);
await queryRunner.query(`DROP TABLE "instance"`);
await queryRunner.query(`DROP INDEX "IDX_307be5f1d1252e0388662acb96"`);
await queryRunner.query(`DROP INDEX "IDX_6516c5a6f3c015b4eed39978be"`);
await queryRunner.query(`DROP INDEX "IDX_24e0042143a18157b234df186c"`);
await queryRunner.query(`DROP INDEX "IDX_582f8fab771a9040a12961f3e7"`);
await queryRunner.query(`DROP TABLE "following"`);
await queryRunner.query(`DROP TABLE "meta"`);
await queryRunner.query(`DROP INDEX "IDX_3c601b70a1066d2c8b517094cb"`);
await queryRunner.query(`DROP INDEX "IDX_b11a5e627c41d4dc3170f1d370"`);
await queryRunner.query(`DROP TABLE "notification"`);
await queryRunner.query(`DROP INDEX "IDX_d908433a4953cc13216cd9c274"`);
await queryRunner.query(`DROP INDEX "IDX_e637cba4dc4410218c4251260e"`);
await queryRunner.query(`DROP INDEX "IDX_56b0166d34ddae49d8ef7610bb"`);
await queryRunner.query(`DROP TABLE "note_unread"`);
await queryRunner.query(`DROP INDEX "IDX_a42c93c69989ce1d09959df4cf"`);
await queryRunner.query(`DROP INDEX "IDX_44499765eec6b5489d72c4253b"`);
await queryRunner.query(`DROP INDEX "IDX_03e7028ab8388a3f5e3ce2a861"`);
await queryRunner.query(`DROP INDEX "IDX_b0134ec406e8d09a540f818288"`);
await queryRunner.query(`DROP INDEX "IDX_318cdf42a9cfc11f479bd802bb"`);
await queryRunner.query(`DROP TABLE "note_watching"`);
await queryRunner.query(`DROP INDEX "IDX_ad0c221b25672daf2df320a817"`);
await queryRunner.query(`DROP INDEX "IDX_45145e4953780f3cd5656f0ea6"`);
await queryRunner.query(`DROP INDEX "IDX_13761f64257f40c5636d0ff95e"`);
await queryRunner.query(`DROP INDEX "IDX_01f4581f114e0ebd2bbb876f0b"`);
await queryRunner.query(`DROP TABLE "note_reaction"`);
await queryRunner.query(`DROP INDEX "IDX_50bd7164c5b78f1f4a42c4d21f"`);
await queryRunner.query(`DROP INDEX "IDX_aecfbd5ef60374918e63ee95fa"`);
await queryRunner.query(`DROP INDEX "IDX_66d2bd2ee31d14bcc23069a89f"`);
await queryRunner.query(`DROP INDEX "IDX_0fb627e1c2f753262a74f0562d"`);
await queryRunner.query(`DROP TABLE "poll_vote"`);
await queryRunner.query(`DROP INDEX "IDX_7125a826ab192eb27e11d358a5"`);
await queryRunner.query(`DROP INDEX "IDX_88937d94d7443d9a99a76fa5c0"`);
await queryRunner.query(`DROP INDEX "IDX_54ebcb6d27222913b908d56fd8"`);
await queryRunner.query(`DROP INDEX "IDX_796a8c03959361f97dc2be1d5c"`);
await queryRunner.query(`DROP INDEX "IDX_25dfc71b0369b003a4cd434d0b"`);
await queryRunner.query(`DROP INDEX "IDX_51c063b6a133a9cb87145450f5"`);
await queryRunner.query(`DROP INDEX "IDX_153536c67d05e9adb24e99fc2b"`);
await queryRunner.query(`DROP INDEX "IDX_5b87d9d19127bd5d92026017a7"`);
await queryRunner.query(`DROP INDEX "IDX_52ccc804d7c69037d558bac4c9"`);
await queryRunner.query(`DROP INDEX "IDX_17cb3553c700a4985dff5a30ff"`);
await queryRunner.query(`DROP INDEX "IDX_e7c0567f5261063592f022e9b5"`);
await queryRunner.query(`DROP TABLE "note"`);
await queryRunner.query(`DROP TYPE "note_visibility_enum"`);
await queryRunner.query(`DROP INDEX "IDX_9949557d0e1b2c19e5344c171e"`);
await queryRunner.query(`DROP INDEX "IDX_64c327441248bae40f7d92f34f"`);
await queryRunner.query(`DROP INDEX "IDX_70ba8f6af34bc924fc9e12adb8"`);
await queryRunner.query(`DROP TABLE "access_token"`);
await queryRunner.query(`DROP INDEX "IDX_f49922d511d666848f250663c4"`);
await queryRunner.query(`DROP INDEX "IDX_3f5b0899ef90527a3462d7c2cb"`);
await queryRunner.query(`DROP INDEX "IDX_048a757923ed8b157e9895da53"`);
await queryRunner.query(`DROP TABLE "app"`);
await queryRunner.query(`DROP INDEX "IDX_5deb01ae162d1d70b80d064c27"`);
await queryRunner.query(`DROP INDEX "IDX_a854e557b1b14814750c7c7b0c"`);
await queryRunner.query(`DROP INDEX "IDX_be623adaa4c566baf5d29ce0c8"`);
await queryRunner.query(`DROP INDEX "IDX_3252a5df8d5bbd16b281f7799e"`);
await queryRunner.query(`DROP INDEX "IDX_fa99d777623947a5b05f394cae"`);
await queryRunner.query(`DROP INDEX "IDX_a27b942a0d6dcff90e3ee9b5e8"`);
await queryRunner.query(`DROP INDEX "IDX_80ca6e6ef65fb9ef34ea8c90f4"`);
await queryRunner.query(`DROP INDEX "IDX_e11e649824a45d8ed01d597fd9"`);
await queryRunner.query(`DROP TABLE "user"`);
await queryRunner.query(`DROP INDEX "IDX_bb90d1956dafc4068c28aa7560"`);
await queryRunner.query(`DROP INDEX "IDX_e5848eac4940934e23dbc17581"`);
await queryRunner.query(`DROP INDEX "IDX_c55b2b7c284d9fef98026fc88e"`);
await queryRunner.query(`DROP INDEX "IDX_e74022ce9a074b3866f70e0d27"`);
await queryRunner.query(`DROP INDEX "IDX_d85a184c2540d2deba33daf642"`);
await queryRunner.query(`DROP INDEX "IDX_a40b8df8c989d7db937ea27cf6"`);
await queryRunner.query(`DROP INDEX "IDX_37bb9a1b4585f8a3beb24c62d6"`);
await queryRunner.query(`DROP INDEX "IDX_92779627994ac79277f070c91e"`);
await queryRunner.query(`DROP INDEX "IDX_860fa6f6c7df5bb887249fba22"`);
await queryRunner.query(`DROP INDEX "IDX_c8dfad3b72196dd1d6b5db168a"`);
await queryRunner.query(`DROP TABLE "drive_file"`);
await queryRunner.query(`DROP INDEX "IDX_00ceffb0cdc238b3233294f08f"`);
await queryRunner.query(`DROP INDEX "IDX_f4fc06e49c0171c85f1c48060d"`);
await queryRunner.query(`DROP INDEX "IDX_02878d441ceae15ce060b73daf"`);
await queryRunner.query(`DROP TABLE "drive_folder"`);
await queryRunner.query(`DROP INDEX "IDX_584b536b49e53ac81beb39a177"`);
await queryRunner.query(`DROP INDEX "IDX_8cb40cfc8f3c28261e6f887b03"`);
await queryRunner.query(`DROP INDEX "IDX_8e4eb51a35d81b64dda28eed0a"`);
await queryRunner.query(`DROP TABLE "log"`);
await queryRunner.query(`DROP TYPE "log_level_enum"`);
}
}

View File

@@ -0,0 +1,29 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class webauthn1561706992953 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`CREATE TABLE "attestation_challenge" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "challenge" character varying(64) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "registrationChallenge" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_d0ba6786e093f1bcb497572a6b5" PRIMARY KEY ("id", "userId"))`);
await queryRunner.query(`CREATE INDEX "IDX_f1a461a618fa1755692d0e0d59" ON "attestation_challenge" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_47efb914aed1f72dd39a306c7b" ON "attestation_challenge" ("challenge") `);
await queryRunner.query(`CREATE TABLE "user_security_key" ("id" character varying NOT NULL, "userId" character varying(32) NOT NULL, "publicKey" character varying NOT NULL, "lastUsed" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(30) NOT NULL, CONSTRAINT "PK_3e508571121ab39c5f85d10c166" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_ff9ca3b5f3ee3d0681367a9b44" ON "user_security_key" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_0d7718e562dcedd0aa5cf2c9f7" ON "user_security_key" ("publicKey") `);
await queryRunner.query(`ALTER TABLE "user_profile" ADD "securityKeysAvailable" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`ALTER TABLE "attestation_challenge" ADD CONSTRAINT "FK_f1a461a618fa1755692d0e0d592" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_security_key" ADD CONSTRAINT "FK_ff9ca3b5f3ee3d0681367a9b447" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "user_security_key" DROP CONSTRAINT "FK_ff9ca3b5f3ee3d0681367a9b447"`);
await queryRunner.query(`ALTER TABLE "attestation_challenge" DROP CONSTRAINT "FK_f1a461a618fa1755692d0e0d592"`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "securityKeysAvailable"`);
await queryRunner.query(`DROP INDEX "IDX_0d7718e562dcedd0aa5cf2c9f7"`);
await queryRunner.query(`DROP INDEX "IDX_ff9ca3b5f3ee3d0681367a9b44"`);
await queryRunner.query(`DROP TABLE "user_security_key"`);
await queryRunner.query(`DROP INDEX "IDX_47efb914aed1f72dd39a306c7b"`);
await queryRunner.query(`DROP INDEX "IDX_f1a461a618fa1755692d0e0d59"`);
await queryRunner.query(`DROP TABLE "attestation_challenge"`);
}
}

View File

@@ -0,0 +1,201 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class ChartIndexes1561873850023 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`CREATE INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc" ON "__chart__active_users" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_15e91a03aeeac9dbccdf43fc06" ON "__chart__active_users" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_00ed5f86db1f7efafb1978bf21" ON "__chart__active_users" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_20f57cc8f142c131340ee16742" ON "__chart__active_users" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_9a3ed15a30ab7e3a37702e6e08" ON "__chart__active_users" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_c26e2c1cbb6e911e0554b27416" ON "__chart__active_users" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_13565815f618a1ff53886c5b28" ON "__chart__drive" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_3fa0d0f17ca72e3dc80999a032" ON "__chart__drive" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_7a170f67425e62a8fabb76c872" ON "__chart__drive" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_6e1df243476e20cbf86572ecc0" ON "__chart__drive" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_3313d7288855ec105b5bbf6c21" ON "__chart__drive" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_06690fc959f1c9fdaf21928222" ON "__chart__drive" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_36cb699c49580d4e6c2e6159f9" ON "__chart__federation" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_e447064455928cf627590ef527" ON "__chart__federation" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_76e87c7bfc5d925fcbba405d84" ON "__chart__federation" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_2d416e6af791a82e338c79d480" ON "__chart__federation" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_dd907becf76104e4b656659e6b" ON "__chart__federation" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_e9cd07672b37d8966cf3709283" ON "__chart__federation" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_07747a1038c05f532a718fe1de" ON "__chart__hashtag" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_fcc181fb8283009c61cc4083ef" ON "__chart__hashtag" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_99a7d2faaef84a6f728d714ad6" ON "__chart__hashtag" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_49975586f50ed7b800fdd88fbd" ON "__chart__hashtag" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_25a97c02003338124b2b75fdbc" ON "__chart__hashtag" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_6d6f156ceefc6bc5f273a0e370" ON "__chart__hashtag" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_6b8f34a1a64b06014b6fb66824" ON "__chart__instance" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_c12f0af4a66cdd30c2287ce8aa" ON "__chart__instance" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_da8a46ba84ca1d8bb5a29bfb63" ON "__chart__instance" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_d0a4f79af5a97b08f37b547197" ON "__chart__instance" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_39ee857ab2f23493037c6b6631" ON "__chart__instance" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_f5448d9633cff74208d850aabe" ON "__chart__instance" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_a1efd3e0048a5f2793a47360dc" ON "__chart__network" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_f8dd01baeded2ffa833e0a610a" ON "__chart__network" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_7b5da130992ec9df96712d4290" ON "__chart__network" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_08fac0eb3b11f04c200c0b40dd" ON "__chart__network" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_0a905b992fecd2b5c3fb98759e" ON "__chart__network" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_9ff6944f01acb756fdc92d7563" ON "__chart__network" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_42eb716a37d381cdf566192b2b" ON "__chart__notes" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_e69096589f11e3baa98ddd64d0" ON "__chart__notes" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_7036f2957151588b813185c794" ON "__chart__notes" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_0c9a159c5082cbeef3ca6706b5" ON "__chart__notes" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_f09d543e3acb16c5976bdb31fa" ON "__chart__notes" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_924fc196c80ca24bae01dd37e4" ON "__chart__notes" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_5f86db6492274e07c1a3cdf286" ON "__chart__per_user_drive" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_328f259961e60c4fa0bfcf55ca" ON "__chart__per_user_drive" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_e496ca8096d28f6b9b509264dc" ON "__chart__per_user_drive" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_42ea9381f0fda8dfe0fa1c8b53" ON "__chart__per_user_drive" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_30bf67687f483ace115c5ca642" ON "__chart__per_user_drive" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_f2aeafde2ae6fbad38e857631b" ON "__chart__per_user_drive" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7af07790712aa3438ff6773f3b" ON "__chart__per_user_following" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_f92dd6d03f8d994f29987f6214" ON "__chart__per_user_following" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_4b3593098b6edc9c5afe36b18b" ON "__chart__per_user_following" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_57b5458d0d3d6d1e7f13d4e57f" ON "__chart__per_user_following" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_b77d4dd9562c3a899d9a286fcd" ON "__chart__per_user_following" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_4db3b84c7be0d3464714f3e0b1" ON "__chart__per_user_following" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_84234bd1abb873f07329681c83" ON "__chart__per_user_notes" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_8d2cbbc8114d90d19b44d626b6" ON "__chart__per_user_notes" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_55bf20f366979f2436de99206b" ON "__chart__per_user_notes" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_046feeb12e9ef5f783f409866a" ON "__chart__per_user_notes" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_5048e9daccbbbc6d567bb142d3" ON "__chart__per_user_notes" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_f68a5ab958f9f5fa17a32ac23b" ON "__chart__per_user_notes" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_f7bf4c62059764c2c2bb40fdab" ON "__chart__per_user_reaction" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_65633a106bce43fc7c5c30a5c7" ON "__chart__per_user_reaction" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_8cf3156fd7a6b15c43459c6e3b" ON "__chart__per_user_reaction" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_edeb73c09c3143a81bcb34d569" ON "__chart__per_user_reaction" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_229a41ad465f9205f1f5703291" ON "__chart__per_user_reaction" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_e316f01a6d24eb31db27f88262" ON "__chart__per_user_reaction" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_0c641990ecf47d2545df4edb75" ON "__chart__test_grouped" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_2be7ec6cebddc14dc11e206686" ON "__chart__test_grouped" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_234dff3c0b56a6150b95431ab9" ON "__chart__test_grouped" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_a5133470f4825902e170328ca5" ON "__chart__test_grouped" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_b14489029e4b3aaf4bba5fb524" ON "__chart__test_grouped" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_84e661abb7bd1e51b690d4b017" ON "__chart__test_grouped" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_437bab3c6061d90f6bb65fd2cc" ON "__chart__test_unique" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_5c73bf61da4f6e6f15bae88ed1" ON "__chart__test_unique" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_bbfa573a8181018851ed0b6357" ON "__chart__test_unique" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_d70c86baedc68326be11f9c0ce" ON "__chart__test_unique" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_a0cd75442dd10d0643a17c4a49" ON "__chart__test_unique" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_66e1e1ecd2f29e57778af35b59" ON "__chart__test_unique" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_b070a906db04b44c67c6c2144d" ON "__chart__test" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_92255988735563f0fe4aba1f05" ON "__chart__test" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_d41cce6aee1a50bfc062038f9b" ON "__chart__test" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_c5870993e25c3d5771f91f5003" ON "__chart__test" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_a319e5dbf47e8a17497623beae" ON "__chart__test" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_f170de677ea75ad4533de2723e" ON "__chart__test" ("span", "date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_845254b3eaf708ae8a6cac3026" ON "__chart__users" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_7c184198ecf66a8d3ecb253ab3" ON "__chart__users" ("span") `);
await queryRunner.query(`CREATE INDEX "IDX_ed9b95919c672a13008e9487ee" ON "__chart__users" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_f091abb24193d50c653c6b77fc" ON "__chart__users" ("span", "date") `);
await queryRunner.query(`CREATE INDEX "IDX_337e9599f278bd7537fe30876f" ON "__chart__users" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_a770a57c70e668cc61590c9161" ON "__chart__users" ("span", "date", "group") `);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP INDEX "IDX_a770a57c70e668cc61590c9161"`);
await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`);
await queryRunner.query(`DROP INDEX "IDX_f091abb24193d50c653c6b77fc"`);
await queryRunner.query(`DROP INDEX "IDX_ed9b95919c672a13008e9487ee"`);
await queryRunner.query(`DROP INDEX "IDX_7c184198ecf66a8d3ecb253ab3"`);
await queryRunner.query(`DROP INDEX "IDX_845254b3eaf708ae8a6cac3026"`);
await queryRunner.query(`DROP INDEX "IDX_f170de677ea75ad4533de2723e"`);
await queryRunner.query(`DROP INDEX "IDX_a319e5dbf47e8a17497623beae"`);
await queryRunner.query(`DROP INDEX "IDX_c5870993e25c3d5771f91f5003"`);
await queryRunner.query(`DROP INDEX "IDX_d41cce6aee1a50bfc062038f9b"`);
await queryRunner.query(`DROP INDEX "IDX_92255988735563f0fe4aba1f05"`);
await queryRunner.query(`DROP INDEX "IDX_b070a906db04b44c67c6c2144d"`);
await queryRunner.query(`DROP INDEX "IDX_66e1e1ecd2f29e57778af35b59"`);
await queryRunner.query(`DROP INDEX "IDX_a0cd75442dd10d0643a17c4a49"`);
await queryRunner.query(`DROP INDEX "IDX_d70c86baedc68326be11f9c0ce"`);
await queryRunner.query(`DROP INDEX "IDX_bbfa573a8181018851ed0b6357"`);
await queryRunner.query(`DROP INDEX "IDX_5c73bf61da4f6e6f15bae88ed1"`);
await queryRunner.query(`DROP INDEX "IDX_437bab3c6061d90f6bb65fd2cc"`);
await queryRunner.query(`DROP INDEX "IDX_84e661abb7bd1e51b690d4b017"`);
await queryRunner.query(`DROP INDEX "IDX_b14489029e4b3aaf4bba5fb524"`);
await queryRunner.query(`DROP INDEX "IDX_a5133470f4825902e170328ca5"`);
await queryRunner.query(`DROP INDEX "IDX_234dff3c0b56a6150b95431ab9"`);
await queryRunner.query(`DROP INDEX "IDX_2be7ec6cebddc14dc11e206686"`);
await queryRunner.query(`DROP INDEX "IDX_0c641990ecf47d2545df4edb75"`);
await queryRunner.query(`DROP INDEX "IDX_e316f01a6d24eb31db27f88262"`);
await queryRunner.query(`DROP INDEX "IDX_229a41ad465f9205f1f5703291"`);
await queryRunner.query(`DROP INDEX "IDX_edeb73c09c3143a81bcb34d569"`);
await queryRunner.query(`DROP INDEX "IDX_8cf3156fd7a6b15c43459c6e3b"`);
await queryRunner.query(`DROP INDEX "IDX_65633a106bce43fc7c5c30a5c7"`);
await queryRunner.query(`DROP INDEX "IDX_f7bf4c62059764c2c2bb40fdab"`);
await queryRunner.query(`DROP INDEX "IDX_f68a5ab958f9f5fa17a32ac23b"`);
await queryRunner.query(`DROP INDEX "IDX_5048e9daccbbbc6d567bb142d3"`);
await queryRunner.query(`DROP INDEX "IDX_046feeb12e9ef5f783f409866a"`);
await queryRunner.query(`DROP INDEX "IDX_55bf20f366979f2436de99206b"`);
await queryRunner.query(`DROP INDEX "IDX_8d2cbbc8114d90d19b44d626b6"`);
await queryRunner.query(`DROP INDEX "IDX_84234bd1abb873f07329681c83"`);
await queryRunner.query(`DROP INDEX "IDX_4db3b84c7be0d3464714f3e0b1"`);
await queryRunner.query(`DROP INDEX "IDX_b77d4dd9562c3a899d9a286fcd"`);
await queryRunner.query(`DROP INDEX "IDX_57b5458d0d3d6d1e7f13d4e57f"`);
await queryRunner.query(`DROP INDEX "IDX_4b3593098b6edc9c5afe36b18b"`);
await queryRunner.query(`DROP INDEX "IDX_f92dd6d03f8d994f29987f6214"`);
await queryRunner.query(`DROP INDEX "IDX_7af07790712aa3438ff6773f3b"`);
await queryRunner.query(`DROP INDEX "IDX_f2aeafde2ae6fbad38e857631b"`);
await queryRunner.query(`DROP INDEX "IDX_30bf67687f483ace115c5ca642"`);
await queryRunner.query(`DROP INDEX "IDX_42ea9381f0fda8dfe0fa1c8b53"`);
await queryRunner.query(`DROP INDEX "IDX_e496ca8096d28f6b9b509264dc"`);
await queryRunner.query(`DROP INDEX "IDX_328f259961e60c4fa0bfcf55ca"`);
await queryRunner.query(`DROP INDEX "IDX_5f86db6492274e07c1a3cdf286"`);
await queryRunner.query(`DROP INDEX "IDX_924fc196c80ca24bae01dd37e4"`);
await queryRunner.query(`DROP INDEX "IDX_f09d543e3acb16c5976bdb31fa"`);
await queryRunner.query(`DROP INDEX "IDX_0c9a159c5082cbeef3ca6706b5"`);
await queryRunner.query(`DROP INDEX "IDX_7036f2957151588b813185c794"`);
await queryRunner.query(`DROP INDEX "IDX_e69096589f11e3baa98ddd64d0"`);
await queryRunner.query(`DROP INDEX "IDX_42eb716a37d381cdf566192b2b"`);
await queryRunner.query(`DROP INDEX "IDX_9ff6944f01acb756fdc92d7563"`);
await queryRunner.query(`DROP INDEX "IDX_0a905b992fecd2b5c3fb98759e"`);
await queryRunner.query(`DROP INDEX "IDX_08fac0eb3b11f04c200c0b40dd"`);
await queryRunner.query(`DROP INDEX "IDX_7b5da130992ec9df96712d4290"`);
await queryRunner.query(`DROP INDEX "IDX_f8dd01baeded2ffa833e0a610a"`);
await queryRunner.query(`DROP INDEX "IDX_a1efd3e0048a5f2793a47360dc"`);
await queryRunner.query(`DROP INDEX "IDX_f5448d9633cff74208d850aabe"`);
await queryRunner.query(`DROP INDEX "IDX_39ee857ab2f23493037c6b6631"`);
await queryRunner.query(`DROP INDEX "IDX_d0a4f79af5a97b08f37b547197"`);
await queryRunner.query(`DROP INDEX "IDX_da8a46ba84ca1d8bb5a29bfb63"`);
await queryRunner.query(`DROP INDEX "IDX_c12f0af4a66cdd30c2287ce8aa"`);
await queryRunner.query(`DROP INDEX "IDX_6b8f34a1a64b06014b6fb66824"`);
await queryRunner.query(`DROP INDEX "IDX_6d6f156ceefc6bc5f273a0e370"`);
await queryRunner.query(`DROP INDEX "IDX_25a97c02003338124b2b75fdbc"`);
await queryRunner.query(`DROP INDEX "IDX_49975586f50ed7b800fdd88fbd"`);
await queryRunner.query(`DROP INDEX "IDX_99a7d2faaef84a6f728d714ad6"`);
await queryRunner.query(`DROP INDEX "IDX_fcc181fb8283009c61cc4083ef"`);
await queryRunner.query(`DROP INDEX "IDX_07747a1038c05f532a718fe1de"`);
await queryRunner.query(`DROP INDEX "IDX_e9cd07672b37d8966cf3709283"`);
await queryRunner.query(`DROP INDEX "IDX_dd907becf76104e4b656659e6b"`);
await queryRunner.query(`DROP INDEX "IDX_2d416e6af791a82e338c79d480"`);
await queryRunner.query(`DROP INDEX "IDX_76e87c7bfc5d925fcbba405d84"`);
await queryRunner.query(`DROP INDEX "IDX_e447064455928cf627590ef527"`);
await queryRunner.query(`DROP INDEX "IDX_36cb699c49580d4e6c2e6159f9"`);
await queryRunner.query(`DROP INDEX "IDX_06690fc959f1c9fdaf21928222"`);
await queryRunner.query(`DROP INDEX "IDX_3313d7288855ec105b5bbf6c21"`);
await queryRunner.query(`DROP INDEX "IDX_6e1df243476e20cbf86572ecc0"`);
await queryRunner.query(`DROP INDEX "IDX_7a170f67425e62a8fabb76c872"`);
await queryRunner.query(`DROP INDEX "IDX_3fa0d0f17ca72e3dc80999a032"`);
await queryRunner.query(`DROP INDEX "IDX_13565815f618a1ff53886c5b28"`);
await queryRunner.query(`DROP INDEX "IDX_c26e2c1cbb6e911e0554b27416"`);
await queryRunner.query(`DROP INDEX "IDX_9a3ed15a30ab7e3a37702e6e08"`);
await queryRunner.query(`DROP INDEX "IDX_20f57cc8f142c131340ee16742"`);
await queryRunner.query(`DROP INDEX "IDX_00ed5f86db1f7efafb1978bf21"`);
await queryRunner.query(`DROP INDEX "IDX_15e91a03aeeac9dbccdf43fc06"`);
await queryRunner.query(`DROP INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc"`);
await queryRunner.query(`DROP INDEX "IDX_90148bbc2bf0854428786bfc15"`);
await queryRunner.query(`DROP INDEX "IDX_88937d94d7443d9a99a76fa5c0"`);
await queryRunner.query(`DROP INDEX "IDX_54ebcb6d27222913b908d56fd8"`);
await queryRunner.query(`DROP INDEX "IDX_796a8c03959361f97dc2be1d5c"`);
await queryRunner.query(`DROP INDEX "IDX_25dfc71b0369b003a4cd434d0b"`);
await queryRunner.query(`DROP INDEX "IDX_51c063b6a133a9cb87145450f5"`);
await queryRunner.query(`DROP INDEX "IDX_fa99d777623947a5b05f394cae"`);
await queryRunner.query(`DROP INDEX "IDX_315c779174fe8247ab324f036e"`);
await queryRunner.query(`DROP INDEX "IDX_c5d46cbfda48b1c33ed852e21b"`);
await queryRunner.query(`DROP INDEX "IDX_8cb40cfc8f3c28261e6f887b03"`);
}
}

View File

@@ -1,7 +1,7 @@
import * as fs from 'fs';
import config from './config';
const config = require('./built/config').default;
const entities = require('./built/db/postgre').entities;
const json = {
module.exports = {
type: 'postgres',
host: config.db.host,
port: config.db.port,
@@ -9,11 +9,9 @@ const json = {
password: config.db.pass,
database: config.db.db,
extra: config.db.extra,
entities: ['src/models/entities/*.ts'],
entities: entities,
migrations: ['migration/*.ts'],
cli: {
migrationsDir: 'migration'
}
};
fs.writeFileSync('ormconfig.json', JSON.stringify(json));

View File

@@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "11.20.0",
"version": "11.24.0",
"codename": "daybreak",
"repository": {
"type": "git",
@@ -11,9 +11,9 @@
"private": true,
"scripts": {
"start": "node ./index.js",
"init": "node ./built/init.js",
"init": "npm run migrate",
"ormconfig": "node ./built/ormconfig.js",
"migrate": "npm run ormconfig && ts-node ./node_modules/typeorm/cli.js migration:run",
"migrate": "ts-node ./node_modules/typeorm/cli.js migration:run",
"migrateandstart": "npm run migrate && npm run start",
"build": "webpack && gulp build",
"webpack": "webpack",
@@ -25,106 +25,114 @@
"test": "gulp test",
"format": "gulp format"
},
"resolutions": {
"gulp-cssnano/cssnano/postcss-svgo/svgo/js-yaml": "^3.13.1",
"video-thumbnail-generator/lodash": "^4.17.11"
},
"dependencies": {
"@elastic/elasticsearch": "7.0.0-rc.2",
"@fortawesome/fontawesome-svg-core": "1.2.15",
"@fortawesome/free-brands-svg-icons": "5.7.2",
"@fortawesome/free-regular-svg-icons": "5.7.2",
"@fortawesome/free-solid-svg-icons": "5.7.2",
"@fortawesome/vue-fontawesome": "0.1.5",
"@koa/cors": "2.2.3",
"@elastic/elasticsearch": "7.1.0",
"@fortawesome/fontawesome-svg-core": "1.2.19",
"@fortawesome/free-brands-svg-icons": "5.9.0",
"@fortawesome/free-regular-svg-icons": "5.9.0",
"@fortawesome/free-solid-svg-icons": "5.9.0",
"@fortawesome/vue-fontawesome": "0.1.6",
"@koa/cors": "3.0.0",
"@typescript-eslint/parser": "1.11.0",
"@types/bcryptjs": "2.4.2",
"@types/bull": "3.5.11",
"@types/bull": "3.5.15",
"@types/cbor": "2.0.0",
"@types/dateformat": "3.0.0",
"@types/deep-equal": "1.0.1",
"@types/double-ended-queue": "2.1.0",
"@types/double-ended-queue": "2.1.1",
"@types/gulp": "4.0.6",
"@types/gulp-mocha": "0.0.32",
"@types/gulp-rename": "0.0.33",
"@types/gulp-replace": "0.0.31",
"@types/gulp-uglify": "3.0.6",
"@types/gulp-util": "3.0.34",
"@types/is-root": "1.0.0",
"@types/is-root": "2.1.2",
"@types/is-url": "1.2.28",
"@types/js-yaml": "3.12.1",
"@types/jsdom": "12.2.3",
"@types/jsdom": "12.2.4",
"@types/katex": "0.10.1",
"@types/koa": "2.0.48",
"@types/koa": "2.0.49",
"@types/koa-bodyparser": "5.0.2",
"@types/koa-compress": "2.0.9",
"@types/koa-cors": "0.0.0",
"@types/koa-favicon": "2.0.19",
"@types/koa-logger": "3.1.1",
"@types/koa-mount": "3.0.1",
"@types/koa-mount": "4.0.0",
"@types/koa-multer": "1.0.0",
"@types/koa-router": "7.0.40",
"@types/koa-router": "7.0.42",
"@types/koa-send": "4.1.2",
"@types/koa-views": "2.0.3",
"@types/koa__cors": "2.2.3",
"@types/lolex": "3.1.1",
"@types/minio": "7.0.1",
"@types/mocha": "5.2.6",
"@types/node": "11.13.8",
"@types/nodemailer": "4.6.8",
"@types/nprogress": "0.0.29",
"@types/minio": "7.0.2",
"@types/mocha": "5.2.7",
"@types/node": "12.0.10",
"@types/nodemailer": "6.2.0",
"@types/nprogress": "0.2.0",
"@types/oauth": "0.9.1",
"@types/parse5": "5.0.0",
"@types/parsimmon": "1.10.0",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.3.2",
"@types/qrcode": "1.3.3",
"@types/random-seed": "0.3.3",
"@types/ratelimiter": "2.1.28",
"@types/redis": "2.8.12",
"@types/redis": "2.8.13",
"@types/rename": "1.0.1",
"@types/request": "2.48.1",
"@types/request-promise-native": "1.0.16",
"@types/request-stats": "3.0.0",
"@types/rimraf": "2.0.2",
"@types/seedrandom": "2.4.28",
"@types/sharp": "0.22.1",
"@types/showdown": "1.9.2",
"@types/sharp": "0.22.2",
"@types/showdown": "1.9.3",
"@types/speakeasy": "2.0.4",
"@types/systeminformation": "3.23.1",
"@types/tinycolor2": "1.4.1",
"@types/tinycolor2": "1.4.2",
"@types/tmp": "0.1.0",
"@types/uuid": "3.4.4",
"@types/uuid": "3.4.5",
"@types/web-push": "3.3.0",
"@types/webpack": "4.4.29",
"@types/webpack": "4.4.34",
"@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.40",
"@types/ws": "6.0.1",
"animejs": "3.0.1",
"apexcharts": "3.6.12",
"apexcharts": "3.8.1",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autwh": "0.1.0",
"bcryptjs": "2.4.3",
"bootstrap": "4.3.1",
"bootstrap-vue": "2.0.0-rc.13",
"bull": "3.9.1",
"bull": "3.10.0",
"cafy": "15.1.1",
"cbor": "4.1.5",
"chai": "4.2.0",
"chalk": "2.4.2",
"cli-highlight": "2.1.1",
"commander": "2.20.0",
"content-disposition": "0.5.3",
"crc-32": "1.2.0",
"css-loader": "2.1.1",
"css-loader": "3.0.0",
"cssnano": "4.1.10",
"dateformat": "3.0.3",
"deep-equal": "1.0.1",
"diskusage": "1.1.1",
"diskusage": "1.1.2",
"double-ended-queue": "2.1.0-0",
"emojilib": "2.4.0",
"eslint": "5.16.0",
"eslint-plugin-vue": "5.2.2",
"eventemitter3": "3.1.2",
"feed": "2.0.4",
"file-type": "10.11.0",
"eslint": "6.0.1",
"eslint-plugin-vue": "5.2.3",
"eventemitter3": "4.0.0",
"feed": "3.0.0",
"file-type": "12.0.0",
"fuckadblock": "3.2.1",
"gulp": "4.0.2",
"gulp-cssnano": "2.1.3",
"gulp-imagemin": "5.0.3",
"gulp-imagemin": "6.0.0",
"gulp-mocha": "6.0.0",
"gulp-rename": "1.4.0",
"gulp-replace": "1.0.0",
@@ -139,12 +147,13 @@
"http-signature": "1.2.0",
"insert-text-at-cursor": "0.2.0",
"is-root": "2.1.0",
"is-svg": "4.1.0",
"is-svg": "4.2.0",
"js-yaml": "3.13.1",
"jsdom": "15.1.0",
"jsdom": "15.1.1",
"json5": "2.1.0",
"json5-loader": "2.0.0",
"katex": "0.10.1",
"json5-loader": "3.0.0",
"jsrsasign": "8.0.12",
"katex": "0.10.2",
"koa": "2.7.0",
"koa-bodyparser": "4.2.1",
"koa-compress": "3.0.0",
@@ -159,16 +168,16 @@
"koa-views": "6.2.0",
"langmap": "0.0.16",
"loader-utils": "1.2.3",
"lolex": "3.1.0",
"lolex": "4.1.0",
"lookup-dns-cache": "2.1.0",
"minio": "7.0.8",
"minio": "7.0.10",
"mocha": "6.1.4",
"moji": "0.5.1",
"moment": "2.24.0",
"ms": "2.1.1",
"nested-property": "0.0.7",
"node-fetch": "2.5.0",
"nodemailer": "6.1.1",
"ms": "2.1.2",
"nested-property": "1.0.1",
"node-fetch": "2.6.0",
"nodemailer": "6.2.1",
"nprogress": "0.2.0",
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
@@ -182,7 +191,7 @@
"promise-any": "0.2.0",
"promise-limit": "2.7.0",
"promise-sequential": "1.1.1",
"pug": "2.0.3",
"pug": "2.0.4",
"punycode": "2.1.1",
"pureimage": "0.1.6",
"qrcode": "1.3.3",
@@ -206,27 +215,26 @@
"showdown": "1.9.0",
"showdown-highlightjs-extension": "0.1.2",
"speakeasy": "2.0.0",
"stringz": "1.0.0",
"stringz": "2.0.0",
"style-loader": "0.23.1",
"stylus": "0.54.5",
"stylus-loader": "3.0.2",
"summaly": "2.2.0",
"systeminformation": "4.1.6",
"summaly": "2.3.0",
"systeminformation": "4.13.1",
"syuilo-password-strength": "0.0.1",
"terser-webpack-plugin": "1.2.4",
"terser-webpack-plugin": "1.3.0",
"textarea-caret": "3.1.0",
"tinycolor2": "1.4.1",
"tmp": "0.1.0",
"ts-loader": "5.3.3",
"ts-node": "7.0.1",
"tslint": "5.15.0",
"tslint": "5.18.0",
"tslint-sonarts": "1.9.0",
"typeorm": "0.2.16-rc.1",
"typescript": "3.3.3333",
"typescript-eslint-parser": "22.0.0",
"typeorm": "0.2.18",
"typescript": "3.5.2",
"uglify-es": "3.3.9",
"ulid": "2.3.0",
"url-loader": "1.1.2",
"url-loader": "2.0.1",
"uuid": "3.3.2",
"v-animate-css": "0.0.3",
"v-debounce": "0.1.2",
@@ -234,7 +242,7 @@
"vue": "2.6.10",
"vue-color": "2.7.0",
"vue-content-loading": "1.6.0",
"vue-cropperjs": "3.0.0",
"vue-cropperjs": "4.0.0",
"vue-i18n": "8.11.2",
"vue-js-modal": "1.3.31",
"vue-json-pretty": "1.6.0",
@@ -244,17 +252,17 @@
"vue-router": "3.0.6",
"vue-sequential-entrance": "1.1.3",
"vue-style-loader": "4.1.2",
"vue-svg-inline-loader": "1.2.15",
"vue-svg-inline-loader": "1.2.16",
"vue-template-compiler": "2.6.10",
"vuedraggable": "2.21.0",
"vuedraggable": "2.23.0",
"vuewordcloud": "18.7.11",
"vuex": "3.1.1",
"vuex-persistedstate": "2.5.4",
"web-push": "3.3.5",
"webpack": "4.32.2",
"webpack-cli": "3.3.2",
"webpack": "4.35.2",
"webpack-cli": "3.3.5",
"websocket": "1.0.28",
"ws": "7.0.0",
"ws": "7.0.1",
"xev": "2.0.1"
}
}

803
src/@types/jsrsasign.d.ts vendored Normal file
View File

@@ -0,0 +1,803 @@
// Attention: Partial Type Definition
declare module 'jsrsasign' {
//// HELPER TYPES
/**
* Attention: The value might be changed by the function.
*/
type Mutable<T> = T;
/**
* Deprecated: The function might be deleted in future release.
*/
type Deprecated<T> = T;
//// COMMON TYPES
/**
* byte number
*/
type ByteNumber = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255;
/**
* hexadecimal string /[0-9A-F]/
*/
type HexString = string;
/**
* binary string /[01]/
*/
type BinString = string;
/**
* base64 string /[A-Za-z0-9+/]=+/
*/
type Base64String = string;
/**
* base64 URL encoded string /[A-Za-z0-9_-]/
*/
type Base64URLString = string;
/**
* time value (ex. "151231235959Z")
*/
type TimeValue = string;
/**
* OID string (ex. '1.2.3.4.567')
*/
type OID = string;
/**
* OID name
*/
type OIDName = string;
/**
* PEM formatted string
*/
type PEM = string;
//// ASN1 TYPES
class ASN1Object {
public isModified: boolean;
public hTLV: ASN1TLV;
public hT: ASN1T;
public hL: ASN1L;
public hV: ASN1V;
public getLengthHexFromValue(): HexString;
public getEncodedHex(): ASN1TLV;
public getValueHex(): ASN1V;
public getFreshValueHex(): ASN1V;
}
class DERAbstractStructured extends ASN1Object {
constructor(params?: Partial<Record<'array', ASN1Object[]>>);
public setByASN1ObjectArray(asn1ObjectArray: ASN1Object[]): void;
public appendASN1Object(asn1Object: ASN1Object): void;
}
class DERSequence extends DERAbstractStructured {
constructor(params?: Partial<Record<'array', ASN1Object[]>>);
public getFreshValueHex(): ASN1V;
}
//// ASN1HEX TYPES
/**
* ASN.1 DER encoded data (hexadecimal string)
*/
type ASN1S = HexString;
/**
* index of something
*/
type Idx<T extends { [idx: string]: unknown } | { [idx: number]: unknown }> = ASN1S extends { [idx: string]: unknown } ? string : ASN1S extends { [idx: number]: unknown } ? number : never;
/**
* byte length of something
*/
type ByteLength<T extends { length: unknown }> = T['length'];
/**
* ASN.1 L(length) (hexadecimal string)
*/
type ASN1L = HexString;
/**
* ASN.1 T(tag) (hexadecimal string)
*/
type ASN1T = HexString;
/**
* ASN.1 V(value) (hexadecimal string)
*/
type ASN1V = HexString;
/**
* ASN.1 TLV (hexadecimal string)
*/
type ASN1TLV = HexString;
/**
* ASN.1 object string
*/
type ASN1ObjectString = string;
/**
* nth
*/
type Nth = number;
/**
* ASN.1 DER encoded OID value (hexadecimal string)
*/
type ASN1OIDV = HexString;
class ASN1HEX {
public static getLblen(s: ASN1S, idx: Idx<ASN1S>): ByteLength<ASN1L>;
public static getL(s: ASN1S, idx: Idx<ASN1S>): ASN1L;
public static getVblen(s: ASN1S, idx: Idx<ASN1S>): ByteLength<ASN1V>;
public static getVidx(s: ASN1S, idx: Idx<ASN1S>): Idx<ASN1V>;
public static getV(s: ASN1S, idx: Idx<ASN1S>): ASN1V;
public static getTLV(s: ASN1S, idx: Idx<ASN1S>): ASN1TLV;
public static getNextSiblingIdx(s: ASN1S, idx: Idx<ASN1S>): Idx<ASN1ObjectString>;
public static getChildIdx(h: ASN1S, pos: Idx<ASN1S>): Idx<ASN1ObjectString>[];
public static getNthChildIdx(h: ASN1S, idx: Idx<ASN1S>, nth: Nth): Idx<ASN1ObjectString>;
public static getIdxbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string): Idx<Mutable<Nth[]>>;
public static getTLVbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string): ASN1TLV;
public static getVbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string, removeUnusedbits?: boolean): ASN1V;
public static hextooidstr(hex: ASN1OIDV): OID;
public static dump(hexOrObj: ASN1S | ASN1Object, flags?: Record<string, unknown>, idx?: Idx<ASN1S>, indent?: string): string;
public static isASN1HEX(hex: string): hex is HexString;
public static oidname(oidDotOrHex: OID | ASN1OIDV): OIDName;
}
//// BIG INTEGER TYPES (PARTIAL)
class BigInteger {
constructor(a: null);
constructor(a: number, b: SecureRandom);
constructor(a: number, b: number, c: SecureRandom);
constructor(a: unknown);
constructor(a: string, b: number);
public am(i: number, x: number, w: number, j: number, c: number, n: number): number;
public DB: number;
public DM: number;
public DV: number;
public FV: number;
public F1: number;
public F2: number;
protected copyTo(r: Mutable<BigInteger>): void;
protected fromInt(x: number): void;
protected fromString(s: string, b: number): void;
protected clamp(): void;
public toString(b: number): string;
public negate(): BigInteger;
public abs(): BigInteger;
public compareTo(a: BigInteger): number;
public bitLength(): number;
protected dlShiftTo(n: number, r: Mutable<BigInteger>): void;
protected drShiftTo(n: number, r: Mutable<BigInteger>): void;
protected lShiftTo(n: number, r: Mutable<BigInteger>): void;
protected rShiftTo(n: number, r: Mutable<BigInteger>): void;
protected subTo(a: BigInteger, r: Mutable<BigInteger>): void;
protected multiplyTo(a: BigInteger, r: Mutable<BigInteger>): void;
protected squareTo(r: Mutable<BigInteger>): void;
protected divRemTo(m: BigInteger, q: Mutable<BigInteger>, r: Mutable<BigInteger>): void;
public mod(a: BigInteger): BigInteger;
protected invDigit(): number;
protected isEven(): boolean;
protected exp(e: number, z: Classic | Montgomery): BigInteger;
public modPowInt(e: number, m: BigInteger): BigInteger;
public static ZERO: BigInteger;
public static ONE: BigInteger;
}
class Classic {
constructor(m: BigInteger);
public convert(x: BigInteger): BigInteger;
public revert(x: BigInteger): BigInteger;
public reduce(x: Mutable<BigInteger>): void;
public mulTo(x: BigInteger, r: Mutable<BigInteger>): void;
public sqrTo(x: BigInteger, y: BigInteger, r: Mutable<BigInteger>): void;
}
class Montgomery {
constructor(m: BigInteger);
public convert(x: BigInteger): BigInteger;
public revert(x: BigInteger): BigInteger;
public reduce(x: Mutable<BigInteger>): void;
public mulTo(x: BigInteger, r: Mutable<BigInteger>): void;
public sqrTo(x: BigInteger, y: BigInteger, r: Mutable<BigInteger>): void;
}
//// KEYUTIL TYPES
type DecryptAES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
type Decrypt3DES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
type DecryptDES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
type EncryptAES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
type Encrypt3DES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
type EncryptDES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
type AlgList = {
'AES-256-CBC': { 'proc': DecryptAES; 'eproc': EncryptAES; keylen: 32; ivlen: 16; };
'AES-192-CBC': { 'proc': DecryptAES; 'eproc': EncryptAES; keylen: 24; ivlen: 16; };
'AES-128-CBC': { 'proc': DecryptAES; 'eproc': EncryptAES; keylen: 16; ivlen: 16; };
'DES-EDE3-CBC': { 'proc': Decrypt3DES; 'eproc': Encrypt3DES; keylen: 24; ivlen: 8; };
'DES-CBC': { 'proc': DecryptDES; 'eproc': EncryptDES; keylen: 8; ivlen: 8; };
};
type AlgName = keyof AlgList;
type PEMHeadAlgName = 'RSA' | 'EC' | 'DSA';
type GetKeyRSAParam = RSAKey | {
n: BigInteger;
e: number;
} | Record<'n' | 'e', HexString> | Record<'n' | 'e', HexString> & Record<'d' | 'p' | 'q' | 'dp' | 'dq' | 'co', HexString | null> | {
n: BigInteger;
e: number;
d: BigInteger;
} | {
kty: 'RSA';
} & Record<'n' | 'e', Base64URLString> | {
kty: 'RSA';
} & Record<'n' | 'e' | 'd' | 'p' | 'q' | 'dp' | 'dq' | 'qi', Base64URLString> | {
kty: 'RSA';
} & Record<'n' | 'e' | 'd', Base64URLString>;
type GetKeyECDSAParam = KJUR.crypto.ECDSA | {
curve: KJUR.crypto.CurveName;
xy: HexString;
} | {
curve: KJUR.crypto.CurveName;
d: HexString;
} | {
kty: 'EC';
crv: KJUR.crypto.CurveName;
x: Base64URLString;
y: Base64URLString;
} | {
kty: 'EC';
crv: KJUR.crypto.CurveName;
x: Base64URLString;
y: Base64URLString;
d: Base64URLString;
};
type GetKeyDSAParam = KJUR.crypto.DSA | Record<'p' | 'q' | 'g', BigInteger> & Record<'y', BigInteger | null> | Record<'p' | 'q' | 'g' | 'x', BigInteger> & Record<'y', BigInteger | null>;
type GetKeyParam = GetKeyRSAParam | GetKeyECDSAParam | GetKeyDSAParam | string;
class KEYUTIL {
public version: '1.0.0';
public parsePKCS5PEM(sPKCS5PEM: PEM): Partial<Record<'type' | 's', string>> & (Record<'cipher' | 'ivsalt', string> | Record<'cipher' | 'ivsalt', undefined>);
public getKeyAndUnusedIvByPasscodeAndIvsalt(algName: AlgName, passcode: string, ivsaltHex: HexString): Record<'keyhex' | 'ivhex', HexString>;
public decryptKeyB64(privateKeyB64: Base64String, sharedKeyAlgName: AlgName, sharedKeyHex: HexString, ivsaltHex: HexString): Base64String;
public getDecryptedKeyHex(sEncryptedPEM: PEM, passcode: string): HexString;
public getEncryptedPKCS5PEMFromPrvKeyHex(pemHeadAlg: PEMHeadAlgName, hPrvKey: string, passcode: string, sharedKeyAlgName?: AlgName | null, ivsaltHex?: HexString | null): PEM;
public parseHexOfEncryptedPKCS8(sHEX: HexString): {
ciphertext: ASN1V;
encryptionSchemeAlg: 'TripleDES';
encryptionSchemeIV: ASN1V;
pbkdf2Salt: ASN1V;
pbkdf2Iter: number;
};
public getPBKDF2KeyHexFromParam(info: ReturnType<this['parseHexOfEncryptedPKCS8']>, passcode: string): HexString;
private _getPlainPKCS8HexFromEncryptedPKCS8PEM(pkcs8PEM: PEM, passcode: string): HexString;
public getKeyFromEncryptedPKCS8PEM(prvKeyHex: HexString): ReturnType<this['getKeyFromPlainPrivatePKCS8Hex']>;
public parsePlainPrivatePKCS8Hex(pkcs8PrvHex: HexString): {
algparam: ASN1V | null;
algoid: ASN1V;
keyidx: Idx<ASN1V>;
};
public getKeyFromPlainPrivatePKCS8PEM(prvKeyHex: HexString): ReturnType<this['getKeyFromPlainPrivatePKCS8Hex']>;
public getKeyFromPlainPrivatePKCS8Hex(prvKeyHex: HexString): RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA;
private _getKeyFromPublicPKCS8Hex(h: HexString): RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA;
public parsePublicRawRSAKeyHex(pubRawRSAHex: HexString): Record<'n' | 'e', ASN1V>;
public parsePublicPKCS8Hex(pkcs8PubHex: HexString): {
algparam: ASN1V | Record<'p' | 'q' | 'g', ASN1V> | null;
algoid: ASN1V;
key: ASN1V;
};
public static getKey(param: GetKeyRSAParam): RSAKey;
public static getKey(param: GetKeyECDSAParam): KJUR.crypto.ECDSA;
public static getKey(param: GetKeyDSAParam): KJUR.crypto.DSA;
public static getKey(param: string, passcode?: string, hextype?: string): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
public static generateKeypair(alg: 'RSA', keylen: number): Record<'prvKeyObj' | 'pubKeyObj', RSAKey>;
public static generateKeypair(alg: 'EC', curve: KJUR.crypto.CurveName): Record<'prvKeyObj' | 'pubKeyObj', KJUR.crypto.ECDSA>;
public static getPEM(keyObjOrHex: RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA, formatType?: 'PKCS1PRV' | 'PKCS5PRV' | 'PKCS8PRV', passwd?: string, encAlg?: 'DES-CBC' | 'DES-EDE3-CBC' | 'AES-128-CBC' | 'AES-192-CBC' | 'AES-256-CBC', hexType?: string, ivsaltHex?: HexString): object; // To Do
public static getKeyFromCSRPEM(csrPEM: PEM): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
public static getKeyFromCSRHex(csrHex: HexString): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
public static parseCSRHex(csrHex: HexString): Record<'p8pubkeyhex', ASN1TLV>;
public static getJWKFromKey(keyObj: RSAKey): {
kty: 'RSA';
} & Record<'n' | 'e' | 'd' | 'p' | 'q' | 'dp' | 'dq' | 'qi', Base64URLString> | {
kty: 'RSA';
} & Record<'n' | 'e', Base64URLString>;
public static getJWKFromKey(keyObj: KJUR.crypto.ECDSA): {
kty: 'EC';
crv: KJUR.crypto.CurveName;
x: Base64URLString;
y: Base64URLString;
d: Base64URLString;
} | {
kty: 'EC';
crv: KJUR.crypto.CurveName;
x: Base64URLString;
y: Base64URLString;
};
}
//// KJUR NAMESPACE (PARTIAL)
namespace KJUR {
namespace crypto {
type CurveName = 'secp128r1' | 'secp160k1' | 'secp160r1' | 'secp192k1' | 'secp192r1' | 'secp224r1' | 'secp256k1' | 'secp256r1' | 'secp384r1' | 'secp521r1';
class DSA {
public p: BigInteger | null;
public q: BigInteger | null;
public g: BigInteger | null;
public y: BigInteger | null;
public x: BigInteger | null;
public type: 'DSA';
public isPrivate: boolean;
public isPublic: boolean;
public setPrivate(p: BigInteger, q: BigInteger, g: BigInteger, y: BigInteger | null, x: BigInteger): void;
public setPrivateHex(hP: HexString, hQ: HexString, hG: HexString, hY: HexString | null, hX: HexString): void;
public setPublic(p: BigInteger, q: BigInteger, g: BigInteger, y: BigInteger): void;
public setPublicHex(hP: HexString, hQ: HexString, hG: HexString, hY: HexString): void;
public signWithMessageHash(sHashHex: HexString): HexString;
public verifyWithMessageHash(sHashHex: HexString, hSigVal: HexString): boolean;
public parseASN1Signature(hSigVal: HexString): [BigInteger, BigInteger];
public readPKCS5PrvKeyHex(h: HexString): void;
public readPKCS8PrvKeyHex(h: HexString): void;
public readPKCS8PubKeyHex(h: HexString): void;
public readCertPubKeyHex(h: HexString, nthPKI: number): void;
}
class ECDSA {
constructor(params?: {
curve?: CurveName;
prv?: HexString;
pub?: HexString;
});
public p: BigInteger | null;
public q: BigInteger | null;
public g: BigInteger | null;
public y: BigInteger | null;
public x: BigInteger | null;
public type: 'EC';
public isPrivate: boolean;
public isPublic: boolean;
public getBigRandom(limit: BigInteger): BigInteger;
public setNamedCurve(curveName: CurveName): void;
public setPrivateKeyHex(prvKeyHex: HexString): void;
public setPublicKeyHex(pubKeyHex: HexString): void;
public getPublicKeyXYHex(): Record<'x' | 'y', HexString>;
public getShortNISTPCurveName(): 'P-256' | 'P-384' | null;
public generateKeyPairHex(): Record<'ecprvhex' | 'ecpubhex', HexString>;
public signWithMessageHash(hashHex: HexString): HexString;
public signHex(hashHex: HexString, privHex: HexString): HexString;
public verifyWithMessageHash(sHashHex: HexString, hSigVal: HexString): boolean;
public parseASN1Signature(hSigVal: HexString): [BigInteger, BigInteger];
public readPKCS5PrvKeyHex(h: HexString): void;
public readPKCS8PrvKeyHex(h: HexString): void;
public readPKCS8PubKeyHex(h: HexString): void;
public readCertPubKeyHex(h: HexString, nthPKI: number): void;
public static parseSigHex(sigHex: HexString): Record<'r' | 's', BigInteger>;
public static parseSigHexInHexRS(sigHex: HexString): Record<'r' | 's', ASN1V>;
public static asn1SigToConcatSig(asn1Sig: HexString): HexString;
public static concatSigToASN1Sig(concatSig: HexString): ASN1TLV;
public static hexRSSigToASN1Sig(hR: HexString, hS: HexString): ASN1TLV;
public static biRSSigToASN1Sig(biR: BigInteger, biS: BigInteger): ASN1TLV;
public static getName(s: CurveName | HexString): 'secp256r1' | 'secp256k1' | 'secp384r1' | null;
}
class Signature {
constructor(params?: ({
alg: string;
prov?: string;
} | {}) & ({
psssaltlen: number;
} | {}) & ({
prvkeypem: PEM;
prvkeypas?: never;
} | {}));
private _setAlgNames(): void;
private _zeroPaddingOfSignature(hex: HexString, bitLength: number): HexString;
public setAlgAndProvider(alg: string, prov: string): void;
public init(key: GetKeyParam, pass?: string): void;
public updateString(str: string): void;
public updateHex(hex: HexString): void;
public sign(): HexString;
public signString(str: string): HexString;
public signHex(hex: HexString): HexString;
public verify(hSigVal: string): boolean | 0;
}
}
}
//// RSAKEY TYPES
class RSAKey {
public n: BigInteger | null;
public e: number;
public d: BigInteger | null;
public p: BigInteger | null;
public q: BigInteger | null;
public dmp1: BigInteger | null;
public dmq1: BigInteger | null;
public coeff: BigInteger | null;
public type: 'RSA';
public isPrivate?: boolean;
public isPublic?: boolean;
//// RSA PUBLIC
protected doPublic(x: BigInteger): BigInteger;
public setPublic(N: BigInteger, E: number): void;
public setPublic(N: HexString, E: HexString): void;
public encrypt(text: string): HexString | null;
public encryptOAEP(text: string, hash?: string, hashLen?: number): HexString | null;
public encryptOAEP(text: string, hash?: (s: string) => string, hashLen?: number): HexString | null;
//// RSA PRIVATE
protected doPrivate(x: BigInteger): BigInteger;
public setPrivate(N: BigInteger, E: number, D: BigInteger): void;
public setPrivate(N: HexString, E: HexString, D: HexString): void;
public setPrivateEx(N: HexString, E: HexString, D?: HexString | null, P?: HexString | null, Q?: HexString | null, DP?: HexString | null, DQ?: HexString | null, C?: HexString | null): void;
public generate(B: number, E: HexString): void;
public decrypt(ctext: HexString): string;
public decryptOAEP(ctext: HexString, hash?: string, hashLen?: number): string | null;
public encryptOAEP(ctext: HexString, hash?: (s: string) => string, hashLen?: number): string | null;
//// RSA PEM
public getPosArrayOfChildrenFromHex(hPrivateKey: PEM): Idx<ASN1ObjectString>[];
public getHexValueArrayOfChildrenFromHex(hPrivateKey: PEM): Idx<ASN1ObjectString>[];
public readPrivateKeyFromPEMString(keyPEM: PEM): void;
public readPKCS5PrvKeyHex(h: HexString): void;
public readPKCS8PrvKeyHex(h: HexString): void;
public readPKCS5PubKeyHex(h: HexString): void;
public readPKCS8PubKeyHex(h: HexString): void;
public readCertPubKeyHex(h: HexString, nthPKI: Nth): void;
//// RSA SIGN
public sign(s: string, hashAlg: string): HexString;
public signWithMessageHash(sHashHex: HexString, hashAlg: string): HexString;
public signPSS(s: string, hashAlg: string, sLen: number): HexString;
public signWithMessageHashPSS(hHash: HexString, hashAlg: string, sLen: number): HexString;
public verify(sMsg: string, hSig: HexString): boolean | 0;
public verifyWithMessageHash(sHashHex: HexString, hSig: HexString): boolean | 0;
public verifyPSS(sMsg: string, hSig: HexString, hashAlg: string, sLen: number): boolean;
public verifyWithMessageHashPSS(hHash: HexString, hSig: HexString, hashAlg: string, sLen: number): boolean;
public static SALT_LEN_HLEN: -1;
public static SALT_LEN_MAX: -2;
public static SALT_LEN_RECOVER: -2;
}
/// RNG TYPES
class SecureRandom {
public nextBytes(ba: Mutable<ByteNumber[]>): void;
}
//// X509 TYPES
type ExtInfo = {
critical: boolean;
oid: OID;
vidx: Idx<ASN1V>;
};
type ExtAIAInfo = Record<'ocsp' | 'caissuer', string>;
type ExtCertificatePolicy = {
id: OIDName;
} & Partial<{
cps: string;
} | {
unotice: string;
}>;
class X509 {
public hex: HexString | null;
public version: number;
public foffset: number;
public aExtInfo: null;
public getVersion(): number;
public getSerialNumberHex(): ASN1V;
public getSignatureAlgorithmField(): OIDName;
public getIssuerHex(): ASN1TLV;
public getIssuerString(): HexString;
public getSubjectHex(): ASN1TLV;
public getSubjectString(): HexString;
public getNotBefore(): TimeValue;
public getNotAfter(): TimeValue;
public getPublicKeyHex(): ASN1TLV;
public getPublicKeyIdx(): Idx<Mutable<Nth[]>>;
public getPublicKeyContentIdx(): Idx<Mutable<Nth[]>>;
public getPublicKey(): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
public getSignatureAlgorithmName(): OIDName;
public getSignatureValueHex(): ASN1V;
public verifySignature(pubKey: GetKeyParam): boolean | 0;
public parseExt(): void;
public getExtInfo(oidOrName: OID | string): ExtInfo | undefined;
public getExtBasicConstraints(): ExtInfo | {} | {
cA: true;
pathLen?: number;
};
public getExtKeyUsageBin(): BinString;
public getExtKeyUsageString(): string;
public getExtSubjectKeyIdentifier(): ASN1V | undefined;
public getExtAuthorityKeyIdentifier(): {
kid: ASN1V;
} | undefined;
public getExtExtKeyUsageName(): OIDName[] | undefined;
public getExtSubjectAltName(): Deprecated<string[]>;
public getExtSubjectAltName2(): ['MAIL' | 'DNS' | 'DN' | 'URI' | 'IP', string][] | undefined;
public getExtCRLDistributionPointsURI(): string[] | undefined;
public getExtAIAInfo(): ExtAIAInfo | undefined;
public getExtCertificatePolicies(): ExtCertificatePolicy[] | undefined;
public readCertPEM(sCertPEM: PEM): void;
public readCertHex(sCertHex: HexString): void;
public getInfo(): string;
public static hex2dn(hex: HexString, idx?: Idx<HexString>): string;
public static hex2rdn(hex: HexString, idx?: Idx<HexString>): string;
public static hex2attrTypeValue(hex: HexString, idx?: Idx<HexString>): string;
public static getPublicKeyFromCertPEM(sCertPEM: PEM): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
public static getPublicKeyInfoPropOfCertPEM(sCertPEM: PEM): {
algparam: ASN1V | null;
leyhex: ASN1V;
algoid: ASN1V;
};
}
}

View File

@@ -79,6 +79,7 @@ export async function masterMain() {
require('../daemons/server-stats').default();
require('../daemons/notes-stats').default();
require('../daemons/queue-stats').default();
require('../daemons/janitor').default();
}
bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, null, true);

View File

@@ -124,7 +124,7 @@ export default Vue.extend({
this.connection = this.$root.stream.useSharedConnection('serverStats');
this.updateStats();
this.clock = setInterval(this.updateStats, 1000);
this.clock = setInterval(this.updateStats, 3000);
this.$root.getMeta().then(meta => {
this.meta = meta;

View File

@@ -0,0 +1,61 @@
<template>
<div>
<ui-card>
<template #title><fa :icon="faDatabase"/> {{ $t('tables') }}</template>
<section v-if="tables">
<div v-for="table in Object.keys(tables)"><b>{{ table }}</b> {{ tables[table].count | number }} {{ tables[table].size | bytes }}</div>
</section>
<section>
<header><fa :icon="faBroom"/> {{ $t('vacuum') }}</header>
<ui-info>{{ $t('vacuum-info') }}</ui-info>
<ui-switch v-model="fullVacuum">FULL</ui-switch>
<ui-switch v-model="analyzeVacuum">ANALYZE</ui-switch>
<ui-button @click="vacuum()"><fa :icon="faBroom"/> {{ $t('vacuum') }}</ui-button>
<ui-info warn>{{ $t('vacuum-exclamation') }}</ui-info>
</section>
</ui-card>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import i18n from '../../i18n';
import { faDatabase, faBroom } from '@fortawesome/free-solid-svg-icons';
export default Vue.extend({
i18n: i18n('admin/views/db.vue'),
data() {
return {
tables: null,
fullVacuum: true,
analyzeVacuum: true,
faDatabase, faBroom
};
},
mounted() {
this.fetch();
},
methods: {
fetch() {
this.$root.api('admin/get-table-stats').then(tables => {
this.tables = tables;
});
},
vacuum() {
this.$root.api('admin/vacuum', {
full: this.fullVacuum,
analyze: this.analyzeVacuum,
}).then(() => {
this.$root.dialog({
type: 'success',
splash: true
});
});
},
}
});
</script>

View File

@@ -22,6 +22,7 @@
<li @click="nav('instance')" :class="{ active: page == 'instance' }"><fa icon="cog" fixed-width/>{{ $t('instance') }}</li>
<li @click="nav('queue')" :class="{ active: page == 'queue' }"><fa :icon="faTasks" fixed-width/>{{ $t('queue') }}</li>
<li @click="nav('logs')" :class="{ active: page == 'logs' }"><fa :icon="faStream" fixed-width/>{{ $t('logs') }}</li>
<li @click="nav('db')" :class="{ active: page == 'db' }"><fa :icon="faDatabase" fixed-width/>{{ $t('db') }}</li>
<li @click="nav('moderators')" :class="{ active: page == 'moderators' }"><fa :icon="faHeadset" fixed-width/>{{ $t('moderators') }}</li>
<li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>{{ $t('users') }}</li>
<li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li>
@@ -43,6 +44,7 @@
<div v-if="page == 'instance'"><x-instance/></div>
<div v-if="page == 'queue'"><x-queue/></div>
<div v-if="page == 'logs'"><x-logs/></div>
<div v-if="page == 'db'"><x-db/></div>
<div v-if="page == 'moderators'"><x-moderators/></div>
<div v-if="page == 'users'"><x-users/></div>
<div v-if="page == 'emoji'"><x-emoji/></div>
@@ -59,19 +61,20 @@
import Vue from 'vue';
import i18n from '../../i18n';
import { version } from '../../config';
import XDashboard from "./dashboard.vue";
import XInstance from "./instance.vue";
import XQueue from "./queue.vue";
import XLogs from "./logs.vue";
import XModerators from "./moderators.vue";
import XEmoji from "./emoji.vue";
import XAnnouncements from "./announcements.vue";
import XUsers from "./users.vue";
import XDrive from "./drive.vue";
import XAbuse from "./abuse.vue";
import XFederation from "./federation.vue";
import XDashboard from './dashboard.vue';
import XInstance from './instance.vue';
import XQueue from './queue.vue';
import XLogs from './logs.vue';
import XDb from './db.vue';
import XModerators from './moderators.vue';
import XEmoji from './emoji.vue';
import XAnnouncements from './announcements.vue';
import XUsers from './users.vue';
import XDrive from './drive.vue';
import XAbuse from './abuse.vue';
import XFederation from './federation.vue';
import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream } from '@fortawesome/free-solid-svg-icons';
import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream, faDatabase } from '@fortawesome/free-solid-svg-icons';
import { faGrin } from '@fortawesome/free-regular-svg-icons';
// Detect the user agent
@@ -85,6 +88,7 @@ export default Vue.extend({
XInstance,
XQueue,
XLogs,
XDb,
XModerators,
XEmoji,
XAnnouncements,
@@ -108,7 +112,8 @@ export default Vue.extend({
faGlobe,
faExclamationCircle,
faTasks,
faStream
faStream,
faDatabase,
};
},
methods: {

View File

@@ -129,6 +129,7 @@
<ui-input v-model="smtpPass" type="password" :with-password-toggle="true" :disabled="!enableEmail || !smtpAuth">{{ $t('smtp-pass') }}</ui-input>
</ui-horizon-group>
<ui-switch v-model="smtpSecure" :disabled="!enableEmail">{{ $t('smtp-secure') }}<template #desc>{{ $t('smtp-secure-info') }}</template></ui-switch>
<ui-button @click="testEmail()">{{ $t('test-email') }}</ui-button>
</template>
</section>
<section>
@@ -424,6 +425,24 @@ export default Vue.extend({
});
},
async testEmail() {
this.$root.api('admin/send-email', {
to: this.maintainerEmail,
subject: 'Test email',
text: 'Yo'
}).then(x => {
this.$root.dialog({
type: 'success',
splash: true
});
}).catch(e => {
this.$root.dialog({
type: 'error',
text: e
});
});
},
updateMeta() {
this.$root.api('admin/update-meta', {
maintainerName: this.maintainerName,

View File

@@ -1,7 +1,7 @@
<template>
<div class="form">
<header>
<h1 v-html="$t('share-access', { name: app.name })"></h1>
<h1 v-html="$t('share-access', { name })"></h1>
<img :src="app.iconUrl"/>
</header>
<div class="app">
@@ -34,6 +34,11 @@ export default Vue.extend({
i18n: i18n('auth/views/form.vue'),
props: ['session'],
computed: {
name(): string {
const el = document.createElement('div');
el.textContent = this.app.name
return el.innerHTML;
},
app(): any {
return this.session.app;
}

View File

@@ -41,7 +41,6 @@
if (`${url.pathname}/`.startsWith('/dev/')) app = 'dev';
if (`${url.pathname}/`.startsWith('/auth/')) app = 'auth';
if (`${url.pathname}/`.startsWith('/admin/')) app = 'admin';
if (`${url.pathname}/`.startsWith('/test/')) app = 'test';
//#endregion
// Script version

View File

@@ -60,9 +60,9 @@ export default function <T extends object>(data: {
save() {
if (this.platform == 'deck') {
this.$store.commit('device/updateDeckColumn', this.column);
this.$store.commit('updateDeckColumn', this.column);
} else {
this.$store.commit('device/updateWidget', this.widget);
this.$store.commit('updateWidget', this.widget);
}
}
}

View File

@@ -0,0 +1,5 @@
export function hexifyAB(buffer) {
return Array.from(new Uint8Array(buffer))
.map(item => item.toString(16).padStart(2, 0))
.join('');
}

View File

@@ -83,9 +83,19 @@ export default (opts: Opts = {}) => ({
if (this.appearNote.text) {
const ast = parse(this.appearNote.text);
// TODO: 再帰的にURL要素がないか調べる
return unique(ast
const urls = unique(ast
.filter(t => ((t.node.type == 'url' || t.node.type == 'link') && t.node.props.url && !t.node.props.silent))
.map(t => t.node.props.url));
// unique without hash
// [ http://a/#1, http://a/#2, http://b/#3 ] => [ http://a/#1, http://b/#3 ]
const removeHash = x => x.replace(/#[^#]*$/, '');
return urls.reduce((array, url) => {
const removed = removeHash(url);
if (!array.map(x => removeHash(x)).includes(removed)) array.push(url);
return array;
}, []);
} else {
return null;
}

View File

@@ -5,6 +5,7 @@ export default (opts) => ({
return {
items: [],
queue: [],
offset: 0,
fetching: true,
moreFetching: false,
inited: false,
@@ -80,6 +81,7 @@ export default (opts) => ({
this.items = x;
this.more = false;
}
this.offset = x.length;
this.inited = true;
this.fetching = false;
if (opts.onInited) opts.onInited(this);
@@ -96,7 +98,11 @@ export default (opts) => ({
if (params && params.then) params = await params;
await this.$root.api(this.pagination.endpoint, {
limit: (this.pagination.limit || 10) + 1,
untilId: this.items[this.items.length - 1].id,
...(this.pagination.endpoint === 'notes/search' ? {
offset: this.offset,
} : {
untilId: this.items[this.items.length - 1].id,
}),
...params
}).then(x => {
if (x.length == (this.pagination.limit || 10) + 1) {
@@ -107,6 +113,7 @@ export default (opts) => ({
this.items = this.items.concat(x);
this.more = false;
}
this.offset += x.length;
this.moreFetching = false;
}, e => {
this.moreFetching = false;

View File

@@ -16,7 +16,7 @@
</ol>
<ol class="emojis" ref="suggests" v-if="emojis.length > 0">
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-else-if="!useOsDefaultEmojis"><img :src="emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-else>{{ emoji.emoji }}</span>
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
@@ -31,6 +31,7 @@ import Vue from 'vue';
import * as emojilib from 'emojilib';
import contains from '../../../common/scripts/contains';
import { twemojiBase } from '../../../../../misc/twemoji-base';
import { getStaticImageUrl } from '../../../common/scripts/get-static-image-url';
type EmojiDef = {
emoji: string;
@@ -78,6 +79,7 @@ export default Vue.extend({
data() {
return {
getStaticImageUrl,
fetching: true,
users: [],
hashtags: [],

View File

@@ -33,7 +33,7 @@
</template>
</ui-select>
<ui-horizon-group no-grow class="buttons fit-bottom" v-if="!splash && (showOkButton || showCancelButton)">
<ui-button @click="ok" v-if="showOkButton" primary :autofocus="!input && !select && !user">{{ (showCancelButton || input || select || user) ? $t('@.ok') : $t('@.got-it') }}</ui-button>
<ui-button @click="ok" v-if="showOkButton" primary :autofocus="!input && !select && !user" :disabled="!canOk">{{ (showCancelButton || input || select || user) ? $t('@.ok') : $t('@.got-it') }}</ui-button>
<ui-button @click="cancel" v-if="showCancelButton || input || select || user">{{ $t('@.cancel') }}</ui-button>
</ui-horizon-group>
</template>
@@ -99,11 +99,26 @@ export default Vue.extend({
inputValue: this.input && this.input.default ? this.input.default : null,
userInputValue: null,
selectedValue: this.select ? this.select.items ? this.select.items[0].value : this.select.groupedItems[0].items[0].value : null,
canOk: true,
faTimesCircle, faQuestionCircle
};
},
watch: {
userInputValue() {
if (this.user) {
this.$root.api('users/show', parseAcct(this.userInputValue)).then(u => {
this.canOk = u != null;
}).catch(() => {
this.canOk = false;
});
}
}
},
mounted() {
if (this.user) this.canOk = false;
this.$nextTick(() => {
(this.$refs.bg as any).style.pointerEvents = 'auto';
anime({
@@ -131,6 +146,7 @@ export default Vue.extend({
methods: {
async ok() {
if (!this.canOk) return;
if (!this.showOkButton) return;
if (this.user) {

View File

@@ -92,6 +92,14 @@ export default Vue.extend({
try {
if (this.isFollowing) {
const { canceled } = await this.$root.dialog({
type: 'warning',
text: this.$t('@.unfollow-confirm', { name: this.user.name || this.user.username }),
showCancelButton: true
});
if (canceled) return;
await this.$root.api('following/delete', {
userId: this.user.id
});

View File

@@ -23,11 +23,11 @@
</div>
<div class="board">
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
<div class="labels-x" v-if="$store.state.settings.gamesReversiShowBoardLabels">
<span v-for="i in game.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
</div>
<div class="flex">
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
<div class="labels-y" v-if="$store.state.settings.gamesReversiShowBoardLabels">
<div v-for="i in game.map.length">{{ i }}</div>
</div>
<div class="cells" :style="cellsStyle">
@@ -35,7 +35,7 @@
:class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.isEnded, myTurn: !game.isEnded && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }"
@click="set(i)"
:title="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`">
<template v-if="$store.state.settings.games.reversi.useAvatarStones">
<template v-if="$store.state.settings.gamesReversiUseAvatarStones">
<img v-if="stone === true" :src="blackUser.avatarUrl" alt="black">
<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="white">
</template>
@@ -45,11 +45,11 @@
</template>
</div>
</div>
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
<div class="labels-y" v-if="this.$store.state.settings.gamesReversiShowBoardLabels">
<div v-for="i in game.map.length">{{ i }}</div>
</div>
</div>
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
<div class="labels-x" v-if="this.$store.state.settings.gamesReversiShowBoardLabels">
<span v-for="i in game.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<template>
<div class="onchrpzrvnoruiaenfcqvccjfuupzzwv" :class="{ isMobile: $root.isMobile }">
<div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ hukidasi }" ref="popover">
<div class="popover" :class="{ bubble }" ref="popover">
<template v-for="item, i in items">
<div v-if="item === null"></div>
<button v-if="item" @click="clicked(item.action)" :tabindex="i">
@@ -28,7 +28,7 @@ export default Vue.extend({
},
data() {
return {
hukidasi: !this.$root.isMobile
bubble: !this.$root.isMobile
};
},
mounted() {
@@ -56,12 +56,12 @@ export default Vue.extend({
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset;
this.hukidasi = false;
this.bubble = false;
}
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset;
this.hukidasi = false;
this.bubble = false;
}
if (top < 0) {
@@ -150,7 +150,7 @@ export default Vue.extend({
$balloon-size = 16px
&.hukidasi
&.bubble
margin-top $balloon-size
transform-origin center -($balloon-size)

View File

@@ -15,6 +15,8 @@ export default Vue.extend({
<style lang="stylus" scoped>
.havbbuyv
white-space pre-wrap
>>> .title
display block
margin-bottom 4px

View File

@@ -9,7 +9,6 @@ import Vue from 'vue';
import i18n from '../../../i18n';
import { url } from '../../../config';
import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
import { concat, intersperse } from '../../../../../prelude/array';
import { faCopy, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({
@@ -129,6 +128,13 @@ export default Vue.extend({
splash: true
});
this.destroyDom();
}).catch(e => {
if (e.id === '72dab508-c64d-498f-8740-a8eec1ba385a') {
this.$root.dialog({
type: 'error',
text: this.$t('pin-limit-exceeded')
});
}
});
},

View File

@@ -89,9 +89,7 @@ export default Vue.extend({
get() {
const at = () => {
const [date] = moment(this.atDate).toISOString().split('T');
const [hour, minute] = this.atTime.split(':');
return moment(`${date}T${hour}:${minute}Z`).valueOf();
return moment(`${this.atDate} ${this.atTime}`).valueOf();
};
const after = () => {

View File

@@ -1,11 +1,54 @@
<template>
<div class="2fa">
<div class="2fa totp-section">
<p style="margin-top:0;">{{ $t('intro') }}<a :href="$t('url')" target="_blank">{{ $t('detail') }}</a></p>
<ui-info warn>{{ $t('caution') }}</ui-info>
<p v-if="!data && !$store.state.i.twoFactorEnabled"><ui-button @click="register">{{ $t('register') }}</ui-button></p>
<template v-if="$store.state.i.twoFactorEnabled">
<h2 class="heading">{{ $t('totp-header') }}</h2>
<p>{{ $t('already-registered') }}</p>
<ui-button @click="unregister">{{ $t('unregister') }}</ui-button>
<template v-if="supportsCredentials">
<hr class="totp-method-sep">
<h2 class="heading">{{ $t('security-key-header') }}</h2>
<p>{{ $t('security-key') }}</p>
<div class="key-list">
<div class="key" v-for="key in $store.state.i.securityKeysList">
<h3>
{{ key.name }}
</h3>
<div class="last-used">
{{ $t('last-used') }}
<mk-time :time="key.lastUsed"/>
</div>
<ui-button @click="unregisterKey(key)">
{{ $t('unregister') }}
</ui-button>
</div>
</div>
<ui-info warn v-if="registration && registration.error">{{ $t('something-went-wrong') }} {{ registration.error }}</ui-info>
<ui-button v-if="!registration || registration.error" @click="addSecurityKey">{{ $t('register') }}</ui-button>
<ol v-if="registration && !registration.error">
<li v-if="registration.stage >= 0">
{{ $t('activate-key') }}
<fa icon="spinner" pulse fixed-width v-if="registration.saving && registration.stage == 0" />
</li>
<li v-if="registration.stage >= 1">
<ui-form :disabled="registration.stage != 1 || registration.saving">
<ui-input v-model="keyName" :max="30">
<span>{{ $t('security-key-name') }}</span>
</ui-input>
<ui-button @click="registerKey" :disabled="this.keyName.length == 0">
{{ $t('register-security-key') }}
</ui-button>
<fa icon="spinner" pulse fixed-width v-if="registration.saving && registration.stage == 1" />
</ui-form>
</li>
</ol>
</template>
</template>
<div v-if="data && !$store.state.i.twoFactorEnabled">
<ol>
@@ -24,12 +67,21 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../../i18n';
import { hostname } from '../../../../config';
import { hexifyAB } from '../../../scripts/2fa';
function stringifyAB(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}
export default Vue.extend({
i18n: i18n('desktop/views/components/settings.2fa.vue'),
data() {
return {
data: null,
supportsCredentials: !!navigator.credentials,
registration: null,
keyName: '',
token: null
};
},
@@ -76,7 +128,116 @@ export default Vue.extend({
}).catch(() => {
this.$notify(this.$t('failed'));
});
},
registerKey() {
this.registration.saving = true;
this.$root.api('i/2fa/key-done', {
password: this.registration.password,
name: this.keyName,
challengeId: this.registration.challengeId,
// we convert each 16 bits to a string to serialise
clientDataJSON: stringifyAB(this.registration.credential.response.clientDataJSON),
attestationObject: hexifyAB(this.registration.credential.response.attestationObject)
}).then(key => {
this.registration = null;
key.lastUsed = new Date();
this.$notify(this.$t('success'));
})
},
unregisterKey(key) {
this.$root.dialog({
title: this.$t('enter-password'),
input: {
type: 'password'
}
}).then(({ canceled, result: password }) => {
if (canceled) return;
return this.$root.api('i/2fa/remove-key', {
password,
credentialId: key.id
}).then(() => {
this.$notify(this.$t('key-unregistered'));
});
});
},
addSecurityKey() {
this.$root.dialog({
title: this.$t('enter-password'),
input: {
type: 'password'
}
}).then(({ canceled, result: password }) => {
if (canceled) return;
this.$root.api('i/2fa/register-key', {
password
}).then(registration => {
this.registration = {
password,
challengeId: registration.challengeId,
stage: 0,
publicKeyOptions: {
challenge: Buffer.from(
registration.challenge
.replace(/\-/g, "+")
.replace(/_/g, "/"),
'base64'
),
rp: {
id: hostname,
name: 'Misskey'
},
user: {
id: Uint8Array.from(this.$store.state.i.id, c => c.charCodeAt(0)),
name: this.$store.state.i.username,
displayName: this.$store.state.i.name,
},
pubKeyCredParams: [{alg: -7, type: 'public-key'}],
timeout: 60000,
attestation: 'direct'
},
saving: true
};
return navigator.credentials.create({
publicKey: this.registration.publicKeyOptions
});
}).then(credential => {
this.registration.credential = credential;
this.registration.saving = false;
this.registration.stage = 1;
}).catch(err => {
console.warn('Error while registering?', err);
this.registration.error = err.message;
this.registration.stage = -1;
});
});
}
}
});
</script>
<style lang="stylus" scoped>
.totp-section
.totp-method-sep
margin 1.5em 0 1em
border none
border-top solid var(--lineWidth) var(--faceDivider)
h2.heading
margin 0
.key
padding 1em
margin 0.5em 0
background #161616
border-radius 6px
h3
margin-top 0
margin-bottom .3em
.last-used
margin-bottom .5em
</style>

View File

@@ -131,6 +131,13 @@
</section>
</section>
<section>
<header>{{ $t('@._settings.sync') }}</header>
<ui-input v-if="$root.isMobile" v-model="mobileHomeProfile" :datalist="Object.keys($store.state.settings.mobileHomeProfiles)">{{ $t('@._settings.home-profile') }}</ui-input>
<ui-input v-else v-model="homeProfile" :datalist="Object.keys($store.state.settings.homeProfiles)">{{ $t('@._settings.home-profile') }}</ui-input>
<ui-input v-model="deckProfile" :datalist="Object.keys($store.state.settings.deckProfiles)">{{ $t('@._settings.deck-profile') }}</ui-input>
</section>
<section>
<header>{{ $t('@._settings.web-search-engine') }}</header>
<ui-input v-model="webSearchEngine">{{ $t('@._settings.web-search-engine') }}<template #desc>{{ $t('@._settings.web-search-engine-desc') }}</template></ui-input>
@@ -472,13 +479,13 @@ export default Vue.extend({
},
games_reversi_showBoardLabels: {
get() { return this.$store.state.settings.games.reversi.showBoardLabels; },
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.showBoardLabels', value }); }
get() { return this.$store.state.settings.gamesReversiShowBoardLabels; },
set(value) { this.$store.dispatch('settings/set', { key: 'gamesReversiShowBoardLabels', value }); }
},
games_reversi_useAvatarStones: {
get() { return this.$store.state.settings.games.reversi.useAvatarStones; },
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.useAvatarStones', value }); }
get() { return this.$store.state.settings.gamesReversiUseAvatarStones; },
set(value) { this.$store.dispatch('settings/set', { key: 'gamesReversiUseAvatarStones', value }); }
},
disableAnimatedMfm: {
@@ -500,6 +507,21 @@ export default Vue.extend({
get() { return this.$store.state.device.mobileNotificationPosition; },
set(value) { this.$store.commit('device/set', { key: 'mobileNotificationPosition', value }); }
},
homeProfile: {
get() { return this.$store.state.device.homeProfile; },
set(value) { this.$store.commit('device/set', { key: 'homeProfile', value }); }
},
mobileHomeProfile: {
get() { return this.$store.state.device.mobileHomeProfile; },
set(value) { this.$store.commit('device/set', { key: 'mobileHomeProfile', value }); }
},
deckProfile: {
get() { return this.$store.state.device.deckProfile; },
set(value) { this.$store.commit('device/set', { key: 'deckProfile', value }); }
},
},
created() {
this.$root.getMeta().then(meta => {

View File

@@ -1,23 +1,40 @@
<template>
<form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit">
<form class="mk-signin" :class="{ signing, totpLogin }" @submit.prevent="onSubmit">
<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div>
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @input="onUsernameChange">
<span>{{ $t('username') }}</span>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</ui-input>
<ui-input v-model="password" type="password" :with-password-toggle="true" required>
<span>{{ $t('password') }}</span>
<template #prefix><fa icon="lock"/></template>
</ui-input>
<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required>
<span>{{ $t('@.2fa') }}</span>
<template #prefix><fa icon="gavel"/></template>
</ui-input>
<ui-button type="submit" :disabled="signing">{{ signing ? $t('signing-in') : $t('@.signin') }}</ui-button>
<p v-if="meta && meta.enableTwitterIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`"><fa :icon="['fab', 'twitter']"/> {{ $t('signin-with-twitter') }}</a></p>
<p v-if="meta && meta.enableGithubIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`"><fa :icon="['fab', 'github']"/> {{ $t('signin-with-github') }}</a></p>
<p v-if="meta && meta.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`"><fa :icon="['fab', 'discord']"/> {{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
<div class="normal-signin" v-if="!totpLogin">
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @input="onUsernameChange">
<span>{{ $t('username') }}</span>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</ui-input>
<ui-input v-model="password" type="password" :with-password-toggle="true" required>
<span>{{ $t('password') }}</span>
<template #prefix><fa icon="lock"/></template>
</ui-input>
<ui-button type="submit" :disabled="signing">{{ signing ? $t('signing-in') : $t('@.signin') }}</ui-button>
<p v-if="meta && meta.enableTwitterIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`"><fa :icon="['fab', 'twitter']"/> {{ $t('signin-with-twitter') }}</a></p>
<p v-if="meta && meta.enableGithubIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`"><fa :icon="['fab', 'github']"/> {{ $t('signin-with-github') }}</a></p>
<p v-if="meta && meta.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`"><fa :icon="['fab', 'discord']"/> {{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
</div>
<div class="2fa-signin" v-if="totpLogin" :class="{ securityKeys: user && user.securityKeys }">
<div v-if="user && user.securityKeys" class="twofa-group tap-group">
<p>{{ $t('tap-key') }}</p>
<ui-button @click="queryKey" v-if="!queryingKey">
{{ $t('@.error.retry') }}
</ui-button>
</div>
<div class="or-hr" v-if="user && user.securityKeys">
<p class="or-msg">{{ $t('or') }}</p>
</div>
<div class="twofa-group totp-group">
<p style="margin-bottom:0;">{{ $t('enter-2fa-code') }}</p>
<ui-input v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required>
<span>{{ $t('@.2fa') }}</span>
<template #prefix><fa icon="gavel"/></template>
</ui-input>
<ui-button type="submit" :disabled="signing">{{ signing ? $t('signing-in') : $t('@.signin') }}</ui-button>
</div>
</div>
</form>
</template>
@@ -26,6 +43,7 @@ import Vue from 'vue';
import i18n from '../../../i18n';
import { apiUrl, host } from '../../../config';
import { toUnicode } from 'punycode';
import { hexifyAB } from '../../scripts/2fa';
export default Vue.extend({
i18n: i18n('common/views/components/signin.vue'),
@@ -47,7 +65,11 @@ export default Vue.extend({
token: '',
apiUrl,
host: toUnicode(host),
meta: null
meta: null,
totpLogin: false,
credential: null,
challengeData: null,
queryingKey: false,
};
},
@@ -68,23 +90,87 @@ export default Vue.extend({
});
},
onSubmit() {
this.signing = true;
this.$root.api('signin', {
username: this.username,
password: this.password,
token: this.user && this.user.twoFactorEnabled ? this.token : undefined
queryKey() {
this.queryingKey = true;
return navigator.credentials.get({
publicKey: {
challenge: Buffer.from(
this.challengeData.challenge
.replace(/\-/g, '+')
.replace(/_/g, '/'),
'base64'
),
allowCredentials: this.challengeData.securityKeys.map(key => ({
id: Buffer.from(key.id, 'hex'),
type: 'public-key',
transports: ['usb', 'ble', 'nfc']
})),
timeout: 60 * 1000
}
}).catch(err => {
this.queryingKey = false;
console.warn(err);
return Promise.reject(null);
}).then(credential => {
this.queryingKey = false;
this.signing = true;
return this.$root.api('signin', {
username: this.username,
password: this.password,
signature: hexifyAB(credential.response.signature),
authenticatorData: hexifyAB(credential.response.authenticatorData),
clientDataJSON: hexifyAB(credential.response.clientDataJSON),
credentialId: credential.id,
challengeId: this.challengeData.challengeId
});
}).then(res => {
localStorage.setItem('i', res.i);
location.reload();
}).catch(() => {
}).catch(err => {
if(err === null) return;
console.error(err);
this.$root.dialog({
type: 'error',
text: this.$t('login-failed')
});
this.signing = false;
});
},
onSubmit() {
this.signing = true;
if (!this.totpLogin && this.user && this.user.twoFactorEnabled) {
if (window.PublicKeyCredential && this.user.securityKeys) {
this.$root.api('i/2fa/getkeys', {
username: this.username,
password: this.password
}).then(res => {
this.totpLogin = true;
this.signing = false;
this.challengeData = res;
return this.queryKey();
});
} else {
this.totpLogin = true;
this.signing = false;
}
} else {
this.$root.api('signin', {
username: this.username,
password: this.password,
token: this.user && this.user.twoFactorEnabled ? this.token : undefined
}).then(res => {
localStorage.setItem('i', res.i);
location.reload();
}).catch(() => {
this.$root.dialog({
type: 'error',
text: this.$t('login-failed')
});
this.signing = false;
});
}
}
}
});
@@ -94,6 +180,48 @@ export default Vue.extend({
.mk-signin
color #555
.or-hr,
.or-hr .or-msg,
.twofa-group,
.twofa-group p
color var(--text)
.tap-group > button
margin-bottom 1em
.securityKeys .or-hr
&
position relative
.or-msg
&:before
right 100%
margin-right 0.125em
&:after
left 100%
margin-left 0.125em
&:before, &:after
content ""
position absolute
top 50%
width 100%
height 2px
background #555
&
position relative
margin auto
left 0
right 0
top 0
bottom 0
font-size 1.5em
height 1.5em
width 3em
text-align center
&.signing
&, *
cursor wait !important

View File

@@ -43,7 +43,7 @@
</i18n>
</ui-switch>
<div v-if="meta.enableRecaptcha" class="g-recaptcha" :data-sitekey="meta.recaptchaSiteKey" style="margin: 16px 0;"></div>
<ui-button type="submit" :disabled="!(meta.ToSUrl ? ToSAgreement : true)">{{ $t('create') }}</ui-button>
<ui-button type="submit" :disabled="!(meta.ToSUrl ? ToSAgreement : true) || passwordRetypeState == 'not-match'">{{ $t('create') }}</ui-button>
</template>
</form>
</template>

View File

@@ -30,7 +30,7 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../i18n';
import { url as local } from '../../../config';
import { url as local, lang } from '../../../config';
export default Vue.extend({
i18n: i18n('common/views/components/url-preview.vue'),
@@ -89,10 +89,10 @@ export default Vue.extend({
},
created() {
const url = new URL(this.url);
const requestUrl = new URL(this.url);
if (this.detail && url.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(url.pathname)) {
this.tweetUrl = url;
if (this.detail && requestUrl.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(requestUrl.pathname)) {
this.tweetUrl = requestUrl;
const twttr = (window as any).twttr || {};
const loadTweet = () => twttr.widgets.load(this.$refs.tweet);
@@ -113,10 +113,15 @@ export default Vue.extend({
return;
}
if (url.hostname === 'music.youtube.com')
url.hostname = 'youtube.com';
if (requestUrl.hostname === 'music.youtube.com') {
requestUrl.hostname = 'youtube.com';
}
fetch(`/url?url=${encodeURIComponent(this.url)}`).then(res => {
const requestLang = (lang || 'ja-JP').replace('ja-KS', 'ja-JP');
requestUrl.hash = '';
fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${requestLang}`).then(res => {
res.json().then(info => {
if (info.url == null) return;
this.title = info.title;

View File

@@ -5,6 +5,9 @@
<span class="hostname">{{ hostname }}</span>
<span class="port" v-if="port != ''">:{{ port }}</span>
</template>
<template v-if="pathname === '/' && self">
<span class="self">{{ hostname }}</span>
</template>
<span class="pathname" v-if="pathname != ''">{{ self ? pathname.substr(1) : pathname }}</span>
<span class="query">{{ query }}</span>
<span class="hash">{{ hash }}</span>
@@ -21,10 +24,11 @@ export default Vue.extend({
props: ['url', 'rel'],
data() {
const isSelf = this.url.startsWith(local);
const hasRoute =
const hasRoute = isSelf && (
(this.url.substr(local.length) === '/') ||
this.url.substr(local.length).startsWith('/@') ||
this.url.substr(local.length).startsWith('/notes/') ||
this.url.substr(local.length).startsWith('/pages/');
this.url.substr(local.length).startsWith('/pages/'));
return {
local,
schema: null,
@@ -54,19 +58,28 @@ export default Vue.extend({
<style lang="stylus" scoped>
.mk-url
word-break break-all
> [data-icon]
padding-left 2px
font-size .9em
font-weight 400
font-style normal
> .self
font-weight bold
> .schema
opacity 0.5
> .hostname
font-weight bold
> .pathname
opacity 0.8
> .query
opacity 0.5
> .hash
font-style italic
</style>

View File

@@ -146,7 +146,8 @@ export default Vue.extend({
toggleActive() {
if (!this.isStacked) return;
const vms = this.$store.state.device.deck.layout.find(ids => ids.indexOf(this.column.id) != -1).map(id => this.getColumnVm(id));
const deck = this.$store.state.device.deckProfile ? this.$store.state.settings.deckProfiles[this.$store.state.device.deckProfile] : this.$store.state.device.deck;
const vms = deck.layout.find(ids => ids.indexOf(this.column.id) != -1).map(id => this.getColumnVm(id));
if (this.active && countIf(vm => vm.$el.classList.contains('active'), vms) == 1) return;
this.active = !this.active;
},
@@ -179,50 +180,50 @@ export default Vue.extend({
}
}).then(({ canceled, result: name }) => {
if (canceled) return;
this.$store.commit('device/renameDeckColumn', { id: this.column.id, name });
this.$store.commit('renameDeckColumn', { id: this.column.id, name });
});
}
}, null, {
icon: 'arrow-left',
text: this.$t('swap-left'),
action: () => {
this.$store.commit('device/swapLeftDeckColumn', this.column.id);
this.$store.commit('swapLeftDeckColumn', this.column.id);
}
}, {
icon: 'arrow-right',
text: this.$t('swap-right'),
action: () => {
this.$store.commit('device/swapRightDeckColumn', this.column.id);
this.$store.commit('swapRightDeckColumn', this.column.id);
}
}, this.isStacked ? {
icon: faArrowUp,
text: this.$t('swap-up'),
action: () => {
this.$store.commit('device/swapUpDeckColumn', this.column.id);
this.$store.commit('swapUpDeckColumn', this.column.id);
}
} : undefined, this.isStacked ? {
icon: faArrowDown,
text: this.$t('swap-down'),
action: () => {
this.$store.commit('device/swapDownDeckColumn', this.column.id);
this.$store.commit('swapDownDeckColumn', this.column.id);
}
} : undefined, null, {
icon: ['far', 'window-restore'],
text: this.$t('stack-left'),
action: () => {
this.$store.commit('device/stackLeftDeckColumn', this.column.id);
this.$store.commit('stackLeftDeckColumn', this.column.id);
}
}, this.isStacked ? {
icon: faWindowMaximize,
text: this.$t('pop-right'),
action: () => {
this.$store.commit('device/popRightDeckColumn', this.column.id);
this.$store.commit('popRightDeckColumn', this.column.id);
}
} : undefined, null, {
icon: ['far', 'trash-alt'],
text: this.$t('remove'),
action: () => {
this.$store.commit('device/removeDeckColumn', this.column.id);
this.$store.commit('removeDeckColumn', this.column.id);
}
}];
@@ -306,7 +307,7 @@ export default Vue.extend({
const id = e.dataTransfer.getData('mk-deck-column');
if (id != null && id != '') {
this.$store.commit('device/swapDeckColumn', {
this.$store.commit('swapDeckColumn', {
a: this.column.id,
b: id
});

View File

@@ -4,8 +4,8 @@
<mk-avatar class="avatar" :user="notification.user"/>
<div>
<header>
<mk-reaction-icon :reaction="notification.reaction"/>
<router-link :to="notification.user | userPage">
<mk-reaction-icon :reaction="notification.reaction" class="icon"/>
<router-link :to="notification.user | userPage" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
<mk-time :time="notification.createdAt"/>
@@ -22,8 +22,8 @@
<mk-avatar class="avatar" :user="notification.user"/>
<div>
<header>
<fa icon="retweet"/>
<router-link :to="notification.user | userPage">
<fa icon="retweet" class="icon"/>
<router-link :to="notification.user | userPage" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
<mk-time :time="notification.createdAt"/>
@@ -40,8 +40,8 @@
<mk-avatar class="avatar" :user="notification.user"/>
<div>
<header>
<fa icon="user-plus"/>
<router-link :to="notification.user | userPage">
<fa icon="user-plus" class="icon"/>
<router-link :to="notification.user | userPage" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
<mk-time :time="notification.createdAt"/>
@@ -53,9 +53,9 @@
<mk-avatar class="avatar" :user="notification.user"/>
<div>
<header>
<fa icon="user-clock"/>
<fa icon="user-clock" class="icon"/>
<router-link :to="notification.user | userPage">
<mk-user-name :user="notification.user"/>
<mk-user-name :user="notification.user" class="name"/>
</router-link>
<mk-time :time="notification.createdAt"/>
</header>
@@ -66,9 +66,9 @@
<mk-avatar class="avatar" :user="notification.user"/>
<div>
<header>
<fa icon="chart-pie"/>
<fa icon="chart-pie" class="icon"/>
<router-link :to="notification.user | userPage">
<mk-user-name :user="notification.user"/>
<mk-user-name :user="notification.user" class="name"/>
</router-link>
<mk-time :time="notification.createdAt"/>
</header>
@@ -137,9 +137,13 @@ export default Vue.extend({
align-items baseline
white-space nowrap
[data-icon], .mk-reaction-icon
> .icon
margin-right 4px
> .name
overflow hidden
text-overflow ellipsis
> .mk-time
margin-left auto
color var(--noteHeaderInfo)

View File

@@ -90,7 +90,7 @@ export default Vue.extend({
methods: {
onChangeSettings(v) {
this.$store.commit('device/updateDeckColumn', this.column);
this.$store.commit('updateDeckColumn', this.column);
},
focus() {

View File

@@ -97,7 +97,9 @@ export default Vue.extend({
const image = [
'image/jpeg',
'image/png',
'image/gif'
'image/gif',
'image/apng',
'image/vnd.mozilla.apng',
];
this.$root.api('users/notes', {

View File

@@ -25,20 +25,25 @@ import * as uuid from 'uuid';
export default Vue.extend({
i18n: i18n('deck'),
components: {
XColumnCore
},
computed: {
deck() {
return this.$store.getters.deck;
},
columns(): any[] {
if (this.$store.state.device.deck == null) return [];
return this.$store.state.device.deck.columns;
if (this.deck == null) return [];
return this.deck.columns;
},
layout(): any[] {
if (this.$store.state.device.deck == null) return [];
if (this.$store.state.device.deck.layout == null) return this.$store.state.device.deck.columns.map(c => [c.id]);
return this.$store.state.device.deck.layout;
if (this.deck == null) return [];
if (this.deck.layout == null) return this.deck.columns.map(c => [c.id]);
return this.deck.layout;
},
style(): any {
@@ -75,7 +80,7 @@ export default Vue.extend({
},
created() {
if (this.$store.state.device.deck == null) {
if (this.deck == null) {
const deck = {
columns: [/*{
type: 'widgets',
@@ -101,10 +106,7 @@ export default Vue.extend({
deck.layout = deck.columns.map(c => [c.id]);
this.$store.commit('device/set', {
key: 'deck',
value: deck
});
this.$store.commit('setDeck', deck);
}
},
@@ -129,7 +131,7 @@ export default Vue.extend({
icon: 'home',
text: this.$t('@deck.home'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'home'
});
@@ -138,7 +140,7 @@ export default Vue.extend({
icon: ['far', 'comments'],
text: this.$t('@deck.local'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'local'
});
@@ -147,7 +149,7 @@ export default Vue.extend({
icon: 'share-alt',
text: this.$t('@deck.hybrid'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'hybrid'
});
@@ -156,7 +158,7 @@ export default Vue.extend({
icon: 'globe',
text: this.$t('@deck.global'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'global'
});
@@ -165,7 +167,7 @@ export default Vue.extend({
icon: 'at',
text: this.$t('@deck.mentions'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'mentions'
});
@@ -174,7 +176,7 @@ export default Vue.extend({
icon: ['far', 'envelope'],
text: this.$t('@deck.direct'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'direct'
});
@@ -195,7 +197,7 @@ export default Vue.extend({
showCancelButton: true
});
if (canceled) return;
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'list',
list: lists.find(l => l.id === listId)
@@ -210,7 +212,7 @@ export default Vue.extend({
input: true
}).then(({ canceled, result: title }) => {
if (canceled) return;
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'hashtag',
tagTlId: this.$store.state.settings.tagTimelines.find(x => x.title == title).id
@@ -221,7 +223,7 @@ export default Vue.extend({
icon: ['far', 'bell'],
text: this.$t('@deck.notifications'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'notifications'
});
@@ -230,7 +232,7 @@ export default Vue.extend({
icon: 'calculator',
text: this.$t('@deck.widgets'),
action: () => {
this.$store.commit('device/addDeckColumn', {
this.$store.commit('addDeckColumn', {
id: uuid(),
type: 'widgets',
widgets: []

View File

@@ -110,7 +110,7 @@ export default Vue.extend({
},
addWidget() {
this.$store.commit('device/addDeckWidget', {
this.$store.commit('addDeckWidget', {
id: this.column.id,
widget: {
name: this.widgetAdderSelected,
@@ -123,14 +123,14 @@ export default Vue.extend({
},
removeWidget(widget) {
this.$store.commit('device/removeDeckWidget', {
this.$store.commit('removeDeckWidget', {
id: this.column.id,
widget
});
},
saveWidgets() {
this.$store.commit('device/updateDeckColumn', this.column);
this.$store.commit('updateDeckColumn', this.column);
}
}
});

View File

@@ -1,5 +1,5 @@
<template>
<div v-if="page" class="iroscrza" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners, center: page.alignCenter }" :style="{ fontFamily: page.font }">
<div v-if="page" class="iroscrza" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners, center: page.alignCenter }" :style="{ fontFamily: page.font }" :key="path">
<header>
<div class="title">{{ page.title }}</div>
</header>
@@ -85,30 +85,46 @@ export default Vue.extend({
};
},
computed: {
path(): string {
return this.username + '/' + this.pageName;
}
},
watch: {
path() {
this.fetch();
}
},
created() {
this.$root.api('pages/show', {
name: this.pageName,
username: this.username,
}).then(page => {
this.page = page;
this.$emit('init', {
title: this.page.title,
icon: faStickyNote
});
const pageVars = this.getPageVars();
this.script = new Script(new ASEvaluator(this.page.variables, pageVars, {
randomSeed: Math.random(),
user: page.user,
visitor: this.$store.state.i,
page: page,
url: url
}), e => {
console.dir(e);
});
});
this.fetch();
},
methods: {
fetch() {
this.$root.api('pages/show', {
name: this.pageName,
username: this.username,
}).then(page => {
this.page = page;
this.$emit('init', {
title: this.page.title,
icon: faStickyNote
});
const pageVars = this.getPageVars();
this.script = new Script(new ASEvaluator(this.page.variables, pageVars, {
randomSeed: Math.random(),
user: page.user,
visitor: this.$store.state.i,
page: page,
url: url
}), e => {
console.dir(e);
});
});
},
getPageVars() {
return collectPageVars(this.page.content);
},

View File

@@ -3,6 +3,8 @@
<p>Maintainer: <b><a :href="'mailto:' + meta.maintainerEmail" target="_blank">{{ meta.maintainerName }}</a></b></p>
<p>Machine: {{ meta.machine }}</p>
<p>Node: {{ meta.node }}</p>
<p>PSQL: {{ meta.psql }}</p>
<p>Redis: {{ meta.redis }}</p>
<p>Version: {{ meta.version }} </p>
</div>
</template>

View File

@@ -91,6 +91,7 @@ export default ($root: any) => {
? Promise.resolve(file)
: $root.$chooseDriveFile({
multiple: false,
type: 'image/*',
title: locale['desktop']['choose-avatar']
});

View File

@@ -91,6 +91,7 @@ export default ($root: any) => {
? Promise.resolve(file)
: $root.$chooseDriveFile({
multiple: false,
type: 'image/*',
title: locale['desktop']['choose-banner']
});

View File

@@ -77,6 +77,7 @@ init(async (launch, os) => {
if (document.body.clientWidth > 800) {
const w = this.$root.new(MkChooseFileFromDriveWindow, {
title: o.title,
type: o.type,
multiple: o.multiple,
initFolder: o.currentFolder
});

View File

@@ -11,7 +11,7 @@
<div class="weekday"
v-for="(day, i) in Array(7).fill(0)"
:data-today="year == today.getFullYear() && month == today.getMonth() + 1 && today.getDay() == i"
:data-is-donichi="i == 0 || i == 6"
:data-is-weekend="i == 0 || i == 6"
>{{ weekdayText[i] }}</div>
</template>
<div v-for="n in paddingDays"></div>
@@ -19,7 +19,7 @@
:data-today="isToday(i + 1)"
:data-selected="isSelected(i + 1)"
:data-is-out-of-range="isOutOfRange(i + 1)"
:data-is-donichi="isDonichi(i + 1)"
:data-is-weekend="isWeekend(i + 1)"
@click="go(i + 1)"
:title="isOutOfRange(i + 1) ? null : $t('go')"
>
@@ -96,7 +96,7 @@ export default Vue.extend({
(this.start ? test < (this.start as any).getTime() : false);
},
isDonichi(day) {
isWeekend(day) {
const weekday = (new Date(this.year, this.month - 1, day)).getDay();
return weekday == 0 || weekday == 6;
},
@@ -199,14 +199,14 @@ export default Vue.extend({
&.weekday
color var(--calendarWeek)
&[data-is-donichi]
&[data-is-weekend]
color var(--calendarSaturdayOrSunday)
&[data-today]
box-shadow 0 0 0 var(--lineWidth) var(--calendarWeek) inset
border-radius 6px
&[data-is-donichi]
&[data-is-weekend]
box-shadow 0 0 0 var(--lineWidth) var(--calendarSaturdayOrSunday) inset
&.day
@@ -222,7 +222,7 @@ export default Vue.extend({
&:active > div
background var(--faceClearButtonActive)
&[data-is-donichi]
&[data-is-weekend]
color var(--calendarSaturdayOrSunday)
&[data-is-out-of-range]

View File

@@ -11,6 +11,7 @@
<x-drive
ref="browser"
class="browser"
:type="type"
:multiple="multiple"
@selected="onSelected"
@change-selection="onChangeSelection"
@@ -33,6 +34,11 @@ export default Vue.extend({
XDrive: () => import('./drive.vue').then(m => m.default),
},
props: {
type: {
type: String,
required: false,
default: undefined
},
multiple: {
default: false
}

View File

@@ -21,6 +21,7 @@
import Vue from 'vue';
import i18n from '../../../i18n';
import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css';
import * as url from '../../../../../prelude/url';
export default Vue.extend({

View File

@@ -80,6 +80,11 @@ export default Vue.extend({
type: Object,
required: false
},
type: {
type: String,
required: false,
default: undefined
},
multiple: {
type: Boolean,
default: false
@@ -540,6 +545,7 @@ export default Vue.extend({
// ファイル一覧取得
this.$root.api('drive/files', {
folderId: this.folder ? this.folder.id : null,
type: this.type,
limit: filesMax + 1
}).then(files => {
if (files.length == filesMax + 1) {
@@ -570,6 +576,7 @@ export default Vue.extend({
// ファイル一覧取得
this.$root.api('drive/files', {
folderId: this.folder ? this.folder.id : null,
type: this.type,
untilId: this.files[this.files.length - 1].id,
limit: max + 1
}).then(files => {

View File

@@ -84,6 +84,7 @@ import XWelcome from '../pages/welcome.vue';
export default Vue.extend({
i18n: i18n('desktop/views/components/home.vue'),
components: {
XDraggable,
XWelcome
@@ -102,7 +103,7 @@ export default Vue.extend({
computed: {
home(): any[] {
if (this.$store.getters.isSignedIn) {
return this.$store.state.device.home || [];
return this.$store.getters.home || [];
} else {
return [{
name: 'instance',
@@ -138,7 +139,9 @@ export default Vue.extend({
},
created() {
if (this.$store.getters.isSignedIn) {
if (!this.$store.getters.isSignedIn) return;
if (this.$store.getters.home == null) {
const defaultDesktopHomeWidgets = {
left: [
'profile',
@@ -183,9 +186,7 @@ export default Vue.extend({
}
//#endregion
if (this.$store.state.device.home == null) {
this.$store.commit('device/setHome', _defaultDesktopHomeWidgets);
}
this.$store.commit('setHome', _defaultDesktopHomeWidgets);
}
},
@@ -223,7 +224,7 @@ export default Vue.extend({
},
addWidget() {
this.$store.commit('device/addHomeWidget', {
this.$store.commit('addHomeWidget', {
name: this.widgetAdderSelected,
id: uuid(),
place: 'left',
@@ -234,7 +235,7 @@ export default Vue.extend({
saveHome() {
const left = this.widgets.left;
const right = this.widgets.right;
this.$store.commit('device/setHome', left.concat(right));
this.$store.commit('setHome', left.concat(right));
for (const w of left) w.place = 'left';
for (const w of right) w.place = 'right';
},
@@ -245,7 +246,7 @@ export default Vue.extend({
focus() {
(this.$refs.content as any).focus();
}
},
}
});
</script>

View File

@@ -38,7 +38,9 @@ export default Vue.extend({
const image = [
'image/jpeg',
'image/png',
'image/gif'
'image/gif',
'image/apng',
'image/vnd.mozilla.apng',
];
this.$root.api('users/notes', {

View File

@@ -186,7 +186,9 @@ export default Vue.extend({
const image = [
'image/jpeg',
'image/png',
'image/gif'
'image/gif',
'image/apng',
'image/vnd.mozilla.apng',
];
this.$root.api('notes/local-timeline', {

View File

@@ -173,10 +173,9 @@ export default class MiOS extends EventEmitter {
// Init service worker
if (this.shouldRegisterSw) {
// #4813
//this.getMeta().then(data => {
// this.registerSw(data.swPublickey);
//});
this.getMeta().then(data => {
this.registerSw(data.swPublickey);
});
}
};
@@ -282,7 +281,7 @@ export default class MiOS extends EventEmitter {
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
alert(locale['common']['my-token-regenerated'])
alert(locale['common']['my-token-regenerated']);
this.signout();
});
}

View File

@@ -8,6 +8,7 @@
</header>
<x-drive class="drive" ref="browser"
:select-file="true"
:type="type"
:multiple="multiple"
@change-selection="onChangeSelection"
@selected="onSelected"
@@ -25,7 +26,7 @@ export default Vue.extend({
components: {
XDrive: () => import('./drive.vue').then(m => m.default),
},
props: ['multiple'],
props: ['type', 'multiple'],
data() {
return {
files: []

View File

@@ -30,7 +30,9 @@ export default Vue.extend({
const image = [
'image/jpeg',
'image/png',
'image/gif'
'image/gif',
'image/apng',
'image/vnd.mozilla.apng',
];
this.$root.api('users/notes', {
userId: this.user.id,

View File

@@ -110,7 +110,9 @@ export default Vue.extend({
const image = [
'image/jpeg',
'image/png',
'image/gif'
'image/gif',
'image/apng',
'image/vnd.mozilla.apng',
];
this.$root.api('notes/local-timeline', {

View File

@@ -72,13 +72,13 @@ export default Vue.extend({
computed: {
widgets(): any[] {
return this.$store.state.device.mobileHome;
return this.$store.getters.mobileHome || [];
}
},
created() {
if (this.widgets.length == 0) {
this.$store.commit('device/setMobileHome', [{
this.$store.commit('setMobileHome', [{
name: 'calendar',
id: 'a', data: {}
}, {
@@ -98,6 +98,12 @@ export default Vue.extend({
id: 'g', data: {}
}]);
}
this.$watch('$store.getters.mobileHome', () => {
this.$store.dispatch('settings/updateMobileHomeProfile');
}, {
deep: true
});
},
mounted() {
@@ -122,7 +128,7 @@ export default Vue.extend({
},
addWidget() {
this.$store.commit('device/addMobileHomeWidget', {
this.$store.commit('addMobileHomeWidget', {
name: this.widgetAdderSelected,
id: uuid(),
data: {}
@@ -130,11 +136,11 @@ export default Vue.extend({
},
removeWidget(widget) {
this.$store.commit('device/removeMobileHomeWidget', widget);
this.$store.commit('removeMobileHomeWidget', widget);
},
saveHome() {
this.$store.commit('device/setMobileHome', this.widgets);
this.$store.commit('setMobileHome', this.widgets);
}
}
});

View File

@@ -1,3 +1,4 @@
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import * as nestedProperty from 'nested-property';
@@ -31,18 +32,18 @@ const defaultSettings = {
wallpaper: null,
webSearchEngine: 'https://www.google.com/?#q={{query}}',
mutedWords: [],
games: {
reversi: {
showBoardLabels: false,
useAvatarStones: true,
}
}
gamesReversiShowBoardLabels: false,
gamesReversiUseAvatarStones: true,
disableAnimatedMfm: false,
homeProfiles: {},
mobileHomeProfiles: {},
deckProfiles: {},
};
const defaultDeviceSettings = {
home: null,
mobileHome: [],
deck: null,
homeProfile: 'Default',
mobileHomeProfile: 'Default',
deckProfile: 'Default',
deckMode: false,
deckColumnAlign: 'center',
deckColumnWidth: 'normal',
@@ -85,7 +86,13 @@ export default (os: MiOS) => new Vuex.Store({
},
getters: {
isSignedIn: state => state.i != null
isSignedIn: state => state.i != null,
home: state => state.settings.homeProfiles[state.device.homeProfile],
mobileHome: state => state.settings.mobileHomeProfiles[state.device.mobileHomeProfile],
deck: state => state.settings.deckProfiles[state.device.deckProfile],
},
mutations: {
@@ -115,6 +122,216 @@ export default (os: MiOS) => new Vuex.Store({
clearBehindNotes(state) {
state.behindNotes = [];
document.title = os.instanceName;
},
setHome(state, data) {
Vue.set(state.settings.homeProfiles, state.device.homeProfile, data);
os.store.dispatch('settings/updateHomeProfile');
},
setDeck(state, data) {
Vue.set(state.settings.deckProfiles, state.device.deckProfile, data);
os.store.dispatch('settings/updateDeckProfile');
},
addHomeWidget(state, widget) {
state.settings.homeProfiles[state.device.homeProfile].unshift(widget);
os.store.dispatch('settings/updateHomeProfile');
},
setMobileHome(state, data) {
Vue.set(state.settings.mobileHomeProfiles, state.device.mobileHomeProfile, data);
os.store.dispatch('settings/updateMobileHomeProfile');
},
updateWidget(state, x) {
let w;
//#region Desktop home
const home = state.settings.homeProfiles[state.device.homeProfile];
if (home) {
w = home.find(w => w.id == x.id);
if (w) {
w.data = x.data;
os.store.dispatch('settings/updateHomeProfile');
}
}
//#endregion
//#region Mobile home
const mobileHome = state.settings.mobileHomeProfiles[state.device.mobileHomeProfile];
if (mobileHome) {
w = mobileHome.find(w => w.id == x.id);
if (w) {
w.data = x.data;
os.store.dispatch('settings/updateMobileHomeProfile');
}
}
//#endregion
},
addMobileHomeWidget(state, widget) {
state.settings.mobileHomeProfiles[state.device.mobileHomeProfile].unshift(widget);
os.store.dispatch('settings/updateMobileHomeProfile');
},
removeMobileHomeWidget(state, widget) {
Vue.set('state.settings.mobileHomeProfiles', state.device.mobileHomeProfile, state.settings.mobileHomeProfiles[state.device.mobileHomeProfile].filter(w => w.id != widget.id));
os.store.dispatch('settings/updateMobileHomeProfile');
},
addDeckColumn(state, column) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
if (column.name == undefined) column.name = null;
deck.columns.push(column);
deck.layout.push([column.id]);
os.store.dispatch('settings/updateDeckProfile');
},
removeDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
deck.columns = deck.columns.filter(c => c.id != id);
deck.layout = deck.layout.map(ids => erase(id, ids));
deck.layout = deck.layout.filter(ids => ids.length > 0);
os.store.dispatch('settings/updateDeckProfile');
},
swapDeckColumn(state, x) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const a = x.a;
const b = x.b;
const aX = deck.layout.findIndex(ids => ids.indexOf(a) != -1);
const aY = deck.layout[aX].findIndex(id => id == a);
const bX = deck.layout.findIndex(ids => ids.indexOf(b) != -1);
const bY = deck.layout[bX].findIndex(id => id == b);
deck.layout[aX][aY] = b;
deck.layout[bX][bY] = a;
os.store.dispatch('settings/updateDeckProfile');
},
swapLeftDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
deck.layout.some((ids, i) => {
if (ids.indexOf(id) != -1) {
const left = deck.layout[i - 1];
if (left) {
// https://vuejs.org/v2/guide/list.html#Caveats
//state.deck.layout[i - 1] = state.deck.layout[i];
//state.deck.layout[i] = left;
deck.layout.splice(i - 1, 1, deck.layout[i]);
deck.layout.splice(i, 1, left);
}
return true;
}
});
os.store.dispatch('settings/updateDeckProfile');
},
swapRightDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
deck.layout.some((ids, i) => {
if (ids.indexOf(id) != -1) {
const right = deck.layout[i + 1];
if (right) {
// https://vuejs.org/v2/guide/list.html#Caveats
//state.deck.layout[i + 1] = state.deck.layout[i];
//state.deck.layout[i] = right;
deck.layout.splice(i + 1, 1, deck.layout[i]);
deck.layout.splice(i, 1, right);
}
return true;
}
});
os.store.dispatch('settings/updateDeckProfile');
},
swapUpDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const ids = deck.layout.find(ids => ids.indexOf(id) != -1);
ids.some((x, i) => {
if (x == id) {
const up = ids[i - 1];
if (up) {
// https://vuejs.org/v2/guide/list.html#Caveats
//ids[i - 1] = id;
//ids[i] = up;
ids.splice(i - 1, 1, id);
ids.splice(i, 1, up);
}
return true;
}
});
os.store.dispatch('settings/updateDeckProfile');
},
swapDownDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const ids = deck.layout.find(ids => ids.indexOf(id) != -1);
ids.some((x, i) => {
if (x == id) {
const down = ids[i + 1];
if (down) {
// https://vuejs.org/v2/guide/list.html#Caveats
//ids[i + 1] = id;
//ids[i] = down;
ids.splice(i + 1, 1, id);
ids.splice(i, 1, down);
}
return true;
}
});
os.store.dispatch('settings/updateDeckProfile');
},
stackLeftDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const i = deck.layout.findIndex(ids => ids.indexOf(id) != -1);
deck.layout = deck.layout.map(ids => erase(id, ids));
const left = deck.layout[i - 1];
if (left) deck.layout[i - 1].push(id);
deck.layout = deck.layout.filter(ids => ids.length > 0);
os.store.dispatch('settings/updateDeckProfile');
},
popRightDeckColumn(state, id) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const i = deck.layout.findIndex(ids => ids.indexOf(id) != -1);
deck.layout = deck.layout.map(ids => erase(id, ids));
deck.layout.splice(i + 1, 0, [id]);
deck.layout = deck.layout.filter(ids => ids.length > 0);
os.store.dispatch('settings/updateDeckProfile');
},
addDeckWidget(state, x) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const column = deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.widgets.unshift(x.widget);
os.store.dispatch('settings/updateDeckProfile');
},
removeDeckWidget(state, x) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const column = deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.widgets = column.widgets.filter(w => w.id != x.widget.id);
os.store.dispatch('settings/updateDeckProfile');
},
renameDeckColumn(state, x) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
const column = deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.name = x.name;
os.store.dispatch('settings/updateDeckProfile');
},
updateDeckColumn(state, x) {
const deck = state.settings.deckProfiles[state.device.deckProfile];
let column = deck.columns.find(c => c.id == x.id);
if (column == null) return;
column = x;
os.store.dispatch('settings/updateDeckProfile');
}
},
@@ -162,176 +379,6 @@ export default (os: MiOS) => new Vuex.Store({
setVisibility(state, visibility) {
state.visibility = visibility;
},
setHome(state, data) {
state.home = data;
},
addHomeWidget(state, widget) {
state.home.unshift(widget);
},
setMobileHome(state, data) {
state.mobileHome = data;
},
updateWidget(state, x) {
let w;
//#region Desktop home
if (state.home) {
w = state.home.find(w => w.id == x.id);
if (w) {
w.data = x.data;
}
}
//#endregion
//#region Mobile home
if (state.mobileHome) {
w = state.mobileHome.find(w => w.id == x.id);
if (w) {
w.data = x.data;
}
}
//#endregion
},
addMobileHomeWidget(state, widget) {
state.mobileHome.unshift(widget);
},
removeMobileHomeWidget(state, widget) {
state.mobileHome = state.mobileHome.filter(w => w.id != widget.id);
},
addDeckColumn(state, column) {
if (column.name == undefined) column.name = null;
state.deck.columns.push(column);
state.deck.layout.push([column.id]);
},
removeDeckColumn(state, id) {
state.deck.columns = state.deck.columns.filter(c => c.id != id);
state.deck.layout = state.deck.layout.map(ids => erase(id, ids));
state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
},
swapDeckColumn(state, x) {
const a = x.a;
const b = x.b;
const aX = state.deck.layout.findIndex(ids => ids.indexOf(a) != -1);
const aY = state.deck.layout[aX].findIndex(id => id == a);
const bX = state.deck.layout.findIndex(ids => ids.indexOf(b) != -1);
const bY = state.deck.layout[bX].findIndex(id => id == b);
state.deck.layout[aX][aY] = b;
state.deck.layout[bX][bY] = a;
},
swapLeftDeckColumn(state, id) {
state.deck.layout.some((ids, i) => {
if (ids.indexOf(id) != -1) {
const left = state.deck.layout[i - 1];
if (left) {
// https://vuejs.org/v2/guide/list.html#Caveats
//state.deck.layout[i - 1] = state.deck.layout[i];
//state.deck.layout[i] = left;
state.deck.layout.splice(i - 1, 1, state.deck.layout[i]);
state.deck.layout.splice(i, 1, left);
}
return true;
}
});
},
swapRightDeckColumn(state, id) {
state.deck.layout.some((ids, i) => {
if (ids.indexOf(id) != -1) {
const right = state.deck.layout[i + 1];
if (right) {
// https://vuejs.org/v2/guide/list.html#Caveats
//state.deck.layout[i + 1] = state.deck.layout[i];
//state.deck.layout[i] = right;
state.deck.layout.splice(i + 1, 1, state.deck.layout[i]);
state.deck.layout.splice(i, 1, right);
}
return true;
}
});
},
swapUpDeckColumn(state, id) {
const ids = state.deck.layout.find(ids => ids.indexOf(id) != -1);
ids.some((x, i) => {
if (x == id) {
const up = ids[i - 1];
if (up) {
// https://vuejs.org/v2/guide/list.html#Caveats
//ids[i - 1] = id;
//ids[i] = up;
ids.splice(i - 1, 1, id);
ids.splice(i, 1, up);
}
return true;
}
});
},
swapDownDeckColumn(state, id) {
const ids = state.deck.layout.find(ids => ids.indexOf(id) != -1);
ids.some((x, i) => {
if (x == id) {
const down = ids[i + 1];
if (down) {
// https://vuejs.org/v2/guide/list.html#Caveats
//ids[i + 1] = id;
//ids[i] = down;
ids.splice(i + 1, 1, id);
ids.splice(i, 1, down);
}
return true;
}
});
},
stackLeftDeckColumn(state, id) {
const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1);
state.deck.layout = state.deck.layout.map(ids => erase(id, ids));
const left = state.deck.layout[i - 1];
if (left) state.deck.layout[i - 1].push(id);
state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
},
popRightDeckColumn(state, id) {
const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1);
state.deck.layout = state.deck.layout.map(ids => erase(id, ids));
state.deck.layout.splice(i + 1, 0, [id]);
state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
},
addDeckWidget(state, x) {
const column = state.deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.widgets.unshift(x.widget);
},
removeDeckWidget(state, x) {
const column = state.deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.widgets = column.widgets.filter(w => w.id != x.widget.id);
},
renameDeckColumn(state, x) {
const column = state.deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.name = x.name;
},
updateDeckColumn(state, x) {
let column = state.deck.columns.find(c => c.id == x.id);
if (column == null) return;
column = x;
}
}
},
@@ -364,6 +411,42 @@ export default (os: MiOS) => new Vuex.Store({
});
}
},
updateHomeProfile(ctx) {
const profiles = ctx.state.homeProfiles;
ctx.commit('set', {
key: 'homeProfiles',
value: profiles
});
os.api('i/update-client-setting', {
name: 'homeProfiles',
value: profiles
});
},
updateMobileHomeProfile(ctx) {
const profiles = ctx.state.mobileHomeProfiles;
ctx.commit('set', {
key: 'mobileHomeProfiles',
value: profiles
});
os.api('i/update-client-setting', {
name: 'mobileHomeProfiles',
value: profiles
});
},
updateDeckProfile(ctx) {
const profiles = ctx.state.deckProfiles;
ctx.commit('set', {
key: 'deckProfiles',
value: profiles
});
os.api('i/update-client-setting', {
name: 'deckProfiles',
value: profiles
});
},
}
}
}

View File

@@ -1,25 +0,0 @@
import VueRouter from 'vue-router';
// Style
import './style.styl';
import init from '../init';
import Index from './views/index.vue';
import NotFound from '../common/views/pages/not-found.vue';
init(launch => {
document.title = 'Misskey';
// Init router
const router = new VueRouter({
mode: 'history',
base: '/test/',
routes: [
{ path: '/', component: Index },
{ path: '*', component: NotFound }
]
});
// Launch the app
launch(router);
});

View File

@@ -1,6 +0,0 @@
@import "../app"
@import "../reset"
html
height 100%
background var(--bg)

View File

@@ -1,82 +0,0 @@
<template>
<main>
<ui-card>
<template #title>MFM Playground</template>
<section class="fit-top">
<ui-textarea v-model="mfm">
<span>MFM</span>
</ui-textarea>
</section>
<section>
<header>Preview</header>
<mfm :text="mfm" :i="$store.state.i"/>
</section>
<section>
<header style="margin-bottom:0;">AST</header>
<ui-textarea v-model="mfmAst" readonly tall style="margin-top:16px;"></ui-textarea>
</section>
</ui-card>
<ui-card>
<template #title>Dialog Generator</template>
<section class="fit-top">
<ui-select v-model="dialogType" placeholder="">
<option value="info">Information</option>
<option value="success">Success</option>
<option value="warning">Warning</option>
<option value="error">Error</option>
</ui-select>
<ui-input v-model="dialogTitle">
<span>Title</span>
</ui-input>
<ui-input v-model="dialogText">
<span>Text</span>
</ui-input>
<ui-switch v-model="dialogShowCancelButton">With cancel button</ui-switch>
<ui-button @click="showDialog">Show</ui-button>
</section>
</ui-card>
</main>
</template>
<script lang="ts">
import Vue from 'vue';
import { parse } from '../../../../mfm/parse';
import * as JSON5 from 'json5';
export default Vue.extend({
data() {
return {
mfm: '',
dialogType: 'success',
dialogTitle: '',
dialogText: 'Hello World!',
dialogShowCancelButton: false
};
},
computed: {
mfmAst(): any {
return JSON5.stringify(parse(this.mfm), null, 2);
}
},
methods: {
showDialog() {
this.$root.dialog({
type: this.dialogType,
title: this.dialogTitle,
text: this.dialogText,
showCancelButton: this.dialogShowCancelButton
});
}
}
});
</script>
<style lang="stylus" scoped>
main
max-width 700px
margin 0 auto
</style>

View File

@@ -3,7 +3,6 @@
*/
import * as fs from 'fs';
import { URL } from 'url';
import * as yaml from 'js-yaml';
import { Source, Mixin } from './types';
import * as pkg from '../../package.json';

View File

@@ -14,6 +14,7 @@ export type Source = {
db: string;
user: string;
pass: string;
disableCache?: boolean;
extra?: { [x: string]: string };
};
redis: {

18
src/daemons/janitor.ts Normal file
View File

@@ -0,0 +1,18 @@
const interval = 30 * 60 * 1000;
import { AttestationChallenges } from '../models';
import { LessThan } from 'typeorm';
/**
* Clean up database occasionally
*/
export default function() {
async function tick() {
await AttestationChallenges.delete({
createdAt: LessThan(new Date(new Date().getTime() - 5 * 60 * 1000))
});
}
tick();
setInterval(tick, interval);
}

View File

@@ -43,6 +43,8 @@ import { Poll } from '../models/entities/poll';
import { UserKeypair } from '../models/entities/user-keypair';
import { UserPublickey } from '../models/entities/user-publickey';
import { UserProfile } from '../models/entities/user-profile';
import { UserSecurityKey } from '../models/entities/user-security-key';
import { AttestationChallenge } from '../models/entities/attestation-challenge';
import { Page } from '../models/entities/page';
import { PageLike } from '../models/entities/page-like';
@@ -80,6 +82,53 @@ class MyCustomLogger implements Logger {
}
}
export const entities = [
Meta,
Instance,
App,
AuthSession,
AccessToken,
User,
UserProfile,
UserKeypair,
UserPublickey,
UserList,
UserListJoining,
UserGroup,
UserGroupJoining,
UserGroupInvite,
UserNotePining,
UserSecurityKey,
AttestationChallenge,
Following,
FollowRequest,
Muting,
Blocking,
Note,
NoteFavorite,
NoteReaction,
NoteWatching,
NoteUnread,
Page,
PageLike,
Log,
DriveFile,
DriveFolder,
Poll,
PollVote,
Notification,
Emoji,
Hashtag,
SwSubscription,
AbuseUserReport,
RegistrationTicket,
MessagingMessage,
Signin,
ReversiGame,
ReversiMatching,
...charts as any
];
export function initDb(justBorrow = false, sync = false, log = false) {
try {
const conn = getConnection();
@@ -96,63 +145,20 @@ export function initDb(justBorrow = false, sync = false, log = false) {
extra: config.db.extra,
synchronize: process.env.NODE_ENV === 'test' || sync,
dropSchema: process.env.NODE_ENV === 'test' && !justBorrow,
cache: {
cache: !config.db.disableCache ? {
type: 'redis',
options: {
host: config.redis.host,
port: config.redis.port,
options:{
auth_pass: config.redis.pass,
options: {
password: config.redis.pass,
prefix: config.redis.prefix,
db: config.redis.db || 0
}
}
},
} : false,
logging: log,
logger: log ? new MyCustomLogger() : undefined,
entities: [
Meta,
Instance,
App,
AuthSession,
AccessToken,
User,
UserProfile,
UserKeypair,
UserPublickey,
UserList,
UserListJoining,
UserGroup,
UserGroupJoining,
UserGroupInvite,
UserNotePining,
Following,
FollowRequest,
Muting,
Blocking,
Note,
NoteFavorite,
NoteReaction,
NoteWatching,
NoteUnread,
Page,
PageLike,
Log,
DriveFile,
DriveFolder,
Poll,
PollVote,
Notification,
Emoji,
Hashtag,
SwSubscription,
AbuseUserReport,
RegistrationTicket,
MessagingMessage,
Signin,
ReversiGame,
ReversiMatching,
...charts as any
]
entities: entities
});
}

View File

@@ -5,7 +5,7 @@ export default redis.createClient(
config.redis.port,
config.redis.host,
{
auth_pass: config.redis.pass,
password: config.redis.pass,
prefix: config.redis.prefix,
db: config.redis.db || 0
}

View File

@@ -257,7 +257,7 @@ export default class Reversi {
public get winner(): Color | null {
return this.isEnded ?
this.blackCount == this.whiteCount ? null :
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
undefined as never;
}
}

View File

@@ -1,5 +1,4 @@
import { parseFragment, DefaultTreeDocumentFragment } from 'parse5';
import { URL } from 'url';
import { urlRegex } from './prelude';
export function fromHtml(html: string): string {

View File

@@ -6,8 +6,8 @@ import { toUnicode } from 'punycode';
import { emojiRegex } from '../misc/emoji-regex';
export function removeOrphanedBrackets(s: string): string {
const openBrackets = ['(', '「'];
const closeBrackets = [')', '」'];
const openBrackets = ['(', '「', '['];
const closeBrackets = [')', '」', ']'];
const xs = cumulativeSum(s.split('').map(c => {
if (openBrackets.includes(c)) return 1;
if (closeBrackets.includes(c)) return -1;
@@ -98,13 +98,13 @@ export const mfmLanguage = P.createLanguage({
const text = input.substr(i);
const match = text.match(/^(\*|_)([a-zA-Z0-9]+?[\s\S]*?)\1/);
if (!match) return P.makeFailure(i, 'not a italic');
if (input[i - 1] != null && input[i - 1].match(/[a-z0-9]/i)) return P.makeFailure(i, 'not a italic');
if (input[i - 1] != null && input[i - 1] != ' ' && input[i - 1] != '\n') return P.makeFailure(i, 'not a italic');
return P.makeSuccess(i + match[0].length, match[2]);
});
return P.alt(xml, underscore).map(x => createTree('italic', r.inline.atLeast(1).tryParse(x), {}));
},
strike: r => P.regexp(/~~(.+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})),
strike: r => P.regexp(/~~([^\n~]+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})),
motion: r => {
const paren = P.regexp(/\(\(\(([\s\S]+?)\)\)\)/, 1);
const xml = P.regexp(/<motion>(.+?)<\/motion>/, 1);
@@ -157,15 +157,19 @@ export const mfmLanguage = P.createLanguage({
let url: string;
if (!match) {
const match = text.match(/^<(https?:\/\/.*?)>/);
if (!match)
if (!match) {
return P.makeFailure(i, 'not a url');
}
url = match[1];
i += 2;
} else
} else {
url = match[0];
}
url = removeOrphanedBrackets(url);
if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.'));
if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(','));
while (url.endsWith('.') || url.endsWith(',')) {
if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.'));
if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(','));
}
return P.makeSuccess(i + url.length, url);
}).map(x => createLeaf('url', { url: x }));
},

View File

@@ -161,7 +161,7 @@ export class ASEvaluator {
subtract: (a: number, b: number) => a - b,
multiply: (a: number, b: number) => a * b,
divide: (a: number, b: number) => a / b,
remind: (a: number, b: number) => a % b,
mod: (a: number, b: number) => a % b,
strLen: (a: string) => a.length,
strPick: (a: string, b: number) => a[b - 1],
strReplace: (a: string, b: string, c: string) => a.split(b).join(c),
@@ -171,6 +171,7 @@ export class ASEvaluator {
numberToString: (a: number) => a.toString(),
splitStrByLine: (a: string) => a.split('\n'),
pick: (list: any[], i: number) => list[i - 1],
listLen: (list: any[]) => list.length,
random: (probability: number) => Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * 100) < probability,
rannum: (min: number, max: number) => min + Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * (max - min + 1)),
randomPick: (list: any[]) => list[Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * list.length)],

View File

@@ -58,7 +58,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, },
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, },
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
remind: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, },
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, },
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, },
@@ -74,6 +74,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
numberToString: { in: ['number'], out: 'string', category: 'convert', icon: faExchangeAlt, },
splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: faExchangeAlt, },
pick: { in: [null, 'number'], out: null, category: 'list', icon: faIndent, },
listLen: { in: [null], out: 'number', category: 'list', icon: faIndent, },
rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: faDice, },

View File

@@ -1,6 +1,5 @@
import config from '../config';
import { toASCII } from 'punycode';
import { URL } from 'url';
export function getFullApAccount(username: string, host: string | null) {
return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`;

View File

@@ -1,5 +1,5 @@
import * as fs from 'fs';
import fileType from 'file-type';
import fileType = require('file-type');
import checkSvg from '../misc/check-svg';
export async function detectMine(path: string) {

View File

@@ -5,7 +5,7 @@ import chalk from 'chalk';
import Logger from '../services/logger';
export async function downloadUrl(url: string, path: string) {
const logger = new Logger('download-url');
const logger = new Logger('download');
await new Promise((res, rej) => {
logger.info(`Downloading ${chalk.cyan(url)} ...`);
@@ -25,10 +25,8 @@ export async function downloadUrl(url: string, path: string) {
rej(error);
});
const requestUrl = new URL(url).pathname.match(/[^\u0021-\u00ff]/) ? encodeURI(url) : url;
const req = request({
url: requestUrl,
url: new URL(url).href, // https://github.com/syuilo/misskey/issues/2637
proxy: config.proxy,
timeout: 10 * 1000,
headers: {

File diff suppressed because one or more lines are too long

View File

@@ -2,6 +2,8 @@ export function nyaize(text: string): string {
return text
// ja-JP
.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ')
// en-US
.replace(/morning/gi, 'mornyan').replace(/everyone/gi, 'everynyan')
// ko-KR
.replace(/[나-낳]/g, match => String.fromCharCode(
match.codePointAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0)

View File

@@ -1,17 +1,3 @@
export const types = {
boolean: 'boolean' as 'boolean',
string: 'string' as 'string',
number: 'number' as 'number',
array: 'array' as 'array',
object: 'object' as 'object',
any: 'any' as 'any',
};
export const bool = {
true: true as true,
false: false as false,
};
export type Schema = {
type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any';
nullable: boolean;

View File

@@ -1,4 +1,4 @@
export const twemojiBase = 'https://cdn.jsdelivr.net/npm/twemoji@11.3.0';
// https://cdn.jsdelivr.net/npm/twemoji@11.3.0
// https://cdnjs.cloudflare.com/ajax/libs/twemoji/11.3.0
export const twemojiBase = 'https://cdn.jsdelivr.net/npm/twemoji@12.0.1';
// https://cdn.jsdelivr.net/npm/twemoji@12.0.1
// https://cdnjs.cloudflare.com/ajax/libs/twemoji/12.0.1
// https://twemoji.maxcdn.com

View File

@@ -0,0 +1,46 @@
import { PrimaryColumn, Entity, JoinColumn, Column, ManyToOne, Index } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class AttestationChallenge {
@PrimaryColumn(id())
public id: string;
@Index()
@PrimaryColumn(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column('varchar', {
length: 64,
comment: 'Hex-encoded sha256 hash of the challenge.'
})
public challenge: string;
@Column('timestamp with time zone', {
comment: 'The date challenge was created for expiry purposes.'
})
public createdAt: Date;
@Column('boolean', {
comment:
'Indicates that the challenge is only for registration purposes if true to prevent the challenge for being used as authentication.',
default: false
})
public registrationChallenge: boolean;
constructor(data: Partial<AttestationChallenge>) {
if (data == null) return;
for (const [k, v] of Object.entries(data)) {
(this as any)[k] = v;
}
}
}

View File

@@ -72,6 +72,7 @@ export class DriveFile {
})
public properties: Record<string, any>;
@Index()
@Column('boolean')
public storedInternal: boolean;
@@ -146,6 +147,7 @@ export class DriveFile {
/**
* 外部の(信頼されていない)URLへの直リンクか否か
*/
@Index()
@Column('boolean', {
default: false,
comment: 'Whether the DriveFile is direct link to remote server.'

View File

@@ -76,6 +76,11 @@ export class UserProfile {
})
public twoFactorEnabled: boolean;
@Column('boolean', {
default: false,
})
public securityKeysAvailable: boolean;
@Column('varchar', {
length: 128, nullable: true,
comment: 'The password hash of the User. It will be null if the origin of the user is local.'

View File

@@ -0,0 +1,48 @@
import { PrimaryColumn, Entity, JoinColumn, Column, ManyToOne, Index } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class UserSecurityKey {
@PrimaryColumn('varchar', {
comment: 'Variable-length id given to navigator.credentials.get()'
})
public id: string;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column('varchar', {
comment:
'Variable-length public key used to verify attestations (hex-encoded).'
})
public publicKey: string;
@Column('timestamp with time zone', {
comment:
'The date of the last time the UserSecurityKey was successfully validated.'
})
public lastUsed: Date;
@Column('varchar', {
comment: 'User-defined name for this key',
length: 30
})
public name: string;
constructor(data: Partial<UserSecurityKey>) {
if (data == null) return;
for (const [k, v] of Object.entries(data)) {
(this as any)[k] = v;
}
}
}

Some files were not shown because too many files have changed in this diff Show More