Compare commits

..

37 Commits

Author SHA1 Message Date
syuilo
27d22f954a 11.26.2 2019-07-25 02:23:42 +09:00
Satsuki Yanagi
88f5e8e8e2 Bye moment from package.json (#5215)
* Bye moment from package.json

* Use Mapped types for argument type definition
2019-07-25 01:36:48 +09:00
syuilo
fd2ae6d3cf Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-07-24 02:17:04 +09:00
syuilo
238edd36f7 Fix error 2019-07-24 02:16:41 +09:00
MeiMei
5d847f9808 Fix: some post form errors (#5212)
* Fix: type mismatch in post-form-attaches

* Fix: 'this is null' in post-form-window
2019-07-24 02:15:40 +09:00
syuilo
ac914af9c3 Fix #5210 2019-07-23 00:19:29 +09:00
Aya Morisawa
636f90ca0c Improve CONTRIBUTING.md (#5158) 2019-07-22 14:57:23 +09:00
syuilo
29469bb7c6 Better error 2019-07-22 10:18:27 +09:00
syuilo
4f043b1841 Update signup.ts 2019-07-22 10:16:25 +09:00
syuilo
85008303f5 Prevent username reusing 2019-07-22 10:15:00 +09:00
syuilo
3432d6e615 Update dependencies 🚀 2019-07-22 07:31:02 +09:00
syuilo
855c990a17 11.26.1 2019-07-21 22:59:57 +09:00
syuilo
eef2dc2f62 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-07-21 22:59:15 +09:00
syuilo
fa54140973 Update CHANGELOG.md 2019-07-21 22:58:57 +09:00
syuilo
e770d32916 New Crowdin translations (#5206)
* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Czech)
2019-07-21 22:58:51 +09:00
Oni-Men
8aeabf530c Patch #5060 (#5205)
* fix #5060

* forgot ";" :p
2019-07-21 22:27:36 +09:00
syuilo
6fbf1cfc28 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-07-21 21:59:51 +09:00
syuilo
5480df35bc Update CHANGELOG.md 2019-07-21 21:58:48 +09:00
Aya Morisawa
8b5104d564 Update deprecated vscode extension (#5209) 2019-07-21 21:57:15 +09:00
Aya Morisawa
3c1192d6bf Unignore .vscode/extensions.json (#5208) 2019-07-21 20:27:43 +09:00
Satsuki Yanagi
eb8ef35122 Fix activity calendar for desktop widget (#5200)
* Fix activity calendar for desktop widget

* fetch past 21 weeks for activity widgets

* Cleanup

* forEach -> map

* Revert "forEach -> map"

This reverts commit b72e180ee4.
2019-07-21 19:12:16 +09:00
syuilo
8a31e5fd0f Update CHANGELOG.md 2019-07-21 03:27:17 +09:00
syuilo
751728db84 Update CHANGELOG.md 2019-07-21 03:25:10 +09:00
MeiMei
e695f54ef0 投稿フォームが画面外にはみ出さないように (#5203)
* 上下はみ出したウィンドウは上基準で収めるように

* 投稿フォームを画面より長くしないように
2019-07-20 17:50:01 +09:00
MeiMei
b2ed45ae38 Fix: スクロールしてると絵文字ピッカーの位置がずれる (#5204) 2019-07-20 17:47:40 +09:00
syuilo
5e36f75f8a Clean up: Remove unused imports 2019-07-20 04:09:33 +09:00
rinsuki
7ac13a386c Improve GenerateVideoThumbnail (#5186)
* Improve GenerateVideoThumbnail

* use fluent-ffmpeg

* Update src/services/drive/generate-video-thumbnail.ts
2019-07-20 03:28:14 +09:00
Satsuki Yanagi
56c8ad9df3 Improve usability of quote note by pasting url (#5196) 2019-07-20 03:23:16 +09:00
MeiMei
f1ab918ecd Fix question (#5197) 2019-07-20 03:20:06 +09:00
Acid Chicken (硫酸鶏)
42af8c7695 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-07-20 02:02:48 +09:00
imgbot[bot]
0de2e150cb [ImgBot] Optimize images (#5189)
/assets/ss/user.jpg -- 148.15kb -> 148.15kb (0%)
2019-07-20 01:56:09 +09:00
Acid Chicken (硫酸鶏)
1ac498c8fe Update README.md [AUTOGEN] (#5199) 2019-07-20 01:53:09 +09:00
Acid Chicken (硫酸鶏)
545d29a40a Update README.md [AUTOGEN] (#5193) 2019-07-20 00:40:08 +09:00
syuilo
73bbef2922 Merge branch 'master' into develop 2019-07-19 06:14:21 +09:00
syuilo
26567cdeb2 🎨 2019-07-19 06:13:56 +09:00
syuilo
84941cbb97 Update CHANGELOG.md 2019-07-19 04:13:20 +09:00
Acid Chicken (硫酸鶏)
0a29ce13b6 Nothing 2019-07-14 11:08:13 +09:00
42 changed files with 421 additions and 317 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
# Visual Studio Code
/.vscode
!/.vscode/extensions.json
# Intelij-IDEA
/.idea

View File

@@ -2,10 +2,10 @@
"recommendations": [
"ducksoupdev.vue2",
"editorconfig.editorconfig",
"eg2.tslint",
"eg2.vscode-npm-script",
"hollowtree.vue-snippets",
"ms-vscode.typescript-javascript-grammar",
"ms-vscode.vscode-typescript-tslint-plugin",
"octref.vetur",
"sysoev.language-stylus"
]

View File

@@ -1,10 +1,30 @@
ChangeLog
=========
11.26.2 (2019/07/25)
--------------------
### 🐛Fixes
* すでに使われたことのあるユーザー名を再度使えないように
* モバイルのウィジェットページが常に i/update-client-setting を呼び続ける問題を修正
* 投稿フォームのヘッダに添付ファイル数がちゃんと表示されない問題を修正
11.26.1 (2019/07/21)
--------------------
### 🐛Fixes
* リモートアンケートの期限が保存されないのを修正
* 自分をブロックしているユーザーがおすすめユーザーに表示されている問題を修正
* スクロールしてると絵文字ピッカーの位置がずれる問題を修正
* 投稿フォームが画面外にはみ出さないように
* 投稿フォームの「引用付き」の表示が見づらい問題の修正
* 投稿フォームにもうリノートや引用ノートのデータがある場合はリンクを貼っても「引用として添付しますか?」のダイアログボックスが出ないように
* 「タイムライン上部に投稿フォームを表示する」機能の使用時、ノートを投稿しても引用ノートのデータが残る問題の修正
* デスクトップ版のアクティビティウィジェットの日付とデータの表示が変だったのを修正
11.26.0 (2019/07/19)
--------------------
### ✨Improvements
* モデレーターログを記録して確認できるように
* プロフィールに追加情報を設定できるように
* Mastodonのリンクの所有者認証に対応
* AP: Delete Person アクティビティを配信するように
* AP: Delete アクティビティの後にフォロー解除するように
@@ -21,6 +41,7 @@ ChangeLog
* ログインのログが正しく保存されない問題を修正
* 同じユーザー名のユーザーが作成できてしまうことがある問題を修正
* 報告されたレポート内容が表示されない問題を修正
* リモートのプロフィールの追加情報が表示されない問題を修正
* 「見つける」のタグが大文字小文字区別されている問題を修正
* 管理画面のインスタンス一覧でソートが正しく機能していない問題を修正
* プロフィール設定でバナーに動画を設定すると以降編集ができない問題を修正

View File

@@ -7,12 +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.
* If you have multiple independent issues, please submit them separately.
## Branches
* **master** branch is tracking the latest release and used for production purposes.
* **develop** branch is where we work for the next release.
* **l10n_develop** branch is reserved for localization management.
## Localization (l10n)
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
You can improve our translations with your Crowdin account.
Changes you make in Crowdin will be merged into the develop branch by @syuilo.
Your changes in Crowdin are automatically submitted as a PR (with the title "New Crowdin translations") to the repository.
The owner [@syuilo](https://github.com/syuilo) merges the PR into the develop branch before the next release.
If you cannot find the language you want to contribute with, please open an issue.
If your language is not listed in Crowdin, please open an issue.
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
@@ -33,7 +39,6 @@ Misskey uses CircleCI for executing automated tests.
Configuration files are located in [`/.circleci`](/.circleci).
## FAQ
### How to resolve conflictions occurred at yarn.lock?
Just execute `yarn` to fix it.
@@ -93,6 +98,8 @@ Good:
if (foo) bar;
```
Make sure that the condition and the body statement are on the same line.
### Do not use `==` when it can simply be replaced with `===`.
🥰

View File

@@ -104,24 +104,25 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<!-- PATREON_START -->
<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/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/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/776209" alt="Denshi" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1.jpe?token-time=2145916800&token-hash=bqwLTk0Wo0hUJJ8J5y7ii05bLzz-_CDA7Bo0Mp4RFU0%3D" alt="ne_moni" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/4.jpe?token-time=2145916800&token-hash=zEyJqVM7u9d8Ri-65fJYSJcWF1jBH1nJ5a3taRzrTmw%3D" alt="Melilot" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon" width="100"></td>
</tr><tr>
<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/user?u=19045173">kiritan</a></td>
<td><a href="https://www.patreon.com/user?u=776209">Denshi</a></td>
<td><a href="https://www.patreon.com/user?u=557245">mkatze</a></td>
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
</tr></table>
<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://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>
@@ -131,6 +132,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/osapon">osapon</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/mydarkstar">mydarkstar</a></td>
@@ -173,7 +175,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table>
**Last updated:** Tue, 16 Jul 2019 10:23:06 UTC
**Last updated:** Fri, 19 Jul 2019 15:41:09 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

@@ -89,6 +89,7 @@ common:
"read:notifications": "Prohlížet oznámení"
"write:notifications": "Pracovat s oznámeními"
"read:reactions": "Prohlížet reakce"
"write:reactions": "Narabět s reakcemi"
"write:votes": "Hlasovat"
empty-timeline-info:
follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose"
@@ -664,6 +665,8 @@ common/views/components/profile-editor.vue:
danger-zone: "Nebezpečná zóna"
delete-account: "Smazat účet"
account-deleted: "Váš účet byl smazán. Může chvilku trvat než zmizí všechna data."
profile-metadata: "Metadata profilu"
metadata-label: "Popis"
metadata-content: "Obsah"
common/views/components/user-list-editor.vue:
users: "Uživatel"

View File

@@ -118,6 +118,7 @@ common:
add-visible-user: "Ajouter un utilisateur"
cw-placeholder: "Commenter le contenu (optionnel)"
username-prompt: "Saisir un nom d'utilisateur"
enter-file-name: "Éditer le nom du fichier"
weekday-short:
sunday: "D"
monday: "L"
@@ -184,6 +185,7 @@ common:
remember-note-visibility: "Se souvenir du mode de visibilité de la publication"
web-search-engine: "Moteur de recherche Web"
web-search-engine-desc: "Exemple: https://www.google.com/?#q={{query}}"
paste: "Coller"
keep-cw: "Maintenir l'avertissement de contenu"
keep-cw-desc: "Lorsque vous répondez à un message, le même avertissement de contenu est reprit par défaut dans la réponse, le même que celui qui a été défini dans le message original."
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
@@ -557,6 +559,7 @@ common/views/components/poll-editor.vue:
remove: "Supprimer ce choix"
add: "+ Ajouter un choix"
destroy: "Annuler ce sondage"
multiple: "Autoriser le multi-choix"
expiration: "Valide jusqu'à"
infinite: "Illimité"
at: "Choisir une date et une durée"
@@ -725,6 +728,8 @@ common/views/components/profile-editor.vue:
danger-zone: "Zone de danger"
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."
profile-metadata: "Métadonnées du profil"
metadata-label: "Étiquette"
metadata-content: "Contenu"
common/views/components/user-list-editor.vue:
users: "Utilisateur·rice"
@@ -885,6 +890,7 @@ desktop/views/components/drive.file.vue:
copied: "Copié"
copied-url-to-clipboard: "L'URL a été copiée dans le presse-papier"
desktop/views/components/drive.folder.vue:
upload-folder: "Emplacement de téléversement par défaut"
unable-to-process: "L'opération n'a pas pu être complétée"
circular-reference-detected: "Le dossier de destination est un sous-dossier du dossier que vous souhaitez déplacer."
unhandled-error: "Erreur inconnue"

View File

@@ -0,0 +1,13 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class UsedUsername1563757595828 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`CREATE TABLE "used_username" ("username" character varying(128) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT "PK_78fd79d2d24c6ac2f4cc9a31a5d" PRIMARY KEY ("username"))`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP TABLE "used_username"`);
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "11.26.0",
"version": "11.26.2",
"codename": "daybreak",
"repository": {
"type": "git",
@@ -27,7 +27,7 @@
},
"resolutions": {
"gulp-cssnano/cssnano/postcss-svgo/svgo/js-yaml": "^3.13.1",
"video-thumbnail-generator/lodash": "^4.17.13"
"lodash": "^4.17.13"
},
"dependencies": {
"@elastic/elasticsearch": "7.1.0",
@@ -100,7 +100,7 @@
"@types/ws": "6.0.1",
"@typescript-eslint/parser": "1.11.0",
"animejs": "3.0.1",
"apexcharts": "3.8.2",
"apexcharts": "3.8.3",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autwh": "0.1.0",
@@ -116,18 +116,19 @@
"commander": "2.20.0",
"content-disposition": "0.5.3",
"crc-32": "1.2.0",
"css-loader": "3.0.0",
"css-loader": "3.1.0",
"cssnano": "4.1.10",
"dateformat": "3.0.3",
"deep-equal": "1.0.1",
"diskusage": "1.1.3",
"double-ended-queue": "2.1.0-0",
"emojilib": "2.4.0",
"eslint": "6.0.1",
"eslint": "6.1.0",
"eslint-plugin-vue": "5.2.3",
"eventemitter3": "4.0.0",
"feed": "3.0.0",
"file-type": "12.0.1",
"fluent-ffmpeg": "2.1.2",
"fuckadblock": "3.2.1",
"gulp": "4.0.2",
"gulp-cssnano": "2.1.3",
@@ -158,7 +159,7 @@
"koa-compress": "3.0.0",
"koa-favicon": "2.0.1",
"koa-json-body": "5.3.0",
"koa-logger": "3.2.0",
"koa-logger": "3.2.1",
"koa-mount": "4.0.0",
"koa-multer": "1.0.2",
"koa-router": "7.4.0",
@@ -170,13 +171,12 @@
"lolex": "4.1.0",
"lookup-dns-cache": "2.1.0",
"minio": "7.0.10",
"mocha": "6.1.4",
"mocha": "6.2.0",
"moji": "0.5.1",
"moment": "2.24.0",
"ms": "2.1.2",
"nested-property": "1.0.1",
"node-fetch": "2.6.0",
"nodemailer": "6.2.1",
"nodemailer": "6.3.0",
"nprogress": "0.2.0",
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
@@ -193,7 +193,7 @@
"pug": "2.0.4",
"punycode": "2.1.1",
"pureimage": "0.1.6",
"qrcode": "1.4.0",
"qrcode": "1.4.1",
"random-seed": "0.3.0",
"randomcolor": "0.5.4",
"ratelimiter": "3.3.0",
@@ -219,7 +219,7 @@
"stylus": "0.54.5",
"stylus-loader": "3.0.2",
"summaly": "2.3.0",
"systeminformation": "4.14.3",
"systeminformation": "4.14.4",
"syuilo-password-strength": "0.0.1",
"terser-webpack-plugin": "1.3.0",
"textarea-caret": "3.1.0",
@@ -230,14 +230,13 @@
"tslint": "5.18.0",
"tslint-sonarts": "1.9.0",
"typeorm": "0.2.18",
"typescript": "3.5.2",
"typescript": "3.5.3",
"uglify-es": "3.3.9",
"ulid": "2.3.0",
"url-loader": "2.0.1",
"url-loader": "2.1.0",
"uuid": "3.3.2",
"v-animate-css": "0.0.3",
"v-debounce": "0.1.2",
"video-thumbnail-generator": "1.1.3",
"vue": "2.6.10",
"vue-color": "2.7.0",
"vue-content-loading": "1.6.0",
@@ -245,7 +244,7 @@
"vue-i18n": "8.12.0",
"vue-js-modal": "1.3.31",
"vue-json-pretty": "1.6.0",
"vue-loader": "15.7.0",
"vue-loader": "15.7.1",
"vue-marquee-text-component": "1.1.1",
"vue-prism-component": "1.1.1",
"vue-router": "3.0.7",
@@ -258,10 +257,13 @@
"vuex": "3.1.1",
"vuex-persistedstate": "2.5.4",
"web-push": "3.3.5",
"webpack": "4.35.3",
"webpack-cli": "3.3.5",
"webpack": "4.36.1",
"webpack-cli": "3.3.6",
"websocket": "1.0.29",
"ws": "7.1.0",
"ws": "7.1.1",
"xev": "2.0.1"
},
"devDependencies": {
"@types/fluent-ffmpeg": "2.1.10"
}
}

View File

@@ -328,6 +328,7 @@ export default (opts) => ({
this.text = '';
this.files = [];
this.poll = false;
this.quoteId = null;
this.$emit('change-attached-files', this.files);
},
@@ -357,7 +358,7 @@ export default (opts) => ({
const paste = e.clipboardData.getData('text');
if (paste.startsWith(url + '/notes/')) {
if (!this.renote && !this.quoteId && paste.startsWith(url + '/notes/')) {
e.preventDefault();
this.$root.dialog({

View File

@@ -52,9 +52,11 @@
<script lang="ts">
import Vue from 'vue';
import * as moment from 'moment';
import i18n from '../../../i18n';
import { erase } from '../../../../../prelude/array';
import { addTimespan } from '../../../../../prelude/time';
import { formatDateTimeString } from '../../../../../misc/format-time-string';
export default Vue.extend({
i18n: i18n('common/views/components/poll-editor.vue'),
data() {
@@ -62,7 +64,7 @@ export default Vue.extend({
choices: ['', ''],
multiple: false,
expiration: 'infinite',
atDate: moment().add(1, 'day').toISOString().split('T')[0],
atDate: formatDateTimeString(addTimespan(new Date(), 1, 'days'), 'yyyy-MM-dd'),
atTime: '00:00',
after: 0,
unit: 'second'
@@ -95,7 +97,7 @@ export default Vue.extend({
get() {
const at = () => {
return moment(`${this.atDate} ${this.atTime}`).valueOf();
return new Date(`${this.atDate} ${this.atTime}`).getTime();
};
const after = () => {

View File

@@ -36,7 +36,7 @@ export default Vue.extend({
required: true
},
detachMediaFn: {
type: Object,
type: Function,
required: false
}
},

View File

@@ -432,7 +432,5 @@ export default Vue.extend({
> header
padding 8px 0px
font-weight bold
> div
padding-left 16px
</style>

View File

@@ -5,7 +5,7 @@
:x="record.x" :y="record.date.weekday"
rx="1" ry="1"
fill="transparent">
<title>{{ record.date.year }}/{{ record.date.month }}/{{ record.date.day }}</title>
<title>{{ record.date.year }}/{{ record.date.month + 1 }}/{{ record.date.day }}</title>
</rect>
<rect v-for="record in data" class="day"
:width="record.v" :height="record.v"
@@ -39,17 +39,17 @@ export default Vue.extend({
const month = now.getMonth();
const day = now.getDate();
let x = 0;
this.data.slice().reverse().forEach((d, i) => {
let x = 20;
this.data.slice().forEach((d, i) => {
d.x = x;
const date = new Date(year, month, day - i);
d.date = {
year: date.getFullYear(),
month: date.getMonth(),
day: date.getDate()
day: date.getDate(),
weekday: date.getDay()
};
d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
d.v = peak == 0 ? 0 : d.total / (peak / 2);
if (d.v > 1) d.v = 1;
@@ -58,7 +58,7 @@ export default Vue.extend({
const cl = 15 + ((1 - d.v) * 80);
d.color = `hsl(${ch}, ${cs}%, ${cl}%)`;
if (d.date.weekday == 6) x++;
if (d.date.weekday == 0) x--;
});
}
});

View File

@@ -46,7 +46,7 @@ export default Vue.extend({
props: ['data'],
data() {
return {
viewBoxX: 140,
viewBoxX: 147,
viewBoxY: 60,
zoom: 1,
pos: 0,

View File

@@ -48,7 +48,7 @@ export default Vue.extend({
this.$root.api('charts/user/notes', {
userId: this.user.id,
span: 'day',
limit: 7 * 20
limit: 7 * 21
}).then(activity => {
this.activity = activity.diffs.normal.map((_, i) => ({
total: activity.diffs.normal[i] + activity.diffs.reply[i] + activity.diffs.renote[i],

View File

@@ -75,7 +75,7 @@ export default Vue.extend({
<style lang="stylus" scoped>
.gcafiosrssbtbnbzqupfmglvzgiaipyv
position fixed
position absolute
top 0
left 0
z-index 3000

View File

@@ -5,12 +5,12 @@
<span class="icon" v-if="geo"><fa icon="map-marker-alt"/></span>
<span v-if="!reply">{{ $t('note') }}</span>
<span v-if="reply">{{ $t('reply') }}</span>
<span class="count" v-if="files.length != 0">{{ this.$t('attaches').replace('{}', files.length) }}</span>
<span class="count" v-if="uploadings.length != 0">{{ this.$t('uploading-media').replace('{}', uploadings.length) }}<mk-ellipsis/></span>
<span class="count" v-if="files.length != 0">{{ $t('attaches').replace('{}', files.length) }}</span>
<span class="count" v-if="uploadings.length != 0">{{ $t('uploading-media').replace('{}', uploadings.length) }}<mk-ellipsis/></span>
</span>
</template>
<div class="mk-post-form-window--body">
<div class="mk-post-form-window--body" :style="{ maxHeight: `${maxHeight}px` }">
<mk-note-preview v-if="reply" class="notePreview" :note="reply"/>
<x-post-form ref="form"
:reply="reply"
@@ -61,6 +61,12 @@ export default Vue.extend({
};
},
computed: {
maxHeight() {
return window.innerHeight - 50;
},
},
mounted() {
this.$nextTick(() => {
(this.$refs.form as any).focus();

View File

@@ -6,18 +6,18 @@
@drop.stop="onDrop"
>
<div class="content">
<div v-if="visibility == 'specified'" class="visibleUsers">
<div class="hashtags" v-if="recentHashtags.length > 0 && $store.state.settings.suggestRecentHashtags">
<b>{{ $t('@.post-form.recent-tags') }}:</b>
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('@.post-form.click-to-tagging')">#{{ tag }}</a>
</div>
<div class="with-quote" v-if="quoteId">{{ $t('@.post-form.quote-attached') }} <a @click="quoteId = null">[x]</a></div>
<div v-if="visibility === 'specified'" class="visibleUsers">
<span v-for="u in visibleUsers">
<mk-user-name :user="u"/><a @click="removeVisibleUser(u)">[x]</a>
</span>
<a @click="addVisibleUser">{{ $t('@.post-form.add-visible-user') }}</a>
</div>
<div class="hashtags" v-if="recentHashtags.length > 0 && $store.state.settings.suggestRecentHashtags">
<b>{{ $t('@.post-form.recent-tags') }}:</b>
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('@.post-form.click-to-tagging')">#{{ tag }}</a>
</div>
<div class="with-quote" v-if="quoteId">{{ $t('@.post-form.quote-attached') }}</div>
<div class="local-only" v-if="localOnly == true">{{ $t('@.post-form.local-only-message') }}</div>
<div class="local-only" v-if="localOnly === true">{{ $t('@.post-form.local-only-message') }}</div>
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('@.post-form.cw-placeholder')" v-autocomplete="{ model: 'cw' }">
<div class="textarea">
<textarea :class="{ with: (files.length != 0 || poll) }"
@@ -190,14 +190,6 @@ export default Vue.extend({
border-radius 0 0 4px 4px
transition border-color .3s ease
> .visibleUsers
margin-bottom 8px
font-size 14px
> span
margin-right 16px
color var(--primary)
> .hashtags
margin 0 0 8px 0
overflow hidden
@@ -211,6 +203,18 @@ export default Vue.extend({
margin-right 8px
white-space nowrap
> .with-quote
margin 0 0 8px 0
color var(--primary)
> .visibleUsers
margin-bottom 8px
font-size 14px
> span
margin-right 16px
color var(--primary)
> .local-only
margin 0 0 8px 0
color var(--primary)

View File

@@ -260,14 +260,14 @@ export default Vue.extend({
let moveLeft = me.clientX - moveBaseX;
let moveTop = me.clientY - moveBaseY;
// はみ出し
if (moveTop < 0) moveTop = 0;
// はみ出し
if (moveTop + windowHeight > browserHeight) moveTop = browserHeight - windowHeight;
// 左はみ出し
if (moveLeft < 0) moveLeft = 0;
// はみ出し
if (moveTop + windowHeight > browserHeight) moveTop = browserHeight - windowHeight;
// はみ出し
if (moveTop < 0) moveTop = 0;
// 右はみ出し
if (moveLeft + windowWidth > browserWidth) moveLeft = browserWidth - windowWidth;
@@ -442,10 +442,10 @@ export default Vue.extend({
const browserHeight = window.innerHeight;
const windowWidth = main.offsetWidth;
const windowHeight = main.offsetHeight;
if (position.left < 0) main.style.left = 0;
if (position.top < 0) main.style.top = 0;
if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px';
if (position.top + windowHeight > browserHeight) main.style.top = browserHeight - windowHeight + 'px';
if (position.left < 0) main.style.left = 0; // 左はみ出し
if (position.top + windowHeight > browserHeight) main.style.top = browserHeight - windowHeight + 'px'; // 下はみ出し
if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px'; // 右はみ出し
if (position.top < 0) main.style.top = 0; // 上はみ出し
}
}
});

View File

@@ -174,7 +174,7 @@ export default class MiOS extends EventEmitter {
// Init service worker
if (this.shouldRegisterSw) {
this.getMeta().then(data => {
this.registerSw(data.swPublickey);
if (data.swPublickey) this.registerSw(data.swPublickey);
});
}
};
@@ -291,7 +291,7 @@ export default class MiOS extends EventEmitter {
* Register service worker
*/
@autobind
private registerSw(swPublickey) {
private registerSw(swPublickey: string) {
// Check whether service worker and push manager supported
const isSwSupported =
('serviceWorker' in navigator) && ('PushManager' in window);

View File

@@ -17,16 +17,17 @@
<div class="form">
<mk-note-preview class="preview" v-if="reply" :note="reply"/>
<mk-note-preview class="preview" v-if="renote" :note="renote"/>
<div v-if="visibility == 'specified'" class="visibleUsers">
<div class="with-quote" v-if="quoteId">{{ $t('@.post-form.quote-attached') }} <a @click="quoteId = null">[x]</a></div>
<div v-if="visibility === 'specified'" class="visibleUsers">
<span v-for="u in visibleUsers">
<mk-user-name :user="u"/>
<a @click="removeVisibleUser(u)">[x]</a>
</span>
<a @click="addVisibleUser">+{{ $t('@.post-form.add-visible-user') }}</a>
</div>
<div class="local-only" v-if="localOnly === true">{{ $t('@.post-form.local-only-message') }}</div>
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('@.post-form.cw-placeholder')" v-autocomplete="{ model: 'cw' }">
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder" v-autocomplete="{ model: 'text' }" @paste="onPaste"></textarea>
<div class="with-quote" v-if="quoteId">{{ $t('@.post-form.quote-attached') }}</div>
<x-post-form-attaches class="attaches" :files="files"/>
<x-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="onPollUpdate()"/>
<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
@@ -140,6 +141,10 @@ export default Vue.extend({
> .preview
padding 16px
> .with-quote
margin 0 0 8px 0
color var(--primary)
> .visibleUsers
margin 5px
font-size 14px
@@ -148,6 +153,10 @@ export default Vue.extend({
margin-right 16px
color var(--text)
> .local-only
margin 0 0 8px 0
color var(--primary)
> input
z-index 1

View File

@@ -98,12 +98,6 @@ export default Vue.extend({
id: 'g', data: {}
}]);
}
this.$watch('$store.getters.mobileHome', () => {
this.$store.dispatch('settings/updateMobileHomeProfile');
}, {
deep: true
});
},
mounted() {

View File

@@ -48,6 +48,7 @@ import { AttestationChallenge } from '../models/entities/attestation-challenge';
import { Page } from '../models/entities/page';
import { PageLike } from '../models/entities/page-like';
import { ModerationLog } from '../models/entities/moderation-log';
import { UsedUsername } from '../models/entities/used-username';
const sqlLogger = dbLogger.createSubLogger('sql', 'white', false);
@@ -100,6 +101,7 @@ export const entities = [
UserGroupInvite,
UserNotePining,
UserSecurityKey,
UsedUsername,
AttestationChallenge,
Following,
FollowRequest,

View File

@@ -20,7 +20,7 @@ function formatLocaleString(date: Date, format: string): string {
});
}
function formatDateTimeString(date: Date, format: string): string {
export function formatDateTimeString(date: Date, format: string): string {
return format
.replace(/yyyy/g, date.getFullYear().toString())
.replace(/yy/g, date.getFullYear().toString().slice(-2))

View File

@@ -0,0 +1,20 @@
import { PrimaryColumn, Entity, Column } from 'typeorm';
@Entity()
export class UsedUsername {
@PrimaryColumn('varchar', {
length: 128,
})
public username: string;
@Column('timestamp with time zone')
public createdAt: Date;
constructor(data: Partial<UsedUsername>) {
if (data == null) return;
for (const [k, v] of Object.entries(data)) {
(this as any)[k] = v;
}
}
}

View File

@@ -43,6 +43,7 @@ import { HashtagRepository } from './repositories/hashtag';
import { PageRepository } from './repositories/page';
import { PageLikeRepository } from './repositories/page-like';
import { ModerationLogRepository } from './repositories/moderation-logs';
import { UsedUsername } from './entities/used-username';
export const Apps = getCustomRepository(AppRepository);
export const Notes = getCustomRepository(NoteRepository);
@@ -64,6 +65,7 @@ export const UserGroups = getCustomRepository(UserGroupRepository);
export const UserGroupJoinings = getRepository(UserGroupJoining);
export const UserGroupInvites = getCustomRepository(UserGroupInviteRepository);
export const UserNotePinings = getRepository(UserNotePining);
export const UsedUsernames = getRepository(UsedUsername);
export const Followings = getCustomRepository(FollowingRepository);
export const FollowRequests = getCustomRepository(FollowRequestRepository);
export const Instances = getRepository(Instance);

31
src/prelude/time.ts Normal file
View File

@@ -0,0 +1,31 @@
const dateTimeIntervals = {
'days': 86400000,
'hours': 3600000,
};
export function DateUTC(time: number[]): Date {
const r = new Date(0);
r.setUTCFullYear(time[0], time[1], time[2]);
if (time[3]) r.setUTCHours(time[3], ...time.slice(4));
return r;
}
export function isTimeSame(a: Date, b: Date): boolean {
return (a.getTime() - b.getTime()) === 0;
}
export function isTimeBefore(a: Date, b: Date): boolean {
return (a.getTime() - b.getTime()) < 0;
}
export function isTimeAfter(a: Date, b: Date): boolean {
return (a.getTime() - b.getTime()) > 0;
}
export function addTimespan(x: Date, value: number, span: keyof typeof dateTimeIntervals): Date {
return new Date(x.getTime() + (value * dateTimeIntervals[span]));
}
export function subtractTimespan(x: Date, value: number, span: keyof typeof dateTimeIntervals): Date {
return new Date(x.getTime() - (value * dateTimeIntervals[span]));
}

View File

@@ -215,8 +215,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
const apEmojis = emojis.map(emoji => emoji.name);
const questionUri = note._misskey_question;
const poll = await extractPollFromQuestion(note._misskey_question || note, resolver).catch(() => undefined);
const poll = await extractPollFromQuestion(note, resolver).catch(() => undefined);
// ユーザーの情報が古かったらついでに更新しておく
if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
@@ -239,7 +238,6 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
apMentions,
apHashtags,
apEmojis,
questionUri,
poll,
uri: note.id
}, silent);

View File

@@ -15,7 +15,7 @@ export async function extractPollFromQuestion(source: string | IObject, resolver
}
const multiple = !question.oneOf;
const expiresAt = question.endTime ? new Date(question.endTime) : null;
const expiresAt = question.endTime ? new Date(question.endTime) : question.closed ? new Date(question.closed) : null;
if (multiple && !question.anyOf) {
throw new Error('invalid question');

View File

@@ -90,14 +90,11 @@ export default async function renderNote(note: Note, dive = true): Promise<any>
poll = await Polls.findOne({ noteId: note.id });
}
let question: string | undefined;
if (poll) {
if (text == null) text = '';
const url = `${config.url}/notes/${note.id}`;
// TODO: i18n
text += `\n[リモートで結果を表示](${url})`;
question = `${config.url}/questions/${note.id}`;
}
let apText = text;
@@ -156,7 +153,6 @@ export default async function renderNote(note: Note, dive = true): Promise<any>
content,
_misskey_content: text,
_misskey_quote: quote,
_misskey_question: question,
published: note.createdAt.toISOString(),
to,
cc,

View File

@@ -74,17 +74,16 @@ export interface INote extends IObject {
type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video';
_misskey_content?: string;
_misskey_quote?: string;
_misskey_question?: string;
}
export interface IQuestion extends IObject {
type: 'Note' | 'Question';
_misskey_content?: string;
_misskey_quote?: string;
_misskey_question?: string;
oneOf?: IQuestionChoice[];
anyOf?: IQuestionChoice[];
endTime?: Date;
closed?: Date;
}
export const isQuestion = (object: IObject): object is IQuestion =>

View File

@@ -11,10 +11,9 @@ import Outbox, { packActivity } from './activitypub/outbox';
import Followers from './activitypub/followers';
import Following from './activitypub/following';
import Featured from './activitypub/featured';
import renderQuestion from '../remote/activitypub/renderer/question';
import { inbox as processInbox } from '../queue';
import { isSelfHost } from '../misc/convert-host';
import { Notes, Users, Emojis, UserKeypairs, Polls } from '../models';
import { Notes, Users, Emojis, UserKeypairs } from '../models';
import { ILocalUser, User } from '../models/entities/user';
import { In } from 'typeorm';
import { ensure } from '../prelude/ensure';
@@ -109,28 +108,6 @@ router.get('/notes/:note/activity', async ctx => {
setResponseType(ctx);
});
// question
router.get('/questions/:question', async (ctx, next) => {
const pollNote = await Notes.findOne({
id: ctx.params.question,
userHost: null,
visibility: In(['public', 'home']),
localOnly: false,
hasPoll: true
});
if (pollNote == null) {
ctx.status = 404;
return;
}
const user = await Users.findOne(pollNote.userId).then(ensure);
const poll = await Polls.findOne({ noteId: pollNote.id }).then(ensure);
ctx.body = renderActivity(await renderQuestion(user as ILocalUser, pollNote, poll));
setResponseType(ctx);
});
// outbox
router.get('/users/:user/outbox', Outbox);

View File

@@ -0,0 +1,19 @@
import { User } from '../../../models/entities/user';
import { Blockings } from '../../../models';
import { SelectQueryBuilder } from 'typeorm';
export function generateBlockQueryForUsers(q: SelectQueryBuilder<any>, me: User) {
const blockingQuery = Blockings.createQueryBuilder('blocking')
.select('blocking.blockeeId')
.where('blocking.blockerId = :blockerId', { blockerId: me.id });
const blockedQuery = Blockings.createQueryBuilder('blocking')
.select('blocking.blockerId')
.where('blocking.blockeeId = :blockeeId', { blockeeId: me.id });
q.andWhere(`user.id NOT IN (${ blockingQuery.getQuery() })`);
q.setParameters(blockingQuery.getParameters());
q.andWhere(`user.id NOT IN (${ blockedQuery.getQuery() })`);
q.setParameters(blockedQuery.getParameters());
}

View File

@@ -1,6 +1,6 @@
import $ from 'cafy';
import define from '../../define';
import { Users } from '../../../../models';
import { Users, UsedUsernames } from '../../../../models';
export const meta = {
tags: ['users'],
@@ -21,7 +21,9 @@ export default define(meta, async (ps) => {
usernameLower: ps.username.toLowerCase()
});
const exist2 = await UsedUsernames.count({ username: ps.username.toLowerCase() });
return {
available: exist === 0
available: exist === 0 && exist2 === 0
};
});

View File

@@ -3,6 +3,7 @@ import $ from 'cafy';
import define from '../../define';
import { Users, Followings } from '../../../../models';
import { generateMuteQueryForUsers } from '../../common/generate-mute-query';
import { generateBlockQueryForUsers } from '../../common/generate-block-query';
export const meta = {
desc: {
@@ -47,6 +48,7 @@ export default define(meta, async (ps, me) => {
.orderBy('user.followersCount', 'DESC');
generateMuteQueryForUsers(query, me);
generateBlockQueryForUsers(query, me);
const followingQuery = Followings.createQueryBuilder('following')
.select('following.followeeId')

View File

@@ -5,7 +5,7 @@ import generateUserToken from '../common/generate-native-user-token';
import config from '../../../config';
import { fetchMeta } from '../../../misc/fetch-meta';
import * as recaptcha from 'recaptcha-promise';
import { Users, Signins, RegistrationTickets } from '../../../models';
import { Users, Signins, RegistrationTickets, UsedUsernames } from '../../../models';
import { genId } from '../../../misc/gen-id';
import { usersChart } from '../../../services/chart';
import { User } from '../../../models/entities/user';
@@ -13,6 +13,7 @@ import { UserKeypair } from '../../../models/entities/user-keypair';
import { toPunyNullable } from '../../../misc/convert-host';
import { UserProfile } from '../../../models/entities/user-profile';
import { getConnection } from 'typeorm';
import { UsedUsername } from '../../../models/entities/used-username';
export default async (ctx: Koa.BaseContext) => {
const body = ctx.request.body as any;
@@ -78,11 +79,18 @@ export default async (ctx: Koa.BaseContext) => {
// Generate secret
const secret = generateUserToken();
// Check username duplication
if (await Users.findOne({ usernameLower: username.toLowerCase(), host: null })) {
ctx.status = 400;
return;
}
// Check deleted username duplication
if (await UsedUsernames.findOne({ username: username.toLowerCase() })) {
ctx.status = 400;
return;
}
const keyPair = await new Promise<string[]>((s, j) =>
generateKeyPair('rsa', {
modulusLength: 4096,
@@ -109,7 +117,7 @@ export default async (ctx: Koa.BaseContext) => {
host: null
});
if (exist) throw 'already registered';
if (exist) throw new Error(' the username is already used');
account = await transactionalEntityManager.save(new User({
id: genId(),
@@ -133,6 +141,11 @@ export default async (ctx: Koa.BaseContext) => {
autoWatch: false,
password: hash,
}));
await transactionalEntityManager.save(new UsedUsername({
createdAt: new Date(),
username: username.toLowerCase(),
}));
});
usersChart.update(account, true);

View File

@@ -4,18 +4,16 @@
* Tests located in test/chart
*/
import * as moment from 'moment';
import * as nestedProperty from 'nested-property';
import autobind from 'autobind-decorator';
import Logger from '../logger';
import { Schema } from '../../misc/schema';
import { EntitySchema, getRepository, Repository, LessThan, MoreThanOrEqual } from 'typeorm';
import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
import { DateUTC, isTimeSame, isTimeBefore, subtractTimespan } from '../../prelude/time';
const logger = new Logger('chart', 'white', process.env.NODE_ENV !== 'test');
const utc = moment.utc;
export type Obj = { [key: string]: any };
export type DeepPartial<T> = {
@@ -131,8 +129,8 @@ export default abstract class Chart<T extends Record<string, any>> {
}
@autobind
private static momentToTimestamp(x: moment.Moment): Log['date'] {
return x.unix();
private static dateToTimestamp(x: Date): Log['date'] {
return Math.floor(x.getTime() / 1000);
}
@autobind
@@ -215,12 +213,12 @@ export default abstract class Chart<T extends Record<string, any>> {
@autobind
private getCurrentDate(): [number, number, number, number] {
const now = moment().utc();
const now = new Date();
const y = now.year();
const m = now.month();
const d = now.date();
const h = now.hour();
const y = now.getUTCFullYear();
const m = now.getUTCMonth();
const d = now.getUTCDate();
const h = now.getUTCHours();
return [y, m, d, h];
}
@@ -242,14 +240,14 @@ export default abstract class Chart<T extends Record<string, any>> {
const [y, m, d, h] = this.getCurrentDate();
const current =
span == 'day' ? utc([y, m, d]) :
span == 'hour' ? utc([y, m, d, h]) :
span == 'day' ? DateUTC([y, m, d]) :
span == 'hour' ? DateUTC([y, m, d, h]) :
null as never;
// 現在(今日または今のHour)のログ
const currentLog = await this.repository.findOne({
span: span,
date: Chart.momentToTimestamp(current),
date: Chart.dateToTimestamp(current),
...(group ? { group: group } : {})
});
@@ -290,7 +288,7 @@ export default abstract class Chart<T extends Record<string, any>> {
log = await this.repository.save({
group: group,
span: span,
date: Chart.momentToTimestamp(current),
date: Chart.dateToTimestamp(current),
...Chart.convertObjectToFlattenColumns(data)
});
} catch (e) {
@@ -358,8 +356,8 @@ export default abstract class Chart<T extends Record<string, any>> {
const [y, m, d, h] = this.getCurrentDate();
const gt =
span == 'day' ? utc([y, m, d]).subtract(range, 'days') :
span == 'hour' ? utc([y, m, d, h]).subtract(range, 'hours') :
span == 'day' ? subtractTimespan(DateUTC([y, m, d]), range, 'days') :
span == 'hour' ? subtractTimespan(DateUTC([y, m, d, h]), range, 'hours') :
null as never;
// ログ取得
@@ -367,7 +365,7 @@ export default abstract class Chart<T extends Record<string, any>> {
where: {
group: group,
span: span,
date: MoreThanOrEqual(Chart.momentToTimestamp(gt))
date: MoreThanOrEqual(Chart.dateToTimestamp(gt))
},
order: {
date: -1
@@ -392,13 +390,13 @@ export default abstract class Chart<T extends Record<string, any>> {
}
// 要求された範囲の最も古い箇所に位置するログが存在しなかったら
} else if (!utc(logs[logs.length - 1].date * 1000).isSame(gt)) {
} else if (!isTimeSame(new Date(logs[logs.length - 1].date * 1000), gt)) {
// 要求された範囲の最も古い箇所時点での最も新しいログを持ってきて末尾に追加する
// (隙間埋めできないため)
const outdatedLog = await this.repository.findOne({
group: group,
span: span,
date: LessThan(Chart.momentToTimestamp(gt))
date: LessThan(Chart.dateToTimestamp(gt))
}, {
order: {
date: -1
@@ -415,18 +413,18 @@ export default abstract class Chart<T extends Record<string, any>> {
// 整形
for (let i = (range - 1); i >= 0; i--) {
const current =
span == 'day' ? utc([y, m, d]).subtract(i, 'days') :
span == 'hour' ? utc([y, m, d, h]).subtract(i, 'hours') :
span == 'day' ? subtractTimespan(DateUTC([y, m, d]), i, 'days') :
span == 'hour' ? subtractTimespan(DateUTC([y, m, d, h]), i, 'hours') :
null as never;
const log = logs.find(l => utc(l.date * 1000).isSame(current));
const log = logs.find(l => isTimeSame(new Date(l.date * 1000), current));
if (log) {
const data = Chart.convertFlattenColumnsToObject(log as Record<string, any>);
chart.unshift(data);
} else {
// 隙間埋め
const latest = logs.find(l => utc(l.date * 1000).isBefore(current));
const latest = logs.find(l => isTimeBefore(new Date(l.date * 1000), current));
const data = latest ? Chart.convertFlattenColumnsToObject(latest as Record<string, any>) : null;
chart.unshift(this.getNewLog(data));
}

View File

@@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as tmp from 'tmp';
import { IImage, convertToJpeg } from './image-processor';
const ThumbnailGenerator = require('video-thumbnail-generator').default;
import * as FFmpeg from 'fluent-ffmpeg';
export async function GenerateVideoThumbnail(path: string): Promise<IImage> {
const [outDir, cleanup] = await new Promise<[string, any]>((res, rej) => {
@@ -11,14 +11,18 @@ export async function GenerateVideoThumbnail(path: string): Promise<IImage> {
});
});
const tg = new ThumbnailGenerator({
sourcePath: path,
thumbnailPath: outDir,
});
await tg.generateOneByPercent(5, {
size: '100%',
filename: 'output.png',
await new Promise((res, rej) => {
FFmpeg({
source: path
})
.on('end', res)
.on('error', rej)
.screenshot({
folder: outDir,
filename: 'output.png',
count: 1,
timestamps: ['5%']
});
});
const outPath = `${outDir}/output.png`;
@@ -26,7 +30,7 @@ export async function GenerateVideoThumbnail(path: string): Promise<IImage> {
const thumbnail = await convertToJpeg(outPath, 498, 280);
// cleanup
fs.unlinkSync(outPath);
await fs.promises.unlink(outPath);
cleanup();
return thumbnail;

View File

@@ -100,7 +100,6 @@ type Option = {
apMentions?: User[] | null;
apHashtags?: string[] | null;
apEmojis?: string[] | null;
questionUri?: string | null;
uri?: string | null;
app?: App | null;
};

307
yarn.lock
View File

@@ -263,6 +263,13 @@
resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.0.tgz#a61ab476e5e628cd07a846330df53b85e05c8ce0"
integrity sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw==
"@types/fluent-ffmpeg@2.1.10":
version "2.1.10"
resolved "https://registry.yarnpkg.com/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.10.tgz#e6a73fc671cb97b4f5e06e00ac86efb8cb162015"
integrity sha512-QWwPavtDBW9e3ndfquVgFZRc2GDQEEf0d3vDNg1hS6HztvYWdjCA2paxAVPay+PmFlcKAZQcfvnskdktBQNCaA==
dependencies:
"@types/node" "*"
"@types/glob-stream@*":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@types/glob-stream/-/glob-stream-6.1.0.tgz#7ede8a33e59140534f8d8adfb8ac9edfb31897bc"
@@ -803,10 +810,10 @@
lodash.unescape "4.0.1"
semver "5.5.0"
"@vue/component-compiler-utils@^2.5.1":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz#aa46d2a6f7647440b0b8932434d22f12371e543b"
integrity sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==
"@vue/component-compiler-utils@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz#d16fa26b836c06df5baaeb45f3d80afc47e35634"
integrity sha512-am+04/0UX7ektcmvhYmrf84BDVAD8afFOf4asZjN84q8xzxFclbk5x0MtxuKGfp+zjN5WWPJn3fjFAWtDdIGSw==
dependencies:
consolidate "^0.15.1"
hash-sum "^1.0.2"
@@ -1206,10 +1213,10 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
apexcharts@3.8.2:
version "3.8.2"
resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.8.2.tgz#56bd8aa0ce58534a945a8bc4c3925d0685da1cba"
integrity sha512-3k30M1FlVT9JjtTZf6xUl7pExUmWnbXCMM6ajrsaMW0NorFBens7BWsYCaCxbBAavvJOlxeu0W6RbL8kBQiopA==
apexcharts@3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.8.3.tgz#ad9dafa1404b2dbcb1052f924da7fa5b8fb02cdf"
integrity sha512-PybD3+7kMBW9tpc93O5kN4uCwl1x1ic87Nh+C/NLLHS+iqsYV/K9MM8jpEFlqsVKjkpa7MiIANCXAyp9iFMDKA==
dependencies:
promise-polyfill "8.1.0"
svg.draggable.js "^2.2.2"
@@ -1488,18 +1495,23 @@ async@2.6.0:
dependencies:
lodash "^4.14.0"
async@>=0.2.9, async@^2.6.0:
version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
dependencies:
lodash "^4.17.14"
async@>=0.2.9:
version "3.1.0"
resolved "https://registry.yarnpkg.com/async/-/async-3.1.0.tgz#42b3b12ae1b74927b5217d8c0016baaf62463772"
integrity sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==
async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
async@^2.6.0:
version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
dependencies:
lodash "^4.17.14"
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -1722,11 +1734,6 @@ block-stream2@^1.0.0:
inherits "^2.0.1"
readable-stream "^2.0.4"
bluebird@3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
integrity sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=
bluebird@^3.1.1, bluebird@^3.4.1, bluebird@^3.5.1, bluebird@^3.5.5:
version "3.5.5"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
@@ -1971,16 +1978,11 @@ busboy@^0.2.11:
dicer "0.2.5"
readable-stream "1.1.x"
bytes@3.1.0, bytes@^3.0.0:
bytes@3.1.0, bytes@^3.0.0, bytes@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
bytes@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a"
integrity sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=
cacache@^11.3.2:
version "11.3.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc"
@@ -2901,10 +2903,10 @@ css-declaration-sorter@^4.0.1:
postcss "^7.0.1"
timsort "^0.3.0"
css-loader@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.0.0.tgz#bdd48a4921eefedf1f0a55266585944d4e5efc63"
integrity sha512-WR6KZuCkFbnMhRrGPlkwAA7SSCtwqPwpyXJAPhotYkYsc0mKU9n/fu5wufy4jl2WhBw9Ia8gUQMIp/1w98DuPw==
css-loader@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.1.0.tgz#6f008b993b8ce812e6bab57f3cbfdc7a7cf28685"
integrity sha512-MuL8WsF/KSrHCBCYaozBKlx+r7vIfUaDTEreo7wR7Vv3J6N0z6fqWjRk3e/6wjneitXN1r/Y9FTK1psYNOBdJQ==
dependencies:
camelcase "^5.3.1"
cssesc "^3.0.0"
@@ -2917,7 +2919,7 @@ css-loader@3.0.0:
postcss-modules-scope "^2.1.0"
postcss-modules-values "^3.0.0"
postcss-value-parser "^4.0.0"
schema-utils "^1.0.0"
schema-utils "^2.0.0"
css-parse@1.7.x:
version "1.7.0"
@@ -3381,19 +3383,6 @@ defined@^1.0.0:
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
del@2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=
dependencies:
globby "^5.0.0"
is-path-cwd "^1.0.0"
is-path-in-cwd "^1.0.0"
object-assign "^4.0.1"
pify "^2.0.0"
pinkie-promise "^2.0.0"
rimraf "^2.2.8"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -3858,7 +3847,7 @@ eslint-plugin-vue@5.2.3:
dependencies:
vue-eslint-parser "^5.0.0"
eslint-scope@^4.0.0, eslint-scope@^4.0.3:
eslint-scope@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==
@@ -3866,6 +3855,14 @@ eslint-scope@^4.0.0, eslint-scope@^4.0.3:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-scope@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-utils@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c"
@@ -3878,10 +3875,10 @@ eslint-visitor-keys@^1.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
eslint@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.0.1.tgz#4a32181d72cb999d6f54151df7d337131f81cda7"
integrity sha512-DyQRaMmORQ+JsWShYsSg4OPTjY56u1nCjAmICrE8vLWqyLKxhFXOthwMj1SA8xwfrv0CofLNVnqbfyhwCkaO0w==
eslint@6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.1.0.tgz#06438a4a278b1d84fb107d24eaaa35471986e646"
integrity sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==
dependencies:
"@babel/code-frame" "^7.0.0"
ajv "^6.10.0"
@@ -3889,7 +3886,7 @@ eslint@6.0.1:
cross-spawn "^6.0.5"
debug "^4.0.1"
doctrine "^3.0.0"
eslint-scope "^4.0.3"
eslint-scope "^5.0.0"
eslint-utils "^1.3.1"
eslint-visitor-keys "^1.0.0"
espree "^6.0.0"
@@ -3897,28 +3894,29 @@ eslint@6.0.1:
esutils "^2.0.2"
file-entry-cache "^5.0.1"
functional-red-black-tree "^1.0.1"
glob-parent "^3.1.0"
glob-parent "^5.0.0"
globals "^11.7.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
inquirer "^6.2.2"
inquirer "^6.4.1"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.3.0"
lodash "^4.17.11"
lodash "^4.17.14"
minimatch "^3.0.4"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
optionator "^0.8.2"
progress "^2.0.0"
regexpp "^2.0.1"
semver "^5.5.1"
strip-ansi "^4.0.0"
strip-json-comments "^2.0.1"
semver "^6.1.2"
strip-ansi "^5.2.0"
strip-json-comments "^3.0.1"
table "^5.2.3"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
espree@^4.1.0:
version "4.1.0"
@@ -4408,10 +4406,10 @@ flatten@^1.0.2:
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=
fluent-ffmpeg@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fluent-ffmpeg/-/fluent-ffmpeg-2.1.0.tgz#e6ab85e75ba8e49119a3900cd9df10d39831d392"
integrity sha1-5quF51uo5JEZo5AM2d8Q05gx05I=
fluent-ffmpeg@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz#c952de2240f812ebda0aa8006d7776ee2acf7d74"
integrity sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=
dependencies:
async ">=0.2.9"
which "^1.1.1"
@@ -4667,6 +4665,13 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
glob-parent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954"
integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
dependencies:
is-glob "^4.0.1"
glob-stream@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4"
@@ -4736,7 +4741,7 @@ glob@7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.1.4"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
@@ -4789,18 +4794,6 @@ globals@^11.7.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
globby@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=
dependencies:
array-union "^1.0.1"
arrify "^1.0.0"
glob "^7.0.3"
object-assign "^4.0.1"
pify "^2.0.0"
pinkie-promise "^2.0.0"
globby@^8.0.1:
version "8.0.2"
resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d"
@@ -5586,7 +5579,7 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
inquirer@^6.2.2:
inquirer@^6.4.1:
version "6.5.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42"
integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==
@@ -5842,7 +5835,7 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
is-glob@^4.0.0:
is-glob@^4.0.0, is-glob@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
@@ -5900,25 +5893,6 @@ is-object@^1.0.1:
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA=
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
is-path-in-cwd@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
dependencies:
is-path-inside "^1.0.0"
is-path-inside@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
dependencies:
path-is-inside "^1.0.1"
is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
@@ -6411,13 +6385,13 @@ koa-json-body@5.3.0:
dependencies:
co-body "^5.0.0"
koa-logger@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/koa-logger/-/koa-logger-3.2.0.tgz#8aef64d8b848fb6253a9b31aa708d0e05141f0e6"
integrity sha512-IQhaKkWvvbjnmMIcHSK/cH2RCYt64jOxliazVF1wZdXH0KbmM5VHgn1v3r9a9mqInDPDMR+JoiErSFc83epLaQ==
koa-logger@3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/koa-logger/-/koa-logger-3.2.1.tgz#ab9db879526db3837cc9ce4fd983c025b1689f22"
integrity sha512-MjlznhLLKy9+kG8nAXKJLM0/ClsQp/Or2vI3a5rbSQmgl8IJBQO0KI5FA70BvW+hqjtxjp49SpH2E7okS6NmHg==
dependencies:
bytes "^2.5.0"
chalk "^1.1.3"
bytes "^3.1.0"
chalk "^2.4.2"
humanize-number "0.0.2"
passthrough-counter "^1.0.0"
@@ -6887,7 +6861,7 @@ lodash.uniq@^4.3.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@4.17.4, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.14.2, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.4:
lodash@^4.13.1, lodash@^4.14.0, lodash@^4.14.2, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.4:
version "4.17.14"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
@@ -7320,10 +7294,10 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@
dependencies:
minimist "0.0.8"
mocha@6.1.4:
version "6.1.4"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.1.4.tgz#e35fada242d5434a7e163d555c705f6875951640"
integrity sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==
mocha@6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.0.tgz#f896b642843445d1bb8bca60eabd9206b8916e56"
integrity sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==
dependencies:
ansi-colors "3.2.3"
browser-stdout "1.3.1"
@@ -7380,12 +7354,7 @@ moment-timezone@^0.5.25:
dependencies:
moment ">= 2.9.0"
moment@2.22.2:
version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
moment@2.24.0, "moment@>= 2.9.0":
"moment@>= 2.9.0":
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
@@ -7612,10 +7581,10 @@ node-releases@^1.1.25:
dependencies:
semver "^5.3.0"
nodemailer@6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.2.1.tgz#20d773925eb8f7a06166a0b62c751dc8290429f3"
integrity sha512-TagB7iuIi9uyNgHExo8lUDq3VK5/B0BpbkcjIgNvxbtVrjNqq0DwAOTuzALPVkK76kMhTSzIgHqg8X1uklVs6g==
nodemailer@6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.3.0.tgz#a89b0c62d3937bdcdeecbf55687bd7911b627e12"
integrity sha512-TEHBNBPHv7Ie/0o3HXnb7xrPSSQmH1dXwQKRaMKDBGt/ZN54lvDVujP6hKkO/vjkIYL9rK8kHSG11+G42Nhxuw==
nofilter@^1.0.1:
version "1.0.2"
@@ -8255,11 +8224,6 @@ path-is-absolute@1.0.1, path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-is-inside@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
@@ -9423,10 +9387,10 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qrcode@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.0.tgz#b4b41b4bbfd5eeac8d5163efacef34ee5b8ad455"
integrity sha512-18u+bdSosXO0+wx6F1UUFzJz01VRfMBcb/wbBw/tKYRD0A2Vho5WQ4xz30pHwhh4IE/qhObqIs5yNO0mGdHKkA==
qrcode@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.1.tgz#2126814985d0dbbd9aee050fc523d319c6a7dc3b"
integrity sha512-3JhHQJkKqJL4PfoM6t+B40f0GWv9eNJAJmuNx2X/sHEOLvMyvEPN8GfbdN1qmr19O8N2nLraOzeWjXocHz1S4w==
dependencies:
dijkstrajs "^1.0.1"
isarray "^2.0.1"
@@ -9996,7 +9960,7 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
rimraf@2.6.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
@@ -10103,6 +10067,14 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
schema-utils@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.0.1.tgz#1eec2e059556af841b7f3a83b61af13d7a3f9196"
integrity sha512-HJFKJ4JixDpRur06QHwi8uu2kZbng318ahWEKgBjc0ZklcE4FDvmm2wghb448q0IRaABxIESt8vqPFvwgMB80A==
dependencies:
ajv "^6.1.0"
ajv-keywords "^3.1.0"
scrollmonitor@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/scrollmonitor/-/scrollmonitor-1.2.4.tgz#823d04cc1574aa3b71de7cc70ef91ebe633344a0"
@@ -10149,7 +10121,7 @@ semver-truncate@^1.1.2:
dependencies:
semver "^5.3.0"
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0:
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0:
version "5.7.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
@@ -10164,7 +10136,7 @@ semver@5.5.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
semver@^6.0.0, semver@^6.1.1:
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2:
version "6.2.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db"
integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==
@@ -10700,11 +10672,16 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
strip-json-comments@2.0.1, strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
strip-json-comments@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
strip-outer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631"
@@ -10898,10 +10875,10 @@ symbol-tree@^3.2.2:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
systeminformation@4.14.3:
version "4.14.3"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.14.3.tgz#ccd7f02dc0c0a0da537f278684b085a56302b8f0"
integrity sha512-heYWYVekEA1Ana61U4/eoaGMS+UeoSNSbcr9MDQxD9N6+ItumJIdcNnP3VcC47mfe0e/m9ZYRTYs/cyW4RGguQ==
systeminformation@4.14.4:
version "4.14.4"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.14.4.tgz#0c74d8fa9da614eda382539dd2420e32c58442db"
integrity sha512-ib2dodksiiaGOW4rcKvFr5naHkODI9GwQPugLb6FLKppkIsE7rj2dfY2UdMBr7oX0/iZP981hoxmbk2e6zl99Q==
syuilo-password-strength@0.0.1:
version "0.0.1"
@@ -11391,10 +11368,10 @@ typeorm@0.2.18:
yargonaut "^1.1.2"
yargs "^13.2.1"
typescript@3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c"
integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==
typescript@3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
uglify-es@3.3.9:
version "3.3.9"
@@ -11562,14 +11539,14 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
url-loader@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.0.1.tgz#6c47fc7090e3d48939e01fe3c6efcba5938dcec5"
integrity sha512-nd+jtHG6VgYx/NnXxXSWCJ7FtHIhuyk6Pe48HKhq29Avq3r5FSdIrenvzlbb67A3SNFaQyLk0/lMZfubj0+5ww==
url-loader@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.1.0.tgz#bcc1ecabbd197e913eca23f5e0378e24b4412961"
integrity sha512-kVrp/8VfEm5fUt+fl2E0FQyrpmOYgMEkBsv8+UDP1wFhszECq5JyGF33I7cajlVY90zRZ6MyfgKXngLvHYZX8A==
dependencies:
loader-utils "^1.1.0"
loader-utils "^1.2.3"
mime "^2.4.4"
schema-utils "^1.0.0"
schema-utils "^2.0.0"
url-parse-lax@^1.0.0:
version "1.0.0"
@@ -11652,7 +11629,7 @@ v-debounce@0.1.2:
resolved "https://registry.yarnpkg.com/v-debounce/-/v-debounce-0.1.2.tgz#cab75df7def2783215bf449ef85c69c2decf0a55"
integrity sha1-yrdd997yeDIVv0Se+Fxpwt7PClU=
v8-compile-cache@2.0.3:
v8-compile-cache@2.0.3, v8-compile-cache@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
@@ -11701,17 +11678,6 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
video-thumbnail-generator@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/video-thumbnail-generator/-/video-thumbnail-generator-1.1.3.tgz#b8bd9398697205c35cfed6dd12809d5b41068f9d"
integrity sha1-uL2TmGlyBcNc/tbdEoCdW0EGj50=
dependencies:
bluebird "3.5.0"
del "2.2.2"
fluent-ffmpeg "2.1.0"
lodash "4.17.4"
moment "2.22.2"
vinyl-fs@^3.0.0, vinyl-fs@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7"
@@ -11847,12 +11813,12 @@ vue-json-pretty@1.6.0:
resolved "https://registry.yarnpkg.com/vue-json-pretty/-/vue-json-pretty-1.6.0.tgz#ea3efaa7d574ee987e636908395ae4a7044f9aee"
integrity sha512-yLQ2Kuk4S+fPxVncww9kPO72pTiGrZfgyi1P+Vhmy1kR7J1CwzYli8uyhgdTMPaz0h2zqiDF0VGtzX+FTrwbig==
vue-loader@15.7.0:
version "15.7.0"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.7.0.tgz#27275aa5a3ef4958c5379c006dd1436ad04b25b3"
integrity sha512-x+NZ4RIthQOxcFclEcs8sXGEWqnZHodL2J9Vq+hUz+TDZzBaDIh1j3d9M2IUlTjtrHTZy4uMuRdTi8BGws7jLA==
vue-loader@15.7.1:
version "15.7.1"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.7.1.tgz#6ccacd4122aa80f69baaac08ff295a62e3aefcfd"
integrity sha512-fwIKtA23Pl/rqfYP5TSGK7gkEuLhoTvRYW+TU7ER3q9GpNLt/PjG5NLv3XHRDiTg7OPM1JcckBgds+VnAc+HbA==
dependencies:
"@vue/component-compiler-utils" "^2.5.1"
"@vue/component-compiler-utils" "^3.0.0"
hash-sum "^1.0.2"
loader-utils "^1.1.0"
vue-hot-reload-api "^2.3.0"
@@ -11987,10 +11953,10 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
webpack-cli@3.3.5:
version "3.3.5"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.5.tgz#f4d1238a66a2843d9cebf189835ea22142e72767"
integrity sha512-w0j/s42c5UhchwTmV/45MLQnTVwRoaUTu9fM5LuyOd/8lFoCNCELDogFoecx5NzRUndO0yD/gF2b02XKMnmAWQ==
webpack-cli@3.3.6:
version "3.3.6"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.6.tgz#2c8c399a2642133f8d736a359007a052e060032c"
integrity sha512-0vEa83M7kJtxK/jUhlpZ27WHIOndz5mghWL2O53kiDoA9DIxSKnfqB92LoqEn77cT4f3H2cZm1BMEat/6AZz3A==
dependencies:
chalk "2.4.2"
cross-spawn "6.0.5"
@@ -12012,10 +11978,10 @@ webpack-sources@^1.0.1, webpack-sources@^1.3.0:
source-list-map "^2.0.0"
source-map "~0.6.1"
webpack@4.35.3:
version "4.35.3"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.35.3.tgz#66bc35ef215a7b75e8790f84d560013ffecf0ca3"
integrity sha512-xggQPwr9ILlXzz61lHzjvgoqGU08v5+Wnut19Uv3GaTtzN4xBTcwnobodrXE142EL1tOiS5WVEButooGzcQzTA==
webpack@4.36.1:
version "4.36.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.36.1.tgz#f546fda7a403a76faeaaa7196c50d12370ed18a9"
integrity sha512-Ej01/N9W8DVyhEpeQnbUdGvOECw0L46FxS12cCOs8gSK7bhUlrbHRnWkjiXckGlHjUrmL89kDpTRIkUk6Y+fKg==
dependencies:
"@webassemblyjs/ast" "1.8.5"
"@webassemblyjs/helper-module-context" "1.8.5"
@@ -12197,7 +12163,14 @@ write@1.0.3:
dependencies:
mkdirp "^0.5.1"
ws@7.1.0, ws@^7.0.0:
ws@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.1.1.tgz#f9942dc868b6dffb72c14fd8f2ba05f77a4d5983"
integrity sha512-o41D/WmDeca0BqYhsr3nJzQyg9NF5X8l/UdnFNux9cS3lwB+swm8qGWX5rn+aD6xfBU3rGmtHij7g7x6LxFU3A==
dependencies:
async-limiter "^1.0.0"
ws@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.1.0.tgz#0395646c6fcc3ac56abf61ce1a42039637a6bd98"
integrity sha512-Swie2C4fs7CkwlHu1glMePLYJJsWjzhl1vm3ZaLplD0h7OMkZyZ6kLTB/OagiU923bZrPFXuDTeEqaEN4NWG4g==