Merge branch 'develop'

This commit is contained in:
syuilo 2019-04-17 02:58:09 +09:00
commit 532ef744f4
No known key found for this signature in database
GPG Key ID: BDC4C49D06AB9D69
46 changed files with 379 additions and 189 deletions

View File

@ -5,12 +5,6 @@ executors:
working_directory: /tmp/workspace working_directory: /tmp/workspace
docker: docker:
- image: misskey/ci:latest - image: misskey/ci:latest
- image: circleci/mongo:latest
with-redis:
working_directory: /tmp/workspace
docker:
- image: misskey/ci:latest
- image: circleci/mongo:latest
- image: circleci/redis:latest - image: circleci/redis:latest
docker: docker:
working_directory: /tmp/workspace working_directory: /tmp/workspace

View File

@ -5,6 +5,16 @@ If you encounter any problems with updating, please try the following:
1. `npm run clean` or `npm run cleanall` 1. `npm run clean` or `npm run cleanall`
2. Retry update (Don't forget `npm i`) 2. Retry update (Don't forget `npm i`)
11.1.4 (2019/04/17)
-------------------
### Fixes
* タイムライン取得時に削除されたファイルを添付している投稿が含まれているとサーバーでエラーになる問題を修正
* 管理画面のインスタンスメニューで変更前の設定が読み込まれないことがある問題を修正
* 猫ではないのに猫のままで表示される問題を修正
* admin/driveのアイコンがずれてる問題を修正
* チャートで大きな数値を扱えない問題を修正
* UIの修正
11.1.3 (2019/04/16) 11.1.3 (2019/04/16)
------------------- -------------------
### Fixes ### Fixes

View File

@ -140,7 +140,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
</tr></table> </tr></table>
<table><tr> <table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4.jpe?token-time=2145916800&token-hash=UslrPVM-8TXOe8AapuNiaFYjcIJgPNcU-fKpGbfGJNI%3D" alt="Damillora" width="100"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4.jpe?token-time=2145916800&token-hash=UslrPVM-8TXOe8AapuNiaFYjcIJgPNcU-fKpGbfGJNI%3D" alt="Damillora" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/935a10339daa4ede8e555903a0707060/1.png?token-time=2145916800&token-hash=c1XAS1qGBPxVdCvnICxtAUmx41mVkMG87h7cIRF9YYE%3D" alt="Atsuko Tominaga" width="100"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/83884b38afc74d4cbe83c30a13b10edd/1.png?token-time=2145916800&token-hash=R5Tog8RWg0rguRoCIoir3lThokrdPvs8Utfikhc0nhY%3D" alt="Atsuko Tominaga" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
@ -163,7 +163,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
</tr><tr> </tr><tr>
</tr></table> </tr></table>
**Last updated:** Mon, 15 Apr 2019 01:59:07 UTC **Last updated:** Mon, 15 Apr 2019 12:07:08 UTC
<!-- PATREON_END --> <!-- PATREON_END -->
:four_leaf_clover: Copyright :four_leaf_clover: Copyright

View File

@ -9,9 +9,17 @@ This guide describes how to install and setup Misskey with Docker.
*1.* Download Misskey *1.* Download Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
1. `git clone -b master git://github.com/syuilo/misskey.git` Clone Misskey repository's master branch. 1. Clone Misskey repository's master branch.
2. `cd misskey` Move to misskey directory.
3. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) tag. `git clone -b master git://github.com/syuilo/misskey.git`
2. Move to misskey directory.
`cd misskey`
3. Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) tag.
`git checkout master`
*2.* Configure Misskey *2.* Configure Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
@ -71,9 +79,9 @@ Well done! Now you have an environment to run Misskey.
Just `docker-compose up -d`. GLHF! Just `docker-compose up -d`. GLHF!
### How to update your Misskey server to the latest version ### How to update your Misskey server to the latest version
1. `git fetch` 1. `git stash`
2. `git stash` 2. `git checkout master`
3. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` 3. `git pull`
4. `git stash pop` 4. `git stash pop`
5. `docker-compose build` 5. `docker-compose build`
6. Check [ChangeLog](../CHANGELOG.md) for migration information 6. Check [ChangeLog](../CHANGELOG.md) for migration information

View File

@ -10,9 +10,17 @@ Ce guide explique comment installer et configurer Misskey avec Docker.
*1.* Télécharger Misskey *1.* Télécharger Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
1. `git clone -b master git://github.com/syuilo/misskey.git` Clone le dépôt de Misskey sur la branche master. 1. Clone le dépôt de Misskey sur la branche master.
2. `cd misskey` Naviguez dans le dossier du dépôt.
3. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout sur le tag de la [dernière version](https://github.com/syuilo/misskey/releases/latest). `git clone -b master git://github.com/syuilo/misskey.git`
2. Naviguez dans le dossier du dépôt.
`cd misskey`
3. Checkout sur le tag de la [dernière version](https://github.com/syuilo/misskey/releases/latest).
`git checkout master`
*2.* Configuration de Misskey *2.* Configuration de Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
@ -38,9 +46,9 @@ Parfait, Vous avez un environnement prêt pour démarrer Misskey.
Utilisez la commande `docker-compose up -d`. GLHF! Utilisez la commande `docker-compose up -d`. GLHF!
### How to update your Misskey server to the latest version ### How to update your Misskey server to the latest version
1. `git fetch` 1. `git stash`
2. `git stash` 2. `git checkout master`
3. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` 3. `git pull`
4. `git stash pop` 4. `git stash pop`
5. `docker-compose build` 5. `docker-compose build`
6. Consultez le [ChangeLog](../CHANGELOG.md) pour avoir les éventuelles informations de migration 6. Consultez le [ChangeLog](../CHANGELOG.md) pour avoir les éventuelles informations de migration
@ -52,14 +60,28 @@ Utilisez la commande `docker-compose up -d`. GLHF!
### Configuration d'ElasticSearch (pour la fonction de recherche) ### Configuration d'ElasticSearch (pour la fonction de recherche)
*1.* Préparation de l'environnement *1.* Préparation de l'environnement
---------------------------------------------------------------- ----------------------------------------------------------------
1. `mkdir elasticsearch && chown 1000:1000 elasticsearch` Permet de créer le dossier d'accueil de la base ElasticSearch aves les bons droits 1. Permet de créer le dossier d'accueil de la base ElasticSearch aves les bons droits
2. `sysctl -w vm.max_map_count=262144` Augmente la valeur max du paramètre map_count du système (valeur minimum pour pouvoir lancer ES)
`mkdir elasticsearch && chown 1000:1000 elasticsearch`
2. Augmente la valeur max du paramètre map_count du système (valeur minimum pour pouvoir lancer ES)
`sysctl -w vm.max_map_count=262144`
*2.* Après lancement du docker-compose, initialisation de la base ElasticSearch *2.* Après lancement du docker-compose, initialisation de la base ElasticSearch
---------------------------------------------------------------- ----------------------------------------------------------------
1. `docker-compose -it web /bin/sh` Connexion dans le conteneur web 1. Connexion dans le conteneur web
2. `apk add curl` Ajout du paquet curl
3. `curl -X PUT "es:9200/misskey" -H 'Content-Type: application/json' -d'{ "settings" : { "index" : { } }}'` Création de la base ES `docker-compose -it web /bin/sh`
2. Ajout du paquet curl
`apk add curl`
3. Création de la base ES
`curl -X PUT "es:9200/misskey" -H 'Content-Type: application/json' -d'{ "settings" : { "index" : { } }}'`
4. `exit` 4. `exit`
---------------------------------------------------------------- ----------------------------------------------------------------

View File

@ -9,9 +9,17 @@ Dockerを使ったMisskey構築方法
*1.* Misskeyのダウンロード *1.* Misskeyのダウンロード
---------------------------------------------------------------- ----------------------------------------------------------------
1. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン 1. masterブランチからMisskeyレポジトリをクローン
2. `cd misskey` misskeyディレクトリに移動
3. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認 `git clone -b master git://github.com/syuilo/misskey.git`
2. misskeyディレクトリに移動
`cd misskey`
3. [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
`git checkout master`
*2.* 設定ファイルの作成と編集 *2.* 設定ファイルの作成と編集
---------------------------------------------------------------- ----------------------------------------------------------------
@ -71,9 +79,9 @@ docker-compose run --rm web npm run init
`docker-compose up -d`するだけです。GLHF! `docker-compose up -d`するだけです。GLHF!
### Misskeyを最新バージョンにアップデートする方法: ### Misskeyを最新バージョンにアップデートする方法:
1. `git fetch` 1. `git stash`
2. `git stash` 2. `git checkout master`
3. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` 3. `git pull`
4. `git stash pop` 4. `git stash pop`
5. `docker-compose build` 5. `docker-compose build`
6. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する 6. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する

View File

@ -29,7 +29,7 @@ server {
listen [::]:443 http2; listen [::]:443 http2;
server_name example.tld; server_name example.tld;
ssl on; ssl on;
ssl_session_cache shared:ssl_session_cache:10m; ssl_session_cache shared:ssl_session_cache:10m;
# To use Let's Encrypt certificate # To use Let's Encrypt certificate
ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;

View File

@ -32,15 +32,32 @@ Please install and setup these softwares:
*3.* Install Misskey *3.* Install Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
1. `su - misskey` Connect to misskey user. 1. Connect to misskey user.
2. `git clone -b master git://github.com/syuilo/misskey.git` Clone the misskey repo from master branch.
3. `cd misskey` Navigate to misskey directory `su - misskey`
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
5. `npm install` Install misskey dependencies. 2. Clone the misskey repo from master branch.
`git clone -b master git://github.com/syuilo/misskey.git`
3. Navigate to misskey directory
`cd misskey`
4. Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
`git checkout master`
5. Install misskey dependencies.
`npm install`
*4.* Configure Misskey *4.* Configure Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`. 1. Copy the `.config/example.yml` and rename it to `default.yml`.
`cp .config/example.yml .config/default.yml`
2. Edit `default.yml` 2. Edit `default.yml`
*5.* Build Misskey *5.* Build Misskey
@ -74,37 +91,45 @@ Just `NODE_ENV=production npm start`. GLHF!
### Launch with systemd ### Launch with systemd
1. Create a systemd service here: `/etc/systemd/system/misskey.service` 1. Create a systemd service here
`/etc/systemd/system/misskey.service`
2. Edit it, and paste this and save: 2. Edit it, and paste this and save:
``` ```
[Unit] [Unit]
Description=Misskey daemon Description=Misskey daemon
[Service] [Service]
Type=simple Type=simple
User=misskey User=misskey
ExecStart=/usr/bin/npm start ExecStart=/usr/bin/npm start
WorkingDirectory=/home/misskey/misskey WorkingDirectory=/home/misskey/misskey
Environment="NODE_ENV=production" Environment="NODE_ENV=production"
TimeoutSec=60 TimeoutSec=60
StandardOutput=syslog StandardOutput=syslog
StandardError=syslog StandardError=syslog
SyslogIdentifier=misskey SyslogIdentifier=misskey
Restart=always Restart=always
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
3. `systemctl daemon-reload ; systemctl enable misskey` Reload systemd and enable the misskey service. 3. Reload systemd and enable the misskey service.
4. `systemctl start misskey` Start the misskey service.
`systemctl daemon-reload ; systemctl enable misskey`
4. Start the misskey service.
`systemctl start misskey`
You can check if the service is running with `systemctl status misskey`. 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 fetch` 1. `git checkout master`
2. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` 2. `git pull`
3. `npm install` 3. `npm install`
4. `NODE_ENV=production npm run build` 4. `NODE_ENV=production npm run build`
5. Check [ChangeLog](../CHANGELOG.md) for migration information 5. Check [ChangeLog](../CHANGELOG.md) for migration information

View File

@ -32,15 +32,32 @@ Installez les paquets suivants :
*3.* Installation de Misskey *3.* Installation de Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
1. `su - misskey` Basculez vers l'utilisateur misskey. 1. Basculez vers l'utilisateur misskey.
2. `git clone -b master git://github.com/syuilo/misskey.git` Clonez la branche master du dépôt misskey.
3. `cd misskey` Accédez au dossier misskey. `su - misskey`
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
5. `npm install` Installez les dépendances de misskey. 2. Clonez la branche master du dépôt misskey.
`git clone -b master git://github.com/syuilo/misskey.git`
3. Accédez au dossier misskey.
`cd misskey`
4. Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
`git checkout master`
5. Installez les dépendances de misskey.
`npm install`
*4.* Création du fichier de configuration *4.* Création du fichier de configuration
---------------------------------------------------------------- ----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le`default.yml`. 1. Copiez le fichier `.config/example.yml` et renommez-le`default.yml`.
`cp .config/example.yml .config/default.yml`
2. Editez le fichier `default.yml` 2. Editez le fichier `default.yml`
*5.* Construction de Misskey *5.* Construction de Misskey
@ -68,37 +85,45 @@ Lancez tout simplement `NODE_ENV=production npm start`. Bonne chance et amusez-v
### Démarrage avec systemd ### Démarrage avec systemd
1. Créez un service systemd sur : `/etc/systemd/system/misskey.service` 1. Créez un service systemd sur
`/etc/systemd/system/misskey.service`
2. Editez-le puis copiez et coller ceci dans le fichier : 2. Editez-le puis copiez et coller ceci dans le fichier :
``` ```
[Unit] [Unit]
Description=Misskey daemon Description=Misskey daemon
[Service] [Service]
Type=simple Type=simple
User=misskey User=misskey
ExecStart=/usr/bin/npm start ExecStart=/usr/bin/npm start
WorkingDirectory=/home/misskey/misskey WorkingDirectory=/home/misskey/misskey
Environment="NODE_ENV=production" Environment="NODE_ENV=production"
TimeoutSec=60 TimeoutSec=60
StandardOutput=syslog StandardOutput=syslog
StandardError=syslog StandardError=syslog
SyslogIdentifier=misskey SyslogIdentifier=misskey
Restart=always Restart=always
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
3. `systemctl daemon-reload ; systemctl enable misskey` Redémarre systemd et active le service misskey. 3. Redémarre systemd et active le service misskey.
4. `systemctl start misskey` Démarre le service misskey.
`systemctl daemon-reload ; systemctl enable misskey`
4. Démarre le service misskey.
`systemctl start misskey`
Vous pouvez vérifier si le service a démarré en utilisant la commande `systemctl status misskey`. Vous pouvez vérifier si le service a démarré en utilisant la commande `systemctl status misskey`.
### 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 fetch` 1. `git checkout master`
2. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` 2. `git pull`
3. `npm install` 3. `npm install`
4. `NODE_ENV=production npm run build` 4. `NODE_ENV=production npm run build`
5. Consultez [ChangeLog](../CHANGELOG.md) pour les information de migration. 5. Consultez [ChangeLog](../CHANGELOG.md) pour les information de migration.

View File

@ -33,15 +33,32 @@ adduser --disabled-password --disabled-login misskey
*3.* Misskeyのインストール *3.* Misskeyのインストール
---------------------------------------------------------------- ----------------------------------------------------------------
1. `su - misskey` misskeyユーザーを使用 1. misskeyユーザーを使用
2. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン
3. `cd misskey` misskeyディレクトリに移動 `su - misskey`
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
5. `npm install` Misskeyの依存パッケージをインストール 2. masterブランチからMisskeyレポジトリをクローン
`git clone -b master git://github.com/syuilo/misskey.git`
3. misskeyディレクトリに移動
`cd misskey`
4. [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
`git checkout master`
5. Misskeyの依存パッケージをインストール
`npm install`
*4.* 設定ファイルを作成する *4.* 設定ファイルを作成する
---------------------------------------------------------------- ----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする。 1. `.config/example.yml`をコピーし名前を`default.yml`にする。
`cp .config/example.yml .config/default.yml`
2. `default.yml` を編集する。 2. `default.yml` を編集する。
*5.* Misskeyのビルド *5.* Misskeyのビルド
@ -73,38 +90,47 @@ npm run init
`NODE_ENV=production npm start`するだけです。GLHF! `NODE_ENV=production npm start`するだけです。GLHF!
### systemdを用いた起動 ### systemdを用いた起動
1. systemdサービスのファイルを作成: `/etc/systemd/system/misskey.service` 1. systemdサービスのファイルを作成
`/etc/systemd/system/misskey.service`
2. エディタで開き、以下のコードを貼り付けて保存: 2. エディタで開き、以下のコードを貼り付けて保存:
``` ```
[Unit] [Unit]
Description=Misskey daemon Description=Misskey daemon
[Service] [Service]
Type=simple Type=simple
User=misskey User=misskey
ExecStart=/usr/bin/npm start ExecStart=/usr/bin/npm start
WorkingDirectory=/home/misskey/misskey WorkingDirectory=/home/misskey/misskey
Environment="NODE_ENV=production" Environment="NODE_ENV=production"
TimeoutSec=60 TimeoutSec=60
StandardOutput=syslog StandardOutput=syslog
StandardError=syslog StandardError=syslog
SyslogIdentifier=misskey SyslogIdentifier=misskey
Restart=always Restart=always
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
CentOSで1024以下のポートを使用してMisskeyを使用する場合は`ExecStart=/usr/bin/sudo /usr/bin/npm start`に変更する必要があります。
3. `systemctl daemon-reload ; systemctl enable misskey` systemdを再読み込みしmisskeyサービスを有効化 CentOSで1024以下のポートを使用してMisskeyを使用する場合は`ExecStart=/usr/bin/sudo /usr/bin/npm start`に変更する必要があります。
4. `systemctl start misskey` misskeyサービスの起動
3. systemdを再読み込みしmisskeyサービスを有効化
`systemctl daemon-reload ; systemctl enable misskey`
4. misskeyサービスの起動
`systemctl start misskey`
`systemctl status misskey`と入力すると、サービスの状態を調べることができます。 `systemctl status misskey`と入力すると、サービスの状態を調べることができます。
### Misskeyを最新バージョンにアップデートする方法: ### Misskeyを最新バージョンにアップデートする方法:
1. `git fetch` 1. `git checkout master`
2. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` 2. `git pull`
3. `npm install` 3. `npm install`
4. `NODE_ENV=production npm run build` 4. `NODE_ENV=production npm run build`
5. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する 5. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する

View File

@ -313,6 +313,7 @@ common:
nav: "ナビゲーション" nav: "ナビゲーション"
tips: "ヒント" tips: "ヒント"
hashtags: "ハッシュタグ" hashtags: "ハッシュタグ"
queue: "キュー"
dev: "アプリの作成に失敗しました。再度お試しください。" dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい" ai-chan-kawaii: "藍ちゃかわいい"
@ -1549,6 +1550,7 @@ desktop/views/widgets/polls.vue:
desktop/views/widgets/post-form.vue: desktop/views/widgets/post-form.vue:
title: "投稿" title: "投稿"
note: "投稿" note: "投稿"
something-happened: "何らかの事情で投稿できませんでした。"
desktop/views/widgets/profile.vue: desktop/views/widgets/profile.vue:
update-banner: "クリックでバナー編集" update-banner: "クリックでバナー編集"
@ -1641,7 +1643,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "この投稿を引用... (オプション)" quote-placeholder: "この投稿を引用... (オプション)"
reply-placeholder: "この投稿への返信..." reply-placeholder: "この投稿への返信..."
cw-placeholder: "内容への注釈 (オプション)" cw-placeholder: "内容への注釈 (オプション)"
location-alert: "お使いの端末は位置情報に対応していません" geolocation-alert: "お使いの端末は位置情報に対応していません"
error: "エラー" error: "エラー"
username-prompt: "ユーザー名を入力してください" username-prompt: "ユーザー名を入力してください"

View File

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "11.1.3", "version": "11.1.4",
"codename": "daybreak", "codename": "daybreak",
"repository": { "repository": {
"type": "git", "type": "git",
@ -64,8 +64,6 @@
"@types/lolex": "3.1.1", "@types/lolex": "3.1.1",
"@types/minio": "7.0.1", "@types/minio": "7.0.1",
"@types/mocha": "5.2.6", "@types/mocha": "5.2.6",
"@types/mongodb": "3.1.22",
"@types/monk": "6.0.0",
"@types/node": "11.13.4", "@types/node": "11.13.4",
"@types/nodemailer": "4.6.7", "@types/nodemailer": "4.6.7",
"@types/nprogress": "0.0.29", "@types/nprogress": "0.0.29",
@ -167,8 +165,6 @@
"mocha": "6.1.3", "mocha": "6.1.3",
"moji": "0.5.1", "moji": "0.5.1",
"moment": "2.24.0", "moment": "2.24.0",
"mongodb": "3.2.3",
"monk": "6.0.6",
"ms": "2.1.1", "ms": "2.1.1",
"nested-property": "0.0.7", "nested-property": "0.0.7",
"node-fetch": "2.3.0", "node-fetch": "2.3.0",

View File

@ -242,7 +242,7 @@ export default Vue.extend({
> div:nth-child(1) > div:nth-child(1)
> .thumbnail > .thumbnail
display block display flex
width 64px width 64px
height 64px height 64px
background-size cover background-size cover

View File

@ -195,7 +195,7 @@ export default Vue.extend({
}, },
created() { created() {
this.$root.getMeta().then(meta => { this.$root.getMeta(true).then(meta => {
this.maintainerName = meta.maintainerName; this.maintainerName = meta.maintainerName;
this.maintainerEmail = meta.maintainerEmail; this.maintainerEmail = meta.maintainerEmail;
this.disableRegistration = meta.disableRegistration; this.disableRegistration = meta.disableRegistration;

View File

@ -134,7 +134,7 @@ export default (opts: Opts = {}) => ({
}, },
reactDirectly(reaction) { reactDirectly(reaction) {
(this.$root.api('notes/reactions/create', { this.$root.api('notes/reactions/create', {
noteId: this.appearNote.id, noteId: this.appearNote.id,
reaction: reaction reaction: reaction
}); });

View File

@ -85,7 +85,10 @@ export default Vue.extend({
} }
} else { } else {
if (items[0].kind == 'file') { if (items[0].kind == 'file') {
alert(this.$t('only-one-file-attached')); this.$root.dialog({
type: 'error',
text: this.$t('only-one-file-attached')
});
} }
} }
}, },
@ -107,7 +110,10 @@ export default Vue.extend({
return; return;
} else if (e.dataTransfer.files.length > 1) { } else if (e.dataTransfer.files.length > 1) {
e.preventDefault(); e.preventDefault();
alert(this.$t('only-one-file-attached')); this.$root.dialog({
type: 'error',
text: this.$t('only-one-file-attached')
});
return; return;
} }

View File

@ -125,7 +125,10 @@ export default Vue.extend({
this.form.upload(e.dataTransfer.files[0]); this.form.upload(e.dataTransfer.files[0]);
return; return;
} else if (e.dataTransfer.files.length > 1) { } else if (e.dataTransfer.files.length > 1) {
alert(this.$t('only-one-file-attached')); this.$root.dialog({
type: 'error',
text: this.$t('only-one-file-attached')
});
return; return;
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="skeikyzd" v-show="files.length != 0"> <div class="skeikyzd" v-show="files.length != 0">
<x-draggable class="files" :list="files" :options="{ animation: 150 }"> <x-draggable class="files" :list="files" animation="150">
<div v-for="file in files" :key="file.id" @click="showFileMenu(file, $event)" @contextmenu.prevent="showFileMenu(file, $event)"> <div v-for="file in files" :key="file.id" @click="showFileMenu(file, $event)" @contextmenu.prevent="showFileMenu(file, $event)">
<x-file-thumbnail :data-id="file.id" class="thumbnail" :file="file" fit="cover"/> <x-file-thumbnail :data-id="file.id" class="thumbnail" :file="file" fit="cover"/>
<img class="remove" @click.stop="detachMedia(file.id)" src="/assets/desktop/remove.png" :title="$t('attach-cancel')" alt=""/> <img class="remove" @click.stop="detachMedia(file.id)" src="/assets/desktop/remove.png" :title="$t('attach-cancel')" alt=""/>

View File

@ -84,7 +84,7 @@
<ui-info v-else warn>{{ $t('email-not-verified') }}</ui-info> <ui-info v-else warn>{{ $t('email-not-verified') }}</ui-info>
</template> </template>
<ui-input v-model="email" type="email"><span>{{ $t('email-address') }}</span></ui-input> <ui-input v-model="email" type="email"><span>{{ $t('email-address') }}</span></ui-input>
<ui-button @click="updateEmail()"><fa :icon="faSave"/> {{ $t('save') }}</ui-button> <ui-button @click="updateEmail()" :disabled="email === $store.state.i.email"><fa :icon="faSave"/> {{ $t('save') }}</ui-button>
</div> </div>
</section> </section>

View File

@ -542,8 +542,8 @@ export default Vue.extend({
this.latestVersion = newer; this.latestVersion = newer;
if (newer == null) { if (newer == null) {
this.$root.dialog({ this.$root.dialog({
title: this.$t('no-updates'), title: this.$t('@._settings.no-updates'),
text: this.$t('no-updates-desc') text: this.$t('@._settings.no-updates-desc')
}); });
} else { } else {
this.$root.dialog({ this.$root.dialog({

View File

@ -79,7 +79,10 @@ export default Vue.extend({
localStorage.setItem('i', res.i); localStorage.setItem('i', res.i);
location.reload(); location.reload();
}).catch(() => { }).catch(() => {
alert(this.$t('login-failed')); this.$root.dialog({
type: 'error',
text: this.$t('login-failed')
});
this.signing = false; this.signing = false;
}); });
} }

View File

@ -153,7 +153,10 @@ export default Vue.extend({
location.href = '/'; location.href = '/';
}); });
}).catch(() => { }).catch(() => {
alert(this.$t('some-error')); this.$root.dialog({
type: 'error',
text: this.$t('some-error')
});
if (this.meta.enableRecaptcha) { if (this.meta.enableRecaptcha) {
(window as any).grecaptcha.reset(); (window as any).grecaptcha.reset();

View File

@ -21,7 +21,7 @@
<option value="users">{{ $t('@.widgets.users') }}</option> <option value="users">{{ $t('@.widgets.users') }}</option>
<option value="polls">{{ $t('@.widgets.polls') }}</option> <option value="polls">{{ $t('@.widgets.polls') }}</option>
<option value="post-form">{{ $t('@.widgets.post-form') }}</option> <option value="post-form">{{ $t('@.widgets.post-form') }}</option>
<option value="messaging">{{ $t('@.widgets.messaging') }}</option> <option value="messaging">{{ $t('@.messaging') }}</option>
<option value="memo">{{ $t('@.widgets.memo') }}</option> <option value="memo">{{ $t('@.widgets.memo') }}</option>
<option value="hashtags">{{ $t('@.widgets.hashtags') }}</option> <option value="hashtags">{{ $t('@.widgets.hashtags') }}</option>
<option value="posts-monitor">{{ $t('@.widgets.posts-monitor') }}</option> <option value="posts-monitor">{{ $t('@.widgets.posts-monitor') }}</option>
@ -33,7 +33,7 @@
</header> </header>
<x-draggable <x-draggable
:list="column.widgets" :list="column.widgets"
:options="{ animation: 150 }" animation="150"
@sort="onWidgetSort" @sort="onWidgetSort"
> >
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="widgetFunc(widget.id)"> <div v-for="widget in column.widgets" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="widgetFunc(widget.id)">

View File

@ -188,7 +188,10 @@ export default define({
}).then(data => { }).then(data => {
this.clear(); this.clear();
}).catch(err => { }).catch(err => {
alert('Something happened'); this.$root.dialog({
type: 'error',
text: this.$t('something-happened')
});
}).then(() => { }).then(() => {
this.posting = false; this.posting = false;
this.$nextTick(() => { this.$nextTick(() => {

View File

@ -161,7 +161,10 @@ export default Vue.extend({
}); });
break; break;
default: default:
alert(this.$t('unhandled-error')); this.$root.dialog({
type: 'error',
text: this.$t('unhandled-error')
});
} }
}); });
} }

View File

@ -320,7 +320,10 @@ export default Vue.extend({
}); });
break; break;
default: default:
alert(this.$t('unhandled-error')); this.$root.dialog({
type: 'error',
text: this.$t('unhandled-error')
});
} }
}); });
} }

View File

@ -364,7 +364,10 @@ export default Vue.extend({
setGeo() { setGeo() {
if (navigator.geolocation == null) { if (navigator.geolocation == null) {
alert(this.$t('geolocation-alert')); this.$root.dialog({
type: 'warning',
text: this.$t('geolocation-alert')
});
return; return;
} }
@ -372,7 +375,11 @@ export default Vue.extend({
this.geo = pos.coords; this.geo = pos.coords;
this.$emit('geo-attached', this.geo); this.$emit('geo-attached', this.geo);
}, err => { }, err => {
alert(`%i18n:@error%: ${err.message}`); this.$root.dialog({
type: 'error',
title: this.$t('error')
text: err.message
});
}, { }, {
enableHighAccuracy: true enableHighAccuracy: true
}); });

View File

@ -34,7 +34,7 @@
<button @click="addWidget">{{ $t('add') }}</button> <button @click="addWidget">{{ $t('add') }}</button>
</div> </div>
<div class="trash"> <div class="trash">
<x-draggable v-model="trash" :options="{ group: 'x' }" @add="onTrash"></x-draggable> <x-draggable v-model="trash" group="x" @add="onTrash"></x-draggable>
<p>{{ $t('@.trash') }}</p> <p>{{ $t('@.trash') }}</p>
</div> </div>
</div> </div>
@ -45,7 +45,8 @@
:list="widgets[place]" :list="widgets[place]"
:class="place" :class="place"
:data-place="place" :data-place="place"
:options="{ group: 'x', animation: 150 }" group="x"
animation="150"
@sort="onWidgetSort" @sort="onWidgetSort"
:key="place" :key="place"
> >

View File

@ -34,7 +34,7 @@ export default Vue.extend({
document.title = title; document.title = title;
}, },
onOpenFolder(folder) { onOpenFolder(folder) {
const title = folder.name + ' | %i18n:@title%'; const title = `${folder.name} | ${this.$t('title')}`;
// Rewrite URL // Rewrite URL
history.pushState(null, title, `/i/drive/folder/${folder.id}`); history.pushState(null, title, `/i/drive/folder/${folder.id}`);

View File

@ -4,7 +4,7 @@ import { EventEmitter } from 'eventemitter3';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
import initStore from './store'; import initStore from './store';
import { apiUrl, version } from './config'; import { apiUrl, version, locale } from './config';
import Progress from './common/scripts/loading'; import Progress from './common/scripts/loading';
import Err from './common/views/components/connect-failed.vue'; import Err from './common/views/components/connect-failed.vue';
@ -281,7 +281,7 @@ export default class MiOS extends EventEmitter {
// トークンが再生成されたとき // トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる // このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => { main.on('myTokenRegenerated', () => {
alert('%i18n:common.my-token-regenerated%'); alert(locale['common']['my-token-regenerated'])
this.signout(); this.signout();
}); });
} }

View File

@ -136,7 +136,10 @@ export default Vue.extend({
}, },
showCreatedAt() { showCreatedAt() {
alert(new Date(this.file.createdAt).toLocaleString()); this.$root.dialog({
type: 'info',
text: (new Date(this.file.createdAt)).toLocaleString()
});
} }
} }
}); });
@ -150,11 +153,13 @@ export default Vue.extend({
> .preview > .preview
width fit-content width fit-content
width -moz-fit-content
max-width 100% max-width 100%
margin 0 auto margin 0 auto
box-shadow 1px 1px 4px rgba(#000, 0.2) box-shadow 1px 1px 4px rgba(#000, 0.2)
overflow hidden overflow hidden
color var(--driveFileIcon) color var(--driveFileIcon)
justify-content center
> footer > footer
padding 8px 8px 0 8px padding 8px 8px 0 8px

View File

@ -283,14 +283,21 @@ export default Vue.extend({
setGeo() { setGeo() {
if (navigator.geolocation == null) { if (navigator.geolocation == null) {
alert(this.$t('location-alert')); this.$root.dialog({
type: 'warning',
text: this.$t('geolocation-alert')
});
return; return;
} }
navigator.geolocation.getCurrentPosition(pos => { navigator.geolocation.getCurrentPosition(pos => {
this.geo = pos.coords; this.geo = pos.coords;
}, err => { }, err => {
alert(`%i18n:@error%: ${err.message}`); this.$root.dialog({
type: 'error',
title: this.$t('error')
text: err.message
});
}, { }, {
enableHighAccuracy: true enableHighAccuracy: true
}); });

View File

@ -32,7 +32,7 @@ export default Vue.extend({
this.fetch(); this.fetch();
}, },
mounted() { mounted() {
document.title = `${this.$root.instanceName} | %i18n:@notifications%`; document.title = `${this.$root.instanceName} | ${this.$t('@.favorites')}`;
}, },
methods: { methods: {
fetch() { fetch() {

View File

@ -15,7 +15,7 @@ export default Vue.extend({
XReversi: () => import('../../../../common/views/components/games/reversi/reversi.vue').then(m => m.default) XReversi: () => import('../../../../common/views/components/games/reversi/reversi.vue').then(m => m.default)
}, },
mounted() { mounted() {
document.title = `${this.$root.instanceName} %i18n:@reversi%`; document.title = `${this.$root.instanceName} | ${this.$t('reversi')}`;
}, },
methods: { methods: {
nav(game, actualNav) { nav(game, actualNav) {

View File

@ -50,7 +50,7 @@ export default Vue.extend({
} }
}, },
mounted() { mounted() {
document.title = `%i18n:@search%: ${this.q} | ${this.$root.instanceName}`; document.title = `${this.$t('search')}: ${this.q} | ${this.$root.instanceName}`;
}, },
methods: { methods: {
inited() { inited() {

View File

@ -29,7 +29,8 @@
</header> </header>
<x-draggable <x-draggable
:list="widgets" :list="widgets"
:options="{ handle: '.handle', animation: 150 }" handle=".handle"
animation="150"
@sort="onWidgetSort" @sort="onWidgetSort"
> >
<div v-for="widget in widgets" class="customize-container" :key="widget.id"> <div v-for="widget in widgets" class="customize-container" :key="widget.id">
@ -106,7 +107,10 @@ export default Vue.extend({
methods: { methods: {
hint() { hint() {
alert(this.$t('widgets-hints')); this.$root.dialog({
type: 'info',
text: this.$t('widgets-hints')
});
}, },
widgetFunc(id) { widgetFunc(id) {

View File

@ -1,4 +1,4 @@
@charset 'utf-8' @charset "utf-8"
/* /*
::selection ::selection

View File

@ -130,10 +130,12 @@ Misskeyのストリームに接続しただけでは、まだリアルタイム
```json ```json
{ {
type: 'api', type: 'api',
id: 'xxxxxxxxxxxxxxxx', body: {
endpoint: 'notes/create', id: 'xxxxxxxxxxxxxxxx',
data: { endpoint: 'notes/create',
text: 'yee haw!' data: {
text: 'yee haw!'
}
} }
} }
``` ```

View File

@ -1,14 +1,21 @@
import { Meta } from '../models/entities/meta'; import { Meta } from '../models/entities/meta';
import { Metas } from '../models'; import { getConnection } from 'typeorm';
import { genId } from './gen-id';
export default async function(): Promise<Meta> { export default async function(): Promise<Meta> {
const meta = await Metas.findOne(); return await getConnection().transaction(async transactionalEntityManager => {
if (meta) { // バグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する
return meta; const meta = await transactionalEntityManager.findOne(Meta, {
} else { order: {
return Metas.save({ id: 'DESC'
id: genId(), }
} as Meta); });
}
if (meta) {
return meta;
} else {
return await transactionalEntityManager.save(Meta, {
id: 'x'
}) as Meta;
}
});
} }

View File

@ -1,9 +1,11 @@
import { Entity, Column, PrimaryColumn } from 'typeorm'; import { Entity, Column, PrimaryColumn } from 'typeorm';
import { id } from '../id';
@Entity() @Entity()
export class Meta { export class Meta {
@PrimaryColumn(id()) @PrimaryColumn({
type: 'varchar',
length: 32
})
public id: string; public id: string;
@Column('varchar', { @Column('varchar', {

View File

@ -93,12 +93,12 @@ export class Note {
}) })
public localOnly: boolean; public localOnly: boolean;
@Column('integer', { @Column('smallint', {
default: 0 default: 0
}) })
public renoteCount: number; public renoteCount: number;
@Column('integer', { @Column('smallint', {
default: 0 default: 0
}) })
public repliesCount: number; public repliesCount: number;
@ -129,12 +129,14 @@ export class Note {
}) })
public score: number; public score: number;
@Index()
@Column({ @Column({
...id(), ...id(),
array: true, default: '{}' array: true, default: '{}'
}) })
public fileIds: DriveFile['id'][]; public fileIds: DriveFile['id'][];
@Index()
@Column('varchar', { @Column('varchar', {
length: 256, array: true, default: '{}' length: 256, array: true, default: '{}'
}) })

View File

@ -103,7 +103,7 @@ export class NoteRepository extends Repository<Note> {
const host = note.userHost; const host = note.userHost;
async function populatePoll() { async function populatePoll() {
const poll = await Polls.findOne({ noteId: note.id }).then(ensure); const poll = await Polls.findOne(note.id).then(ensure);
const choices = poll.choices.map(c => ({ const choices = poll.choices.map(c => ({
text: c, text: c,
votes: poll.votes[poll.choices.indexOf(c)], votes: poll.votes[poll.choices.indexOf(c)],

View File

@ -84,6 +84,8 @@ export class UserRepository extends Repository<User> {
const pins = opts.detail ? await UserNotePinings.find({ userId: user.id }) : []; const pins = opts.detail ? await UserNotePinings.find({ userId: user.id }) : [];
const profile = opts.detail ? await UserProfiles.findOne({ userId: user.id }).then(ensure) : null; const profile = opts.detail ? await UserProfiles.findOne({ userId: user.id }).then(ensure) : null;
const falsy = opts.detail ? false : undefined;
return await rap({ return await rap({
id: user.id, id: user.id,
name: user.name, name: user.name,
@ -91,10 +93,10 @@ export class UserRepository extends Repository<User> {
host: user.host, host: user.host,
avatarUrl: user.avatarUrl ? user.avatarUrl : config.url + '/avatar/' + user.id, avatarUrl: user.avatarUrl ? user.avatarUrl : config.url + '/avatar/' + user.id,
avatarColor: user.avatarColor, avatarColor: user.avatarColor,
isAdmin: user.isAdmin || undefined, isAdmin: user.isAdmin || falsy,
isBot: user.isBot || undefined, isBot: user.isBot || falsy,
isCat: user.isCat || undefined, isCat: user.isCat || falsy,
isVerified: user.isVerified || undefined, isVerified: user.isVerified || falsy,
// カスタム絵文字添付 // カスタム絵文字添付
emojis: user.emojis.length > 0 ? Emojis.find({ emojis: user.emojis.length > 0 ? Emojis.find({
@ -123,7 +125,7 @@ export class UserRepository extends Repository<User> {
bannerUrl: user.bannerUrl, bannerUrl: user.bannerUrl,
bannerColor: user.bannerColor, bannerColor: user.bannerColor,
isLocked: user.isLocked, isLocked: user.isLocked,
isModerator: user.isModerator || undefined, isModerator: user.isModerator || falsy,
description: profile!.description, description: profile!.description,
location: profile!.location, location: profile!.location,
birthday: profile!.birthday, birthday: profile!.birthday,

View File

@ -1,6 +1,6 @@
import $ from 'cafy'; import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { Metas } from '../../../../models'; import { getConnection } from 'typeorm';
import { Meta } from '../../../../models/entities/meta'; import { Meta } from '../../../../models/entities/meta';
export const meta = { export const meta = {
@ -505,11 +505,17 @@ export default define(meta, async (ps) => {
set.swPrivateKey = ps.swPrivateKey; set.swPrivateKey = ps.swPrivateKey;
} }
const meta = await Metas.findOne(); await getConnection().transaction(async transactionalEntityManager => {
const meta = await transactionalEntityManager.findOne(Meta, {
order: {
id: 'DESC'
}
});
if (meta) { if (meta) {
await Metas.update(meta.id, set); await transactionalEntityManager.update(Meta, meta.id, set);
} else { } else {
await Metas.save(set); await transactionalEntityManager.save(Meta, set);
} }
});
}); });

View File

@ -79,7 +79,7 @@ export default abstract class Chart<T extends Record<string, any>> {
flatColumns(v.properties, p); flatColumns(v.properties, p);
} else { } else {
columns[this.columnPrefix + p] = { columns[this.columnPrefix + p] = {
type: 'integer', type: 'bigint',
}; };
} }
} }

View File

@ -2,7 +2,7 @@ import * as Minio from 'minio';
import config from '../../config'; import config from '../../config';
import { DriveFile } from '../../models/entities/drive-file'; import { DriveFile } from '../../models/entities/drive-file';
import { InternalStorage } from './internal-storage'; import { InternalStorage } from './internal-storage';
import { DriveFiles, Instances } from '../../models'; import { DriveFiles, Instances, Notes } from '../../models';
import { driveChart, perUserDriveChart, instanceChart } from '../chart'; import { driveChart, perUserDriveChart, instanceChart } from '../chart';
export default async function(file: DriveFile, isExpired = false) { export default async function(file: DriveFile, isExpired = false) {
@ -40,6 +40,11 @@ export default async function(file: DriveFile, isExpired = false) {
}); });
} else { } else {
DriveFiles.delete(file.id); DriveFiles.delete(file.id);
// TODO: トランザクション
Notes.createQueryBuilder().delete()
.where(':id = ANY(fileIds)', { id: file.id })
.execute();
} }
// 統計を更新 // 統計を更新