Merge branch 'develop' of https://github.com/syuilo/misskey into develop
This commit is contained in:
commit
42af8c7695
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,5 +1,3 @@
|
|||||||
*.svg -diff -text
|
*.svg -diff -text
|
||||||
*.psd -diff -text
|
*.psd -diff -text
|
||||||
*.ai -diff -text
|
*.ai -diff -text
|
||||||
yarn.lock -diff -text
|
|
||||||
package-lock.json -diff -text
|
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,9 +7,6 @@
|
|||||||
# Node.js
|
# Node.js
|
||||||
/node_modules
|
/node_modules
|
||||||
|
|
||||||
# yarn
|
|
||||||
yarn.lock
|
|
||||||
|
|
||||||
# config
|
# config
|
||||||
/.config/*
|
/.config/*
|
||||||
!/.config/example.yml
|
!/.config/example.yml
|
||||||
|
38
CHANGELOG.md
38
CHANGELOG.md
@ -1,6 +1,38 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
11.26.0 (2019/07/19)
|
||||||
|
--------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* モデレーターログを記録して確認できるように
|
||||||
|
* プロフィールに追加情報を設定できるように
|
||||||
|
* Mastodonのリンクの所有者認証に対応
|
||||||
|
* AP: Delete Person アクティビティを配信するように
|
||||||
|
* AP: Delete アクティビティの後にフォロー解除するように
|
||||||
|
* AP: アカウント削除でもDelete activityを配信するように
|
||||||
|
* Pages: ラジオボタンを追加
|
||||||
|
* AdminページのUsers Viewでユーザーのレコードをクリックすることですぐユーザーを照会できるように
|
||||||
|
* AdminページのUsers Viewでユーザー一覧からユーザー名とホスト情報で検索できるように
|
||||||
|
* 特定ホストへのメンションの特別処理をクライアントに追加
|
||||||
|
* 設定画面でデスクトップ・モバイルモード変更時はすぐにrefreshするか伺うように
|
||||||
|
* ペーストされたファイル名のテンプレート変更時すぐどのようになるか見れるように
|
||||||
|
* (コ`・ヘ・´ケ)を追加
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* ログインのログが正しく保存されない問題を修正
|
||||||
|
* 同じユーザー名のユーザーが作成できてしまうことがある問題を修正
|
||||||
|
* 報告されたレポート内容が表示されない問題を修正
|
||||||
|
* リモートのプロフィールの追加情報が表示されない問題を修正
|
||||||
|
* 「見つける」のタグが大文字小文字区別されている問題を修正
|
||||||
|
* 管理画面のインスタンス一覧でソートが正しく機能していない問題を修正
|
||||||
|
* プロフィール設定でバナーに動画を設定すると以降編集ができない問題を修正
|
||||||
|
* ウェブ検索エンジンの設定でグリッチが発生する問題を修正
|
||||||
|
* MFMの引用がインライン表示になっている問題を修正
|
||||||
|
* アンケートの期限入力部分のタイトル表示がおかしい問題を修正
|
||||||
|
* 画面上の項目がすべていなくなると実際はロードされてないだけのファイルやフォルダーがあるにも関わらず「もっと読み込む」ボタンがなくなり「このフォルダーは空です」っていうplaceholderが表示されてしまう問題を修正
|
||||||
|
* proxy-media後のContent-Typeが違う問題を修正
|
||||||
|
* ビルド時にエラーが出るのを修正
|
||||||
|
|
||||||
11.25.1 (2019/07/09)
|
11.25.1 (2019/07/09)
|
||||||
--------------------
|
--------------------
|
||||||
### 🐛Fixes
|
### 🐛Fixes
|
||||||
@ -637,9 +669,9 @@ mongodb:
|
|||||||
db: misskey
|
db: misskey
|
||||||
```
|
```
|
||||||
3. migration ブランチに切り替え
|
3. migration ブランチに切り替え
|
||||||
4. `npm i`
|
4. `yarn install`
|
||||||
5. `npm run build`
|
5. `yarn build`
|
||||||
6. `npm run migrate`
|
6. `yarn migrate`
|
||||||
7. master ブランチに戻す
|
7. master ブランチに戻す
|
||||||
8. enjoy
|
8. enjoy
|
||||||
|
|
||||||
|
@ -7,18 +7,18 @@ Feature suggestions and bug reports are filed in https://github.com/syuilo/missk
|
|||||||
* Please search existing issues to avoid duplication. If your issue is already filed, please add your reaction or comment to the existing one.
|
* Please search existing issues to avoid duplication. If your issue is already filed, please add your reaction or comment to the existing one.
|
||||||
* If you have multiple independent issues, please submit them separately.
|
* If you have multiple independent issues, please submit them separately.
|
||||||
|
|
||||||
|
|
||||||
## Localization (l10n)
|
## Localization (l10n)
|
||||||
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
|
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
|
||||||
You can improve our translations with your Crowdin account.
|
You can improve our translations with your Crowdin account.
|
||||||
Changes you make in Crowdin will be merged into develop branch.
|
Changes you make in Crowdin will be merged into the develop branch by @syuilo.
|
||||||
|
|
||||||
If you can't find the language you want to contribute with, please open an issue.
|
If you cannot find the language you want to contribute with, please open an issue.
|
||||||
|
|
||||||
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
|
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
|
||||||
|
|
||||||
## Internationalization (i18n)
|
## Internationalization (i18n)
|
||||||
Misskey uses [vue-i18n](https://github.com/kazupon/vue-i18n).
|
Misskey uses the Vue.js plugin [Vue I18n](https://github.com/kazupon/vue-i18n).
|
||||||
|
Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/introduction.html .
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
* Documents for contributors are located in [`/docs`](/docs).
|
* Documents for contributors are located in [`/docs`](/docs).
|
||||||
@ -29,9 +29,15 @@ Misskey uses [vue-i18n](https://github.com/kazupon/vue-i18n).
|
|||||||
* Test codes are located in [`/test`](/test).
|
* Test codes are located in [`/test`](/test).
|
||||||
|
|
||||||
## Continuous integration
|
## Continuous integration
|
||||||
Misskey uses CircleCI for automated test.
|
Misskey uses CircleCI for executing automated tests.
|
||||||
Configuration files are located in [`/.circleci`](/.circleci).
|
Configuration files are located in [`/.circleci`](/.circleci).
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### How to resolve conflictions occurred at yarn.lock?
|
||||||
|
|
||||||
|
Just execute `yarn` to fix it.
|
||||||
|
|
||||||
## Glossary
|
## Glossary
|
||||||
### AP
|
### AP
|
||||||
Stands for _**A**ctivity**P**ub_.
|
Stands for _**A**ctivity**P**ub_.
|
||||||
@ -51,11 +57,15 @@ Convert な(na) to にゃ(nya)
|
|||||||
#### Denyaize
|
#### Denyaize
|
||||||
Revert Nyaize
|
Revert Nyaize
|
||||||
|
|
||||||
## Code style
|
## TypeScript Coding Style
|
||||||
### セミコロンを省略しない
|
### Do not omit semicolons
|
||||||
ASI Hazardを避けるためでもある
|
This is to avoid Automatic Semicolon Insertion (ASI) hazard.
|
||||||
|
|
||||||
### 中括弧を省略しない
|
Ref:
|
||||||
|
* https://www.ecma-international.org/ecma-262/#sec-automatic-semicolon-insertion
|
||||||
|
* https://github.com/tc39/ecma262/pull/1062
|
||||||
|
|
||||||
|
### Do not omit curly brackets
|
||||||
Bad:
|
Bad:
|
||||||
``` ts
|
``` ts
|
||||||
if (foo)
|
if (foo)
|
||||||
@ -73,16 +83,20 @@ if (foo) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
ただし**`if`が一行**の時だけは省略しても良い
|
As a special case, you can omit the curly brackets if
|
||||||
|
|
||||||
|
* the body of the `if`-statement have only one statement and,
|
||||||
|
* the `if`-statement does not have `else`-clause.
|
||||||
|
|
||||||
Good:
|
Good:
|
||||||
``` ts
|
``` ts
|
||||||
if (foo) bar;
|
if (foo) bar;
|
||||||
```
|
```
|
||||||
|
|
||||||
### 特別な理由がない限り`===`を使う
|
### Do not use `==` when it can simply be replaced with `===`.
|
||||||
🥰
|
🥰
|
||||||
|
|
||||||
### null系を除いて、bool以外の値をifに渡さない
|
### Use only boolean (or null related) values in the condition of an `if`-statement.
|
||||||
Bad:
|
Bad:
|
||||||
``` ts
|
``` ts
|
||||||
if (foo.length)
|
if (foo.length)
|
||||||
@ -93,12 +107,12 @@ Good:
|
|||||||
if (foo.length > 0)
|
if (foo.length > 0)
|
||||||
```
|
```
|
||||||
|
|
||||||
### `export default`を使わない
|
### Do not use `export default`
|
||||||
インテリセンスと相性が悪かったりするため
|
This is because the current language support does not work well with `export default`.
|
||||||
|
|
||||||
参考:
|
Ref:
|
||||||
* https://gfx.hatenablog.com/entry/2017/11/24/135343
|
|
||||||
* https://basarat.gitbooks.io/typescript/docs/tips/defaultIsBad.html
|
* https://basarat.gitbooks.io/typescript/docs/tips/defaultIsBad.html
|
||||||
|
* https://gfx.hatenablog.com/entry/2017/11/24/135343
|
||||||
|
|
||||||
Bad:
|
Bad:
|
||||||
``` ts
|
``` ts
|
||||||
|
@ -23,9 +23,9 @@ RUN apk add --no-cache \
|
|||||||
zlib-dev
|
zlib-dev
|
||||||
|
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
RUN npm i
|
RUN yarn install
|
||||||
COPY . ./
|
COPY . ./
|
||||||
RUN npm run build
|
RUN yarn build
|
||||||
|
|
||||||
FROM base AS runner
|
FROM base AS runner
|
||||||
|
|
||||||
|
10
README.md
10
README.md
@ -104,38 +104,38 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<!-- PATREON_START -->
|
<!-- PATREON_START -->
|
||||||
<table><tr>
|
<table><tr>
|
||||||
<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/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/20010324/b8af4bd31ae34fbf8806cc0e6228e400/1.png?token-time=2145916800&token-hash=iyiocfousNIUwASmatsIDq8EOsmLUdrQNkWyktHlmJg%3D" alt="Nemo" 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/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://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/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://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/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/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>
|
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
|
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
|
||||||
|
<td><a href="https://www.patreon.com/user?u=20010324">Nemo</a></td>
|
||||||
<td><a href="https://www.patreon.com/weepjp">weepjp</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=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=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=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=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/user?u=12913507">Melilot</a></td>
|
||||||
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
|
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<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>
|
<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/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/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" 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>
|
<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>
|
||||||
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
|
<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>
|
<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>
|
</tr><tr>
|
||||||
|
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
<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/Yuzulia">YuzuRyo61</a></td>
|
||||||
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</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>
|
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
|
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
|
||||||
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
||||||
@ -175,7 +175,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
**Last updated:** Mon, 01 Jul 2019 21:44:06 UTC
|
**Last updated:** Fri, 19 Jul 2019 15:41:09 UTC
|
||||||
<!-- PATREON_END -->
|
<!-- PATREON_END -->
|
||||||
|
|
||||||
:four_leaf_clover: Copyright
|
:four_leaf_clover: Copyright
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
@ -68,7 +68,7 @@ Build misskey with the following:
|
|||||||
*5.* Init DB
|
*5.* Init DB
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
``` shell
|
``` shell
|
||||||
docker-compose run --rm web npm run init
|
docker-compose run --rm web yarn run init
|
||||||
```
|
```
|
||||||
|
|
||||||
*6.* That is it.
|
*6.* That is it.
|
||||||
|
@ -68,7 +68,7 @@ cp docker_example.env docker.env
|
|||||||
*5.* データベースを初期化
|
*5.* データベースを初期化
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
``` shell
|
``` shell
|
||||||
docker-compose run --rm web npm run init
|
docker-compose run --rm web yarn run init
|
||||||
```
|
```
|
||||||
|
|
||||||
*6.* 以上です!
|
*6.* 以上です!
|
||||||
|
@ -27,6 +27,7 @@ Please install and setup these softwares:
|
|||||||
* **[Redis](https://redis.io/)**
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
##### Optional
|
##### Optional
|
||||||
|
* [Yarn](https://yarnpkg.com/) *Optional but recommended for security reason. If you won't install it, use `npx yarn` instead of `yarn`.*
|
||||||
* [Elasticsearch](https://www.elastic.co/) - required to enable the search feature
|
* [Elasticsearch](https://www.elastic.co/) - required to enable the search feature
|
||||||
* [FFmpeg](https://www.ffmpeg.org/)
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ Please install and setup these softwares:
|
|||||||
|
|
||||||
5. Install misskey dependencies.
|
5. Install misskey dependencies.
|
||||||
|
|
||||||
`npm install`
|
`yarn`
|
||||||
|
|
||||||
*4.* Configure Misskey
|
*4.* Configure Misskey
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@ -65,21 +66,20 @@ Please install and setup these softwares:
|
|||||||
|
|
||||||
Build misskey with the following:
|
Build misskey with the following:
|
||||||
|
|
||||||
`NODE_ENV=production npm run build`
|
`NODE_ENV=production yarn build`
|
||||||
|
|
||||||
If you're on Debian, you will need to install the `build-essential`, `python` package.
|
If you're on Debian, you will need to install the `build-essential`, `python` package.
|
||||||
|
|
||||||
If you're still encountering errors about some modules, use node-gyp:
|
If you're still encountering errors about some modules, use node-gyp:
|
||||||
|
|
||||||
1. `npm install -g node-gyp`
|
1. `npx node-gyp configure`
|
||||||
2. `node-gyp configure`
|
2. `npx node-gyp build`
|
||||||
3. `node-gyp build`
|
3. `NODE_ENV=production yarn build`
|
||||||
4. `NODE_ENV=production npm run build`
|
|
||||||
|
|
||||||
*6.* Init DB
|
*6.* Init DB
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
``` shell
|
``` shell
|
||||||
npm run init
|
yarn run init
|
||||||
```
|
```
|
||||||
|
|
||||||
*7.* That is it.
|
*7.* That is it.
|
||||||
@ -130,15 +130,15 @@ You can check if the service is running with `systemctl status misskey`.
|
|||||||
### How to update your Misskey server to the latest version
|
### How to update your Misskey server to the latest version
|
||||||
1. `git checkout master`
|
1. `git checkout master`
|
||||||
2. `git pull`
|
2. `git pull`
|
||||||
3. `npm install`
|
3. `yarn install`
|
||||||
4. `NODE_ENV=production npm run build`
|
4. `NODE_ENV=production yarn build`
|
||||||
5. `npm run migrate`
|
5. `yarn migrate`
|
||||||
6. Restart your Misskey process to apply changes
|
6. Restart your Misskey process to apply changes
|
||||||
7. Enjoy
|
7. Enjoy
|
||||||
|
|
||||||
If you encounter any problems with updating, please try the following:
|
If you encounter any problems with updating, please try the following:
|
||||||
1. `npm run clean` or `npm run cleanall`
|
1. `yarn clean` or `yarn cleanall`
|
||||||
2. Retry update (Don't forget `npm i`)
|
2. Retry update (Don't forget `yarn install`
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@ Installez les paquets suivants :
|
|||||||
* **[Redis](https://redis.io/)**
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
##### Optionnels
|
##### Optionnels
|
||||||
* [Elasticsearch](https://www.elastic.co/) - requis pour pouvoir activer la fonctionnalité de recherche
|
* [Yarn](https://yarnpkg.com/) - *recommander pour des raisons de sécurité. Si vous ne l'installez pas, utilisez `npx yarn` au lieu de` yarn`.*
|
||||||
|
* [Elasticsearch](https://www.elastic.co/) - *requis pour pouvoir activer la fonctionnalité de recherche.*
|
||||||
* [FFmpeg](https://www.ffmpeg.org/)
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
|
||||||
*3.* Installation de Misskey
|
*3.* Installation de Misskey
|
||||||
@ -50,7 +51,7 @@ Installez les paquets suivants :
|
|||||||
|
|
||||||
5. Installez les dépendances de misskey.
|
5. Installez les dépendances de misskey.
|
||||||
|
|
||||||
`npm install`
|
`yarn install`
|
||||||
|
|
||||||
*4.* Création du fichier de configuration
|
*4.* Création du fichier de configuration
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@ -65,23 +66,22 @@ Installez les paquets suivants :
|
|||||||
|
|
||||||
Construisez Misskey comme ceci :
|
Construisez Misskey comme ceci :
|
||||||
|
|
||||||
`NODE_ENV=production npm run build`
|
`NODE_ENV=production yarn build`
|
||||||
|
|
||||||
Si vous êtes sous Debian, vous serez amené à installer les paquets `build-essential` et `python`.
|
Si vous êtes sous Debian, vous serez amené à installer les paquets `build-essential` et `python`.
|
||||||
|
|
||||||
Si vous rencontrez des erreurs concernant certains modules, utilisez node-gyp:
|
Si vous rencontrez des erreurs concernant certains modules, utilisez node-gyp:
|
||||||
|
|
||||||
1. `npm install -g node-gyp`
|
1. `npx node-gyp configure`
|
||||||
2. `node-gyp configure`
|
2. `npx node-gyp build`
|
||||||
3. `node-gyp build`
|
3. `NODE_ENV=production yarn build`
|
||||||
4. `NODE_ENV=production npm run build`
|
|
||||||
|
|
||||||
*6.* C'est tout.
|
*6.* C'est tout.
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
Excellent ! Maintenant, vous avez un environnement prêt pour lancer Misskey
|
Excellent ! Maintenant, vous avez un environnement prêt pour lancer Misskey
|
||||||
|
|
||||||
### Lancement conventionnel
|
### Lancement conventionnel
|
||||||
Lancez tout simplement `NODE_ENV=production npm start`. Bonne chance et amusez-vous bien !
|
Lancez tout simplement `NODE_ENV=production yarn start`. Bonne chance et amusez-vous bien !
|
||||||
|
|
||||||
### Démarrage avec systemd
|
### Démarrage avec systemd
|
||||||
|
|
||||||
@ -124,9 +124,9 @@ Vous pouvez vérifier si le service a démarré en utilisant la commande `system
|
|||||||
### Méthode de mise à jour vers la plus récente version de Misskey
|
### Méthode de mise à jour vers la plus récente version de Misskey
|
||||||
1. `git checkout master`
|
1. `git checkout master`
|
||||||
2. `git pull`
|
2. `git pull`
|
||||||
3. `npm install`
|
3. `yarn install`
|
||||||
4. `NODE_ENV=production npm run build`
|
4. `NODE_ENV=production yarn build`
|
||||||
5. `npm run migrate`
|
5. `yarn migrate`
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ adduser --disabled-password --disabled-login misskey
|
|||||||
* **[Redis](https://redis.io/)**
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
##### オプション
|
##### オプション
|
||||||
|
* [Yarn](https://yarnpkg.com/)
|
||||||
|
* セキュリティの観点から推奨されます。 yarn をインストールしない方針の場合は、文章中の `yarn` を適宜 `npx yarn` と読み替えてください。
|
||||||
* [Elasticsearch](https://www.elastic.co/)
|
* [Elasticsearch](https://www.elastic.co/)
|
||||||
* 検索機能を有効にするためにはインストールが必要です。
|
* 検索機能を有効にするためにはインストールが必要です。
|
||||||
* [FFmpeg](https://www.ffmpeg.org/)
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
@ -51,7 +53,7 @@ adduser --disabled-password --disabled-login misskey
|
|||||||
|
|
||||||
5. Misskeyの依存パッケージをインストール
|
5. Misskeyの依存パッケージをインストール
|
||||||
|
|
||||||
`npm install`
|
`yarn install`
|
||||||
|
|
||||||
*4.* 設定ファイルを作成する
|
*4.* 設定ファイルを作成する
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
@ -66,20 +68,19 @@ adduser --disabled-password --disabled-login misskey
|
|||||||
|
|
||||||
次のコマンドでMisskeyをビルドしてください:
|
次のコマンドでMisskeyをビルドしてください:
|
||||||
|
|
||||||
`NODE_ENV=production npm run build`
|
`NODE_ENV=production yarn build`
|
||||||
|
|
||||||
Debianをお使いであれば、`build-essential`パッケージをインストールする必要があります。
|
Debianをお使いであれば、`build-essential`パッケージをインストールする必要があります。
|
||||||
|
|
||||||
何らかのモジュールでエラーが発生する場合はnode-gypを使ってください:
|
何らかのモジュールでエラーが発生する場合はnode-gypを使ってください:
|
||||||
1. `npm install -g node-gyp`
|
1. `npx node-gyp configure`
|
||||||
2. `node-gyp configure`
|
2. `npx node-gyp build`
|
||||||
3. `node-gyp build`
|
3. `NODE_ENV=production yarn build`
|
||||||
4. `NODE_ENV=production npm run build`
|
|
||||||
|
|
||||||
*6.* データベースを初期化
|
*6.* データベースを初期化
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
``` shell
|
``` shell
|
||||||
npm run init
|
yarn run init
|
||||||
```
|
```
|
||||||
|
|
||||||
*7.* 以上です!
|
*7.* 以上です!
|
||||||
@ -87,7 +88,7 @@ npm run init
|
|||||||
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
||||||
|
|
||||||
### 通常起動
|
### 通常起動
|
||||||
`NODE_ENV=production npm start`するだけです。GLHF!
|
`NODE_ENV=production yarn start`するだけです。GLHF!
|
||||||
|
|
||||||
### systemdを用いた起動
|
### systemdを用いた起動
|
||||||
1. systemdサービスのファイルを作成
|
1. systemdサービスのファイルを作成
|
||||||
@ -120,7 +121,7 @@ npm run init
|
|||||||
|
|
||||||
3. systemdを再読み込みしmisskeyサービスを有効化
|
3. systemdを再読み込みしmisskeyサービスを有効化
|
||||||
|
|
||||||
`systemctl daemon-reload ; systemctl enable misskey`
|
`systemctl daemon-reload; systemctl enable misskey`
|
||||||
|
|
||||||
4. misskeyサービスの起動
|
4. misskeyサービスの起動
|
||||||
|
|
||||||
@ -131,11 +132,11 @@ npm run init
|
|||||||
### Misskeyを最新バージョンにアップデートする方法:
|
### Misskeyを最新バージョンにアップデートする方法:
|
||||||
1. `git checkout master`
|
1. `git checkout master`
|
||||||
2. `git pull`
|
2. `git pull`
|
||||||
3. `npm install`
|
3. `yarn install`
|
||||||
4. `NODE_ENV=production npm run build`
|
4. `NODE_ENV=production yarn build`
|
||||||
5. `npm run migrate`
|
5. `yarn migrate`
|
||||||
|
|
||||||
なにか問題が発生した場合は、`npm run clean`または`npm run cleanall`すると直る場合があります。
|
なにか問題が発生した場合は、`yarn clean`または`yarn cleanall`すると直る場合があります。
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -454,9 +454,12 @@ common/views/components/messaging.vue:
|
|||||||
no-history: "Žádná historie"
|
no-history: "Žádná historie"
|
||||||
user: "Uživatel"
|
user: "Uživatel"
|
||||||
group: "Skupina"
|
group: "Skupina"
|
||||||
|
start-with-user: "Zahájit konverzaci s uživatelem"
|
||||||
|
start-with-group: "Zahájit skupinovou konverzaci"
|
||||||
common/views/components/messaging-room.vue:
|
common/views/components/messaging-room.vue:
|
||||||
new-message: "Máte novou zprávu"
|
new-message: "Máte novou zprávu"
|
||||||
common/views/components/messaging-room.form.vue:
|
common/views/components/messaging-room.form.vue:
|
||||||
|
input-message-here: "Sem zadejte zprávu"
|
||||||
send: "Odeslat"
|
send: "Odeslat"
|
||||||
attach-from-local: "Přiložit soubory z Vašeho zařízení"
|
attach-from-local: "Přiložit soubory z Vašeho zařízení"
|
||||||
common/views/components/messaging-room.message.vue:
|
common/views/components/messaging-room.message.vue:
|
||||||
@ -644,6 +647,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "Profil byl úspěšně aktualizován"
|
saved: "Profil byl úspěšně aktualizován"
|
||||||
uploading: "Nahrávám"
|
uploading: "Nahrávám"
|
||||||
upload-failed: "Nahrávání selhalo"
|
upload-failed: "Nahrávání selhalo"
|
||||||
|
unable-to-process: "Operace nemohla být dokončena."
|
||||||
email: "Nastavení e-mailů"
|
email: "Nastavení e-mailů"
|
||||||
email-address: "Emailová adresa"
|
email-address: "Emailová adresa"
|
||||||
email-verified: "Váš e-mail byl ověřen"
|
email-verified: "Váš e-mail byl ověřen"
|
||||||
@ -660,6 +664,7 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "Nebezpečná zóna"
|
danger-zone: "Nebezpečná zóna"
|
||||||
delete-account: "Smazat účet"
|
delete-account: "Smazat účet"
|
||||||
account-deleted: "Váš účet byl smazán. Může chvilku trvat než zmizí všechna data."
|
account-deleted: "Váš účet byl smazán. Může chvilku trvat než zmizí všechna data."
|
||||||
|
metadata-content: "Obsah"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "Uživatel"
|
users: "Uživatel"
|
||||||
rename: "Přejmenovat seznam"
|
rename: "Přejmenovat seznam"
|
||||||
@ -733,6 +738,7 @@ desktop:
|
|||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
uploading-avatar: "Nahrál nový avatar"
|
uploading-avatar: "Nahrál nový avatar"
|
||||||
avatar-updated: "Vaše avatar byl aktualizován"
|
avatar-updated: "Vaše avatar byl aktualizován"
|
||||||
|
unable-to-process: "Operace nemohla být dokončena."
|
||||||
invalid-filetype: "Tento formát souboru není podporován"
|
invalid-filetype: "Tento formát souboru není podporován"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Černá ... Celkem"
|
total: "Černá ... Celkem"
|
||||||
@ -1041,6 +1047,8 @@ admin/views/users.vue:
|
|||||||
reset-password-confirm: "Opravdu chcete resetovat Vaše heslo?"
|
reset-password-confirm: "Opravdu chcete resetovat Vaše heslo?"
|
||||||
password-updated: "Heslo je nyní \"{password}\""
|
password-updated: "Heslo je nyní \"{password}\""
|
||||||
update-remote-user: "Aktualizovat informace o vzdáleném účtu"
|
update-remote-user: "Aktualizovat informace o vzdáleném účtu"
|
||||||
|
username: "Přezdívka"
|
||||||
|
host: "Hostitel"
|
||||||
users:
|
users:
|
||||||
title: "Uživatel"
|
title: "Uživatel"
|
||||||
state:
|
state:
|
||||||
|
@ -686,6 +686,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "Profil er opdateret med succes"
|
saved: "Profil er opdateret med succes"
|
||||||
uploading: "Overfører"
|
uploading: "Overfører"
|
||||||
upload-failed: "Fejl ved overførsel"
|
upload-failed: "Fejl ved overførsel"
|
||||||
|
unable-to-process: "Handlingen kunne ikke gennemføres."
|
||||||
email: "Email indstillinger"
|
email: "Email indstillinger"
|
||||||
email-address: "Email adresse"
|
email-address: "Email adresse"
|
||||||
email-verified: "Din email er blevet bekræftet"
|
email-verified: "Din email er blevet bekræftet"
|
||||||
@ -705,6 +706,7 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "Risici"
|
danger-zone: "Risici"
|
||||||
delete-account: "Slet kontoen"
|
delete-account: "Slet kontoen"
|
||||||
account-deleted: "Kontoen er slettet. Det kan vare lidt, inden alle data forsvinder."
|
account-deleted: "Kontoen er slettet. Det kan vare lidt, inden alle data forsvinder."
|
||||||
|
metadata-content: "Indhold"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "Bruger"
|
users: "Bruger"
|
||||||
rename: "Omdøb listen"
|
rename: "Omdøb listen"
|
||||||
@ -811,6 +813,7 @@ desktop:
|
|||||||
uploading-avatar: "Overfør en ny avatar"
|
uploading-avatar: "Overfør en ny avatar"
|
||||||
avatar-updated: "Avatar er overført med succes"
|
avatar-updated: "Avatar er overført med succes"
|
||||||
choose-avatar: "Vælg et billede til din avatar"
|
choose-avatar: "Vælg et billede til din avatar"
|
||||||
|
unable-to-process: "Handlingen kunne ikke gennemføres."
|
||||||
invalid-filetype: "Denne filtype kan ikke benyttes her"
|
invalid-filetype: "Denne filtype kan ikke benyttes her"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Sort ... Total"
|
total: "Sort ... Total"
|
||||||
@ -1278,6 +1281,8 @@ admin/views/users.vue:
|
|||||||
remote-user-updated: "Informationen om den eksterne bruger er nu blevet opdateret."
|
remote-user-updated: "Informationen om den eksterne bruger er nu blevet opdateret."
|
||||||
delete-all-files: "Slet alle filer"
|
delete-all-files: "Slet alle filer"
|
||||||
delete-all-files-confirm: "Er du sikker på, at alle filerne skal slettes?"
|
delete-all-files-confirm: "Er du sikker på, at alle filerne skal slettes?"
|
||||||
|
username: "Brugernavn"
|
||||||
|
host: "Vært"
|
||||||
users:
|
users:
|
||||||
title: "Bruger"
|
title: "Bruger"
|
||||||
sort:
|
sort:
|
||||||
|
@ -567,6 +567,7 @@ common/views/components/profile-editor.vue:
|
|||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
save: "Speichern"
|
save: "Speichern"
|
||||||
|
unable-to-process: "Der Vorgang konnte nicht abgeschlossen werden"
|
||||||
export: "Exportieren"
|
export: "Exportieren"
|
||||||
import: "Importieren"
|
import: "Importieren"
|
||||||
export-targets:
|
export-targets:
|
||||||
@ -600,6 +601,7 @@ common/views/widgets/memo.vue:
|
|||||||
save: "Speichern"
|
save: "Speichern"
|
||||||
desktop:
|
desktop:
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
|
unable-to-process: "Der Vorgang konnte nicht abgeschlossen werden"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Schwarz ... komplett"
|
total: "Schwarz ... komplett"
|
||||||
notes: "Blau ... Hinweise"
|
notes: "Blau ... Hinweise"
|
||||||
@ -784,6 +786,7 @@ admin/views/drive.vue:
|
|||||||
local: "Lokal"
|
local: "Lokal"
|
||||||
delete: "Löschen"
|
delete: "Löschen"
|
||||||
admin/views/users.vue:
|
admin/views/users.vue:
|
||||||
|
username: "Benutzername"
|
||||||
users:
|
users:
|
||||||
origin:
|
origin:
|
||||||
local: "Lokal"
|
local: "Lokal"
|
||||||
|
@ -712,7 +712,7 @@ common/views/components/profile-editor.vue:
|
|||||||
you-can-include-hashtags: "You can also include hashtags in your profile description."
|
you-can-include-hashtags: "You can also include hashtags in your profile description."
|
||||||
language: "Language"
|
language: "Language"
|
||||||
birthday: "Birthday"
|
birthday: "Birthday"
|
||||||
avatar: "Icon"
|
avatar: "Avatar"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
is-cat: "This account is a Cat"
|
is-cat: "This account is a Cat"
|
||||||
is-bot: "This account is a Bot"
|
is-bot: "This account is a Bot"
|
||||||
@ -725,6 +725,9 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "Profile updated successfully"
|
saved: "Profile updated successfully"
|
||||||
uploading: "Uploading"
|
uploading: "Uploading"
|
||||||
upload-failed: "Failed to upload"
|
upload-failed: "Failed to upload"
|
||||||
|
unable-to-process: "The operation could not be completed."
|
||||||
|
avatar-not-an-image: "The file specified as an avatar is not an image"
|
||||||
|
banner-not-an-image: "The file specified as a banner is not an image"
|
||||||
email: "Email settings"
|
email: "Email settings"
|
||||||
email-address: "Email Address"
|
email-address: "Email Address"
|
||||||
email-verified: "Your email has been verified."
|
email-verified: "Your email has been verified."
|
||||||
@ -744,6 +747,9 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "Cautious options"
|
danger-zone: "Cautious options"
|
||||||
delete-account: "Remove the account"
|
delete-account: "Remove the account"
|
||||||
account-deleted: "The account has been deleted. It may take some time until all of the data disappears."
|
account-deleted: "The account has been deleted. It may take some time until all of the data disappears."
|
||||||
|
profile-metadata: "Profile metadata"
|
||||||
|
metadata-label: "Label"
|
||||||
|
metadata-content: "Content"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "User"
|
users: "User"
|
||||||
rename: "Rename list"
|
rename: "Rename list"
|
||||||
@ -853,6 +859,7 @@ desktop:
|
|||||||
uploading-avatar: "Uploading a new avatar"
|
uploading-avatar: "Uploading a new avatar"
|
||||||
avatar-updated: "Successfully updated the avatar"
|
avatar-updated: "Successfully updated the avatar"
|
||||||
choose-avatar: "Select an image for the avatar"
|
choose-avatar: "Select an image for the avatar"
|
||||||
|
unable-to-process: "The operation could not be completed."
|
||||||
invalid-filetype: "This filetype is not acceptable here"
|
invalid-filetype: "This filetype is not acceptable here"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Black ... Total"
|
total: "Black ... Total"
|
||||||
@ -1365,6 +1372,8 @@ admin/views/users.vue:
|
|||||||
remote-user-updated: "The information regarding the remote user has been updated."
|
remote-user-updated: "The information regarding the remote user has been updated."
|
||||||
delete-all-files: "Delete all files"
|
delete-all-files: "Delete all files"
|
||||||
delete-all-files-confirm: "Are you sure that you want to delete all files?"
|
delete-all-files-confirm: "Are you sure that you want to delete all files?"
|
||||||
|
username: "Username"
|
||||||
|
host: "Host"
|
||||||
users:
|
users:
|
||||||
title: "Users"
|
title: "Users"
|
||||||
sort:
|
sort:
|
||||||
|
@ -569,6 +569,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "Perfil actualizado con exito"
|
saved: "Perfil actualizado con exito"
|
||||||
uploading: "Subiendo"
|
uploading: "Subiendo"
|
||||||
upload-failed: "Error al subir"
|
upload-failed: "Error al subir"
|
||||||
|
unable-to-process: "La operación no se puede llevar a cabo"
|
||||||
email: "Preferencias de correo"
|
email: "Preferencias de correo"
|
||||||
email-address: "Correo electrónico"
|
email-address: "Correo electrónico"
|
||||||
email-verified: "Tu cuenta de correo ha sido verificada."
|
email-verified: "Tu cuenta de correo ha sido verificada."
|
||||||
@ -671,6 +672,7 @@ desktop:
|
|||||||
uploading-avatar: "Cargando un nuevo avatar"
|
uploading-avatar: "Cargando un nuevo avatar"
|
||||||
avatar-updated: "Avatar actualizado"
|
avatar-updated: "Avatar actualizado"
|
||||||
choose-avatar: "Escoge una imagen de avatar"
|
choose-avatar: "Escoge una imagen de avatar"
|
||||||
|
unable-to-process: "La operación no se puede llevar a cabo"
|
||||||
invalid-filetype: "Este tipo de archivo no es compatible aquí"
|
invalid-filetype: "Este tipo de archivo no es compatible aquí"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Negro ... Total"
|
total: "Negro ... Total"
|
||||||
@ -964,6 +966,8 @@ admin/views/drive.vue:
|
|||||||
mark-as-sensitive: "Marcar como 'sensible'"
|
mark-as-sensitive: "Marcar como 'sensible'"
|
||||||
unmark-as-sensitive: "Desmarcar como 'sensible'"
|
unmark-as-sensitive: "Desmarcar como 'sensible'"
|
||||||
admin/views/users.vue:
|
admin/views/users.vue:
|
||||||
|
username: "Usuario"
|
||||||
|
host: "Host"
|
||||||
users:
|
users:
|
||||||
state:
|
state:
|
||||||
all: "Todo"
|
all: "Todo"
|
||||||
|
@ -583,6 +583,11 @@ common/views/components/emoji-picker.vue:
|
|||||||
symbols: "Symboles"
|
symbols: "Symboles"
|
||||||
flags: "Drapeaux"
|
flags: "Drapeaux"
|
||||||
common/views/components/settings/app-type.vue:
|
common/views/components/settings/app-type.vue:
|
||||||
|
title: "Mode"
|
||||||
|
choices:
|
||||||
|
auto: "Choisir la disposition automatiquement"
|
||||||
|
desktop: "Toujours utiliser la disposition de bureau"
|
||||||
|
mobile: "Toujours utiliser la disposition mobile"
|
||||||
info: "Le rechargement de la page est requis afin d'appliquer les modifications."
|
info: "Le rechargement de la page est requis afin d'appliquer les modifications."
|
||||||
common/views/components/signin.vue:
|
common/views/components/signin.vue:
|
||||||
username: "Nom d'utilisateur·rice"
|
username: "Nom d'utilisateur·rice"
|
||||||
@ -700,6 +705,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "Profil mis à jour avec succès"
|
saved: "Profil mis à jour avec succès"
|
||||||
uploading: "En cours d’envoi …"
|
uploading: "En cours d’envoi …"
|
||||||
upload-failed: "Échec de l'envoi"
|
upload-failed: "Échec de l'envoi"
|
||||||
|
unable-to-process: "L'opération n'a pas pu être complétée"
|
||||||
email: "Paramètres de messagerie"
|
email: "Paramètres de messagerie"
|
||||||
email-address: "Adresse de courrier électronique"
|
email-address: "Adresse de courrier électronique"
|
||||||
email-verified: "L’adresse du courrier électronique a été vérifiée."
|
email-verified: "L’adresse du courrier électronique a été vérifiée."
|
||||||
@ -719,6 +725,7 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "Zone de danger"
|
danger-zone: "Zone de danger"
|
||||||
delete-account: "Supprimer le compte"
|
delete-account: "Supprimer le compte"
|
||||||
account-deleted: "Le compte a été supprimé. Cela peut prendre un certain temps avant que toutes les données disparaissent."
|
account-deleted: "Le compte a été supprimé. Cela peut prendre un certain temps avant que toutes les données disparaissent."
|
||||||
|
metadata-content: "Contenu"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "Utilisateur·rice"
|
users: "Utilisateur·rice"
|
||||||
rename: "Renommer la liste"
|
rename: "Renommer la liste"
|
||||||
@ -827,6 +834,7 @@ desktop:
|
|||||||
uploading-avatar: "Téléversement du nouvel avatar"
|
uploading-avatar: "Téléversement du nouvel avatar"
|
||||||
avatar-updated: "Mise à jour de l’avatar avec succès"
|
avatar-updated: "Mise à jour de l’avatar avec succès"
|
||||||
choose-avatar: "Choisir un avatar"
|
choose-avatar: "Choisir un avatar"
|
||||||
|
unable-to-process: "L'opération n'a pas pu être complétée"
|
||||||
invalid-filetype: "Ce format de fichier n’est pas pris en charge"
|
invalid-filetype: "Ce format de fichier n’est pas pris en charge"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Noirs ... Total"
|
total: "Noirs ... Total"
|
||||||
@ -887,6 +895,7 @@ desktop/views/components/drive.folder.vue:
|
|||||||
rename-folder: "Renommer le dossier"
|
rename-folder: "Renommer le dossier"
|
||||||
input-new-folder-name: "Entrer un nouveau nom"
|
input-new-folder-name: "Entrer un nouveau nom"
|
||||||
else-folders: "Avancé"
|
else-folders: "Avancé"
|
||||||
|
set-as-upload-folder: "Spécifier en tant que dossier de téléversement par défaut"
|
||||||
desktop/views/components/drive.vue:
|
desktop/views/components/drive.vue:
|
||||||
search: "Rechercher"
|
search: "Rechercher"
|
||||||
empty-draghover: "Drop Welcome!"
|
empty-draghover: "Drop Welcome!"
|
||||||
@ -996,6 +1005,7 @@ desktop/views/components/settings.2fa.vue:
|
|||||||
last-used: "Dernière utilisation :"
|
last-used: "Dernière utilisation :"
|
||||||
activate-key: "Cliquez pour activer la clé de sécurité"
|
activate-key: "Cliquez pour activer la clé de sécurité"
|
||||||
security-key-name: "Nom de la clé"
|
security-key-name: "Nom de la clé"
|
||||||
|
something-went-wrong: "Oula ! Il y a eu un problème lors de l’enregistrement de la clé."
|
||||||
key-unregistered: "La clé a été supprimée"
|
key-unregistered: "La clé a été supprimée"
|
||||||
use-password-less-login: "Utiliser une connexion sans mot de passe"
|
use-password-less-login: "Utiliser une connexion sans mot de passe"
|
||||||
common/views/components/media-image.vue:
|
common/views/components/media-image.vue:
|
||||||
@ -1023,6 +1033,7 @@ common/views/components/drive-settings.vue:
|
|||||||
in-use: "utilisé"
|
in-use: "utilisé"
|
||||||
stats: "Statistiques"
|
stats: "Statistiques"
|
||||||
default-upload-folder-name: "Dossier·s"
|
default-upload-folder-name: "Dossier·s"
|
||||||
|
change-default-upload-folder: "Changer de dossier"
|
||||||
common/views/components/mute-and-block.vue:
|
common/views/components/mute-and-block.vue:
|
||||||
mute-and-block: "Silencés / Bloqués"
|
mute-and-block: "Silencés / Bloqués"
|
||||||
mute: "Mettre en sourdine"
|
mute: "Mettre en sourdine"
|
||||||
@ -1313,6 +1324,8 @@ admin/views/users.vue:
|
|||||||
remote-user-updated: "Les informations de l’utilisateur·rice distant·e ont étés mis à jour"
|
remote-user-updated: "Les informations de l’utilisateur·rice distant·e ont étés mis à jour"
|
||||||
delete-all-files: "Supprimer tous les fichiers"
|
delete-all-files: "Supprimer tous les fichiers"
|
||||||
delete-all-files-confirm: "Êtes vous surs de vouloir supprimer tous les fichiers ?"
|
delete-all-files-confirm: "Êtes vous surs de vouloir supprimer tous les fichiers ?"
|
||||||
|
username: "Nom d'utilisateur·rice"
|
||||||
|
host: "Hôte"
|
||||||
users:
|
users:
|
||||||
title: "Utilisateur·rice·s"
|
title: "Utilisateur·rice·s"
|
||||||
sort:
|
sort:
|
||||||
@ -1682,6 +1695,7 @@ deck/deck.user-column.vue:
|
|||||||
activity: "Activité"
|
activity: "Activité"
|
||||||
timeline: "Fil d’actualité"
|
timeline: "Fil d’actualité"
|
||||||
pinned-notes: "Notes épinglées"
|
pinned-notes: "Notes épinglées"
|
||||||
|
pinned-page: "Page épinglée"
|
||||||
docs:
|
docs:
|
||||||
edit-this-page-on-github: "Vous avez trouvé une erreur ou vous voulez contribuer à la documentation ?"
|
edit-this-page-on-github: "Vous avez trouvé une erreur ou vous voulez contribuer à la documentation ?"
|
||||||
edit-this-page-on-github-link: "Éditez cette page sur GitHub !"
|
edit-this-page-on-github-link: "Éditez cette page sur GitHub !"
|
||||||
@ -1797,6 +1811,7 @@ pages:
|
|||||||
message: "Message à afficher lorsque appuyé"
|
message: "Message à afficher lorsque appuyé"
|
||||||
variable: "Variable à envoyer"
|
variable: "Variable à envoyer"
|
||||||
no-variable: "Aucune"
|
no-variable: "Aucune"
|
||||||
|
radioButton: "Choix"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
name: "Nom de la variable"
|
name: "Nom de la variable"
|
||||||
title: "Titre"
|
title: "Titre"
|
||||||
|
@ -782,6 +782,9 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "プロフィールを保存しました"
|
saved: "プロフィールを保存しました"
|
||||||
uploading: "アップロード中"
|
uploading: "アップロード中"
|
||||||
upload-failed: "アップロードに失敗しました"
|
upload-failed: "アップロードに失敗しました"
|
||||||
|
unable-to-process: "操作を完了できません"
|
||||||
|
avatar-not-an-image: "アイコンとして指定したファイルは画像ではありません"
|
||||||
|
banner-not-an-image: "バナーとして指定したファイルは画像ではありません"
|
||||||
email: "メール設定"
|
email: "メール設定"
|
||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
@ -801,6 +804,9 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "危険な設定"
|
danger-zone: "危険な設定"
|
||||||
delete-account: "アカウントを削除"
|
delete-account: "アカウントを削除"
|
||||||
account-deleted: "アカウントが削除されました。データが消えるまで時間がかかる場合があります。"
|
account-deleted: "アカウントが削除されました。データが消えるまで時間がかかる場合があります。"
|
||||||
|
profile-metadata: "プロフィール補足情報"
|
||||||
|
metadata-label: "ラベル"
|
||||||
|
metadata-content: "内容"
|
||||||
|
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
@ -927,6 +933,7 @@ desktop:
|
|||||||
uploading-avatar: "新しいアバターをアップロードしています"
|
uploading-avatar: "新しいアバターをアップロードしています"
|
||||||
avatar-updated: "アバターを更新しました"
|
avatar-updated: "アバターを更新しました"
|
||||||
choose-avatar: "アバターにする画像を選択"
|
choose-avatar: "アバターにする画像を選択"
|
||||||
|
unable-to-process: "操作を完了できません"
|
||||||
invalid-filetype: "この形式のファイルはサポートされていません"
|
invalid-filetype: "この形式のファイルはサポートされていません"
|
||||||
|
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
@ -1498,6 +1505,8 @@ admin/views/users.vue:
|
|||||||
remote-user-updated: "リモートユーザー情報を更新しました"
|
remote-user-updated: "リモートユーザー情報を更新しました"
|
||||||
delete-all-files: "すべてのファイルを削除"
|
delete-all-files: "すべてのファイルを削除"
|
||||||
delete-all-files-confirm: "すべてのファイルを削除しますか?"
|
delete-all-files-confirm: "すべてのファイルを削除しますか?"
|
||||||
|
username: "ユーザー名"
|
||||||
|
host: "ホスト"
|
||||||
users:
|
users:
|
||||||
title: "ユーザー"
|
title: "ユーザー"
|
||||||
sort:
|
sort:
|
||||||
|
@ -472,6 +472,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "プロフィールを保存したで"
|
saved: "プロフィールを保存したで"
|
||||||
uploading: "アップロードしとります"
|
uploading: "アップロードしとります"
|
||||||
upload-failed: "これアップロードでけへんわ"
|
upload-failed: "これアップロードでけへんわ"
|
||||||
|
unable-to-process: "あかん、無理やわ"
|
||||||
email: "メール設定"
|
email: "メール設定"
|
||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "このメールアドレスOKや!"
|
email-verified: "このメールアドレスOKや!"
|
||||||
@ -565,6 +566,7 @@ desktop:
|
|||||||
uploading-avatar: "新しいアバターをアップロードしとるで"
|
uploading-avatar: "新しいアバターをアップロードしとるで"
|
||||||
avatar-updated: "アバターを更新したで"
|
avatar-updated: "アバターを更新したで"
|
||||||
choose-avatar: "アバターにする画像選んでや"
|
choose-avatar: "アバターにする画像選んでや"
|
||||||
|
unable-to-process: "あかん、無理やわ"
|
||||||
invalid-filetype: "この形式のファイル無理やねん"
|
invalid-filetype: "この形式のファイル無理やねん"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "黒いの ... 全部"
|
total: "黒いの ... 全部"
|
||||||
@ -944,6 +946,8 @@ admin/views/users.vue:
|
|||||||
reset-password: "パスワードをリセット"
|
reset-password: "パスワードをリセット"
|
||||||
password-updated: "パスワードは現在「{password} 」やで"
|
password-updated: "パスワードは現在「{password} 」やで"
|
||||||
suspend: "凍結"
|
suspend: "凍結"
|
||||||
|
username: "ユーザー名"
|
||||||
|
host: "ホスト"
|
||||||
users:
|
users:
|
||||||
title: "ユーザー"
|
title: "ユーザー"
|
||||||
state:
|
state:
|
||||||
|
@ -725,6 +725,9 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "프로필을 저장하였습니다"
|
saved: "프로필을 저장하였습니다"
|
||||||
uploading: "업로드 중"
|
uploading: "업로드 중"
|
||||||
upload-failed: "업로드에 실패하였습니다"
|
upload-failed: "업로드에 실패하였습니다"
|
||||||
|
unable-to-process: "작업을 완료할 수 없습니다"
|
||||||
|
avatar-not-an-image: "아바타로 지정한 파일이 이미지 형식이 아닙니다"
|
||||||
|
banner-not-an-image: "배너로 지정한 파일이 이미지 형식이 아닙니다"
|
||||||
email: "메일 설정"
|
email: "메일 설정"
|
||||||
email-address: "메일 주소"
|
email-address: "메일 주소"
|
||||||
email-verified: "매일 주소가 확인되었습니다"
|
email-verified: "매일 주소가 확인되었습니다"
|
||||||
@ -744,6 +747,9 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "위험한 설정"
|
danger-zone: "위험한 설정"
|
||||||
delete-account: "계정 삭제"
|
delete-account: "계정 삭제"
|
||||||
account-deleted: "계정이 삭제되었습니다. 데이터가 사라질 때까지 시간이 걸릴 수 있습니다."
|
account-deleted: "계정이 삭제되었습니다. 데이터가 사라질 때까지 시간이 걸릴 수 있습니다."
|
||||||
|
profile-metadata: "프로필 추가 정보"
|
||||||
|
metadata-label: "라벨"
|
||||||
|
metadata-content: "내용"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "사용자"
|
users: "사용자"
|
||||||
rename: "리스트 이름 바꾸기"
|
rename: "리스트 이름 바꾸기"
|
||||||
@ -853,6 +859,7 @@ desktop:
|
|||||||
uploading-avatar: "새로운 아바타를 업로드하고 있습니다"
|
uploading-avatar: "새로운 아바타를 업로드하고 있습니다"
|
||||||
avatar-updated: "아바타가 변경되었습니다"
|
avatar-updated: "아바타가 변경되었습니다"
|
||||||
choose-avatar: "아바타 이미지를 선택"
|
choose-avatar: "아바타 이미지를 선택"
|
||||||
|
unable-to-process: "작업을 완료할 수 없습니다"
|
||||||
invalid-filetype: "이 형식의 파일은 지원되지 않습니다"
|
invalid-filetype: "이 형식의 파일은 지원되지 않습니다"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "검은색 ... 전체"
|
total: "검은색 ... 전체"
|
||||||
@ -894,7 +901,7 @@ desktop/views/components/drive.file.vue:
|
|||||||
copy-url: "URL 복사"
|
copy-url: "URL 복사"
|
||||||
download: "다운로드"
|
download: "다운로드"
|
||||||
else-files: "기타"
|
else-files: "기타"
|
||||||
set-as-avatar: "아이콘으로 설정"
|
set-as-avatar: "아바타로 설정"
|
||||||
set-as-banner: "배너로 설정"
|
set-as-banner: "배너로 설정"
|
||||||
open-in-app: "앱에서 열기"
|
open-in-app: "앱에서 열기"
|
||||||
add-app: "앱 추가"
|
add-app: "앱 추가"
|
||||||
@ -1365,6 +1372,8 @@ admin/views/users.vue:
|
|||||||
remote-user-updated: "원격 사용자 정보를 갱신하였습니다"
|
remote-user-updated: "원격 사용자 정보를 갱신하였습니다"
|
||||||
delete-all-files: "모든 파일 삭제"
|
delete-all-files: "모든 파일 삭제"
|
||||||
delete-all-files-confirm: "모든 파일을 삭제하시겠습니까?"
|
delete-all-files-confirm: "모든 파일을 삭제하시겠습니까?"
|
||||||
|
username: "사용자명"
|
||||||
|
host: "관리자"
|
||||||
users:
|
users:
|
||||||
title: "사용자"
|
title: "사용자"
|
||||||
sort:
|
sort:
|
||||||
|
@ -199,6 +199,7 @@ common/views/components/profile-editor.vue:
|
|||||||
name: "Naam"
|
name: "Naam"
|
||||||
avatar: "Gebruikersafbeelding"
|
avatar: "Gebruikersafbeelding"
|
||||||
banner: "Omslagfoto"
|
banner: "Omslagfoto"
|
||||||
|
unable-to-process: "De operatie kan niet worden voltooid."
|
||||||
export-targets:
|
export-targets:
|
||||||
following-list: "Volgend"
|
following-list: "Volgend"
|
||||||
user-lists: "Lijsten"
|
user-lists: "Lijsten"
|
||||||
@ -226,6 +227,7 @@ common/views/pages/follow.vue:
|
|||||||
follow: "Volgend"
|
follow: "Volgend"
|
||||||
desktop:
|
desktop:
|
||||||
banner: "Omslagfoto"
|
banner: "Omslagfoto"
|
||||||
|
unable-to-process: "De operatie kan niet worden voltooid."
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Zwart ... totaal"
|
total: "Zwart ... totaal"
|
||||||
notes: "Blauw ... notities"
|
notes: "Blauw ... notities"
|
||||||
@ -425,6 +427,7 @@ admin/views/drive.vue:
|
|||||||
local: "Lokaal"
|
local: "Lokaal"
|
||||||
delete: "Verwijderen"
|
delete: "Verwijderen"
|
||||||
admin/views/users.vue:
|
admin/views/users.vue:
|
||||||
|
username: "Gebruikersnaam"
|
||||||
users:
|
users:
|
||||||
title: "Gebruiker"
|
title: "Gebruiker"
|
||||||
state:
|
state:
|
||||||
|
@ -346,6 +346,7 @@ admin/views/drive.vue:
|
|||||||
local: "Lokalt"
|
local: "Lokalt"
|
||||||
delete: "Slett"
|
delete: "Slett"
|
||||||
admin/views/users.vue:
|
admin/views/users.vue:
|
||||||
|
username: "Brukernavn"
|
||||||
users:
|
users:
|
||||||
title: "Bruker"
|
title: "Bruker"
|
||||||
state:
|
state:
|
||||||
|
@ -518,6 +518,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "Pomyślnie zaktualizowano profil"
|
saved: "Pomyślnie zaktualizowano profil"
|
||||||
uploading: "Wysyłanie"
|
uploading: "Wysyłanie"
|
||||||
upload-failed: "Wysyłanie nie powiodło się"
|
upload-failed: "Wysyłanie nie powiodło się"
|
||||||
|
unable-to-process: "Nie udało się ukończyć działania."
|
||||||
email: "Ustawienia e-mail"
|
email: "Ustawienia e-mail"
|
||||||
email-address: "Adres e-mail"
|
email-address: "Adres e-mail"
|
||||||
email-verified: "Twój adres e-mail został zweryfikowany."
|
email-verified: "Twój adres e-mail został zweryfikowany."
|
||||||
@ -612,6 +613,7 @@ desktop:
|
|||||||
uploading-avatar: "Wysyłanie awatara"
|
uploading-avatar: "Wysyłanie awatara"
|
||||||
avatar-updated: "Wysłano awatar"
|
avatar-updated: "Wysłano awatar"
|
||||||
choose-avatar: "Wybierz awatar"
|
choose-avatar: "Wybierz awatar"
|
||||||
|
unable-to-process: "Nie udało się ukończyć działania."
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "Czarny … Łącznie"
|
total: "Czarny … Łącznie"
|
||||||
notes: "Niebieski … Wpisy"
|
notes: "Niebieski … Wpisy"
|
||||||
@ -910,6 +912,7 @@ admin/views/drive.vue:
|
|||||||
unmark-as-sensitive: "Cofnij oznaczenie jako zawartość wrażliwą"
|
unmark-as-sensitive: "Cofnij oznaczenie jako zawartość wrażliwą"
|
||||||
admin/views/users.vue:
|
admin/views/users.vue:
|
||||||
user-not-found: "Nie znaleziono użytkownika"
|
user-not-found: "Nie znaleziono użytkownika"
|
||||||
|
username: "Nazwa użytkownika"
|
||||||
users:
|
users:
|
||||||
title: "Użytkownicy"
|
title: "Użytkownicy"
|
||||||
sort:
|
sort:
|
||||||
|
@ -725,6 +725,7 @@ common/views/components/profile-editor.vue:
|
|||||||
saved: "您的个人资料已保存"
|
saved: "您的个人资料已保存"
|
||||||
uploading: "正在上传"
|
uploading: "正在上传"
|
||||||
upload-failed: "上传失败"
|
upload-failed: "上传失败"
|
||||||
|
unable-to-process: "无法完成操作"
|
||||||
email: "邮件设置"
|
email: "邮件设置"
|
||||||
email-address: "电子邮件地址"
|
email-address: "电子邮件地址"
|
||||||
email-verified: "电子邮件地址已验证"
|
email-verified: "电子邮件地址已验证"
|
||||||
@ -744,6 +745,7 @@ common/views/components/profile-editor.vue:
|
|||||||
danger-zone: "危险选项"
|
danger-zone: "危险选项"
|
||||||
delete-account: "删除帐户"
|
delete-account: "删除帐户"
|
||||||
account-deleted: "帐户已被删除。 数据会在一段时间之后清除。"
|
account-deleted: "帐户已被删除。 数据会在一段时间之后清除。"
|
||||||
|
metadata-content: "内容"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "用户"
|
users: "用户"
|
||||||
rename: "重命名列表"
|
rename: "重命名列表"
|
||||||
@ -853,6 +855,7 @@ desktop:
|
|||||||
uploading-avatar: "上传一个新的头像"
|
uploading-avatar: "上传一个新的头像"
|
||||||
avatar-updated: "成功上传头像"
|
avatar-updated: "成功上传头像"
|
||||||
choose-avatar: "选择作为头像的图片"
|
choose-avatar: "选择作为头像的图片"
|
||||||
|
unable-to-process: "无法完成操作"
|
||||||
invalid-filetype: "不接受此文件类型"
|
invalid-filetype: "不接受此文件类型"
|
||||||
desktop/views/components/activity.chart.vue:
|
desktop/views/components/activity.chart.vue:
|
||||||
total: "黑 ... 总计"
|
total: "黑 ... 总计"
|
||||||
@ -1365,6 +1368,8 @@ admin/views/users.vue:
|
|||||||
remote-user-updated: "远程用户信息已更新"
|
remote-user-updated: "远程用户信息已更新"
|
||||||
delete-all-files: "删除所有文件"
|
delete-all-files: "删除所有文件"
|
||||||
delete-all-files-confirm: "删除所有文件吗?"
|
delete-all-files-confirm: "删除所有文件吗?"
|
||||||
|
username: "用户名"
|
||||||
|
host: "主机名"
|
||||||
users:
|
users:
|
||||||
title: "用户"
|
title: "用户"
|
||||||
sort:
|
sort:
|
||||||
@ -1399,6 +1404,7 @@ admin/views/moderators.vue:
|
|||||||
title: "登录"
|
title: "登录"
|
||||||
moderator: "版主"
|
moderator: "版主"
|
||||||
type: "操作"
|
type: "操作"
|
||||||
|
at: "日期和时间"
|
||||||
info: "信息"
|
info: "信息"
|
||||||
admin/views/emoji.vue:
|
admin/views/emoji.vue:
|
||||||
add-emoji:
|
add-emoji:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "11.25.1",
|
"version": "11.26.0",
|
||||||
"codename": "daybreak",
|
"codename": "daybreak",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -37,7 +37,6 @@
|
|||||||
"@fortawesome/free-solid-svg-icons": "5.9.0",
|
"@fortawesome/free-solid-svg-icons": "5.9.0",
|
||||||
"@fortawesome/vue-fontawesome": "0.1.6",
|
"@fortawesome/vue-fontawesome": "0.1.6",
|
||||||
"@koa/cors": "3.0.0",
|
"@koa/cors": "3.0.0",
|
||||||
"@typescript-eslint/parser": "1.11.0",
|
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
"@types/bull": "3.5.15",
|
"@types/bull": "3.5.15",
|
||||||
"@types/cbor": "2.0.0",
|
"@types/cbor": "2.0.0",
|
||||||
@ -82,7 +81,7 @@
|
|||||||
"@types/ratelimiter": "2.1.28",
|
"@types/ratelimiter": "2.1.28",
|
||||||
"@types/redis": "2.8.13",
|
"@types/redis": "2.8.13",
|
||||||
"@types/rename": "1.0.1",
|
"@types/rename": "1.0.1",
|
||||||
"@types/request": "2.48.1",
|
"@types/request": "2.48.2",
|
||||||
"@types/request-promise-native": "1.0.16",
|
"@types/request-promise-native": "1.0.16",
|
||||||
"@types/request-stats": "3.0.0",
|
"@types/request-stats": "3.0.0",
|
||||||
"@types/rimraf": "2.0.2",
|
"@types/rimraf": "2.0.2",
|
||||||
@ -99,6 +98,7 @@
|
|||||||
"@types/webpack-stream": "3.2.10",
|
"@types/webpack-stream": "3.2.10",
|
||||||
"@types/websocket": "0.0.40",
|
"@types/websocket": "0.0.40",
|
||||||
"@types/ws": "6.0.1",
|
"@types/ws": "6.0.1",
|
||||||
|
"@typescript-eslint/parser": "1.11.0",
|
||||||
"animejs": "3.0.1",
|
"animejs": "3.0.1",
|
||||||
"apexcharts": "3.8.2",
|
"apexcharts": "3.8.2",
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<mk-avatar class="avatar" :user="user" :disable-link="true"/>
|
<mk-avatar class="avatar" :user="user" :disable-link="true"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div @click="click(user.id)">
|
||||||
<header>
|
<header>
|
||||||
<b><mk-user-name :user="user"/></b>
|
<b><mk-user-name :user="user"/></b>
|
||||||
<span class="username">@{{ user | acct }}</span>
|
<span class="username">@{{ user | acct }}</span>
|
||||||
@ -32,7 +32,7 @@ import { faSnowflake } from '@fortawesome/free-regular-svg-icons';
|
|||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('admin/views/users.vue'),
|
i18n: i18n('admin/views/users.vue'),
|
||||||
props: ['user'],
|
props: ['user', 'click'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
faSnowflake, faMicrophoneSlash
|
faSnowflake, faMicrophoneSlash
|
||||||
@ -44,7 +44,7 @@ export default Vue.extend({
|
|||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.kofvwchc
|
.kofvwchc
|
||||||
display flex
|
display flex
|
||||||
padding 16px 0
|
padding 16px
|
||||||
border-top solid 1px var(--faceDivider)
|
border-top solid 1px var(--faceDivider)
|
||||||
|
|
||||||
> div:first-child
|
> div:first-child
|
||||||
@ -55,6 +55,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
> div:last-child
|
> div:last-child
|
||||||
flex 1
|
flex 1
|
||||||
|
cursor pointer
|
||||||
padding-left 16px
|
padding-left 16px
|
||||||
|
|
||||||
@media (max-width 500px)
|
@media (max-width 500px)
|
||||||
@ -80,4 +81,15 @@ export default Vue.extend({
|
|||||||
> .is-suspended
|
> .is-suspended
|
||||||
margin 0 0 0 .5em
|
margin 0 0 0 .5em
|
||||||
color #4dabf7
|
color #4dabf7
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
color var(--primaryForeground)
|
||||||
|
background var(--primary)
|
||||||
|
text-decoration none
|
||||||
|
border-radius 3px
|
||||||
|
|
||||||
|
&:active
|
||||||
|
color var(--primaryForeground)
|
||||||
|
background var(--primaryDarken10)
|
||||||
|
border-radius 3px
|
||||||
</style>
|
</style>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
</ui-input>
|
</ui-input>
|
||||||
<ui-button @click="showUser"><fa :icon="faSearch"/> {{ $t('lookup') }}</ui-button>
|
<ui-button @click="showUser"><fa :icon="faSearch"/> {{ $t('lookup') }}</ui-button>
|
||||||
|
|
||||||
<div class="user" v-if="user">
|
<div ref="user" class="user" v-if="user" :key="user.id">
|
||||||
<x-user :user="user"/>
|
<x-user :user="user"/>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<ui-button v-if="user.host != null" @click="updateRemoteUser"><fa :icon="faSync"/> {{ $t('update-remote-user') }}</ui-button>
|
<ui-button v-if="user.host != null" @click="updateRemoteUser"><fa :icon="faSync"/> {{ $t('update-remote-user') }}</ui-button>
|
||||||
@ -54,8 +54,16 @@
|
|||||||
<option value="remote">{{ $t('users.origin.remote') }}</option>
|
<option value="remote">{{ $t('users.origin.remote') }}</option>
|
||||||
</ui-select>
|
</ui-select>
|
||||||
</ui-horizon-group>
|
</ui-horizon-group>
|
||||||
|
<ui-horizon-group searchboxes>
|
||||||
|
<ui-input v-model="searchUsername" type="text" spellcheck="false" @input="fetchUsers(true)">
|
||||||
|
<span>{{ $t('username') }}</span>
|
||||||
|
</ui-input>
|
||||||
|
<ui-input v-model="searchHost" type="text" spellcheck="false" @input="fetchUsers(true)" :disabled="origin === 'local'">
|
||||||
|
<span>{{ $t('host') }}</span>
|
||||||
|
</ui-input>
|
||||||
|
</ui-horizon-group>
|
||||||
<sequential-entrance animation="entranceFromTop" delay="25">
|
<sequential-entrance animation="entranceFromTop" delay="25">
|
||||||
<x-user v-for="user in users" :user='user' :key="user.id"/>
|
<x-user v-for="user in users" :key="user.id" :user='user' :click="showUserOnClick"/>
|
||||||
</sequential-entrance>
|
</sequential-entrance>
|
||||||
<ui-button v-if="existMore" @click="fetchUsers">{{ $t('@.load-more') }}</ui-button>
|
<ui-button v-if="existMore" @click="fetchUsers">{{ $t('@.load-more') }}</ui-button>
|
||||||
</section>
|
</section>
|
||||||
@ -85,6 +93,8 @@ export default Vue.extend({
|
|||||||
sort: '+createdAt',
|
sort: '+createdAt',
|
||||||
state: 'all',
|
state: 'all',
|
||||||
origin: 'local',
|
origin: 'local',
|
||||||
|
searchUsername: '',
|
||||||
|
searchHost: '',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
users: [],
|
users: [],
|
||||||
@ -107,6 +117,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
origin() {
|
origin() {
|
||||||
|
if (this.origin === 'local') this.searchHost = '';
|
||||||
this.users = [];
|
this.users = [];
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
this.fetchUsers();
|
this.fetchUsers();
|
||||||
@ -157,6 +168,15 @@ export default Vue.extend({
|
|||||||
this.target = '';
|
this.target = '';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async showUserOnClick(userId: string) {
|
||||||
|
this.$root.api('admin/show-user', { userId: userId }).then(info => {
|
||||||
|
this.user = info;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.user.scrollIntoView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/** 処理対象ユーザーの情報を更新する */
|
/** 処理対象ユーザーの情報を更新する */
|
||||||
async refreshUser() {
|
async refreshUser() {
|
||||||
this.$root.api('admin/show-user', { userId: this.user.id }).then(info => {
|
this.$root.api('admin/show-user', { userId: this.user.id }).then(info => {
|
||||||
@ -308,13 +328,16 @@ export default Vue.extend({
|
|||||||
return !confirm.canceled;
|
return !confirm.canceled;
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchUsers() {
|
fetchUsers(truncate?: boolean) {
|
||||||
|
if (truncate) this.offset = 0;
|
||||||
this.$root.api('admin/show-users', {
|
this.$root.api('admin/show-users', {
|
||||||
state: this.state,
|
state: this.state,
|
||||||
origin: this.origin,
|
origin: this.origin,
|
||||||
sort: this.sort,
|
sort: this.sort,
|
||||||
offset: this.offset,
|
offset: this.offset,
|
||||||
limit: this.limit + 1
|
limit: this.limit + 1,
|
||||||
|
username: this.searchUsername,
|
||||||
|
hostname: this.searchHost
|
||||||
}).then(users => {
|
}).then(users => {
|
||||||
if (users.length == this.limit + 1) {
|
if (users.length == this.limit + 1) {
|
||||||
users.pop();
|
users.pop();
|
||||||
@ -322,7 +345,7 @@ export default Vue.extend({
|
|||||||
} else {
|
} else {
|
||||||
this.existMore = false;
|
this.existMore = false;
|
||||||
}
|
}
|
||||||
this.users = this.users.concat(users);
|
this.users = truncate ? users : this.users.concat(users);
|
||||||
this.offset += this.limit;
|
this.offset += this.limit;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,8 @@ const faces = [
|
|||||||
'🐡( \'-\' 🐡 )フグパンチ!!!!',
|
'🐡( \'-\' 🐡 )フグパンチ!!!!',
|
||||||
'✌️(´・_・`)✌️',
|
'✌️(´・_・`)✌️',
|
||||||
'(。>﹏<。)',
|
'(。>﹏<。)',
|
||||||
'(Δ・x・Δ)'
|
'(Δ・x・Δ)',
|
||||||
|
'(コ`・ヘ・´ケ)'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default () => faces[Math.floor(Math.random() * faces.length)];
|
export default () => faces[Math.floor(Math.random() * faces.length)];
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-link class="ldlomzub" :to="`/${ canonical }`" v-user-preview="canonical">
|
<router-link class="ldlomzub" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
|
||||||
<span class="me" v-if="isMe">{{ $t('@.you') }}</span>
|
<span class="me" v-if="isMe">{{ $t('@.you') }}</span>
|
||||||
<span class="main">
|
<span class="main">
|
||||||
<span class="username">@{{ username }}</span>
|
<span class="username">@{{ username }}</span>
|
||||||
<span class="host" :class="{ fade: $store.state.settings.contrastedAcct }" v-if="(host != localHost) || $store.state.settings.showFullAcct">@{{ toUnicode(host) }}</span>
|
<span class="host" :class="{ fade: $store.state.settings.contrastedAcct }" v-if="(host != localHost) || $store.state.settings.showFullAcct">@{{ toUnicode(host) }}</span>
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
<a class="ldlomzub" :href="url" target="_blank" rel="noopener" v-else>
|
||||||
|
<span class="main">
|
||||||
|
<span class="username">@{{ username }}</span>
|
||||||
|
<span class="host" :class="{ fade: $store.state.settings.contrastedAcct }">@{{ toUnicode(host) }}</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -32,6 +38,15 @@ export default Vue.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
url(): string {
|
||||||
|
switch (this.host) {
|
||||||
|
case 'twitter.com':
|
||||||
|
case 'github.com':
|
||||||
|
return `https://${this.host}/${this.username}`;
|
||||||
|
default:
|
||||||
|
return `/${this.canonical}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
canonical(): string {
|
canonical(): string {
|
||||||
return this.host === localHost ? `@${this.username}` : `@${this.username}@${toUnicode(this.host)}`;
|
return this.host === localHost ? `@${this.username}` : `@${this.username}@${toUnicode(this.host)}`;
|
||||||
},
|
},
|
||||||
|
@ -30,6 +30,7 @@ export default Vue.extend({
|
|||||||
border-radius 4px
|
border-radius 4px
|
||||||
|
|
||||||
>>> .quote
|
>>> .quote
|
||||||
|
display block
|
||||||
margin 8px
|
margin 8px
|
||||||
padding 6px 0 6px 12px
|
padding 6px 0 6px 12px
|
||||||
color var(--mfmQuote)
|
color var(--mfmQuote)
|
||||||
|
@ -26,13 +26,19 @@
|
|||||||
<option value="after">{{ $t('after') }}</option>
|
<option value="after">{{ $t('after') }}</option>
|
||||||
</ui-select>
|
</ui-select>
|
||||||
<section v-if="expiration === 'at'">
|
<section v-if="expiration === 'at'">
|
||||||
<ui-input v-model="atDate" type="date">{{ $t('deadline-date') }}</ui-input>
|
<ui-input v-model="atDate" type="date">
|
||||||
<ui-input v-model="atTime" type="time">{{ $t('deadline-time') }}</ui-input>
|
<template #title>{{ $t('deadline-date') }}</template>
|
||||||
|
</ui-input>
|
||||||
|
<ui-input v-model="atTime" type="time">
|
||||||
|
<template #title>{{ $t('deadline-time') }}</template>
|
||||||
|
</ui-input>
|
||||||
</section>
|
</section>
|
||||||
<section v-if="expiration === 'after'">
|
<section v-if="expiration === 'after'">
|
||||||
<ui-input v-model="after" type="number">{{ $t('interval') }}</ui-input>
|
<ui-input v-model="after" type="number">
|
||||||
|
<template #title>{{ $t('interval') }}</template>
|
||||||
|
</ui-input>
|
||||||
<ui-select v-model="unit">
|
<ui-select v-model="unit">
|
||||||
<template #label>{{ $t('unit') }}</template>
|
<template #title>{{ $t('unit') }}</template>
|
||||||
<option value="second">{{ $t('second') }}</option>
|
<option value="second">{{ $t('second') }}</option>
|
||||||
<option value="minute">{{ $t('minute') }}</option>
|
<option value="minute">{{ $t('minute') }}</option>
|
||||||
<option value="hour">{{ $t('hour') }}</option>
|
<option value="hour">{{ $t('hour') }}</option>
|
||||||
|
@ -51,6 +51,26 @@
|
|||||||
<template #desc v-if="bannerUploading">{{ $t('uploading') }}<mk-ellipsis/></template>
|
<template #desc v-if="bannerUploading">{{ $t('uploading') }}<mk-ellipsis/></template>
|
||||||
</ui-input>
|
</ui-input>
|
||||||
|
|
||||||
|
<div class="fields">
|
||||||
|
<header>{{ $t('profile-metadata') }}</header>
|
||||||
|
<ui-horizon-group>
|
||||||
|
<ui-input v-model="fieldName0">{{ $t('metadata-label') }}</ui-input>
|
||||||
|
<ui-input v-model="fieldValue0">{{ $t('metadata-content') }}</ui-input>
|
||||||
|
</ui-horizon-group>
|
||||||
|
<ui-horizon-group>
|
||||||
|
<ui-input v-model="fieldName1">{{ $t('metadata-label') }}</ui-input>
|
||||||
|
<ui-input v-model="fieldValue1">{{ $t('metadata-content') }}</ui-input>
|
||||||
|
</ui-horizon-group>
|
||||||
|
<ui-horizon-group>
|
||||||
|
<ui-input v-model="fieldName2">{{ $t('metadata-label') }}</ui-input>
|
||||||
|
<ui-input v-model="fieldValue2">{{ $t('metadata-content') }}</ui-input>
|
||||||
|
</ui-horizon-group>
|
||||||
|
<ui-horizon-group>
|
||||||
|
<ui-input v-model="fieldName3">{{ $t('metadata-label') }}</ui-input>
|
||||||
|
<ui-input v-model="fieldValue3">{{ $t('metadata-content') }}</ui-input>
|
||||||
|
</ui-horizon-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ui-button @click="save(true)"><fa :icon="faSave"/> {{ $t('save') }}</ui-button>
|
<ui-button @click="save(true)"><fa :icon="faSave"/> {{ $t('save') }}</ui-button>
|
||||||
</ui-form>
|
</ui-form>
|
||||||
</section>
|
</section>
|
||||||
@ -189,6 +209,17 @@ export default Vue.extend({
|
|||||||
this.isLocked = this.$store.state.i.isLocked;
|
this.isLocked = this.$store.state.i.isLocked;
|
||||||
this.carefulBot = this.$store.state.i.carefulBot;
|
this.carefulBot = this.$store.state.i.carefulBot;
|
||||||
this.autoAcceptFollowed = this.$store.state.i.autoAcceptFollowed;
|
this.autoAcceptFollowed = this.$store.state.i.autoAcceptFollowed;
|
||||||
|
|
||||||
|
if (this.$store.state.i.fields) {
|
||||||
|
this.fieldName0 = this.$store.state.i.fields[0].name;
|
||||||
|
this.fieldValue0 = this.$store.state.i.fields[0].value;
|
||||||
|
this.fieldName1 = this.$store.state.i.fields[1].name;
|
||||||
|
this.fieldValue1 = this.$store.state.i.fields[1].value;
|
||||||
|
this.fieldName2 = this.$store.state.i.fields[2].name;
|
||||||
|
this.fieldValue2 = this.$store.state.i.fields[2].value;
|
||||||
|
this.fieldName3 = this.$store.state.i.fields[3].name;
|
||||||
|
this.fieldValue3 = this.$store.state.i.fields[3].value;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
@ -237,6 +268,13 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
save(notify) {
|
save(notify) {
|
||||||
|
const fields = [
|
||||||
|
{ name: this.fieldName0, value: this.fieldValue0 },
|
||||||
|
{ name: this.fieldName1, value: this.fieldValue1 },
|
||||||
|
{ name: this.fieldName2, value: this.fieldValue2 },
|
||||||
|
{ name: this.fieldName3, value: this.fieldValue3 },
|
||||||
|
];
|
||||||
|
|
||||||
this.saving = true;
|
this.saving = true;
|
||||||
|
|
||||||
this.$root.api('i/update', {
|
this.$root.api('i/update', {
|
||||||
@ -247,6 +285,7 @@ export default Vue.extend({
|
|||||||
birthday: this.birthday || null,
|
birthday: this.birthday || null,
|
||||||
avatarId: this.avatarId || undefined,
|
avatarId: this.avatarId || undefined,
|
||||||
bannerId: this.bannerId || undefined,
|
bannerId: this.bannerId || undefined,
|
||||||
|
fields,
|
||||||
isCat: !!this.isCat,
|
isCat: !!this.isCat,
|
||||||
isBot: !!this.isBot,
|
isBot: !!this.isBot,
|
||||||
isLocked: !!this.isLocked,
|
isLocked: !!this.isLocked,
|
||||||
@ -265,6 +304,29 @@ export default Vue.extend({
|
|||||||
text: this.$t('saved')
|
text: this.$t('saved')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
this.saving = false;
|
||||||
|
switch(err.id) {
|
||||||
|
case 'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191':
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
title: this.$t('unable-to-process'),
|
||||||
|
text: this.$t('avatar-not-an-image')
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case '75aedb19-2afd-4e6d-87fc-67941256fa60':
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
title: this.$t('unable-to-process'),
|
||||||
|
text: this.$t('banner-not-an-image')
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: this.$t('unable-to-process')
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -366,4 +428,9 @@ export default Vue.extend({
|
|||||||
height 72px
|
height 72px
|
||||||
margin auto
|
margin auto
|
||||||
|
|
||||||
|
.fields
|
||||||
|
> header
|
||||||
|
padding 8px 0px
|
||||||
|
font-weight bold
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -83,6 +83,21 @@ export default ($root: any) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
}).catch(err => {
|
||||||
|
switch (err.id) {
|
||||||
|
case 'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191':
|
||||||
|
$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
title: locale['desktop']['unable-to-process'],
|
||||||
|
text: locale['desktop']['invalid-filetype']
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: locale['desktop']['unable-to-process']
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +83,21 @@ export default ($root: any) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
}).catch(err => {
|
||||||
|
switch (err.id) {
|
||||||
|
case '75aedb19-2afd-4e6d-87fc-67941256fa60':
|
||||||
|
$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
title: locale['desktop']['unable-to-process'],
|
||||||
|
text: locale['desktop']['invalid-filetype']
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: locale['desktop']['unable-to-process']
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BIN
src/client/assets/thumbnail-not-available.png
Normal file
BIN
src/client/assets/thumbnail-not-available.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
@ -148,6 +148,7 @@ export class UserRepository extends Repository<User> {
|
|||||||
description: profile!.description,
|
description: profile!.description,
|
||||||
location: profile!.location,
|
location: profile!.location,
|
||||||
birthday: profile!.birthday,
|
birthday: profile!.birthday,
|
||||||
|
fields: profile!.fields,
|
||||||
followersCount: user.followersCount,
|
followersCount: user.followersCount,
|
||||||
followingCount: user.followingCount,
|
followingCount: user.followingCount,
|
||||||
notesCount: user.notesCount,
|
notesCount: user.notesCount,
|
||||||
|
@ -21,13 +21,24 @@ export async function renderPerson(user: ILocalUser) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const attachment: {
|
const attachment: {
|
||||||
type: string,
|
type: 'PropertyValue',
|
||||||
name: string,
|
name: string,
|
||||||
value: string,
|
value: string,
|
||||||
verified_at?: string,
|
|
||||||
identifier?: IIdentifier
|
identifier?: IIdentifier
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
|
||||||
|
if (profile.fields) {
|
||||||
|
for (const field of profile.fields) {
|
||||||
|
attachment.push({
|
||||||
|
type: 'PropertyValue',
|
||||||
|
name: field.name,
|
||||||
|
value: (field.value != null && field.value.match(/^https?:/))
|
||||||
|
? `<a href="${new URL(field.value).href}" rel="me nofollow noopener" target="_blank">${new URL(field.value).href}</a>`
|
||||||
|
: field.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (profile.twitter) {
|
if (profile.twitter) {
|
||||||
attachment.push({
|
attachment.push({
|
||||||
type: 'PropertyValue',
|
type: 'PropertyValue',
|
||||||
|
@ -2,6 +2,9 @@ import * as Koa from 'koa';
|
|||||||
|
|
||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
import { ILocalUser } from '../../../models/entities/user';
|
import { ILocalUser } from '../../../models/entities/user';
|
||||||
|
import { Signins } from '../../../models';
|
||||||
|
import { genId } from '../../../misc/gen-id';
|
||||||
|
import { publishMainStream } from '../../../services/stream';
|
||||||
|
|
||||||
export default function(ctx: Koa.BaseContext, user: ILocalUser, redirect = false) {
|
export default function(ctx: Koa.BaseContext, user: ILocalUser, redirect = false) {
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
@ -24,4 +27,19 @@ export default function(ctx: Koa.BaseContext, user: ILocalUser, redirect = false
|
|||||||
ctx.body = { i: user.token };
|
ctx.body = { i: user.token };
|
||||||
ctx.status = 200;
|
ctx.status = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
// Append signin history
|
||||||
|
const record = await Signins.save({
|
||||||
|
id: genId(),
|
||||||
|
createdAt: new Date(),
|
||||||
|
userId: user.id,
|
||||||
|
ip: ctx.ip,
|
||||||
|
headers: ctx.headers,
|
||||||
|
success: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Publish signin event
|
||||||
|
publishMainStream(user.id, 'signin', await Signins.pack(record));
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,16 @@ export const meta = {
|
|||||||
'remote',
|
'remote',
|
||||||
]),
|
]),
|
||||||
default: 'local'
|
default: 'local'
|
||||||
|
},
|
||||||
|
|
||||||
|
username: {
|
||||||
|
validator: $.optional.str,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
|
||||||
|
hostname: {
|
||||||
|
validator: $.optional.str,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -70,6 +80,14 @@ export default define(meta, async (ps, me) => {
|
|||||||
case 'remote': query.andWhere('user.host IS NOT NULL'); break;
|
case 'remote': query.andWhere('user.host IS NOT NULL'); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.username) {
|
||||||
|
query.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ps.hostname) {
|
||||||
|
query.andWhere('user.host like :hostname', { hostname: '%' + ps.hostname.toLowerCase() + '%' });
|
||||||
|
}
|
||||||
|
|
||||||
switch (ps.sort) {
|
switch (ps.sort) {
|
||||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||||
|
@ -5,6 +5,7 @@ import deleteFollowing from '../../../../services/following/delete';
|
|||||||
import { Users, Followings } from '../../../../models';
|
import { Users, Followings } from '../../../../models';
|
||||||
import { User } from '../../../../models/entities/user';
|
import { User } from '../../../../models/entities/user';
|
||||||
import { insertModerationLog } from '../../../../services/insert-moderation-log';
|
import { insertModerationLog } from '../../../../services/insert-moderation-log';
|
||||||
|
import { doPostSuspend } from '../../../../services/suspend-user';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
@ -51,7 +52,10 @@ export default define(meta, async (ps, me) => {
|
|||||||
targetId: user.id,
|
targetId: user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
unFollowAll(user);
|
(async () => {
|
||||||
|
await doPostSuspend(user).catch(e => {});
|
||||||
|
await unFollowAll(user).catch(e => {});
|
||||||
|
})();
|
||||||
});
|
});
|
||||||
|
|
||||||
async function unFollowAll(follower: User) {
|
async function unFollowAll(follower: User) {
|
||||||
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||||||
import define from '../../define';
|
import define from '../../define';
|
||||||
import { Users } from '../../../../models';
|
import { Users } from '../../../../models';
|
||||||
import { insertModerationLog } from '../../../../services/insert-moderation-log';
|
import { insertModerationLog } from '../../../../services/insert-moderation-log';
|
||||||
|
import { doPostUnsuspend } from '../../../../services/unsuspend-user';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
@ -40,4 +41,6 @@ export default define(meta, async (ps, me) => {
|
|||||||
insertModerationLog(me, 'unsuspend', {
|
insertModerationLog(me, 'unsuspend', {
|
||||||
targetId: user.id,
|
targetId: user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
doPostUnsuspend(user);
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import * as bcrypt from 'bcryptjs';
|
|||||||
import define from '../../define';
|
import define from '../../define';
|
||||||
import { Users, UserProfiles } from '../../../../models';
|
import { Users, UserProfiles } from '../../../../models';
|
||||||
import { ensure } from '../../../../prelude/ensure';
|
import { ensure } from '../../../../prelude/ensure';
|
||||||
|
import { doPostSuspend } from '../../../../services/suspend-user';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
@ -26,5 +27,8 @@ export default define(meta, async (ps, user) => {
|
|||||||
throw new Error('incorrect password');
|
throw new Error('incorrect password');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 物理削除する前にDelete activityを送信する
|
||||||
|
await doPostSuspend(user).catch(e => {});
|
||||||
|
|
||||||
await Users.delete(user.id);
|
await Users.delete(user.id);
|
||||||
});
|
});
|
||||||
|
@ -77,6 +77,13 @@ export const meta = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
validator: $.optional.arr($.object()).range(1, 4),
|
||||||
|
desc: {
|
||||||
|
'ja-JP': 'プロフィール補足情報'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
isLocked: {
|
isLocked: {
|
||||||
validator: $.optional.bool,
|
validator: $.optional.bool,
|
||||||
desc: {
|
desc: {
|
||||||
@ -226,6 +233,14 @@ export default define(meta, async (ps, user, app) => {
|
|||||||
profileUpdates.pinnedPageId = null;
|
profileUpdates.pinnedPageId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.fields) {
|
||||||
|
profileUpdates.fields = ps.fields
|
||||||
|
.filter(x => typeof x.name === 'string' && x.name !== '' && typeof x.value === 'string' && x.value !== '')
|
||||||
|
.map(x => {
|
||||||
|
return { name: x.name, value: x.value };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//#region emojis/tags
|
//#region emojis/tags
|
||||||
|
|
||||||
let emojis = [] as string[];
|
let emojis = [] as string[];
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as Koa from 'koa';
|
import * as Koa from 'koa';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import * as bcrypt from 'bcryptjs';
|
||||||
import * as speakeasy from 'speakeasy';
|
import * as speakeasy from 'speakeasy';
|
||||||
import { publishMainStream } from '../../../services/stream';
|
|
||||||
import signin from '../common/signin';
|
import signin from '../common/signin';
|
||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '../../../models';
|
import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '../../../models';
|
||||||
@ -53,35 +52,31 @@ export default async (ctx: Koa.BaseContext) => {
|
|||||||
// Compare password
|
// Compare password
|
||||||
const same = await bcrypt.compare(password, profile.password!);
|
const same = await bcrypt.compare(password, profile.password!);
|
||||||
|
|
||||||
async function fail(status?: number, failure?: {error: string}) {
|
async function fail(status?: number, failure?: { error: string }) {
|
||||||
// Append signin history
|
// Append signin history
|
||||||
const record = await Signins.save({
|
await Signins.save({
|
||||||
id: genId(),
|
id: genId(),
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
ip: ctx.ip,
|
ip: ctx.ip,
|
||||||
headers: ctx.headers,
|
headers: ctx.headers,
|
||||||
success: !!(status || failure)
|
success: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Publish signin event
|
ctx.throw(status || 500, failure || { error: 'someting happened' });
|
||||||
publishMainStream(user.id, 'signin', await Signins.pack(record));
|
|
||||||
|
|
||||||
if (status && failure) {
|
|
||||||
ctx.throw(status, failure);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.twoFactorEnabled) {
|
if (!profile.twoFactorEnabled) {
|
||||||
if (same) {
|
if (same) {
|
||||||
signin(ctx, user);
|
signin(ctx, user);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'incorrect password'
|
error: 'incorrect password'
|
||||||
});
|
});
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
if (!same) {
|
if (!same) {
|
||||||
@ -169,6 +164,7 @@ export default async (ctx: Koa.BaseContext) => {
|
|||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
signin(ctx, user);
|
signin(ctx, user);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'invalid challenge data'
|
error: 'invalid challenge data'
|
||||||
@ -191,6 +187,7 @@ export default async (ctx: Koa.BaseContext) => {
|
|||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'no keys found'
|
error: 'no keys found'
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 32 byte challenge
|
// 32 byte challenge
|
||||||
@ -219,6 +216,5 @@ export default async (ctx: Koa.BaseContext) => {
|
|||||||
ctx.status = 200;
|
ctx.status = 200;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// never get here
|
||||||
await fail();
|
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ import generateUserToken from '../common/generate-native-user-token';
|
|||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||||
import * as recaptcha from 'recaptcha-promise';
|
import * as recaptcha from 'recaptcha-promise';
|
||||||
import { Users, RegistrationTickets } from '../../../models';
|
import { Users, Signins, RegistrationTickets } from '../../../models';
|
||||||
import { genId } from '../../../misc/gen-id';
|
import { genId } from '../../../misc/gen-id';
|
||||||
import { usersChart } from '../../../services/chart';
|
import { usersChart } from '../../../services/chart';
|
||||||
import { User } from '../../../models/entities/user';
|
import { User } from '../../../models/entities/user';
|
||||||
@ -137,6 +137,16 @@ export default async (ctx: Koa.BaseContext) => {
|
|||||||
|
|
||||||
usersChart.update(account, true);
|
usersChart.update(account, true);
|
||||||
|
|
||||||
|
// Append signin history
|
||||||
|
await Signins.save({
|
||||||
|
id: genId(),
|
||||||
|
createdAt: new Date(),
|
||||||
|
userId: account.id,
|
||||||
|
ip: ctx.ip,
|
||||||
|
headers: ctx.headers,
|
||||||
|
success: true
|
||||||
|
});
|
||||||
|
|
||||||
const res = await Users.pack(account, account, {
|
const res = await Users.pack(account, account, {
|
||||||
detail: true,
|
detail: true,
|
||||||
includeSecrets: true
|
includeSecrets: true
|
||||||
|
@ -156,11 +156,17 @@ router.get('/@:user', async (ctx, next) => {
|
|||||||
if (user != null) {
|
if (user != null) {
|
||||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta();
|
||||||
|
const me = profile.fields
|
||||||
|
? profile.fields
|
||||||
|
.filter(filed => filed.value != null && filed.value.match(/^https?:/))
|
||||||
|
.map(field => field.value)
|
||||||
|
: [];
|
||||||
|
|
||||||
await ctx.render('user', {
|
await ctx.render('user', {
|
||||||
user, profile,
|
user, profile, me,
|
||||||
instanceName: meta.name || 'Misskey'
|
instanceName: meta.name || 'Misskey'
|
||||||
});
|
});
|
||||||
ctx.set('Cache-Control', 'public, max-age=180');
|
ctx.set('Cache-Control', 'public, max-age=30');
|
||||||
} else {
|
} else {
|
||||||
// リモートユーザーなので
|
// リモートユーザーなので
|
||||||
await next();
|
await next();
|
||||||
|
@ -44,3 +44,4 @@ html
|
|||||||
<svg viewBox="0 0 50 50">
|
<svg viewBox="0 0 50 50">
|
||||||
<path fill=#fb4e4e d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" />
|
<path fill=#fb4e4e d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
block content
|
||||||
|
@ -36,3 +36,8 @@ block meta
|
|||||||
link(rel='alternate' href=user.uri type='application/activity+json')
|
link(rel='alternate' href=user.uri type='application/activity+json')
|
||||||
if profile.url
|
if profile.url
|
||||||
link(rel='alternate' href=profile.url type='text/html')
|
link(rel='alternate' href=profile.url type='text/html')
|
||||||
|
|
||||||
|
block content
|
||||||
|
div#me
|
||||||
|
each m in me
|
||||||
|
a(rel='me' href=`${m}`) #{m}
|
||||||
|
34
src/services/suspend-user.ts
Normal file
34
src/services/suspend-user.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import renderDelete from '../remote/activitypub/renderer/delete';
|
||||||
|
import { renderActivity } from '../remote/activitypub/renderer';
|
||||||
|
import { deliver } from '../queue';
|
||||||
|
import config from '../config';
|
||||||
|
import { User } from '../models/entities/user';
|
||||||
|
import { Users, Followings } from '../models';
|
||||||
|
import { Not, IsNull } from 'typeorm';
|
||||||
|
|
||||||
|
export async function doPostSuspend(user: User) {
|
||||||
|
if (Users.isLocalUser(user)) {
|
||||||
|
// 知り得る全SharedInboxにDelete配信
|
||||||
|
const content = renderActivity(renderDelete(`${config.url}/users/${user.id}`, user));
|
||||||
|
|
||||||
|
const queue: string[] = [];
|
||||||
|
|
||||||
|
const followings = await Followings.find({
|
||||||
|
where: [
|
||||||
|
{ followerSharedInbox: Not(IsNull()) },
|
||||||
|
{ followeeSharedInbox: Not(IsNull()) }
|
||||||
|
],
|
||||||
|
select: ['followerSharedInbox', 'followeeSharedInbox']
|
||||||
|
});
|
||||||
|
|
||||||
|
const inboxes = followings.map(x => x.followerSharedInbox || x.followeeSharedInbox);
|
||||||
|
|
||||||
|
for (const inbox of inboxes) {
|
||||||
|
if (inbox != null && !queue.includes(inbox)) queue.push(inbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const inbox of queue) {
|
||||||
|
deliver(user as any, content, inbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/services/unsuspend-user.ts
Normal file
35
src/services/unsuspend-user.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import renderDelete from '../remote/activitypub/renderer/delete';
|
||||||
|
import renderUndo from '../remote/activitypub/renderer/undo';
|
||||||
|
import { renderActivity } from '../remote/activitypub/renderer';
|
||||||
|
import { deliver } from '../queue';
|
||||||
|
import config from '../config';
|
||||||
|
import { User } from '../models/entities/user';
|
||||||
|
import { Users, Followings } from '../models';
|
||||||
|
import { Not, IsNull } from 'typeorm';
|
||||||
|
|
||||||
|
export async function doPostUnsuspend(user: User) {
|
||||||
|
if (Users.isLocalUser(user)) {
|
||||||
|
// 知り得る全SharedInboxにUndo Delete配信
|
||||||
|
const content = renderActivity(renderUndo(renderDelete(`${config.url}/users/${user.id}`, user), user));
|
||||||
|
|
||||||
|
const queue: string[] = [];
|
||||||
|
|
||||||
|
const followings = await Followings.find({
|
||||||
|
where: [
|
||||||
|
{ followerSharedInbox: Not(IsNull()) },
|
||||||
|
{ followeeSharedInbox: Not(IsNull()) }
|
||||||
|
],
|
||||||
|
select: ['followerSharedInbox', 'followeeSharedInbox']
|
||||||
|
});
|
||||||
|
|
||||||
|
const inboxes = followings.map(x => x.followerSharedInbox || x.followeeSharedInbox);
|
||||||
|
|
||||||
|
for (const inbox of inboxes) {
|
||||||
|
if (inbox != null && !queue.includes(inbox)) queue.push(inbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const inbox of queue) {
|
||||||
|
deliver(user as any, content, inbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user