From d7c0afe65797a3f09590de1d2219a0879ede707b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 4 Dec 2017 20:35:05 +0000 Subject: [PATCH 001/186] fix(package): update @types/chai to version 4.0.8 Closes #963 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b33e560c18..11533731ca 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@prezzemolo/zip": "0.0.3", "@types/bcryptjs": "2.4.1", "@types/body-parser": "1.16.8", - "@types/chai": "4.0.6", + "@types/chai": "4.0.8", "@types/chai-http": "3.0.3", "@types/compression": "0.0.35", "@types/cookie": "0.3.1", From 9542e4b14d84493872a51f0cf47a3d5e0bd00583 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 5 Dec 2017 17:20:23 +0000 Subject: [PATCH 002/186] fix(package): update @types/elasticsearch to version 5.0.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b33e560c18..a2a3360cf2 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@types/cors": "2.8.3", "@types/debug": "0.0.30", "@types/deep-equal": "1.0.1", - "@types/elasticsearch": "5.0.18", + "@types/elasticsearch": "5.0.19", "@types/event-stream": "3.3.33", "@types/eventemitter3": "2.0.2", "@types/express": "4.0.39", From fe5d12587226b615b53740b8980d1252c5e4197e Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 7 Dec 2017 21:56:09 +0000 Subject: [PATCH 003/186] fix(package): update @types/redis to version 2.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26a953d8cd..0b8fa5ce85 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@types/page": "1.5.32", "@types/proxy-addr": "2.0.0", "@types/ratelimiter": "2.1.28", - "@types/redis": "2.8.1", + "@types/redis": "2.8.2", "@types/request": "2.0.8", "@types/rimraf": "2.0.2", "@types/riot": "3.6.1", From d2e7546de713a9e08e45c434604461c08db8090f Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 8 Dec 2017 17:08:34 +0900 Subject: [PATCH 004/186] Update recover.html --- src/web/assets/recover.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/assets/recover.html b/src/web/assets/recover.html index 35afd2adf2..4922b68d35 100644 --- a/src/web/assets/recover.html +++ b/src/web/assets/recover.html @@ -6,7 +6,7 @@ Misskeyのリカバリ + + +

+
+
    +
  1. %i18n:desktop.tags.mk-2fa-setting.authenticator% %i18n:desktop.tags.mk-2fa-setting.howtoinstall%
  2. +
  3. %i18n:desktop.tags.mk-2fa-setting.scan%
  4. +
  5. %i18n:desktop.tags.mk-2fa-setting.done%
    + +
  6. +
+
+ + +
From 9ed68439e550d0f3d95b258df114598e1a05cd92 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 8 Dec 2017 23:13:03 +0900 Subject: [PATCH 010/186] :v: --- locales/en.yml | 3 +++ locales/ja.yml | 3 +++ src/web/app/desktop/tags/settings.tag | 3 +++ 3 files changed, 9 insertions(+) diff --git a/locales/en.yml b/locales/en.yml index 6b39b4b8a7..020fc39497 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -297,6 +297,8 @@ desktop: changed: "Password updated successfully" mk-2fa-setting: + intro: "If you set up 2-step verification, you will need not only a password at sign-in but also a pre-registered physical device (such as your smartphone), which will improve security." + caution: "As a caveat, security improves, but you can not sign in to Misskey if you lose a registered device, etc." register: "Register a device" enter-password: "Enter the password" authenticator: "First, you need install Google Authenticator to your device:" @@ -306,6 +308,7 @@ desktop: submit: "Submit" success: "Setup completed successfully!" failed: "Failed to setup. please ensure that the token is correct." + info: "From the next sign in, enter the token that is displayed on the device in addition to the password." mk-post-form: post-placeholder: "What's happening?" diff --git a/locales/ja.yml b/locales/ja.yml index 672d4ab402..27804aa7c2 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -297,6 +297,8 @@ desktop: changed: "パスワードを変更しました" mk-2fa-setting: + intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。" + caution: "注意点として、セキュリティは向上しますが、登録したデバイスを紛失するなどした場合、Misskeyにサインインできなくなります。" register: "デバイスを登録する" enter-password: "パスワードを入力してください" authenticator: "まず、Google Authenticatorをお使いのデバイスにインストールします:" @@ -306,6 +308,7 @@ desktop: submit: "完了" success: "設定が完了しました!" failed: "設定に失敗しました。トークンに誤りがないかご確認ください。" + info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。" mk-post-form: post-placeholder: "いまどうしてる?" diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag index 5ebe28a144..2c38f13523 100644 --- a/src/web/app/desktop/tags/settings.tag +++ b/src/web/app/desktop/tags/settings.tag @@ -292,6 +292,8 @@ +

%i18n:desktop.tags.mk-2fa-setting.intro%

+

%i18n:desktop.tags.mk-2fa-setting.caution%

    @@ -300,6 +302,7 @@
  1. %i18n:desktop.tags.mk-2fa-setting.done%
  2. +
  3. %i18n:desktop.tags.mk-2fa-setting.info%
From b12c4a061135c3c6ef9a96184217deaeb63377c8 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 9 Dec 2017 01:53:17 +0900 Subject: [PATCH 015/186] v3292 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48372e34cd..718c2d4ba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3292 (2017/12/09) +----------------- +* ユーザビリティの向上 + 3281 (2017/12/08) ----------------- * 二段階認証の実装 (#967) diff --git a/package.json b/package.json index 0f46856de5..8f44258e0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3281", + "version": "0.0.3292", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 23e4674966f87a2292f58c2c0a7fb0e8bbb7dcf9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 9 Dec 2017 02:11:48 +0900 Subject: [PATCH 016/186] Fix bug --- src/web/app/mobile/tags/drive.tag | 5 ++++- src/web/app/mobile/tags/drive/file.tag | 3 ++- src/web/app/mobile/tags/drive/folder.tag | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag index a72c8d51c8..41dbfddae9 100644 --- a/src/web/app/mobile/tags/drive.tag +++ b/src/web/app/mobile/tags/drive.tag @@ -248,6 +248,7 @@ }; this.move = ev => { + ev.preventDefault(); this.cd(ev.item.folder); return false; }; @@ -333,7 +334,9 @@ this.prependFile = file => this.addFile(file, true); this.prependFolder = file => this.addFolder(file, true); - this.goRoot = () => { + this.goRoot = ev => { + ev.preventDefault(); + if (this.folder || this.file) { this.update({ file: null, diff --git a/src/web/app/mobile/tags/drive/file.tag b/src/web/app/mobile/tags/drive/file.tag index 0b3506a430..196dd1141e 100644 --- a/src/web/app/mobile/tags/drive/file.tag +++ b/src/web/app/mobile/tags/drive/file.tag @@ -138,7 +138,8 @@ this.isSelected = selections.some(f => f.id == this.file.id); }); - this.onclick = () => { + this.onclick = ev => { + ev.preventDefault(); this.browser.chooseFile(this.file); return false; }; diff --git a/src/web/app/mobile/tags/drive/folder.tag b/src/web/app/mobile/tags/drive/folder.tag index 785847a9ca..da55cf474e 100644 --- a/src/web/app/mobile/tags/drive/folder.tag +++ b/src/web/app/mobile/tags/drive/folder.tag @@ -1,4 +1,4 @@ - +

%fa:folder%{ folder.name }

%fa:angle-right% @@ -44,7 +44,8 @@ this.browser = this.parent; this.folder = this.opts.folder; - this.onclick = () => { + this.onclick = ev => { + ev.preventDefault(); this.browser.cd(this.folder); return false; }; From 002a5417d85d83aa1627742b471f073903efacf1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 9 Dec 2017 02:12:18 +0900 Subject: [PATCH 017/186] v3294 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 718c2d4ba7..595666f681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3294 (2017/12/09) +----------------- +* バグ修正 + 3292 (2017/12/09) ----------------- * ユーザビリティの向上 diff --git a/package.json b/package.json index 8f44258e0b..4a9dde8593 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3292", + "version": "0.0.3294", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From ce38cb3df83f3d4675323fdc4b4fbf83a62a87bc Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 8 Dec 2017 21:06:24 +0000 Subject: [PATCH 018/186] fix(package): update @fortawesome/fontawesome to version 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4a9dde8593..ae76d52da2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "format": "gulp format" }, "dependencies": { - "@fortawesome/fontawesome": "1.0.0", + "@fortawesome/fontawesome": "1.0.1", "@fortawesome/fontawesome-free-brands": "5.0.0", "@fortawesome/fontawesome-free-regular": "5.0.0", "@fortawesome/fontawesome-free-solid": "5.0.0", From 58b893fd44a1657ba91c1ef29be4ab1dc0f88364 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 8 Dec 2017 21:06:36 +0000 Subject: [PATCH 019/186] fix(package): update @fortawesome/fontawesome-free-solid to version 5.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4a9dde8593..3a823ed9a4 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@fortawesome/fontawesome": "1.0.0", "@fortawesome/fontawesome-free-brands": "5.0.0", "@fortawesome/fontawesome-free-regular": "5.0.0", - "@fortawesome/fontawesome-free-solid": "5.0.0", + "@fortawesome/fontawesome-free-solid": "5.0.1", "@prezzemolo/rap": "0.1.2", "@prezzemolo/zip": "0.0.3", "@types/bcryptjs": "2.4.1", From d475df37e0f74fb21927e3adc93bd437bdadb659 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 8 Dec 2017 21:06:49 +0000 Subject: [PATCH 020/186] fix(package): update @fortawesome/fontawesome-free-regular to version 5.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae76d52da2..c918a95557 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dependencies": { "@fortawesome/fontawesome": "1.0.1", "@fortawesome/fontawesome-free-brands": "5.0.0", - "@fortawesome/fontawesome-free-regular": "5.0.0", + "@fortawesome/fontawesome-free-regular": "5.0.1", "@fortawesome/fontawesome-free-solid": "5.0.0", "@prezzemolo/rap": "0.1.2", "@prezzemolo/zip": "0.0.3", From 4be641b357f25bf6116a9c04502eec5ceac347b4 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 8 Dec 2017 21:07:00 +0000 Subject: [PATCH 021/186] fix(package): update @fortawesome/fontawesome-free-brands to version 5.0.1 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b4fb4b5f68..098677d63b 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ }, "dependencies": { "@fortawesome/fontawesome": "1.0.1", - "@fortawesome/fontawesome-free-brands": "5.0.0", + "@fortawesome/fontawesome-free-brands": "5.0.1", "@fortawesome/fontawesome-free-regular": "5.0.0", - "@fortawesome/fontawesome-free-solid": "5.0.1", + "@fortawesome/fontawesome-free-solid": "5.0.0", "@prezzemolo/rap": "0.1.2", "@prezzemolo/zip": "0.0.3", "@types/bcryptjs": "2.4.1", From 66cb828b07bab7898443bd313c81a576a5071df0 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 8 Dec 2017 23:23:29 +0000 Subject: [PATCH 022/186] fix(package): update pictograph to version 2.1.5 Closes #979 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d7b005324..31d2a71a8c 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "nprogress": "0.2.0", "os-utils": "0.0.14", "page": "1.7.1", - "pictograph": "2.1.2", + "pictograph": "2.1.5", "prominence": "0.2.0", "proxy-addr": "2.0.2", "pug": "2.0.0-rc.4", From b9ad38d56c5d1d05aff694bd05b08b26391dcb56 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 9 Dec 2017 20:23:58 +0900 Subject: [PATCH 023/186] :art: --- locales/en.yml | 1 + locales/ja.yml | 1 + src/web/app/common/tags/authorized-apps.tag | 4 +- src/web/app/common/tags/signin-history.tag | 120 ++++++++----- src/web/app/desktop/style.styl | 65 +------ src/web/app/desktop/tags/settings.tag | 178 ++++++++------------ src/web/app/desktop/ui.styl | 119 +++++++++++++ 7 files changed, 274 insertions(+), 214 deletions(-) create mode 100644 src/web/app/desktop/ui.styl diff --git a/locales/en.yml b/locales/en.yml index 020fc39497..16f68ab632 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -342,6 +342,7 @@ desktop: next: "Next post" mk-settings: + profile: "Profile" security: "Security" password: "Password" 2fa: "Two-factor authentication" diff --git a/locales/ja.yml b/locales/ja.yml index c5996c76b3..f50e50a5ce 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -342,6 +342,7 @@ desktop: next: "次の投稿" mk-settings: + profile: "プロフィール" security: "セキュリティ" password: "パスワード" 2fa: "二段階認証" diff --git a/src/web/app/common/tags/authorized-apps.tag b/src/web/app/common/tags/authorized-apps.tag index 0078a18636..3f3714332e 100644 --- a/src/web/app/common/tags/authorized-apps.tag +++ b/src/web/app/common/tags/authorized-apps.tag @@ -1,5 +1,7 @@ -

%i18n:common.tags.mk-authorized-apps.no-apps%

+
+

%i18n:common.tags.mk-authorized-apps.no-apps%

+

{ app.name }

diff --git a/src/web/app/common/tags/signin-history.tag b/src/web/app/common/tags/signin-history.tag index 03afd72326..cdd58c4c67 100644 --- a/src/web/app/common/tags/signin-history.tag +++ b/src/web/app/common/tags/signin-history.tag @@ -1,55 +1,11 @@
-
- -
- %fa:check% - %fa:times% - { ip } -
-
{ JSON.stringify(headers, null, '    ') }
-
+
+ + +
+ %fa:check% + %fa:times% + { rec.ip } + +
+
{ JSON.stringify(rec.headers, null, 2) }
+ + + + +
diff --git a/src/web/app/desktop/style.styl b/src/web/app/desktop/style.styl index d99e5df2b4..c893e2ed67 100644 --- a/src/web/app/desktop/style.styl +++ b/src/web/app/desktop/style.styl @@ -2,6 +2,8 @@ @import "../reset" @import "../../../../node_modules/cropperjs/dist/cropper.css" +@import "./ui" + *::input-placeholder color #D8CBC5 @@ -47,66 +49,3 @@ html #wait right auto left 15px - -button - font-family sans-serif - - * - pointer-events none - - &.style-normal - &.style-primary - display block - cursor pointer - padding 0 16px - margin 0 - min-width 100px - height 40px - font-size 1em - outline none - border-radius 4px - - &:focus - &:after - content "" - pointer-events none - position absolute - top -5px - right -5px - bottom -5px - left -5px - border 2px solid rgba($theme-color, 0.3) - border-radius 8px - - &:disabled - opacity 0.7 - cursor default - - &.style-normal - color #888 - background linear-gradient(to bottom, #ffffff 0%, #f5f5f5 100%) - border solid 1px #e2e2e2 - - &:hover - background linear-gradient(to bottom, #f9f9f9 0%, #ececec 100%) - border-color #dcdcdc - - &:active - background #ececec - border-color #dcdcdc - - &.style-primary - color $theme-color-foreground - background linear-gradient(to bottom, lighten($theme-color, 25%) 0%, lighten($theme-color, 10%) 100%) - border solid 1px lighten($theme-color, 15%) - - &:not(:disabled) - font-weight bold - - &:hover:not(:disabled) - background linear-gradient(to bottom, lighten($theme-color, 8%) 0%, darken($theme-color, 8%) 100%) - border-color $theme-color - - &:active:not(:disabled) - background $theme-color - border-color $theme-color diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag index 2c38f13523..f44cef8503 100644 --- a/src/web/app/desktop/tags/settings.tag +++ b/src/web/app/desktop/tags/settings.tag @@ -1,47 +1,23 @@
-
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag index 37f90a6ffb..23f7a41985 100644 --- a/src/web/app/desktop/tags/post-detail.tag +++ b/src/web/app/desktop/tags/post-detail.tag @@ -37,7 +37,7 @@
- { +
@@ -208,11 +208,6 @@ > mk-url-preview margin-top 8px - > .media - > img - display block - max-width 100% - > footer font-size 1.2em From 4da6fafe43b61c191e193b6bef985ae2c30e0f3c Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 10 Dec 2017 20:49:12 +0900 Subject: [PATCH 043/186] =?UTF-8?q?URL=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/web/app/desktop/tags/images-viewer.tag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag index 3edd1300b2..9fd6b8de92 100644 --- a/src/web/app/desktop/tags/images-viewer.tag +++ b/src/web/app/desktop/tags/images-viewer.tag @@ -39,7 +39,7 @@ -
{
+
{
+ + + +
+ { +
+ - - - - -
{
-
\ No newline at end of file +
From 1a015457fa251c1f873c8eb81400047d28500c18 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 10 Dec 2017 22:32:09 +0900 Subject: [PATCH 046/186] :art: --- src/web/app/desktop/tags/images-viewer.tag | 104 ------------------ src/web/app/desktop/tags/images.tag | 100 +++++++++++++++++ src/web/app/desktop/tags/index.ts | 2 +- src/web/app/desktop/tags/post-detail-sub.tag | 2 +- src/web/app/desktop/tags/post-detail.tag | 2 +- src/web/app/desktop/tags/sub-post-content.tag | 2 +- src/web/app/desktop/tags/timeline.tag | 2 +- src/web/app/mobile/tags/images-viewer.tag | 26 ----- src/web/app/mobile/tags/images.tag | 78 +++++++++++++ src/web/app/mobile/tags/index.ts | 2 +- src/web/app/mobile/tags/post-detail.tag | 2 +- src/web/app/mobile/tags/sub-post-content.tag | 2 +- src/web/app/mobile/tags/timeline.tag | 2 +- 13 files changed, 187 insertions(+), 139 deletions(-) delete mode 100644 src/web/app/desktop/tags/images-viewer.tag create mode 100644 src/web/app/desktop/tags/images.tag delete mode 100644 src/web/app/mobile/tags/images-viewer.tag create mode 100644 src/web/app/mobile/tags/images.tag diff --git a/src/web/app/desktop/tags/images-viewer.tag b/src/web/app/desktop/tags/images-viewer.tag deleted file mode 100644 index 1ad382dda8..0000000000 --- a/src/web/app/desktop/tags/images-viewer.tag +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - -
- { -
- - -
diff --git a/src/web/app/desktop/tags/images.tag b/src/web/app/desktop/tags/images.tag new file mode 100644 index 0000000000..ce67d26a9f --- /dev/null +++ b/src/web/app/desktop/tags/images.tag @@ -0,0 +1,100 @@ + + + + + + + + + + + + + diff --git a/src/web/app/desktop/tags/index.ts b/src/web/app/desktop/tags/index.ts index 3ec1d108aa..30a13b584d 100644 --- a/src/web/app/desktop/tags/index.ts +++ b/src/web/app/desktop/tags/index.ts @@ -76,7 +76,7 @@ require('./set-avatar-suggestion.tag'); require('./set-banner-suggestion.tag'); require('./repost-form.tag'); require('./sub-post-content.tag'); -require('./images-viewer.tag'); +require('./images.tag'); require('./image-dialog.tag'); require('./donation.tag'); require('./users-list.tag'); diff --git a/src/web/app/desktop/tags/post-detail-sub.tag b/src/web/app/desktop/tags/post-detail-sub.tag index ab45b55234..cccd85c474 100644 --- a/src/web/app/desktop/tags/post-detail-sub.tag +++ b/src/web/app/desktop/tags/post-detail-sub.tag @@ -17,7 +17,7 @@
- +
diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag index 23f7a41985..47c71a6c12 100644 --- a/src/web/app/desktop/tags/post-detail.tag +++ b/src/web/app/desktop/tags/post-detail.tag @@ -37,7 +37,7 @@
- +
diff --git a/src/web/app/desktop/tags/sub-post-content.tag b/src/web/app/desktop/tags/sub-post-content.tag index 8989ff1c5b..1a81b545b6 100644 --- a/src/web/app/desktop/tags/sub-post-content.tag +++ b/src/web/app/desktop/tags/sub-post-content.tag @@ -8,7 +8,7 @@
({ post.media.length }つのメディア) - +
投票 diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag index 77e4a573b1..ed77a9e608 100644 --- a/src/web/app/desktop/tags/timeline.tag +++ b/src/web/app/desktop/tags/timeline.tag @@ -120,7 +120,7 @@ RP:
- +
%fa:quote-right -flip-h% diff --git a/src/web/app/mobile/tags/images-viewer.tag b/src/web/app/mobile/tags/images-viewer.tag deleted file mode 100644 index 8ef4a50be0..0000000000 --- a/src/web/app/mobile/tags/images-viewer.tag +++ /dev/null @@ -1,26 +0,0 @@ - -
{
- - -
diff --git a/src/web/app/mobile/tags/images.tag b/src/web/app/mobile/tags/images.tag new file mode 100644 index 0000000000..aaa80e4fd1 --- /dev/null +++ b/src/web/app/mobile/tags/images.tag @@ -0,0 +1,78 @@ + + + + + + + + + + + + + diff --git a/src/web/app/mobile/tags/index.ts b/src/web/app/mobile/tags/index.ts index 19952c20cd..fd5952ea13 100644 --- a/src/web/app/mobile/tags/index.ts +++ b/src/web/app/mobile/tags/index.ts @@ -25,7 +25,7 @@ require('./home-timeline.tag'); require('./timeline.tag'); require('./post-preview.tag'); require('./sub-post-content.tag'); -require('./images-viewer.tag'); +require('./images.tag'); require('./drive.tag'); require('./drive-selector.tag'); require('./drive-folder-selector.tag'); diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag index 9f212a2496..1816d1bf93 100644 --- a/src/web/app/mobile/tags/post-detail.tag +++ b/src/web/app/mobile/tags/post-detail.tag @@ -34,7 +34,7 @@
- { +
diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag index 9436b6c1d7..adeb84dea0 100644 --- a/src/web/app/mobile/tags/sub-post-content.tag +++ b/src/web/app/mobile/tags/sub-post-content.tag @@ -2,7 +2,7 @@
({ post.media.length }個のメディア) - +
%i18n:mobile.tags.mk-sub-post-content.poll% diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag index 19f90a1c11..9e85f97da3 100644 --- a/src/web/app/mobile/tags/timeline.tag +++ b/src/web/app/mobile/tags/timeline.tag @@ -172,7 +172,7 @@ RP:
- +
via { p.app.name } From cd933d9b3f5e1c2a3717877b67f9cad0f4dc9d92 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 10 Dec 2017 22:34:06 +0900 Subject: [PATCH 047/186] v3334 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1274b0fe98..39fc025286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3334 (2017/12/10) +----------------- +* いい感じにした + 3322 (2017/12/10) ----------------- * :art: diff --git a/package.json b/package.json index 369113ba6c..2b55615cf2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3322", + "version": "0.0.3334", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From d3e5a546d7c7a86967d1ef3cbb3b5fa6432cfa3c Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 11 Dec 2017 02:54:34 +0900 Subject: [PATCH 048/186] :v: --- locales/en.yml | 7 ++-- locales/ja.yml | 9 +++-- src/web/app/desktop/tags/settings.tag | 16 +++++---- src/web/app/mobile/router.ts | 5 --- src/web/app/mobile/tags/index.ts | 1 - src/web/app/mobile/tags/page/settings.tag | 1 - src/web/app/mobile/tags/page/settings/api.tag | 36 ------------------- 7 files changed, 21 insertions(+), 54 deletions(-) delete mode 100644 src/web/app/mobile/tags/page/settings/api.tag diff --git a/locales/en.yml b/locales/en.yml index 8392e170c4..8e1dee826d 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -199,7 +199,11 @@ ch: desktop: tags: mk-api-info: - regenerate-token: "Please enter the password" + intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。" + caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。" + regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。" + regenerate-token: "Regenerate the token" + enter-password: "Please enter the password" mk-drive-browser-base-contextmenu: create-folder: "Create a folder" @@ -524,7 +528,6 @@ mobile: applications: "Applications" twitter-integration: "Twitter integration" signin-history: "Sign in history" - api: "API" link: "MisskeyLink" settings: "Settings" signout: "Sign out" diff --git a/locales/ja.yml b/locales/ja.yml index f9d41d9092..1497bdb6d1 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -199,7 +199,11 @@ ch: desktop: tags: mk-api-info: - regenerate-token: "パスワードを入力してください" + intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。" + caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。" + regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。" + regenerate-token: "トークンを再生成" + enter-password: "パスワードを入力してください" mk-drive-browser-base-contextmenu: create-folder: "フォルダーを作成" @@ -523,8 +527,7 @@ mobile: profile: "プロフィール" applications: "アプリケーション" twitter-integration: "Twitter連携" - signin-history: "ログイン履歴" - api: "API" + signin-history: "サインイン履歴" link: "Misskeyリンク" settings: "設定" signout: "サインアウト" diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag index f7ecfe3e8a..0a9a16250a 100644 --- a/src/web/app/desktop/tags/settings.tag +++ b/src/web/app/desktop/tags/settings.tag @@ -196,18 +196,22 @@ -

Token:{ I.token }

-

APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。

-

アカウントを乗っ取られてしまう可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。

-

万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。(副作用として、ログインしているすべてのデバイスでログアウトが発生します)

+

Token: { I.token }

+

%i18n:desktop.tags.mk-api-info.intro%

+

%fa:exclamation-triangle%%i18n:desktop.tags.mk-api-info.caution%

+

%i18n:desktop.tags.mk-api-info.regeneration-of-token%

+ - - - -

Token:{ I.token }

-

APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。

-

アカウントを乗っ取られてしまう可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。

-

万が一このトークンが漏れたりその可能性がある場合はデスクトップ版Misskeyから再生成できます。

- - -
From 711ddc03afce1adc066cdd0704f407954d269f39 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 11 Dec 2017 02:59:05 +0900 Subject: [PATCH 049/186] #984 --- src/file/server.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/file/server.ts b/src/file/server.ts index 990b6ccbeb..3bda5b14fe 100644 --- a/src/file/server.ts +++ b/src/file/server.ts @@ -82,6 +82,7 @@ function thumbnail(data: stream.Readable, type: string, resize: number): ISend { const stream = g .compress('jpeg') .quality(80) + .interlace('line') .noProfile() // Remove EXIF .stream(); From f849dcb7b91233eaad9b679feef512bb4ad1dcd5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 11 Dec 2017 03:25:58 +0900 Subject: [PATCH 050/186] #983 --- locales/en.yml | 1 - locales/ja.yml | 1 - src/web/app/desktop/tags/post-form.tag | 69 ++++++++++------------- src/web/app/mobile/tags/post-form.tag | 76 ++++++++++---------------- 4 files changed, 60 insertions(+), 87 deletions(-) diff --git a/locales/en.yml b/locales/en.yml index 8e1dee826d..9ac9a36cd5 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -591,7 +591,6 @@ mobile: submit: "Post" reply-placeholder: "Reply to this post..." post-placeholder: "What's happening?" - attach-media-from-local: "Attach media from your device" mk-search-posts: empty: "There is no post related to the 「{}」" diff --git a/locales/ja.yml b/locales/ja.yml index 1497bdb6d1..2f95998a86 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -591,7 +591,6 @@ mobile: submit: "投稿" reply-placeholder: "この投稿への返信..." post-placeholder: "いまどうしてる?" - attach-media-from-local: "デバイスからメディアを添付" mk-search-posts: empty: "「{}」に関する投稿は見つかりませんでした。" diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag index 8e5171c83e..0b4c07906a 100644 --- a/src/web/app/desktop/tags/post-form.tag +++ b/src/web/app/desktop/tags/post-form.tag @@ -1,13 +1,12 @@
-
-
    -
  • +
    +
      +
    • -
    • %fa:plus%

    { 4 - files.length }/4

    @@ -118,8 +117,9 @@ > li display block float left - margin 4px + margin 0 padding 0 + border solid 4px transparent cursor move &:hover > .remove @@ -140,29 +140,6 @@ height 16px cursor pointer - > .add - display block - float left - margin 4px - padding 0 - border dashed 2px rgba($theme-color, 0.2) - cursor pointer - - &:hover - border-color rgba($theme-color, 0.3) - - > i - color rgba($theme-color, 0.4) - - > i - display block - width 60px - height 60px - line-height 60px - text-align center - font-size 1.2em - color rgba($theme-color, 0.2) - > mk-poll-editor background lighten($theme-color, 98%) border solid 1px rgba($theme-color, 0.1) @@ -306,6 +283,7 @@ diff --git a/src/web/app/desktop/tags/images.tag b/src/web/app/desktop/tags/images.tag index ce67d26a9f..5e4be481dc 100644 --- a/src/web/app/desktop/tags/images.tag +++ b/src/web/app/desktop/tags/images.tag @@ -53,7 +53,13 @@ - + + + +
    { + + +
    diff --git a/src/web/app/desktop/tags/index.ts b/src/web/app/desktop/tags/index.ts index 30a13b584d..4edda83534 100644 --- a/src/web/app/desktop/tags/index.ts +++ b/src/web/app/desktop/tags/index.ts @@ -77,7 +77,6 @@ require('./set-banner-suggestion.tag'); require('./repost-form.tag'); require('./sub-post-content.tag'); require('./images.tag'); -require('./image-dialog.tag'); require('./donation.tag'); require('./users-list.tag'); require('./user-following.tag'); From aff688d9bf7f55a6f91a9b50f2dd6809f13683a1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 14 Dec 2017 13:31:17 +0900 Subject: [PATCH 076/186] :v: --- docs/api/endpoints/posts/create.yaml | 53 ++++++++++++++++++++++++++++ src/api/endpoints/posts/create.ts | 4 ++- test/api.js | 34 ++++++++++-------- 3 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 docs/api/endpoints/posts/create.yaml diff --git a/docs/api/endpoints/posts/create.yaml b/docs/api/endpoints/posts/create.yaml new file mode 100644 index 0000000000..db91775cb6 --- /dev/null +++ b/docs/api/endpoints/posts/create.yaml @@ -0,0 +1,53 @@ +endpoint: "posts/create" + +desc: + ja: "投稿します。" + en: "Compose new post." + +params: + - name: "text" + type: "string" + required: true + desc: + ja: "投稿の本文" + en: "Text of a post" + - name: "media_ids" + type: "id(DriveFile)[]" + required: false + desc: + ja: "添付するメディア" + en: "Media you want to attach" + - name: "reply_id" + type: "id(Post)" + required: false + desc: + ja: "返信する投稿" + en: "A post you want to reply" + - name: "repost_id" + type: "id(Post)" + required: false + desc: + ja: "引用する投稿" + en: "A post you want to quote" + - name: "poll" + type: "object(poll)" + required: false + desc: + ja: "投票" + en: "A poll" + +paramDefs: + poll: + - name: "choices" + type: "string[]" + required: true + desc: + ja: "投票の選択肢" + en: "Choices of a poll" + +res: + - name: "created_post" + type: "entity(Post)" + desc: + ja: "作成した投稿" + en: "A post that created" diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index ae4959dae4..7270efaf71 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -222,7 +222,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { const postObj = await serialize(post); // Reponse - res(postObj); + res({ + created_post: postObj + }); //#region Post processes diff --git a/test/api.js b/test/api.js index 49f1faa53a..500b9adb72 100644 --- a/test/api.js +++ b/test/api.js @@ -224,7 +224,8 @@ describe('API', () => { const res = await request('/posts/create', post, me); res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('text').eql(post.text); + res.body.should.have.property('created_post'); + res.body.created_post.should.have.property('text').eql(post.text); })); it('ファイルを添付できる', async(async () => { @@ -237,7 +238,8 @@ describe('API', () => { }, me); res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('media_ids').eql([file._id.toString()]); + res.body.should.have.property('created_post'); + res.body.created_post.should.have.property('media_ids').eql([file._id.toString()]); })); it('他人のファイルは添付できない', async(async () => { @@ -283,10 +285,11 @@ describe('API', () => { const res = await request('/posts/create', post, me); res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('text').eql(post.text); - res.body.should.have.property('reply_id').eql(post.reply_id); - res.body.should.have.property('reply'); - res.body.reply.should.have.property('text').eql(himaPost.text); + res.body.should.have.property('created_post'); + res.body.created_post.should.have.property('text').eql(post.text); + res.body.created_post.should.have.property('reply_id').eql(post.reply_id); + res.body.created_post.should.have.property('reply'); + res.body.created_post.reply.should.have.property('text').eql(himaPost.text); })); it('repostできる', async(async () => { @@ -303,9 +306,10 @@ describe('API', () => { const res = await request('/posts/create', post, me); res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('repost_id').eql(post.repost_id); - res.body.should.have.property('repost'); - res.body.repost.should.have.property('text').eql(himaPost.text); + res.body.should.have.property('created_post'); + res.body.created_post.should.have.property('repost_id').eql(post.repost_id); + res.body.created_post.should.have.property('repost'); + res.body.created_post.repost.should.have.property('text').eql(himaPost.text); })); it('引用repostできる', async(async () => { @@ -323,10 +327,11 @@ describe('API', () => { const res = await request('/posts/create', post, me); res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('text').eql(post.text); - res.body.should.have.property('repost_id').eql(post.repost_id); - res.body.should.have.property('repost'); - res.body.repost.should.have.property('text').eql(himaPost.text); + res.body.should.have.property('created_post'); + res.body.created_post.should.have.property('text').eql(post.text); + res.body.created_post.should.have.property('repost_id').eql(post.repost_id); + res.body.created_post.should.have.property('repost'); + res.body.created_post.repost.should.have.property('text').eql(himaPost.text); })); it('文字数ぎりぎりで怒られない', async(async () => { @@ -395,7 +400,8 @@ describe('API', () => { }, me); res.should.have.status(200); res.body.should.be.a('object'); - res.body.should.have.property('poll'); + res.body.should.have.property('created_post'); + res.body.created_post.should.have.property('poll'); })); it('投票の選択肢が無くて怒られる', async(async () => { From 5166fc92b64af25946b9c5a55ee05cebca0d24fa Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 14 Dec 2017 16:24:41 +0900 Subject: [PATCH 077/186] :pizza: --- gulpfile.ts | 20 ++++- package.json | 4 + src/web/app/app.styl | 38 +--------- src/web/docs/api/endpoints/gulpfile.ts | 75 +++++++++++++++++++ .../web/docs}/api/endpoints/posts/create.yaml | 13 ++-- src/web/docs/api/endpoints/style.styl | 16 ++++ src/web/docs/api/endpoints/view.pug | 60 +++++++++++++++ src/{ => web}/docs/api/entities/post.pug | 0 src/{ => web}/docs/api/entities/user.pug | 0 src/{ => web}/docs/api/getting-started.md | 0 src/{ => web}/docs/api/library.md | 0 src/{ => web}/docs/index.md | 0 src/{ => web}/docs/link-to-twitter.md | 0 src/web/docs/style.styl | 69 +++++++++++++++++ src/{ => web}/docs/tou.md | 0 src/web/server.ts | 6 ++ src/web/style.styl | 38 ++++++++++ 17 files changed, 295 insertions(+), 44 deletions(-) create mode 100644 src/web/docs/api/endpoints/gulpfile.ts rename {docs => src/web/docs}/api/endpoints/posts/create.yaml (87%) create mode 100644 src/web/docs/api/endpoints/style.styl create mode 100644 src/web/docs/api/endpoints/view.pug rename src/{ => web}/docs/api/entities/post.pug (100%) rename src/{ => web}/docs/api/entities/user.pug (100%) rename src/{ => web}/docs/api/getting-started.md (100%) rename src/{ => web}/docs/api/library.md (100%) rename src/{ => web}/docs/index.md (100%) rename src/{ => web}/docs/link-to-twitter.md (100%) create mode 100644 src/web/docs/style.styl rename src/{ => web}/docs/tou.md (100%) create mode 100644 src/web/style.styl diff --git a/gulpfile.ts b/gulpfile.ts index ee11a02dcb..0bc18dd7c4 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -13,6 +13,7 @@ import * as es from 'event-stream'; import cssnano = require('gulp-cssnano'); import * as uglifyComposer from 'gulp-uglify/composer'; import pug = require('gulp-pug'); +import stylus = require('gulp-stylus'); import * as rimraf from 'rimraf'; import chalk from 'chalk'; import imagemin = require('gulp-imagemin'); @@ -47,15 +48,32 @@ if (isDebug) { const constants = require('./src/const.json'); +require('./src/web/docs/api/endpoints/gulpfile.ts'); + gulp.task('build', [ 'build:js', 'build:ts', 'build:copy', - 'build:client' + 'build:client', + 'build:doc' ]); gulp.task('rebuild', ['clean', 'build']); +gulp.task('build:doc', [ + 'doc:endpoints', + 'doc:styles' +]); + +gulp.task('doc:styles', () => + gulp.src('./src/web/docs/**/*.styl') + .pipe(stylus()) + .pipe(isProduction + ? (cssnano as any)() + : gutil.noop()) + .pipe(gulp.dest('./built/web/assets/docs/')) +); + gulp.task('build:js', () => gulp.src(['./src/**/*.js', '!./src/web/**/*.js']) .pipe(gulp.dest('./built/')) diff --git a/package.json b/package.json index c20fd0c52a..69090349e1 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@types/is-root": "1.0.0", "@types/is-url": "1.2.28", "@types/js-yaml": "3.10.1", + "@types/mkdirp": "^0.5.2", "@types/mocha": "2.2.44", "@types/mongodb": "2.2.17", "@types/monk": "1.0.6", @@ -62,6 +63,7 @@ "@types/node": "8.5.1", "@types/page": "1.5.32", "@types/proxy-addr": "2.0.0", + "@types/pug": "^2.0.4", "@types/qrcode": "0.8.0", "@types/ratelimiter": "2.1.28", "@types/redis": "2.8.3", @@ -112,6 +114,7 @@ "gulp-pug": "3.3.0", "gulp-rename": "1.2.2", "gulp-replace": "0.6.1", + "gulp-stylus": "^2.6.0", "gulp-tslint": "8.1.2", "gulp-typescript": "3.2.3", "gulp-uglify": "3.0.0", @@ -122,6 +125,7 @@ "is-url": "1.2.2", "js-yaml": "3.10.0", "mecab-async": "0.1.2", + "mkdirp": "^0.5.1", "mocha": "4.0.1", "moji": "0.5.1", "mongodb": "2.2.33", diff --git a/src/web/app/app.styl b/src/web/app/app.styl index de66df74d4..22043b8833 100644 --- a/src/web/app/app.styl +++ b/src/web/app/app.styl @@ -1,29 +1,4 @@ -json('../../const.json') - -@charset 'utf-8' - -$theme-color = themeColor -$theme-color-foreground = themeColorForeground - -/* - ::selection - background $theme-color - color #fff -*/ - -* - position relative - box-sizing border-box - background-clip padding-box !important - tap-highlight-color rgba($theme-color, 0.7) - -webkit-tap-highlight-color rgba($theme-color, 0.7) - -html, body - margin 0 - padding 0 - scroll-behavior smooth - text-size-adjust 100% - font-family sans-serif +@import "../style" html &.progress @@ -96,17 +71,6 @@ body 100% transform rotate(360deg) -a - text-decoration none - color $theme-color - cursor pointer - - &:hover - text-decoration underline - - * - cursor pointer - code font-family Consolas, 'Courier New', Courier, Monaco, monospace diff --git a/src/web/docs/api/endpoints/gulpfile.ts b/src/web/docs/api/endpoints/gulpfile.ts new file mode 100644 index 0000000000..a2c3944709 --- /dev/null +++ b/src/web/docs/api/endpoints/gulpfile.ts @@ -0,0 +1,75 @@ +/** + * Gulp tasks + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import * as glob from 'glob'; +import * as gulp from 'gulp'; +import * as pug from 'pug'; +import * as yaml from 'js-yaml'; +import * as mkdirp from 'mkdirp'; + +import config from './../../../../conf'; + +const parseParam = param => { + const id = param.type.match(/^id\((.+?)\)/); + const object = param.type.match(/^object\((.+?)\)/); + const isArray = /\[\]$/.test(param.type); + if (id) { + param.kind = 'id'; + param.type = 'string'; + param.entity = id[1]; + if (isArray) { + param.type += '[]'; + } + } + if (object) { + param.kind = 'object'; + param.type = 'object'; + param.def = object[1]; + if (isArray) { + param.type += '[]'; + } + } + + return param; +}; + +gulp.task('doc:endpoints', () => { + glob('./src/web/docs/api/endpoints/**/*.yaml', (globErr, files) => { + if (globErr) { + console.error(globErr); + return; + } + //console.log(files); + files.forEach(file => { + const ep = yaml.safeLoad(fs.readFileSync(file, 'utf-8')); + const vars = { + endpoint: ep.endpoint, + url: `${config.api_url}/${ep.endpoint}`, + desc: ep.desc, + params: ep.params.map(p => parseParam(p)), + paramDefs: Object.keys(ep.paramDefs).map(key => ({ + name: key, + params: ep.paramDefs[key].map(p => parseParam(p)) + })), + res: ep.res.map(p => parseParam(p)) + }; + pug.renderFile('./src/web/docs/api/endpoints/view.pug', vars, (renderErr, html) => { + if (renderErr) { + console.error(renderErr); + return; + } + const htmlPath = `./built/web/docs/api/endpoints/${ep.endpoint}.html`; + mkdirp(path.dirname(htmlPath), (mkdirErr) => { + if (mkdirErr) { + console.error(mkdirErr); + return; + } + fs.writeFileSync(htmlPath, html, 'utf-8'); + }); + }); + }); + }); +}); diff --git a/docs/api/endpoints/posts/create.yaml b/src/web/docs/api/endpoints/posts/create.yaml similarity index 87% rename from docs/api/endpoints/posts/create.yaml rename to src/web/docs/api/endpoints/posts/create.yaml index db91775cb6..b6613038a7 100644 --- a/docs/api/endpoints/posts/create.yaml +++ b/src/web/docs/api/endpoints/posts/create.yaml @@ -7,31 +7,31 @@ desc: params: - name: "text" type: "string" - required: true + optional: false desc: ja: "投稿の本文" en: "Text of a post" - name: "media_ids" type: "id(DriveFile)[]" - required: false + optional: true desc: ja: "添付するメディア" en: "Media you want to attach" - name: "reply_id" type: "id(Post)" - required: false + optional: true desc: ja: "返信する投稿" en: "A post you want to reply" - name: "repost_id" type: "id(Post)" - required: false + optional: true desc: ja: "引用する投稿" en: "A post you want to quote" - name: "poll" type: "object(poll)" - required: false + optional: true desc: ja: "投票" en: "A poll" @@ -40,7 +40,7 @@ paramDefs: poll: - name: "choices" type: "string[]" - required: true + optional: false desc: ja: "投票の選択肢" en: "Choices of a poll" @@ -48,6 +48,7 @@ paramDefs: res: - name: "created_post" type: "entity(Post)" + optional: false desc: ja: "作成した投稿" en: "A post that created" diff --git a/src/web/docs/api/endpoints/style.styl b/src/web/docs/api/endpoints/style.styl new file mode 100644 index 0000000000..12c06fe3af --- /dev/null +++ b/src/web/docs/api/endpoints/style.styl @@ -0,0 +1,16 @@ +@import "../../style" + +#url + padding 8px 12px + font-family Consolas, 'Courier New', Courier, Monaco, monospace + color #fff + background #222e40 + border-radius 4px + +table + .name + font-weight bold + + .type + font-family Consolas, 'Courier New', Courier, Monaco, monospace + diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug new file mode 100644 index 0000000000..d9de9cb74a --- /dev/null +++ b/src/web/docs/api/endpoints/view.pug @@ -0,0 +1,60 @@ +doctype html + +mixin i18n(xs) + each text, lang in xs + span(class=`i18n ${lang}`)= text + +mixin table(params) + table + thead: tr + th Name + th Type + th Optional + th Description + tbody + each param in params + tr + td.name= param.name + td.type + if param.kind == 'id' + | #{param.type} (ID of + = ' ' + a(href=`/docs/api/entities/${param.entity}`)= param.entity + | ) + else if param.kind == 'object' + | #{param.type} ( + a(href=`#${param.def}`)= param.def + | ) + else + = param.type + td.optional= param.optional.toString() + td.desc: +i18n(param.desc) + +html + head + meta(charset="UTF-8") + title #{endpoint} | Misskey API + link(rel="stylesheet" href="/assets/docs/api/endpoints/style.css") + + body + main + h1= endpoint + + p#url= url + + p#desc: +i18n(desc) + + section + h2 Params + +table(params) + + if paramDefs + each paramDef in paramDefs + section(id= paramDef.name) + h3= paramDef.name + +table(paramDef.params) + + section + h2 Response + +table(res) + diff --git a/src/docs/api/entities/post.pug b/src/web/docs/api/entities/post.pug similarity index 100% rename from src/docs/api/entities/post.pug rename to src/web/docs/api/entities/post.pug diff --git a/src/docs/api/entities/user.pug b/src/web/docs/api/entities/user.pug similarity index 100% rename from src/docs/api/entities/user.pug rename to src/web/docs/api/entities/user.pug diff --git a/src/docs/api/getting-started.md b/src/web/docs/api/getting-started.md similarity index 100% rename from src/docs/api/getting-started.md rename to src/web/docs/api/getting-started.md diff --git a/src/docs/api/library.md b/src/web/docs/api/library.md similarity index 100% rename from src/docs/api/library.md rename to src/web/docs/api/library.md diff --git a/src/docs/index.md b/src/web/docs/index.md similarity index 100% rename from src/docs/index.md rename to src/web/docs/index.md diff --git a/src/docs/link-to-twitter.md b/src/web/docs/link-to-twitter.md similarity index 100% rename from src/docs/link-to-twitter.md rename to src/web/docs/link-to-twitter.md diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl new file mode 100644 index 0000000000..9014df87fe --- /dev/null +++ b/src/web/docs/style.styl @@ -0,0 +1,69 @@ +@import "../style" + +body + margin 0 + color #34495e + +main + padding 32px + width 100% + max-width 700px + +footer + padding:32px 0 0 0 + margin 32px 0 0 0 + border-top solid 1px #eee + + .copyright + margin 16px 0 0 0 + color #aaa + +section + margin 32px 0 + +h1 + margin 0 0 24px 0 + padding 16px 0 + font-size 1.5em + border-bottom solid 2px #eee + +h2 + margin 0 0 24px 0 + padding 0 0 16px 0 + font-size 1.4em + border-bottom solid 1px #eee + +h3 + margin 0 + padding 0 + font-size 1.25em + +h4 + margin 0 + +p + margin 1em 0 + line-height 1.6em + +table + width 100% + border-spacing 0 + border-collapse collapse + + thead + font-weight bold + border-bottom solid 2px #eee + + tr + th + text-align left + + tbody + tr + border-bottom dashed 1px #eee + + th, td + padding 8px 16px + +.i18n:not(.ja) + display none diff --git a/src/docs/tou.md b/src/web/docs/tou.md similarity index 100% rename from src/docs/tou.md rename to src/web/docs/tou.md diff --git a/src/web/server.ts b/src/web/server.ts index 1d3687f89e..38e87754f3 100644 --- a/src/web/server.ts +++ b/src/web/server.ts @@ -63,6 +63,12 @@ app.get('/manifest.json', (req, res) => */ app.get(/\/api:url/, require('./service/url-preview')); +/** + * Docs + */ +app.get(/^\/docs\/([a-z_\-\/]+?)$/, (req, res) => + res.sendFile(`${__dirname}/docs/${req.params[0]}.html`)); + /** * Routing */ diff --git a/src/web/style.styl b/src/web/style.styl new file mode 100644 index 0000000000..573df10d78 --- /dev/null +++ b/src/web/style.styl @@ -0,0 +1,38 @@ +json('../const.json') + +@charset 'utf-8' + +$theme-color = themeColor +$theme-color-foreground = themeColorForeground + +/* + ::selection + background $theme-color + color #fff +*/ + +* + position relative + box-sizing border-box + background-clip padding-box !important + tap-highlight-color rgba($theme-color, 0.7) + -webkit-tap-highlight-color rgba($theme-color, 0.7) + +html, body + margin 0 + padding 0 + scroll-behavior smooth + text-size-adjust 100% + font-family sans-serif + +a + text-decoration none + color $theme-color + cursor pointer + + &:hover + text-decoration underline + + * + cursor pointer + From bdaf4b01b17e6cb19637c6f3a42569d1ef19753f Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 14 Dec 2017 09:36:26 +0000 Subject: [PATCH 078/186] fix(package): update style-loader to version 0.19.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 69090349e1..97f2904763 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "sortablejs": "1.7.0", "speakeasy": "2.0.0", "string-replace-webpack-plugin": "0.1.3", - "style-loader": "0.19.0", + "style-loader": "0.19.1", "stylus": "0.54.5", "stylus-loader": "3.0.1", "summaly": "2.0.3", From 503eef4651259c5d53001e5fd7cb41cfa322221c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 14 Dec 2017 11:34:10 +0000 Subject: [PATCH 079/186] fix(package): update uglifyjs-webpack-plugin to version 1.1.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 69090349e1..9305cac9f7 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "tslint": "5.8.0", "typescript": "2.6.2", "uglify-es": "3.2.0", - "uglifyjs-webpack-plugin": "1.1.3", + "uglifyjs-webpack-plugin": "1.1.4", "uuid": "3.1.0", "vhost": "3.0.2", "web-push": "3.2.5", From 5b6641003139606d54e3b8646b156d4fcd05b9d5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 14 Dec 2017 22:36:04 +0900 Subject: [PATCH 080/186] :v: --- src/web/docs/api/endpoints/gulpfile.ts | 39 +++++++++++++++----- src/web/docs/api/endpoints/posts/create.yaml | 21 +++++------ src/web/docs/api/endpoints/view.pug | 6 ++- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/web/docs/api/endpoints/gulpfile.ts b/src/web/docs/api/endpoints/gulpfile.ts index a2c3944709..e375447c55 100644 --- a/src/web/docs/api/endpoints/gulpfile.ts +++ b/src/web/docs/api/endpoints/gulpfile.ts @@ -14,7 +14,8 @@ import config from './../../../../conf'; const parseParam = param => { const id = param.type.match(/^id\((.+?)\)/); - const object = param.type.match(/^object\((.+?)\)/); + const entity = param.type.match(/^entity\((.+?)\)/); + const isObject = /^object/.test(param.type); const isArray = /\[\]$/.test(param.type); if (id) { param.kind = 'id'; @@ -24,18 +25,40 @@ const parseParam = param => { param.type += '[]'; } } - if (object) { - param.kind = 'object'; + if (entity) { + param.kind = 'entity'; param.type = 'object'; - param.def = object[1]; + param.entity = entity[1]; if (isArray) { param.type += '[]'; } } + if (isObject) { + param.kind = 'object'; + } return param; }; +const extractDefs = params => { + const defs = []; + + params.forEach(param => { + if (param.def) { + defs.push({ + name: param.defName, + params: param.def.map(p => parseParam(p)) + }); + + const childDefs = extractDefs(param.def); + + defs.concat(childDefs); + } + }); + + return defs; +}; + gulp.task('doc:endpoints', () => { glob('./src/web/docs/api/endpoints/**/*.yaml', (globErr, files) => { if (globErr) { @@ -50,11 +73,9 @@ gulp.task('doc:endpoints', () => { url: `${config.api_url}/${ep.endpoint}`, desc: ep.desc, params: ep.params.map(p => parseParam(p)), - paramDefs: Object.keys(ep.paramDefs).map(key => ({ - name: key, - params: ep.paramDefs[key].map(p => parseParam(p)) - })), - res: ep.res.map(p => parseParam(p)) + paramDefs: extractDefs(ep.params), + res: ep.res.map(p => parseParam(p)), + resDefs: extractDefs(ep.res) }; pug.renderFile('./src/web/docs/api/endpoints/view.pug', vars, (renderErr, html) => { if (renderErr) { diff --git a/src/web/docs/api/endpoints/posts/create.yaml b/src/web/docs/api/endpoints/posts/create.yaml index b6613038a7..feedf4f0d2 100644 --- a/src/web/docs/api/endpoints/posts/create.yaml +++ b/src/web/docs/api/endpoints/posts/create.yaml @@ -7,7 +7,7 @@ desc: params: - name: "text" type: "string" - optional: false + optional: true desc: ja: "投稿の本文" en: "Text of a post" @@ -30,20 +30,19 @@ params: ja: "引用する投稿" en: "A post you want to quote" - name: "poll" - type: "object(poll)" + type: "object" optional: true desc: ja: "投票" en: "A poll" - -paramDefs: - poll: - - name: "choices" - type: "string[]" - optional: false - desc: - ja: "投票の選択肢" - en: "Choices of a poll" + defName: "poll" + def: + - name: "choices" + type: "string[]" + optional: false + desc: + ja: "投票の選択肢" + en: "Choices of a poll" res: - name: "created_post" diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug index d9de9cb74a..b7b2658a39 100644 --- a/src/web/docs/api/endpoints/view.pug +++ b/src/web/docs/api/endpoints/view.pug @@ -21,9 +21,13 @@ mixin table(params) = ' ' a(href=`/docs/api/entities/${param.entity}`)= param.entity | ) + else if param.kind == 'entity' + | #{param.type} ( + a(href=`/docs/api/entities/${param.entity}`)= param.entity + | ) else if param.kind == 'object' | #{param.type} ( - a(href=`#${param.def}`)= param.def + a(href=`#${param.defName}`)= param.defName | ) else = param.type From a357d5c6a51b1d3b36e2735068a2603ff8e1675a Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 14 Dec 2017 22:50:41 +0900 Subject: [PATCH 081/186] :v: --- src/web/docs/api/endpoints/posts/create.yaml | 4 ++-- src/web/docs/api/endpoints/style.styl | 2 ++ src/web/docs/api/endpoints/view.pug | 5 ++--- src/web/docs/style.styl | 3 +++ 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/web/docs/api/endpoints/posts/create.yaml b/src/web/docs/api/endpoints/posts/create.yaml index feedf4f0d2..498a99159c 100644 --- a/src/web/docs/api/endpoints/posts/create.yaml +++ b/src/web/docs/api/endpoints/posts/create.yaml @@ -15,8 +15,8 @@ params: type: "id(DriveFile)[]" optional: true desc: - ja: "添付するメディア" - en: "Media you want to attach" + ja: "添付するメディア(1~4つ)" + en: "Media you want to attach (1~4)" - name: "reply_id" type: "id(Post)" optional: true diff --git a/src/web/docs/api/endpoints/style.styl b/src/web/docs/api/endpoints/style.styl index 12c06fe3af..ab74e100b5 100644 --- a/src/web/docs/api/endpoints/style.styl +++ b/src/web/docs/api/endpoints/style.styl @@ -11,6 +11,8 @@ table .name font-weight bold + .name .type + .optional font-family Consolas, 'Courier New', Courier, Monaco, monospace diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug index b7b2658a39..841ca8b3f9 100644 --- a/src/web/docs/api/endpoints/view.pug +++ b/src/web/docs/api/endpoints/view.pug @@ -17,10 +17,9 @@ mixin table(params) td.name= param.name td.type if param.kind == 'id' - | #{param.type} (ID of - = ' ' + | #{param.type} ( a(href=`/docs/api/entities/${param.entity}`)= param.entity - | ) + | ID) else if param.kind == 'entity' | #{param.type} ( a(href=`/docs/api/entities/${param.entity}`)= param.entity diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl index 9014df87fe..5c484adc1b 100644 --- a/src/web/docs/style.styl +++ b/src/web/docs/style.styl @@ -62,6 +62,9 @@ table tr border-bottom dashed 1px #eee + &:nth-child(odd) + background #fbfbfb + th, td padding 8px 16px From d6ec5f2fe13bb1e3f4316f04591bf419f587c2bd Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 15 Dec 2017 00:23:45 +0900 Subject: [PATCH 082/186] :v: --- gulpfile.ts | 4 +- src/web/docs/api/endpoints/posts/create.yaml | 8 +- src/web/docs/api/endpoints/style.styl | 12 +- src/web/docs/api/endpoints/view.pug | 75 ++++------- src/web/docs/api/entities/post.yaml | 124 +++++++++++++++++++ src/web/docs/api/entities/style.styl | 1 + src/web/docs/api/entities/view.pug | 23 ++++ src/web/docs/api/{endpoints => }/gulpfile.ts | 78 ++++++++++-- src/web/docs/api/mixins.pug | 33 +++++ src/web/docs/api/style.styl | 11 ++ src/web/docs/layout.pug | 16 +++ 11 files changed, 305 insertions(+), 80 deletions(-) create mode 100644 src/web/docs/api/entities/post.yaml create mode 100644 src/web/docs/api/entities/style.styl create mode 100644 src/web/docs/api/entities/view.pug rename src/web/docs/api/{endpoints => }/gulpfile.ts (50%) create mode 100644 src/web/docs/api/mixins.pug create mode 100644 src/web/docs/api/style.styl create mode 100644 src/web/docs/layout.pug diff --git a/gulpfile.ts b/gulpfile.ts index 0bc18dd7c4..6807b6d571 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -48,7 +48,7 @@ if (isDebug) { const constants = require('./src/const.json'); -require('./src/web/docs/api/endpoints/gulpfile.ts'); +require('./src/web/docs/api/gulpfile.ts'); gulp.task('build', [ 'build:js', @@ -61,7 +61,7 @@ gulp.task('build', [ gulp.task('rebuild', ['clean', 'build']); gulp.task('build:doc', [ - 'doc:endpoints', + 'doc:api', 'doc:styles' ]); diff --git a/src/web/docs/api/endpoints/posts/create.yaml b/src/web/docs/api/endpoints/posts/create.yaml index 498a99159c..5e2307dab4 100644 --- a/src/web/docs/api/endpoints/posts/create.yaml +++ b/src/web/docs/api/endpoints/posts/create.yaml @@ -10,7 +10,7 @@ params: optional: true desc: ja: "投稿の本文" - en: "Text of a post" + en: "The text of your post" - name: "media_ids" type: "id(DriveFile)[]" optional: true @@ -22,19 +22,19 @@ params: optional: true desc: ja: "返信する投稿" - en: "A post you want to reply" + en: "The post you want to reply" - name: "repost_id" type: "id(Post)" optional: true desc: ja: "引用する投稿" - en: "A post you want to quote" + en: "The post you want to quote" - name: "poll" type: "object" optional: true desc: ja: "投票" - en: "A poll" + en: "The poll" defName: "poll" def: - name: "choices" diff --git a/src/web/docs/api/endpoints/style.styl b/src/web/docs/api/endpoints/style.styl index ab74e100b5..07fb7ec2a3 100644 --- a/src/web/docs/api/endpoints/style.styl +++ b/src/web/docs/api/endpoints/style.styl @@ -1,4 +1,4 @@ -@import "../../style" +@import "../style" #url padding 8px 12px @@ -6,13 +6,3 @@ color #fff background #222e40 border-radius 4px - -table - .name - font-weight bold - - .name - .type - .optional - font-family Consolas, 'Courier New', Courier, Monaco, monospace - diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug index 841ca8b3f9..cebef9fa5b 100644 --- a/src/web/docs/api/endpoints/view.pug +++ b/src/web/docs/api/endpoints/view.pug @@ -1,63 +1,30 @@ -doctype html +extends ../../layout.pug +include ../mixins -mixin i18n(xs) - each text, lang in xs - span(class=`i18n ${lang}`)= text +block title + | #{endpoint} | Misskey API -mixin table(params) - table - thead: tr - th Name - th Type - th Optional - th Description - tbody - each param in params - tr - td.name= param.name - td.type - if param.kind == 'id' - | #{param.type} ( - a(href=`/docs/api/entities/${param.entity}`)= param.entity - | ID) - else if param.kind == 'entity' - | #{param.type} ( - a(href=`/docs/api/entities/${param.entity}`)= param.entity - | ) - else if param.kind == 'object' - | #{param.type} ( - a(href=`#${param.defName}`)= param.defName - | ) - else - = param.type - td.optional= param.optional.toString() - td.desc: +i18n(param.desc) +block meta + link(rel="stylesheet" href="/assets/docs/api/endpoints/style.css") -html - head - meta(charset="UTF-8") - title #{endpoint} | Misskey API - link(rel="stylesheet" href="/assets/docs/api/endpoints/style.css") +block main + h1= endpoint - body - main - h1= endpoint + p#url= url - p#url= url + p#desc: +i18n(desc) - p#desc: +i18n(desc) + section + h2 Params + +propTable(params) - section - h2 Params - +table(params) + if paramDefs + each paramDef in paramDefs + section(id= paramDef.name) + h3= paramDef.name + +propTable(paramDef.params) - if paramDefs - each paramDef in paramDefs - section(id= paramDef.name) - h3= paramDef.name - +table(paramDef.params) - - section - h2 Response - +table(res) + section + h2 Response + +propTable(res) diff --git a/src/web/docs/api/entities/post.yaml b/src/web/docs/api/entities/post.yaml new file mode 100644 index 0000000000..551f3b7c3e --- /dev/null +++ b/src/web/docs/api/entities/post.yaml @@ -0,0 +1,124 @@ +name: "Post" + +desc: + ja: "投稿。" + en: "A post." + +props: + - name: "id" + type: "id" + optional: false + desc: + ja: "投稿ID" + en: "The ID of this post" + - name: "created_at" + type: "date" + optional: false + desc: + ja: "投稿日時" + en: "The posted date of this post" + - name: "text" + type: "string" + optional: true + desc: + ja: "投稿の本文" + en: "The text of this post" + - name: "media_ids" + type: "id(DriveFile)[]" + optional: true + desc: + ja: "添付されているメディアのID" + en: "The IDs of the attached media" + - name: "media" + type: "entity(DriveFile)[]" + optional: true + desc: + ja: "添付されているメディア" + en: "The attached media" + - name: "user_id" + type: "id(User)" + optional: false + desc: + ja: "投稿者ID" + en: "The ID of author of this post" + - name: "user" + type: "entity(User)" + optional: true + desc: + ja: "投稿者" + en: "The author of this post" + - name: "my_reaction" + type: "string" + optional: true + desc: + ja: "この投稿に対する自分のリアクション" + en: "The your reaction of this post" + - name: "reaction_counts" + type: "object" + optional: false + desc: + ja: "リアクションをキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト" + - name: "reply_id" + type: "id(Post)" + optional: true + desc: + ja: "返信した投稿のID" + en: "The ID of the replyed post" + - name: "reply" + type: "entity(Post)" + optional: true + desc: + ja: "返信した投稿" + en: "The replyed post" + - name: "repost_id" + type: "id(Post)" + optional: true + desc: + ja: "引用した投稿のID" + en: "The ID of the quoted post" + - name: "repost" + type: "entity(Post)" + optional: true + desc: + ja: "引用した投稿" + en: "The quoted post" + - name: "poll" + type: "object" + optional: true + desc: + ja: "投票" + en: "The poll" + defName: "poll" + def: + - name: "choices" + type: "object[]" + optional: false + desc: + ja: "投票の選択肢" + en: "The choices of this poll" + defName: "choice" + def: + - name: "id" + type: "number" + optional: false + desc: + ja: "選択肢ID" + en: "The ID of this choice" + - name: "is_voted" + type: "boolean" + optional: true + desc: + ja: "自分がこの選択肢に投票したかどうか" + en: "Whether you voted to this choice" + - name: "text" + type: "string" + optional: false + desc: + ja: "選択肢本文" + en: "The text of this choice" + - name: "votes" + type: "number" + optional: false + desc: + ja: "この選択肢に投票された数" + en: "The number voted for this choice" diff --git a/src/web/docs/api/entities/style.styl b/src/web/docs/api/entities/style.styl new file mode 100644 index 0000000000..bddf0f53ab --- /dev/null +++ b/src/web/docs/api/entities/style.styl @@ -0,0 +1 @@ +@import "../style" diff --git a/src/web/docs/api/entities/view.pug b/src/web/docs/api/entities/view.pug new file mode 100644 index 0000000000..f210582f1a --- /dev/null +++ b/src/web/docs/api/entities/view.pug @@ -0,0 +1,23 @@ +extends ../../layout.pug +include ../mixins + +block title + | #{name} | Misskey API + +block meta + link(rel="stylesheet" href="/assets/docs/api/entities/style.css") + +block main + h1= name + + p#desc: +i18n(desc) + + section + h2 Properties + +propTable(props) + + if propDefs + each propDef in propDefs + section(id= propDef.name) + h3= propDef.name + +propTable(propDef.params) diff --git a/src/web/docs/api/endpoints/gulpfile.ts b/src/web/docs/api/gulpfile.ts similarity index 50% rename from src/web/docs/api/endpoints/gulpfile.ts rename to src/web/docs/api/gulpfile.ts index e375447c55..05567b6233 100644 --- a/src/web/docs/api/endpoints/gulpfile.ts +++ b/src/web/docs/api/gulpfile.ts @@ -10,12 +10,15 @@ import * as pug from 'pug'; import * as yaml from 'js-yaml'; import * as mkdirp from 'mkdirp'; -import config from './../../../../conf'; +import config from './../../../conf'; + +const kebab = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); const parseParam = param => { - const id = param.type.match(/^id\((.+?)\)/); + const id = param.type.match(/^id\((.+?)\)|^id/); const entity = param.type.match(/^entity\((.+?)\)/); const isObject = /^object/.test(param.type); + const isDate = /^date/.test(param.type); const isArray = /\[\]$/.test(param.type); if (id) { param.kind = 'id'; @@ -36,30 +39,53 @@ const parseParam = param => { if (isObject) { param.kind = 'object'; } + if (isDate) { + param.kind = 'date'; + param.type = 'string'; + if (isArray) { + param.type += '[]'; + } + } return param; }; +const sortParams = params => { + params.sort((a, b) => { + if (a.name < b.name) + return -1; + if (a.name > b.name) + return 1; + return 0; + }); + return params; +}; + const extractDefs = params => { - const defs = []; + let defs = []; params.forEach(param => { if (param.def) { defs.push({ name: param.defName, - params: param.def.map(p => parseParam(p)) + params: sortParams(param.def.map(p => parseParam(p))) }); const childDefs = extractDefs(param.def); - defs.concat(childDefs); + defs = defs.concat(childDefs); } }); return defs; }; -gulp.task('doc:endpoints', () => { +gulp.task('doc:api', [ + 'doc:api:endpoints', + 'doc:api:entities' +]); + +gulp.task('doc:api:endpoints', () => { glob('./src/web/docs/api/endpoints/**/*.yaml', (globErr, files) => { if (globErr) { console.error(globErr); @@ -72,10 +98,11 @@ gulp.task('doc:endpoints', () => { endpoint: ep.endpoint, url: `${config.api_url}/${ep.endpoint}`, desc: ep.desc, - params: ep.params.map(p => parseParam(p)), + params: sortParams(ep.params.map(p => parseParam(p))), paramDefs: extractDefs(ep.params), - res: ep.res.map(p => parseParam(p)), - resDefs: extractDefs(ep.res) + res: sortParams(ep.res.map(p => parseParam(p))), + resDefs: extractDefs(ep.res), + kebab }; pug.renderFile('./src/web/docs/api/endpoints/view.pug', vars, (renderErr, html) => { if (renderErr) { @@ -94,3 +121,36 @@ gulp.task('doc:endpoints', () => { }); }); }); + +gulp.task('doc:api:entities', () => { + glob('./src/web/docs/api/entities/**/*.yaml', (globErr, files) => { + if (globErr) { + console.error(globErr); + return; + } + files.forEach(file => { + const entity = yaml.safeLoad(fs.readFileSync(file, 'utf-8')); + const vars = { + name: entity.name, + desc: entity.desc, + props: sortParams(entity.props.map(p => parseParam(p))), + propDefs: extractDefs(entity.props), + kebab + }; + pug.renderFile('./src/web/docs/api/entities/view.pug', vars, (renderErr, html) => { + if (renderErr) { + console.error(renderErr); + return; + } + const htmlPath = `./built/web/docs/api/entities/${kebab(entity.name)}.html`; + mkdirp(path.dirname(htmlPath), (mkdirErr) => { + if (mkdirErr) { + console.error(mkdirErr); + return; + } + fs.writeFileSync(htmlPath, html, 'utf-8'); + }); + }); + }); + }); +}); diff --git a/src/web/docs/api/mixins.pug b/src/web/docs/api/mixins.pug new file mode 100644 index 0000000000..b302c78263 --- /dev/null +++ b/src/web/docs/api/mixins.pug @@ -0,0 +1,33 @@ +mixin propTable(props) + table.props + thead: tr + th Name + th Type + th Optional + th Description + tbody + each prop in props + tr + td.name= prop.name + td.type + i= prop.type + if prop.kind == 'id' + if prop.entity + | ( + a(href=`/docs/api/entities/${kebab(prop.entity)}`)= prop.entity + | ID) + else + | (ID) + else if prop.kind == 'entity' + | ( + a(href=`/docs/api/entities/${kebab(prop.entity)}`)= prop.entity + | ) + else if prop.kind == 'object' + if prop.def + | ( + a(href=`#${prop.defName}`)= prop.defName + | ) + else if prop.kind == 'date' + | (Date) + td.optional= prop.optional.toString() + td.desc: +i18n(prop.desc) diff --git a/src/web/docs/api/style.styl b/src/web/docs/api/style.styl new file mode 100644 index 0000000000..3675a4da6f --- /dev/null +++ b/src/web/docs/api/style.styl @@ -0,0 +1,11 @@ +@import "../style" + +table.props + .name + font-weight bold + + .name + .type + .optional + font-family Consolas, 'Courier New', Courier, Monaco, monospace + diff --git a/src/web/docs/layout.pug b/src/web/docs/layout.pug new file mode 100644 index 0000000000..68ca9eb62d --- /dev/null +++ b/src/web/docs/layout.pug @@ -0,0 +1,16 @@ +doctype html + +mixin i18n(xs) + each text, lang in xs + span(class=`i18n ${lang}`)!= text + +html + head + meta(charset="UTF-8") + title + block title + block meta + + body + main + block main From 13e4034ceee1e3983c852a2c40ce89eeb30dcecd Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 15 Dec 2017 00:54:28 +0900 Subject: [PATCH 083/186] :v: --- src/web/docs/api/entities/post.pug | 149 ---------------------------- src/web/docs/api/entities/user.yaml | 137 +++++++++++++++++++++++++ src/web/docs/api/gulpfile.ts | 2 +- 3 files changed, 138 insertions(+), 150 deletions(-) delete mode 100644 src/web/docs/api/entities/post.pug create mode 100644 src/web/docs/api/entities/user.yaml diff --git a/src/web/docs/api/entities/post.pug b/src/web/docs/api/entities/post.pug deleted file mode 100644 index 954f172717..0000000000 --- a/src/web/docs/api/entities/post.pug +++ /dev/null @@ -1,149 +0,0 @@ -extend ../../BASE - -block title - | Entity: Post - -block content - h1 Post - p 投稿を表します。 - - section - h2 Properties - table.entity - thead: tr - td Name - td Type - td Description - tbody - tr.nullable.optional - td app - td: a(href='./app', target='_blank') App - td 投稿したアプリ - tr.nullable - td app_id - td ID - td 投稿したアプリのID - tr - td created_at - td Date - td 投稿日時 - tr - td id - td ID - td 投稿ID - tr.optional - td is_liked - td Boolean - td いいね したかどうか - tr - td likes_count - td Number - td いいね数 - tr.nullable.optional - td media_ids - td ID[] - td 添付されたメディアのIDの配列 - tr.nullable.optional - td media - td: a(href='./drive-file', target='_blank') DriveFile[] - td 添付されたメディアの配列 - tr - td replies_count - td Number - td 返信数 - tr.optional - td reply - td: a(href='./post', target='_blank') Post - td 返信先の投稿 - tr.nullable - td reply_id - td ID - td 返信先の投稿のID - tr.optional - td repost - td: a(href='./post', target='_blank') Post - td Repostした投稿 - tr - td repost_count - td Number - td Repostされた数 - tr.nullable - td repost_id - td ID - td Repostした投稿のID - tr.nullable - td text - td String - td 本文 - tr.optional - td user - td: a(href='./user', target='_blank') User - td 投稿者 - tr - td user_id - td ID - td 投稿者のID - - section - h2 Example - pre: code. - { - "created_at": "2016-12-10T00:28:50.114Z", - "media_ids": null, - "reply_id": "584a16b15860fc52320137e3", - "repost_id": null, - "text": "小日向美穂だぞ!", - "user_id": "5848bf7764e572683f4402f8", - "app_id": null, - "likes_count": 1, - "replies_count": 1, - "id": "584b4c42d8e5186f8f755d0c", - "user": { - "birthday": null, - "created_at": "2016-12-08T02:03:35.332Z", - "bio": "女が嫌いです、女性は好きです", - "followers_count": 11, - "following_count": 11, - "links": null, - "location": "", - "name": "女が嫌い", - "posts_count": 26, - "likes_count": 2, - "liked_count": 20, - "username": "onnnagakirai", - "id": "5848bf7764e572683f4402f8", - "avatar_url": "https://file.himasaku.net/5848c0ec64e572683f4402fc", - "banner_url": "https://file.himasaku.net/5848c12864e572683f4402fd", - "is_following": true, - "is_followed": true - }, - "reply": { - "created_at": "2016-12-09T02:28:01.563Z", - "media_ids": null, - "reply_id": "5849d35e547e4249be329884", - "repost_id": null, - "text": "アイコン小日向美穂?", - "user_id": "57d01a501fdf2d07be417afe", - "app_id": null, - "replies_count": 1, - "id": "584a16b15860fc52320137e3", - "user": { - "birthday": null, - "created_at": "2016-09-07T13:46:56.605Z", - "bio": "どうすれば君だけのために生きていけるの", - "followers_count": 51, - "following_count": 97, - "links": null, - "location": "川崎", - "name": "きな子", - "posts_count": 4813, - "username": "syuilo", - "likes_count": 3141, - "liked_count": 750, - "id": "57d01a501fdf2d07be417afe", - "avatar_url": "https://file.himasaku.net/583ddc6e64df272771f74c1a", - "banner_url": "https://file.himasaku.net/584bfc82d8e5186f8f755ec5" - } - }, - "is_liked": true - } diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml new file mode 100644 index 0000000000..9b1efd1fe6 --- /dev/null +++ b/src/web/docs/api/entities/user.yaml @@ -0,0 +1,137 @@ +name: "User" + +desc: + ja: "ユーザー。" + en: "A user." + +props: + - name: "id" + type: "id" + optional: false + desc: + ja: "ユーザーID" + en: "The ID of this user" + - name: "created_at" + type: "date" + optional: false + desc: + ja: "アカウント作成日時" + en: "The registered date of this user" + - name: "username" + type: "string" + optional: false + desc: + ja: "ユーザー名" + en: "The username of this user" + - name: "description" + type: "string" + optional: false + desc: + ja: "アカウントの説明(自己紹介)" + en: "The description of this user" + - name: "avatar_id" + type: "id(DriveFile)" + optional: true + desc: + ja: "アバターのID" + en: "The ID of the avatar of this user" + - name: "avatar_url" + type: "string" + optional: false + desc: + ja: "アバターのURL" + en: "The URL of the avatar of this user" + - name: "banner_id" + type: "id(DriveFile)" + optional: true + desc: + ja: "バナーのID" + en: "The ID of the banner of this user" + - name: "banner_url" + type: "string" + optional: false + desc: + ja: "バナーのURL" + en: "The URL of the banner of this user" + - name: "followers_count" + type: "number" + optional: false + desc: + ja: "フォロワーの数" + en: "The number of the followers for this user" + - name: "following_count" + type: "number" + optional: false + desc: + ja: "フォローしているユーザーの数" + en: "The number of the following users for this user" + - name: "last_used_at" + type: "date" + optional: false + desc: + ja: "最終利用日時" + en: "The last used date of this user" + - name: "posts_count" + type: "number" + optional: false + desc: + ja: "投稿の数" + en: "The number of the posts of this user" + - name: "pinned_post" + type: "entity(Post)" + optional: true + desc: + ja: "ピン留めされた投稿" + en: "The pinned post of this user" + - name: "pinned_post_id" + type: "id(Post)" + optional: true + desc: + ja: "ピン留めされた投稿のID" + en: "The ID of the pinned post of this user" + - name: "drive_capacity" + type: "number" + optional: false + desc: + ja: "ドライブの容量(bytes)" + en: "The capacity of drive of this user (bytes)" + - name: "twitter" + type: "object" + optional: true + desc: + ja: "連携されているTwitterアカウント情報" + en: "The info of the connected twitter account of this user" + defName: "twitter" + def: + - name: "user_id" + type: "string" + optional: false + desc: + ja: "ユーザーID" + en: "The user ID" + - name: "screen_name" + type: "string" + optional: false + desc: + ja: "ユーザー名" + en: "The screen name of this user" + - name: "profile" + type: "object" + optional: false + desc: + ja: "プロフィール" + en: "The profile of this user" + defName: "profile" + def: + - name: "location" + type: "string" + optional: true + desc: + ja: "場所" + en: "The location of this user" + - name: "birthday" + type: "string" + optional: true + desc: + ja: "誕生日 (YYYY-MM-DD)" + en: "The birthday of this user (YYYY-MM-DD)" diff --git a/src/web/docs/api/gulpfile.ts b/src/web/docs/api/gulpfile.ts index 05567b6233..6453996d31 100644 --- a/src/web/docs/api/gulpfile.ts +++ b/src/web/docs/api/gulpfile.ts @@ -77,7 +77,7 @@ const extractDefs = params => { } }); - return defs; + return sortParams(defs); }; gulp.task('doc:api', [ From 55e266fbbe55ea1dc8bd5cdce4e52d5625eea38d Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 15 Dec 2017 04:43:48 +0900 Subject: [PATCH 084/186] :art: --- src/web/docs/style.styl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl index 5c484adc1b..a4abc5a9a3 100644 --- a/src/web/docs/style.styl +++ b/src/web/docs/style.styl @@ -56,7 +56,12 @@ table tr th + position sticky + top 0 + z-index 1 text-align left + box-shadow 0 1px 0 0 #eee + background #fff tbody tr From 5725e39a707af39c0a5118a04282bbaf186ee922 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 15 Dec 2017 05:07:21 +0900 Subject: [PATCH 085/186] :v: --- src/web/docs/api/entities/user.pug | 122 ---------------------------- src/web/docs/api/entities/user.yaml | 10 +++ 2 files changed, 10 insertions(+), 122 deletions(-) delete mode 100644 src/web/docs/api/entities/user.pug diff --git a/src/web/docs/api/entities/user.pug b/src/web/docs/api/entities/user.pug deleted file mode 100644 index a37886bb19..0000000000 --- a/src/web/docs/api/entities/user.pug +++ /dev/null @@ -1,122 +0,0 @@ -extend ../../BASE - -block title - | Entity: User - -block content - h1 User - p ユーザーを表します。 - - section - h2 Properties - table.entity - thead: tr - td Name - td Type - td Description - tbody - tr.nullable.optional - td avatar_id - td ID - td アバターに設定しているドライブのファイルのID - tr.nullable - td avatar_url - td String - td アバターURL - tr.nullable.optional - td banner_id - td ID - td バナーに設定しているドライブのファイルのID - tr.nullable - td banner_url - td String - td バナーURL - tr.nullable - td bio - td String - td プロフィール - tr.nullable - td birthday - td String - td 誕生日(YYYY-MM-DD) - tr - td created_at - td Date - td アカウント作成日時 - tr.optional - td drive_capacity - td Number - td ドライブの最大容量(byte単位) - tr - td followers_count - td Number - td フォロワー数 - tr - td following_count - td Number - td フォロー数 - tr - td id - td ID - td ユーザーID - tr.optional - td is_bot - td Boolean - td botかどうか - tr.optional - td is_followed - td Boolean - td フォローされているか - tr.optional - td is_following - td Boolean - td フォローしているか - tr - td liked_count - td Number - td 投稿にいいねされた数 - tr - td likes_count - td Number - td 投稿にいいねした数 - tr.nullable - td location - td String - td 住処 - tr - td name - td String - td ニックネーム - tr - td posts_count - td Number - td 投稿数 - tr - td username - td String - td ユーザー名 - - section - h2 Example - pre: code. - { - "avatar_id": "583ddc6e64df272771f74c1a", - "avatar_url": "https://file.himasaku.net/583ddc6e64df272771f74c1a", - "banner_id": "584bfc82d8e5186f8f755ec5", - "banner_url": "https://file.himasaku.net/584bfc82d8e5186f8f755ec5", - "bio": "どうすれば君だけのために生きていけるの", - "birthday": "1997-12-06", - "created_at": "2016-09-07T13:46:56.605Z", - "drive_capacity": 1073741824, - "email": null, - "followers_count": 51, - "following_count": 97, - "id": "57d01a501fdf2d07be417afe", - "liked_count": 750, - "likes_count": 3130, - "links": null, - "location": "川崎", - "name": "きな子", - "posts_count": 4811, - "username": "syuilo" - } diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml index 9b1efd1fe6..abc3f300d2 100644 --- a/src/web/docs/api/entities/user.yaml +++ b/src/web/docs/api/entities/user.yaml @@ -65,6 +65,16 @@ props: desc: ja: "フォローしているユーザーの数" en: "The number of the following users for this user" + - name: "is_following" + type: "boolean" + optional: true + desc: + ja: "自分がこのユーザーをフォローしているか" + - name: "is_followed" + type: "boolean" + optional: true + desc: + ja: "自分がこのユーザーにフォローされているか" - name: "last_used_at" type: "date" optional: false From 169b99a358f166185147970b916adf1a09d23de3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 15 Dec 2017 06:41:57 +0900 Subject: [PATCH 086/186] :v: --- gulpfile.ts | 19 +------- src/web/docs/api/endpoints/view.pug | 3 +- src/web/docs/api/entities/view.pug | 2 +- src/web/docs/api/gulpfile.ts | 60 ++++++++++++++++--------- src/web/docs/api/mixins.pug | 6 +-- src/web/docs/gulpfile.ts | 64 ++++++++++++++++++++++++++ src/web/docs/index.en.pug | 9 ++++ src/web/docs/index.ja.pug | 9 ++++ src/web/docs/index.md | 4 -- src/web/docs/layout.pug | 23 +++++++--- src/web/docs/style.styl | 69 ++++++++++++++++------------- src/web/docs/vars.ts | 36 +++++++++++++++ 12 files changed, 220 insertions(+), 84 deletions(-) create mode 100644 src/web/docs/gulpfile.ts create mode 100644 src/web/docs/index.en.pug create mode 100644 src/web/docs/index.ja.pug delete mode 100644 src/web/docs/index.md create mode 100644 src/web/docs/vars.ts diff --git a/gulpfile.ts b/gulpfile.ts index 6807b6d571..e7d4770610 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -13,7 +13,6 @@ import * as es from 'event-stream'; import cssnano = require('gulp-cssnano'); import * as uglifyComposer from 'gulp-uglify/composer'; import pug = require('gulp-pug'); -import stylus = require('gulp-stylus'); import * as rimraf from 'rimraf'; import chalk from 'chalk'; import imagemin = require('gulp-imagemin'); @@ -48,32 +47,18 @@ if (isDebug) { const constants = require('./src/const.json'); -require('./src/web/docs/api/gulpfile.ts'); +require('./src/web/docs/gulpfile.ts'); gulp.task('build', [ 'build:js', 'build:ts', 'build:copy', 'build:client', - 'build:doc' + 'doc' ]); gulp.task('rebuild', ['clean', 'build']); -gulp.task('build:doc', [ - 'doc:api', - 'doc:styles' -]); - -gulp.task('doc:styles', () => - gulp.src('./src/web/docs/**/*.styl') - .pipe(stylus()) - .pipe(isProduction - ? (cssnano as any)() - : gutil.noop()) - .pipe(gulp.dest('./built/web/assets/docs/')) -); - gulp.task('build:js', () => gulp.src(['./src/**/*.js', '!./src/web/**/*.js']) .pipe(gulp.dest('./built/')) diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug index cebef9fa5b..cab814cabc 100644 --- a/src/web/docs/api/endpoints/view.pug +++ b/src/web/docs/api/endpoints/view.pug @@ -12,7 +12,7 @@ block main p#url= url - p#desc: +i18n(desc) + p#desc= desc[lang] || desc['ja'] section h2 Params @@ -27,4 +27,3 @@ block main section h2 Response +propTable(res) - diff --git a/src/web/docs/api/entities/view.pug b/src/web/docs/api/entities/view.pug index f210582f1a..756e966b53 100644 --- a/src/web/docs/api/entities/view.pug +++ b/src/web/docs/api/entities/view.pug @@ -10,7 +10,7 @@ block meta block main h1= name - p#desc: +i18n(desc) + p#desc= desc[lang] || desc['ja'] section h2 Properties diff --git a/src/web/docs/api/gulpfile.ts b/src/web/docs/api/gulpfile.ts index 6453996d31..6cbae5ea2d 100644 --- a/src/web/docs/api/gulpfile.ts +++ b/src/web/docs/api/gulpfile.ts @@ -12,6 +12,12 @@ import * as mkdirp from 'mkdirp'; import config from './../../../conf'; +import generateVars from '../vars'; + +const commonVars = generateVars(); + +const langs = ['ja', 'en']; + const kebab = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); const parseParam = param => { @@ -102,20 +108,25 @@ gulp.task('doc:api:endpoints', () => { paramDefs: extractDefs(ep.params), res: sortParams(ep.res.map(p => parseParam(p))), resDefs: extractDefs(ep.res), - kebab + kebab, + common: commonVars }; - pug.renderFile('./src/web/docs/api/endpoints/view.pug', vars, (renderErr, html) => { - if (renderErr) { - console.error(renderErr); - return; - } - const htmlPath = `./built/web/docs/api/endpoints/${ep.endpoint}.html`; - mkdirp(path.dirname(htmlPath), (mkdirErr) => { - if (mkdirErr) { - console.error(mkdirErr); + langs.forEach(lang => { + pug.renderFile('./src/web/docs/api/endpoints/view.pug', Object.assign({}, vars, { + lang + }), (renderErr, html) => { + if (renderErr) { + console.error(renderErr); return; } - fs.writeFileSync(htmlPath, html, 'utf-8'); + const htmlPath = `./built/web/docs/${lang}/api/endpoints/${ep.endpoint}.html`; + mkdirp(path.dirname(htmlPath), (mkdirErr) => { + if (mkdirErr) { + console.error(mkdirErr); + return; + } + fs.writeFileSync(htmlPath, html, 'utf-8'); + }); }); }); }); @@ -135,20 +146,25 @@ gulp.task('doc:api:entities', () => { desc: entity.desc, props: sortParams(entity.props.map(p => parseParam(p))), propDefs: extractDefs(entity.props), - kebab + kebab, + common: commonVars }; - pug.renderFile('./src/web/docs/api/entities/view.pug', vars, (renderErr, html) => { - if (renderErr) { - console.error(renderErr); - return; - } - const htmlPath = `./built/web/docs/api/entities/${kebab(entity.name)}.html`; - mkdirp(path.dirname(htmlPath), (mkdirErr) => { - if (mkdirErr) { - console.error(mkdirErr); + langs.forEach(lang => { + pug.renderFile('./src/web/docs/api/entities/view.pug', Object.assign({}, vars, { + lang + }), (renderErr, html) => { + if (renderErr) { + console.error(renderErr); return; } - fs.writeFileSync(htmlPath, html, 'utf-8'); + const htmlPath = `./built/web/docs/${lang}/api/entities/${kebab(entity.name)}.html`; + mkdirp(path.dirname(htmlPath), (mkdirErr) => { + if (mkdirErr) { + console.error(mkdirErr); + return; + } + fs.writeFileSync(htmlPath, html, 'utf-8'); + }); }); }); }); diff --git a/src/web/docs/api/mixins.pug b/src/web/docs/api/mixins.pug index b302c78263..3ddd7cb48a 100644 --- a/src/web/docs/api/mixins.pug +++ b/src/web/docs/api/mixins.pug @@ -14,13 +14,13 @@ mixin propTable(props) if prop.kind == 'id' if prop.entity | ( - a(href=`/docs/api/entities/${kebab(prop.entity)}`)= prop.entity + a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity | ID) else | (ID) else if prop.kind == 'entity' | ( - a(href=`/docs/api/entities/${kebab(prop.entity)}`)= prop.entity + a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity | ) else if prop.kind == 'object' if prop.def @@ -30,4 +30,4 @@ mixin propTable(props) else if prop.kind == 'date' | (Date) td.optional= prop.optional.toString() - td.desc: +i18n(prop.desc) + td.desc!= prop.desc[lang] || prop.desc['ja'] diff --git a/src/web/docs/gulpfile.ts b/src/web/docs/gulpfile.ts new file mode 100644 index 0000000000..6f2351dacb --- /dev/null +++ b/src/web/docs/gulpfile.ts @@ -0,0 +1,64 @@ +/** + * Gulp tasks + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import * as glob from 'glob'; +import * as gulp from 'gulp'; +import * as pug from 'pug'; +//import * as yaml from 'js-yaml'; +import * as mkdirp from 'mkdirp'; +import stylus = require('gulp-stylus'); +import cssnano = require('gulp-cssnano'); + +//import config from './../../conf'; + +import generateVars from './vars'; + +require('./api/gulpfile.ts'); + +gulp.task('doc', [ + 'doc:docs', + 'doc:api', + 'doc:styles' +]); + +const commonVars = generateVars(); + +gulp.task('doc:docs', () => { + glob('./src/web/docs/**/*.*.pug', (globErr, files) => { + if (globErr) { + console.error(globErr); + return; + } + files.forEach(file => { + const [, name, lang] = file.match(/docs\/(.+?)\.(.+?)\.pug$/); + const vars = { + common: commonVars, + lang: lang + }; + pug.renderFile(file, vars, (renderErr, html) => { + if (renderErr) { + console.error(renderErr); + return; + } + const htmlPath = `./built/web/docs/${lang}/${name}.html`; + mkdirp(path.dirname(htmlPath), (mkdirErr) => { + if (mkdirErr) { + console.error(mkdirErr); + return; + } + fs.writeFileSync(htmlPath, html, 'utf-8'); + }); + }); + }); + }); +}); + +gulp.task('doc:styles', () => + gulp.src('./src/web/docs/**/*.styl') + .pipe(stylus()) + .pipe((cssnano as any)()) + .pipe(gulp.dest('./built/web/assets/docs/')) +); diff --git a/src/web/docs/index.en.pug b/src/web/docs/index.en.pug new file mode 100644 index 0000000000..af0bba8b2c --- /dev/null +++ b/src/web/docs/index.en.pug @@ -0,0 +1,9 @@ +extends ./layout.pug + +block title + | Misskey Docs + +block main + h1 Misskey Docs + + p Welcome to docs of Misskey. diff --git a/src/web/docs/index.ja.pug b/src/web/docs/index.ja.pug new file mode 100644 index 0000000000..cd43045f6e --- /dev/null +++ b/src/web/docs/index.ja.pug @@ -0,0 +1,9 @@ +extends ./layout.pug + +block title + | Misskey ドキュメント + +block main + h1 Misskey ドキュメント + + p Misskeyのドキュメントへようこそ diff --git a/src/web/docs/index.md b/src/web/docs/index.md deleted file mode 100644 index 0846cf27e8..0000000000 --- a/src/web/docs/index.md +++ /dev/null @@ -1,4 +0,0 @@ -Misskeyについて -================================================================ - -誰か書いて diff --git a/src/web/docs/layout.pug b/src/web/docs/layout.pug index 68ca9eb62d..d6ecb4b6aa 100644 --- a/src/web/docs/layout.pug +++ b/src/web/docs/layout.pug @@ -1,16 +1,29 @@ doctype html -mixin i18n(xs) - each text, lang in xs - span(class=`i18n ${lang}`)!= text - -html +html(lang= lang) head meta(charset="UTF-8") + meta(name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no") title block title + link(rel="stylesheet" href="/assets/docs/style.css") block meta body + nav + ul + each doc in common.docs + li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja'] + section + h2 API + ul + li Entities + ul + each entity in common.entities + li: a(href=`/docs/${lang}/api/entities/${common.kebab(entity)}`)= entity + li Endpoints + ul + each endpoint in common.endpoints + li: a(href=`/docs/${lang}/api/endpoints/${common.kebab(endpoint)}`)= endpoint main block main diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl index a4abc5a9a3..2e2f9f5743 100644 --- a/src/web/docs/style.styl +++ b/src/web/docs/style.styl @@ -5,10 +5,49 @@ body color #34495e main + margin 0 0 0 256px padding 32px width 100% max-width 700px + section + margin 32px 0 + + h1 + margin 0 0 24px 0 + padding 16px 0 + font-size 1.5em + border-bottom solid 2px #eee + + h2 + margin 0 0 24px 0 + padding 0 0 16px 0 + font-size 1.4em + border-bottom solid 1px #eee + + h3 + margin 0 + padding 0 + font-size 1.25em + + h4 + margin 0 + + p + margin 1em 0 + line-height 1.6em + +nav + display block + position fixed + top 0 + left 0 + width 256px + height 100% + overflow auto + padding 32px + border-right solid 2px #eee + footer padding:32px 0 0 0 margin 32px 0 0 0 @@ -18,33 +57,6 @@ footer margin 16px 0 0 0 color #aaa -section - margin 32px 0 - -h1 - margin 0 0 24px 0 - padding 16px 0 - font-size 1.5em - border-bottom solid 2px #eee - -h2 - margin 0 0 24px 0 - padding 0 0 16px 0 - font-size 1.4em - border-bottom solid 1px #eee - -h3 - margin 0 - padding 0 - font-size 1.25em - -h4 - margin 0 - -p - margin 1em 0 - line-height 1.6em - table width 100% border-spacing 0 @@ -72,6 +84,3 @@ table th, td padding 8px 16px - -.i18n:not(.ja) - display none diff --git a/src/web/docs/vars.ts b/src/web/docs/vars.ts new file mode 100644 index 0000000000..ed2149df4a --- /dev/null +++ b/src/web/docs/vars.ts @@ -0,0 +1,36 @@ +import * as fs from 'fs'; +import * as glob from 'glob'; +import * as yaml from 'js-yaml'; + +export default function() { + const vars = {}; + + const endpoints = glob.sync('./src/web/docs/api/endpoints/**/*.yaml'); + vars['endpoints'] = endpoints.map(ep => { + const _ep = yaml.safeLoad(fs.readFileSync(ep, 'utf-8')); + return _ep.endpoint; + }); + + const entities = glob.sync('./src/web/docs/api/entities/**/*.yaml'); + vars['entities'] = entities.map(x => { + const _x = yaml.safeLoad(fs.readFileSync(x, 'utf-8')); + return _x.name; + }); + + const docs = glob.sync('./src/web/docs/**/*.*.pug'); + vars['docs'] = {}; + docs.forEach(x => { + const [, name, lang] = x.match(/docs\/(.+?)\.(.+?)\.pug$/); + if (vars['docs'][name] == null) { + vars['docs'][name] = { + name, + title: {} + }; + } + vars['docs'][name]['title'][lang] = fs.readFileSync(x, 'utf-8').match(/\r\n\th1 (.+?)\r\n/)[1]; + }); + + vars['kebab'] = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); + + return vars; +} From fae40ad1dde72f09ecd0e0630b4e757cf9758010 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 15 Dec 2017 06:45:19 +0900 Subject: [PATCH 087/186] :v: --- src/web/docs/vars.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/docs/vars.ts b/src/web/docs/vars.ts index ed2149df4a..80fdc9a7de 100644 --- a/src/web/docs/vars.ts +++ b/src/web/docs/vars.ts @@ -27,7 +27,7 @@ export default function() { title: {} }; } - vars['docs'][name]['title'][lang] = fs.readFileSync(x, 'utf-8').match(/\r\n\th1 (.+?)\r\n/)[1]; + vars['docs'][name]['title'][lang] = fs.readFileSync(x, 'utf-8').match(/\r?\n\th1 (.+?)\r?\n/)[1]; }); vars['kebab'] = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); From 3bcdbe151f89622aabc9c38a8a4d69abdec97619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Fri, 15 Dec 2017 09:03:22 +0900 Subject: [PATCH 088/186] :v: --- src/web/docs/api/entities/drive-file.yaml | 73 +++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/web/docs/api/entities/drive-file.yaml diff --git a/src/web/docs/api/entities/drive-file.yaml b/src/web/docs/api/entities/drive-file.yaml new file mode 100644 index 0000000000..2ebbb089ab --- /dev/null +++ b/src/web/docs/api/entities/drive-file.yaml @@ -0,0 +1,73 @@ +name: "DriveFile" + +desc: + ja: "ドライブのファイル。" + en: "A file of Drive." + +props: + - name: "id" + type: "id" + optional: false + desc: + ja: "ファイルID" + en: "The ID of this file" + - name: "created_at" + type: "date" + optional: false + desc: + ja: "アップロード日時" + en: "The upload date of this file" + - name: "user_id" + type: "id(User)" + optional: false + desc: + ja: "所有者ID" + en: "The ID of the owner of this file" + - name: "user" + type: "entity(User)" + optional: true + desc: + ja: "所有者" + en: "The owner of this file" + - name: "name" + type: "string" + optional: false + desc: + ja: "ファイル名" + en: "The name of this file" + - name: "md5" + type: "string" + optional: false + desc: + ja: "ファイルのMD5ハッシュ値" + en: "The md5 hash value of this file" + - name: "type" + type: "string" + optional: false + desc: + ja: "ファイルの種類" + en: "The type of this file" + - name: "datasize" + type: "number" + optional: false + desc: + ja: "ファイルサイズ(bytes)" + en: "The size of this file (bytes)" + - name: "url" + type: "string" + optional: false + desc: + ja: "ファイルのURL" + en: "The URL of this file" + - name: "folder_id" + type: "id(DriveFolder)" + optional: true + desc: + ja: "フォルダID" + en: "The ID of the folder of this file" + - name: "folder" + type: "entity(DriveFolder)" + optional: true + desc: + ja: "フォルダ" + en: "The folder of this file" From e1cc715589f83147b64a76bf0962b7a77dd2d19c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 16 Dec 2017 00:19:10 +0900 Subject: [PATCH 089/186] :v: --- src/web/docs/api/endpoints/view.pug | 3 --- src/web/docs/api/entities/view.pug | 3 --- src/web/docs/api/gulpfile.ts | 14 ++++++++------ src/web/docs/gulpfile.ts | 24 +++++++++++++++++------- src/web/docs/index.en.pug | 10 ++-------- src/web/docs/index.ja.pug | 10 ++-------- src/web/docs/layout.pug | 4 +++- src/web/docs/vars.ts | 2 +- 8 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug index cab814cabc..d456022f6e 100644 --- a/src/web/docs/api/endpoints/view.pug +++ b/src/web/docs/api/endpoints/view.pug @@ -1,9 +1,6 @@ extends ../../layout.pug include ../mixins -block title - | #{endpoint} | Misskey API - block meta link(rel="stylesheet" href="/assets/docs/api/endpoints/style.css") diff --git a/src/web/docs/api/entities/view.pug b/src/web/docs/api/entities/view.pug index 756e966b53..57c6d4cad7 100644 --- a/src/web/docs/api/entities/view.pug +++ b/src/web/docs/api/entities/view.pug @@ -1,9 +1,6 @@ extends ../../layout.pug include ../mixins -block title - | #{name} | Misskey API - block meta link(rel="stylesheet" href="/assets/docs/api/entities/style.css") diff --git a/src/web/docs/api/gulpfile.ts b/src/web/docs/api/gulpfile.ts index 6cbae5ea2d..139ae92412 100644 --- a/src/web/docs/api/gulpfile.ts +++ b/src/web/docs/api/gulpfile.ts @@ -108,12 +108,13 @@ gulp.task('doc:api:endpoints', () => { paramDefs: extractDefs(ep.params), res: sortParams(ep.res.map(p => parseParam(p))), resDefs: extractDefs(ep.res), - kebab, - common: commonVars }; langs.forEach(lang => { pug.renderFile('./src/web/docs/api/endpoints/view.pug', Object.assign({}, vars, { - lang + lang, + title: ep.endpoint, + kebab, + common: commonVars }), (renderErr, html) => { if (renderErr) { console.error(renderErr); @@ -146,12 +147,13 @@ gulp.task('doc:api:entities', () => { desc: entity.desc, props: sortParams(entity.props.map(p => parseParam(p))), propDefs: extractDefs(entity.props), - kebab, - common: commonVars }; langs.forEach(lang => { pug.renderFile('./src/web/docs/api/entities/view.pug', Object.assign({}, vars, { - lang + lang, + title: entity.name, + kebab, + common: commonVars }), (renderErr, html) => { if (renderErr) { console.error(renderErr); diff --git a/src/web/docs/gulpfile.ts b/src/web/docs/gulpfile.ts index 6f2351dacb..2377844650 100644 --- a/src/web/docs/gulpfile.ts +++ b/src/web/docs/gulpfile.ts @@ -36,20 +36,30 @@ gulp.task('doc:docs', () => { const [, name, lang] = file.match(/docs\/(.+?)\.(.+?)\.pug$/); const vars = { common: commonVars, - lang: lang + lang: lang, + title: fs.readFileSync(file, 'utf-8').match(/^h1 (.+?)\r?\n/)[1] }; - pug.renderFile(file, vars, (renderErr, html) => { + pug.renderFile(file, vars, (renderErr, content) => { if (renderErr) { console.error(renderErr); return; } - const htmlPath = `./built/web/docs/${lang}/${name}.html`; - mkdirp(path.dirname(htmlPath), (mkdirErr) => { - if (mkdirErr) { - console.error(mkdirErr); + + pug.renderFile('./src/web/docs/layout.pug', Object.assign({}, vars, { + content + }), (renderErr2, html) => { + if (renderErr2) { + console.error(renderErr2); return; } - fs.writeFileSync(htmlPath, html, 'utf-8'); + const htmlPath = `./built/web/docs/${lang}/${name}.html`; + mkdirp(path.dirname(htmlPath), (mkdirErr) => { + if (mkdirErr) { + console.error(mkdirErr); + return; + } + fs.writeFileSync(htmlPath, html, 'utf-8'); + }); }); }); }); diff --git a/src/web/docs/index.en.pug b/src/web/docs/index.en.pug index af0bba8b2c..1fcc870d3d 100644 --- a/src/web/docs/index.en.pug +++ b/src/web/docs/index.en.pug @@ -1,9 +1,3 @@ -extends ./layout.pug +h1 Misskey Docs -block title - | Misskey Docs - -block main - h1 Misskey Docs - - p Welcome to docs of Misskey. +p Welcome to docs of Misskey. diff --git a/src/web/docs/index.ja.pug b/src/web/docs/index.ja.pug index cd43045f6e..4a0bf7fa1d 100644 --- a/src/web/docs/index.ja.pug +++ b/src/web/docs/index.ja.pug @@ -1,9 +1,3 @@ -extends ./layout.pug +h1 Misskey ドキュメント -block title - | Misskey ドキュメント - -block main - h1 Misskey ドキュメント - - p Misskeyのドキュメントへようこそ +p Misskeyのドキュメントへようこそ diff --git a/src/web/docs/layout.pug b/src/web/docs/layout.pug index d6ecb4b6aa..f8570dd3ac 100644 --- a/src/web/docs/layout.pug +++ b/src/web/docs/layout.pug @@ -5,7 +5,7 @@ html(lang= lang) meta(charset="UTF-8") meta(name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no") title - block title + | #{title} | Misskey Docs link(rel="stylesheet" href="/assets/docs/style.css") block meta @@ -27,3 +27,5 @@ html(lang= lang) li: a(href=`/docs/${lang}/api/endpoints/${common.kebab(endpoint)}`)= endpoint main block main + if content + | !{content} diff --git a/src/web/docs/vars.ts b/src/web/docs/vars.ts index 80fdc9a7de..37bc9d7b0f 100644 --- a/src/web/docs/vars.ts +++ b/src/web/docs/vars.ts @@ -27,7 +27,7 @@ export default function() { title: {} }; } - vars['docs'][name]['title'][lang] = fs.readFileSync(x, 'utf-8').match(/\r?\n\th1 (.+?)\r?\n/)[1]; + vars['docs'][name]['title'][lang] = fs.readFileSync(x, 'utf-8').match(/^h1 (.+?)\r?\n/)[1]; }); vars['kebab'] = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); From 1a733f6b7128aed69fee2993eda1ec5f4ff9d79c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 16 Dec 2017 01:06:28 +0900 Subject: [PATCH 090/186] :v: --- src/web/docs/api.ja.pug | 66 +++++++++++++++++++++++++++++++++++++++++ src/web/docs/style.styl | 2 -- src/web/docs/vars.ts | 3 ++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/web/docs/api.ja.pug diff --git a/src/web/docs/api.ja.pug b/src/web/docs/api.ja.pug new file mode 100644 index 0000000000..588b926bdd --- /dev/null +++ b/src/web/docs/api.ja.pug @@ -0,0 +1,66 @@ +h1 Misskey API + +p MisskeyはWeb APIを公開しており、アプリケーションから様々な操作を行うことができます。 + +section + h2 自分の所有するアカウントからAPIにアクセスする場合 + p 「設定」で、APIにアクセスするのに必要なAPIキーを取得してください。 + p APIにアクセスする際には、リクエストにAPIキーを「i」というパラメータ名で含めます。 + p APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。 + +section + h2 アプリケーションからAPIにアクセスする場合 + p + | あなたのWebサービスやアプリケーションなどからMisskey APIを利用したい場合、 + | ユーザーにアカウントへのアクセスを許可してもらい、ユーザーのアクセストークンを取得する必要があります。 + p アクセストークンを取得するまでの流れを説明します。 + + section + h3 1.アプリケーションを登録する + p まず、あなたのWebサービスやアプリケーションをMisskeyに登録します。 + p デベロッパーセンターから登録を行ってください。 + p 登録が済むとアプリケーションのシークレットキーが入手できます。 + + section + h3 2.ユーザーに認証させる + p あなたのアプリケーションを使ってもらうには、ユーザーにアカウントへのアクセスの許可をもらう必要があります。 + p + | 認証セッションを開始するには、#{common.config.api_url}/auth/session/generate へパラメータに app_secret としてシークレットキーを含めたリクエストを送信します。 + | リクエスト形式はJSONで、メソッドはPOSTです。 + | レスポンスとして認証セッションのトークンや認証フォームのURLが取得できるので、認証フォームのURLをブラウザで表示し、ユーザーにフォームを提示してください。 + + p + | あなたのアプリがコールバックURLを設定している場合、 + | ユーザーがアプリの連携を許可すると設定しているコールバックURLに token という名前でセッションのトークンが含まれたクエリを付けてリダイレクトします。 + + p + | あなたのアプリがコールバックURLを設定していない場合、ユーザーがアプリの連携を許可したことを(何らかの方法で(たとえばボタンを押させるなど))確認出来るようにしてください。 + + section + h3 3.ユーザーのアクセストークンを取得する + p ユーザーが連携を許可したら、#{common.config.api_url}/auth/session/userkey へ次のパラメータを含むリクエストを送信します: + table + thead + tr + th 名前 + th 型 + th 説明 + tbody + tr + td app_secret + td string + td アプリのシークレットキー + tr + td token + td string + td セッションのトークン + p 上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます! + + p アクセストークンが取得できたら、「ユーザーのアクセストークン+アプリのシークレットキーをsha256したもの」を「i」というパラメータでリクエストに含めるだけで、APIにアクセスできます。 + + p APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。 + +section + h2 Misskey APIの利用 + p APIはすべてリクエストのパラメータ・レスポンスともにJSON形式です。また、すべてのエンドポイントはPOSTメソッドのみ受け付けます。 + p APIリファレンスもご確認ください。 diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl index 2e2f9f5743..f222e65bfd 100644 --- a/src/web/docs/style.styl +++ b/src/web/docs/style.styl @@ -77,8 +77,6 @@ table tbody tr - border-bottom dashed 1px #eee - &:nth-child(odd) background #fbfbfb diff --git a/src/web/docs/vars.ts b/src/web/docs/vars.ts index 37bc9d7b0f..ffa262a065 100644 --- a/src/web/docs/vars.ts +++ b/src/web/docs/vars.ts @@ -1,6 +1,7 @@ import * as fs from 'fs'; import * as glob from 'glob'; import * as yaml from 'js-yaml'; +import config from '../../conf'; export default function() { const vars = {}; @@ -32,5 +33,7 @@ export default function() { vars['kebab'] = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); + vars['config'] = config; + return vars; } From 42dad3873f863762262a4abfef2daa479ecc0bc0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 16 Dec 2017 04:10:05 +0900 Subject: [PATCH 091/186] :v: --- src/web/docs/api/getting-started.md | 73 ----------------------------- src/web/docs/api/library.md | 8 ---- src/web/docs/layout.pug | 9 ++-- src/web/docs/link-to-twitter.md | 9 ---- 4 files changed, 5 insertions(+), 94 deletions(-) delete mode 100644 src/web/docs/api/getting-started.md delete mode 100644 src/web/docs/api/library.md delete mode 100644 src/web/docs/link-to-twitter.md diff --git a/src/web/docs/api/getting-started.md b/src/web/docs/api/getting-started.md deleted file mode 100644 index e13659914e..0000000000 --- a/src/web/docs/api/getting-started.md +++ /dev/null @@ -1,73 +0,0 @@ -Getting Started -================================================================ -MisskeyはREST APIやStreaming APIを提供しており、プログラムからMisskeyの全ての機能を利用することができます。 -それらのAPIを利用するには、まずAPIを利用したいアカウントのアクセストークンを取得する必要があります: - -自分のアクセストークンを取得したい場合 ----------------------------------------------------------------- -自分自身のアクセストークンは、設定 > API で確認できます。 -

    - アカウントを乗っ取られてしまう可能性があるため、トークンは第三者に教えないでください(アプリなどにも入力しないでください)。
    - 万が一トークンが漏れたりその可能性がある場合は トークンを再生成できます。(副作用として、ログインしているすべてのデバイスでログアウトが発生します) -

    - -他人のアクセストークンを取得する ----------------------------------------------------------------- -不特定多数のユーザーからAPIを利用したい場合、アプリケーションを作成します。 -アプリケーションを作成すると、ユーザーが連携を許可した時に、そのユーザーのアクセストークンを取得することができます。 - -アプリケーションを作成してアクセストークンを取得するまでの流れを説明します。 - -### アプリケーションを作成する -まずはあなたのアプリケーションを作成しましょう。 - | デベロッパーセンターにアクセスし、アプリ > アプリ作成 に進みます。 - br - | 次に、フォームに必要事項を記入します: - dl - dt アプリケーション名 - dd あなたのアプリケーションの名前。 - dt Named ID - dd アプリを識別する/a-z-/で構成されたID。 - dt アプリの概要 - dd アプリの簡単な説明を入力してください。 - dt コールバックURL - dd あなたのアプリケーションがWebアプリケーションである場合、ユーザーが後述するフォームで認証を終えた際にリダイレクトするURLを設定できます。 - dt 権限 - dd アプリケーションが要求する権限。ここで要求した機能だけがAPIからアクセスできます。 - p.tip - | 権限はアプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーはすべて無効になります。 - p - | アプリケーションを作成すると、作ったアプリの管理ページに進みます。 - br - | アプリのシークレットキー(App Secret)が表示されていますので、メモしておいてください。 - p.tip - | アプリに成りすまされる可能性があるため、極力このシークレットキーは公開しないようにしてください。 - - section - h3 ユーザーに認証させる - p あなたのアプリを使ってもらうには、ユーザーにアカウントへアクセスすることを許可してもらい、Misskeyにそのユーザーのアクセストークンを発行してもらう必要があります。 - p 認証セッションを開始するには、#{api_url}/auth/session/generateへパラメータにapp_secretとしてApp Secretを含めたリクエストを送信します。 - p - | そうすると、レスポンスとして認証セッションのトークンや認証フォームのURLが取得できます。 - br - | この認証フォームのURLをブラウザで表示し、ユーザーにフォームを表示してください。 - section - h4 あなたのアプリがコールバックURLを設定している場合 - p ユーザーがアプリの連携を許可すると設定しているコールバックURLにtokenという名前でセッションのトークンが含まれたクエリを付けてリダイレクトします。 - section - h4 あなたのアプリがコールバックURLを設定していない場合 - p ユーザーがアプリの連携を許可したことを(何らかの方法で(たとえばボタンを押させるなど))確認出来るようにしてください。 - p - | 次に、#{api_url}/auth/session/userkeyapp_secretとしてApp Secretを、tokenとしてセッションのトークンをパラメータとして付与したリクエストを送信してください。 - br - | 上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます! - p - | 以降アクセストークンは、ユーザーのアクセストークン+アプリのシークレットキーをsha256したものとして扱います。 - - p アクセストークンを取得できたら、あとは簡単です。REST APIなら、リクエストにアクセストークンをiとしてパラメータに含めるだけです。 - - section - h2 リクエスト形式 - p application/jsonを受け付けます。 - p.tip - | 現在application/x-www-form-urlencodedも受け付けていますが、将来的にこのサポートはされなくなる予定です。 diff --git a/src/web/docs/api/library.md b/src/web/docs/api/library.md deleted file mode 100644 index 71ddbe345d..0000000000 --- a/src/web/docs/api/library.md +++ /dev/null @@ -1,8 +0,0 @@ -ライブラリ -================================================================ - -Misskey APIを便利に利用するためのライブラリ一覧です。 - -.NET ----------------------------------------------------------------- -* **[Misq (公式)](https://github.com/syuilo/Misq)** diff --git a/src/web/docs/layout.pug b/src/web/docs/layout.pug index f8570dd3ac..ac3743d2f4 100644 --- a/src/web/docs/layout.pug +++ b/src/web/docs/layout.pug @@ -3,28 +3,29 @@ doctype html html(lang= lang) head meta(charset="UTF-8") - meta(name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no") + meta(name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no") title | #{title} | Misskey Docs link(rel="stylesheet" href="/assets/docs/style.css") block meta + base(href=`/docs/${lang}/`) body nav ul each doc in common.docs - li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja'] + li: a(href=`./${doc.name}`)= doc.title[lang] || doc.title['ja'] section h2 API ul li Entities ul each entity in common.entities - li: a(href=`/docs/${lang}/api/entities/${common.kebab(entity)}`)= entity + li: a(href=`./api/entities/${common.kebab(entity)}`)= entity li Endpoints ul each endpoint in common.endpoints - li: a(href=`/docs/${lang}/api/endpoints/${common.kebab(endpoint)}`)= endpoint + li: a(href=`./api/endpoints/${common.kebab(endpoint)}`)= endpoint main block main if content diff --git a/src/web/docs/link-to-twitter.md b/src/web/docs/link-to-twitter.md deleted file mode 100644 index 77fb744576..0000000000 --- a/src/web/docs/link-to-twitter.md +++ /dev/null @@ -1,9 +0,0 @@ -Twitterと連携する -================================================================ - -設定 -> Twitter から、お使いのMisskeyアカウントとお使いのTwitterアカウントを関連付けることができます。 -アカウントの関連付けを行うと、プロフィールにTwitterアカウントへのリンクが表示されたりなどします。 - -MisskeyがあなたのTwitterアカウントでツイートしたり誰かをフォローしたりといったことは、 -一切行いませんのでご安心ください。(Misskeyはそのような権限を取得しないので、行おうと思っても行えません) -Twitterのアプリケーション認証フォームでこの権限の詳細を確認することができます。また、いつでも連携を取り消すことができます。 From 446b6a4f6bb376abdd6ebee5546f568d8c5dbc83 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 16 Dec 2017 05:04:02 +0900 Subject: [PATCH 092/186] :v: --- .../docs/api/endpoints/posts/timeline.yaml | 32 +++++++++++++++++++ src/web/docs/api/endpoints/view.pug | 7 ++-- src/web/docs/api/gulpfile.ts | 4 +-- 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/web/docs/api/endpoints/posts/timeline.yaml diff --git a/src/web/docs/api/endpoints/posts/timeline.yaml b/src/web/docs/api/endpoints/posts/timeline.yaml new file mode 100644 index 0000000000..e1d78c082e --- /dev/null +++ b/src/web/docs/api/endpoints/posts/timeline.yaml @@ -0,0 +1,32 @@ +endpoint: "posts/timeline" + +desc: + ja: "タイムラインを取得します。" + en: "Get your timeline." + +params: + - name: "limit" + type: "number" + optional: true + desc: + ja: "取得する最大の数" + - name: "since_id" + type: "id(Post)" + optional: true + desc: + ja: "指定すると、この投稿を基点としてより新しい投稿を取得します" + - name: "max_id" + type: "id(Post)" + optional: true + desc: + ja: "指定すると、この投稿を基点としてより古い投稿を取得します" + - name: "since_date" + type: "number" + optional: true + desc: + ja: "指定した時間を基点としてより新しい投稿を取得します。数値は、1970 年 1 月 1 日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。" + - name: "max_date" + type: "number" + optional: true + desc: + ja: "指定した時間を基点としてより古い投稿を取得します。数値は、1970 年 1 月 1 日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。" diff --git a/src/web/docs/api/endpoints/view.pug b/src/web/docs/api/endpoints/view.pug index d456022f6e..62a6f59edd 100644 --- a/src/web/docs/api/endpoints/view.pug +++ b/src/web/docs/api/endpoints/view.pug @@ -21,6 +21,7 @@ block main h3= paramDef.name +propTable(paramDef.params) - section - h2 Response - +propTable(res) + if res + section + h2 Response + +propTable(res) diff --git a/src/web/docs/api/gulpfile.ts b/src/web/docs/api/gulpfile.ts index 139ae92412..908280453c 100644 --- a/src/web/docs/api/gulpfile.ts +++ b/src/web/docs/api/gulpfile.ts @@ -106,8 +106,8 @@ gulp.task('doc:api:endpoints', () => { desc: ep.desc, params: sortParams(ep.params.map(p => parseParam(p))), paramDefs: extractDefs(ep.params), - res: sortParams(ep.res.map(p => parseParam(p))), - resDefs: extractDefs(ep.res), + res: ep.res ? sortParams(ep.res.map(p => parseParam(p))) : null, + resDefs: ep.res ? extractDefs(ep.res) : null, }; langs.forEach(lang => { pug.renderFile('./src/web/docs/api/endpoints/view.pug', Object.assign({}, vars, { From b563a67b8a504ce13d13d4b9d9fcb3744634e205 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 16 Dec 2017 22:28:51 +0900 Subject: [PATCH 093/186] v3390 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ab4698abe..a8e1fee789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3390 (2017/12/16) +----------------- +* ドキュメントなど + 3347 (2017/12/11) ----------------- * バグ修正 diff --git a/package.json b/package.json index 69090349e1..29ba72bbe4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3347", + "version": "0.0.3390", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 076956640871df99249e43e7df133f4f4e06043e Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 17 Dec 2017 01:41:22 +0900 Subject: [PATCH 094/186] :v: --- docs/setup.en.md | 2 +- docs/setup.ja.md | 2 +- gulpfile.ts | 15 ++++----------- package.json | 2 -- src/config.ts | 4 ++-- src/web/app/common/tags/introduction.tag | 2 +- src/web/app/common/tags/nav-links.tag | 5 ++++- src/web/app/common/tags/signup.tag | 4 +++- src/web/app/common/tags/twitter-setting.tag | 2 +- src/web/app/desktop/tags/pages/entrance.tag | 2 +- src/web/app/mobile/tags/ui.tag | 4 +++- src/web/docs/about.en.pug | 3 +++ src/web/docs/about.ja.pug | 3 +++ src/web/docs/api/endpoints/view.pug | 2 +- src/web/docs/api/entities/view.pug | 2 +- src/web/docs/api/mixins.pug | 4 ++-- src/web/docs/gulpfile.ts | 2 +- src/web/docs/layout.pug | 4 ++-- src/web/docs/server.ts | 21 +++++++++++++++++++++ src/web/docs/tou.ja.pug | 3 +++ src/web/docs/tou.md | 4 ---- src/web/server.ts | 11 +++++------ tools/letsencrypt/get-cert.sh | 2 +- webpack/plugins/consts.ts | 2 +- 24 files changed, 65 insertions(+), 42 deletions(-) create mode 100644 src/web/docs/about.en.pug create mode 100644 src/web/docs/about.ja.pug create mode 100644 src/web/docs/server.ts create mode 100644 src/web/docs/tou.ja.pug delete mode 100644 src/web/docs/tou.md diff --git a/docs/setup.en.md b/docs/setup.en.md index b81245d892..13b0bdaeb5 100644 --- a/docs/setup.en.md +++ b/docs/setup.en.md @@ -24,7 +24,7 @@ Note that Misskey uses following subdomains: * **api**.*{primary domain}* * **auth**.*{primary domain}* -* **about**.*{primary domain}* +* **docs**.*{primary domain}* * **ch**.*{primary domain}* * **stats**.*{primary domain}* * **status**.*{primary domain}* diff --git a/docs/setup.ja.md b/docs/setup.ja.md index 1662d1ee5a..564c790978 100644 --- a/docs/setup.ja.md +++ b/docs/setup.ja.md @@ -25,7 +25,7 @@ Misskeyは以下のサブドメインを使います: * **api**.*{primary domain}* * **auth**.*{primary domain}* -* **about**.*{primary domain}* +* **docs**.*{primary domain}* * **ch**.*{primary domain}* * **stats**.*{primary domain}* * **status**.*{primary domain}* diff --git a/gulpfile.ts b/gulpfile.ts index e7d4770610..3b7a126407 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -9,7 +9,6 @@ import * as gulp from 'gulp'; import * as gutil from 'gulp-util'; import * as ts from 'gulp-typescript'; import tslint from 'gulp-tslint'; -import * as es from 'event-stream'; import cssnano = require('gulp-cssnano'); import * as uglifyComposer from 'gulp-uglify/composer'; import pug = require('gulp-pug'); @@ -74,16 +73,10 @@ gulp.task('build:ts', () => { }); gulp.task('build:copy', () => - es.merge( - gulp.src([ - './src/**/assets/**/*', - '!./src/web/app/**/assets/**/*' - ]).pipe(gulp.dest('./built/')) as any, - gulp.src([ - './src/web/about/**/*', - '!./src/web/about/**/*.pug' - ]).pipe(gulp.dest('./built/web/about/')) as any - ) + gulp.src([ + './src/**/assets/**/*', + '!./src/web/app/**/assets/**/*' + ]).pipe(gulp.dest('./built/')) ); gulp.task('test', ['lint', 'mocha']); diff --git a/package.json b/package.json index 29ba72bbe4..8c0cf340db 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "@types/debug": "0.0.30", "@types/deep-equal": "1.0.1", "@types/elasticsearch": "5.0.19", - "@types/event-stream": "3.3.33", "@types/eventemitter3": "2.0.2", "@types/express": "4.0.39", "@types/gm": "1.17.33", @@ -99,7 +98,6 @@ "diskusage": "0.2.4", "elasticsearch": "14.0.0", "escape-regexp": "0.0.1", - "event-stream": "3.3.4", "eventemitter3": "3.0.0", "exif-js": "2.3.0", "express": "4.16.2", diff --git a/src/config.ts b/src/config.ts index 3ff8007586..3ffefe278b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -101,7 +101,7 @@ type Mixin = { secondary_scheme: string; api_url: string; auth_url: string; - about_url: string; + docs_url: string; ch_url: string; stats_url: string; status_url: string; @@ -131,7 +131,7 @@ export default function load() { mixin.auth_url = `${mixin.scheme}://auth.${mixin.host}`; mixin.ch_url = `${mixin.scheme}://ch.${mixin.host}`; mixin.dev_url = `${mixin.scheme}://dev.${mixin.host}`; - mixin.about_url = `${mixin.scheme}://about.${mixin.host}`; + mixin.docs_url = `${mixin.scheme}://docs.${mixin.host}`; mixin.stats_url = `${mixin.scheme}://stats.${mixin.host}`; mixin.status_url = `${mixin.scheme}://status.${mixin.host}`; mixin.drive_url = `${mixin.secondary_scheme}://file.${mixin.secondary_host}`; diff --git a/src/web/app/common/tags/introduction.tag b/src/web/app/common/tags/introduction.tag index 3256688d10..28afc6fa46 100644 --- a/src/web/app/common/tags/introduction.tag +++ b/src/web/app/common/tags/introduction.tag @@ -3,7 +3,7 @@

    Misskeyとは?

    Misskeyみすきーは、syuiloが2014年くらいからオープンソースで開発・運営を行っている、ミニブログベースのSNSです。

    無料で誰でも利用でき、広告も掲載していません。

    -

    もっと知りたい方はこちら

    +

    もっと知りたい方はこちら

    + diff --git a/src/web/app/common/tags/signup.tag b/src/web/app/common/tags/signup.tag index 4816fe66db..b488efb927 100644 --- a/src/web/app/common/tags/signup.tag +++ b/src/web/app/common/tags/signup.tag @@ -34,7 +34,7 @@ @@ -182,6 +182,8 @@ this.passwordRetypeState = null; this.recaptchaed = false; + this.aboutUrl = `${_DOCS_URL_}/${_LANG_}/tou`; + window.onRecaptchaed = () => { this.recaptchaed = true; this.update(); diff --git a/src/web/app/common/tags/twitter-setting.tag b/src/web/app/common/tags/twitter-setting.tag index 3b70505ba2..4d57cfa55a 100644 --- a/src/web/app/common/tags/twitter-setting.tag +++ b/src/web/app/common/tags/twitter-setting.tag @@ -1,5 +1,5 @@ -

    %i18n:common.tags.mk-twitter-setting.description%%i18n:common.tags.mk-twitter-setting.detail%

    +

    %i18n:common.tags.mk-twitter-setting.description%%i18n:common.tags.mk-twitter-setting.detail%

    { I.twitter ? '%i18n:common.tags.mk-twitter-setting.reconnect%' : '%i18n:common.tags.mk-twitter-setting.connect%' } diff --git a/src/web/app/desktop/tags/pages/entrance.tag b/src/web/app/desktop/tags/pages/entrance.tag index 44548e4183..b07b22c80c 100644 --- a/src/web/app/desktop/tags/pages/entrance.tag +++ b/src/web/app/desktop/tags/pages/entrance.tag @@ -150,7 +150,7 @@ - %fa:question% + %fa:question%

    { user ? user.name : 'アカウント' }

    diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag index 62e128489a..621f89f336 100644 --- a/src/web/app/mobile/tags/ui.tag +++ b/src/web/app/mobile/tags/ui.tag @@ -248,7 +248,7 @@
  • %fa:cog%%i18n:mobile.tags.mk-ui-nav.settings%%fa:angle-right%
-

%i18n:mobile.tags.mk-ui-nav.about%

+

%i18n:mobile.tags.mk-ui-nav.about%

- diff --git a/src/web/app/common/tags/index.ts b/src/web/app/common/tags/index.ts index 2f4e1181d4..df99d93cc5 100644 --- a/src/web/app/common/tags/index.ts +++ b/src/web/app/common/tags/index.ts @@ -12,7 +12,6 @@ require('./signin.tag'); require('./signup.tag'); require('./forkit.tag'); require('./introduction.tag'); -require('./copyright.tag'); require('./signin-history.tag'); require('./twitter-setting.tag'); require('./authorized-apps.tag'); diff --git a/src/web/app/desktop/tags/pages/entrance.tag b/src/web/app/desktop/tags/pages/entrance.tag index b07b22c80c..974f49a4fe 100644 --- a/src/web/app/desktop/tags/pages/entrance.tag +++ b/src/web/app/desktop/tags/pages/entrance.tag @@ -18,7 +18,7 @@
- +

{ _COPYRIGHT_ }

@@ -101,7 +101,7 @@ text-align center border-top solid 1px #fff - > mk-copyright + > .c margin 0 line-height 64px font-size 10px diff --git a/src/web/app/mobile/tags/page/entrance.tag b/src/web/app/mobile/tags/page/entrance.tag index 380fb780bc..191874caf9 100644 --- a/src/web/app/mobile/tags/page/entrance.tag +++ b/src/web/app/mobile/tags/page/entrance.tag @@ -8,7 +8,7 @@
- +

{ _COPYRIGHT_ }

diff --git a/src/web/app/mobile/router.ts b/src/web/app/mobile/router.ts index d0c6add0b8..afb9aa6201 100644 --- a/src/web/app/mobile/router.ts +++ b/src/web/app/mobile/router.ts @@ -23,7 +23,7 @@ export default (mios: MiOS) => { route('/i/settings/authorized-apps', settingsAuthorizedApps); route('/post/new', newPost); route('/post::post', post); - route('/search::query', search); + route('/search', search); route('/:user', user.bind(null, 'overview')); route('/:user/graphs', user.bind(null, 'graphs')); route('/:user/followers', userFollowers); @@ -83,7 +83,7 @@ export default (mios: MiOS) => { function search(ctx) { const el = document.createElement('mk-search-page'); - el.setAttribute('query', ctx.params.query); + el.setAttribute('query', ctx.querystring.substr(2)); mount(el); } diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag index 967764bc2c..023a35bf62 100644 --- a/src/web/app/mobile/tags/search-posts.tag +++ b/src/web/app/mobile/tags/search-posts.tag @@ -15,6 +15,8 @@ width calc(100% - 32px) diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug new file mode 100644 index 0000000000..f7ec9519f5 --- /dev/null +++ b/src/web/docs/search.ja.pug @@ -0,0 +1,38 @@ +h1 検索 + +p 投稿を検索することができます。 +p + | キーワードを半角スペースで区切ると、and検索になります。 + | 例えば、「git コミット」と検索すると、「gitで編集したファイルの特定の行だけコミットする方法がわからない」などがマッチします。 + +section + h2 オプション + p + | オプションを使用して、より高度な検索をすることもできます。 + | オプションを指定するには、「オプション名:値」という形式でクエリに含めます。 + p 利用可能なオプション一覧です: + + table + thead + tr + th 名前 + th 説明 + tbody + tr + td user + td ユーザー名。投稿者を限定します。 + tr + td reply + td 返信を含めるか否か。(trueかfalse) + tr + td media + td メディアが添付されているか。(trueかfalse) + tr + td until + td 上限の日時。(YYYY-MM-DD) + tr + td since + td 下限の日時。(YYYY-MM-DD) + + p 例えば、「@syuiloの2017年11月1日から2017年12月31日までの『Misskey』というテキストを含む返信ではない投稿」を検索したい場合、クエリは以下のようになります: + code user:syuilo since:2017-11-01 until:2017-12-31 reply:false Misskey From 1b5d788c6c480937da81fba2a5af5f670c598dca Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2017 04:02:46 +0900 Subject: [PATCH 116/186] v3420 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd4f2c1f1b..c8687534bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3420 (2017/12/21) +----------------- +* 検索機能を大幅に強化 + 3415 (2017/12/19) ----------------- * デザインの調整 diff --git a/package.json b/package.json index 39922127ce..6ab49852bd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3415", + "version": "0.0.3420", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 59120063fe792ba0bc230749a36b1e4acf86443f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 06:31:56 +0900 Subject: [PATCH 117/186] #1023 --- src/api/endpoints/posts/search.ts | 21 ++++++++++++++++--- .../app/common/scripts/parse-search-query.ts | 3 +++ src/web/docs/search.ja.pug | 3 +++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index dba7a53b5f..88cdd32dac 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -6,6 +6,7 @@ import $ from 'cafy'; const escapeRegexp = require('escape-regexp'); import Post from '../../models/post'; import User from '../../models/user'; +import getFriends from '../../common/get-friends'; import serialize from '../../serializers/post'; import config from '../../../conf'; @@ -29,6 +30,10 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [username, usernameErr] = $(params.username).optional.string().$; if (usernameErr) return rej('invalid username param'); + // Get 'following' parameter + const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$; + if (followingErr) return rej('invalid following param'); + // Get 'include_replies' parameter const [includeReplies = true, includeRepliesErr] = $(params.include_replies).optional.boolean().$; if (includeRepliesErr) return rej('invalid include_replies param'); @@ -67,11 +72,11 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // If Elasticsearch is available, search by it // If not, search by MongoDB (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, text, user, includeReplies, withMedia, sinceDate, untilDate, offset, limit); + (res, rej, me, text, user, following, includeReplies, withMedia, sinceDate, untilDate, offset, limit); }); // Search by MongoDB -async function byNative(res, rej, me, text, userId, includeReplies, withMedia, sinceDate, untilDate, offset, max) { +async function byNative(res, rej, me, text, userId, following, includeReplies, withMedia, sinceDate, untilDate, offset, max) { const q: any = {}; if (text) { @@ -84,6 +89,16 @@ async function byNative(res, rej, me, text, userId, includeReplies, withMedia, s q.user_id = userId; } + if (following != null) { + const ids = await getFriends(me._id, false); + q.user_id = {}; + if (following) { + q.user_id.$in = ids; + } else { + q.user_id.$nin = ids; + } + } + if (!includeReplies) { q.reply_id = null; } @@ -122,7 +137,7 @@ async function byNative(res, rej, me, text, userId, includeReplies, withMedia, s } // Search by Elasticsearch -async function byElasticsearch(res, rej, me, text, userId, includeReplies, withMedia, sinceDate, untilDate, offset, max) { +async function byElasticsearch(res, rej, me, text, userId, following, includeReplies, withMedia, sinceDate, untilDate, offset, max) { const es = require('../../db/elasticsearch'); es.search({ diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts index adcbfbb8fe..62b2cf51b1 100644 --- a/src/web/app/common/scripts/parse-search-query.ts +++ b/src/web/app/common/scripts/parse-search-query.ts @@ -10,6 +10,9 @@ export default function(qs: string) { case 'user': q['username'] = value; break; + case 'follow': + q['following'] = value == 'null' ? null : value == 'true'; + break; case 'reply': q['include_replies'] = value == 'true'; break; diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index f7ec9519f5..7d4d23fb6a 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -21,6 +21,9 @@ section tr td user td ユーザー名。投稿者を限定します。 + tr + td follow + td フォローしているユーザーのみに限定。(trueかfalse) tr td reply td 返信を含めるか否か。(trueかfalse) From 143a30295d9943a9b5bc4111f995911fe6e5c042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 06:33:03 +0900 Subject: [PATCH 118/186] v3422 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8687534bd..4159d025e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3422 (2017/12/21) +----------------- +* 検索にfollow追加 #1023 + 3420 (2017/12/21) ----------------- * 検索機能を大幅に強化 diff --git a/package.json b/package.json index 6ab49852bd..54fbd9e993 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3420", + "version": "0.0.3422", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 40f5e67ff0f803fab117c405a0614df915381433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 07:35:16 +0900 Subject: [PATCH 119/186] :v: --- src/api/endpoints/posts/search.ts | 130 ++++++++++++++---- .../app/common/scripts/parse-search-query.ts | 7 +- src/web/docs/search.ja.pug | 29 +++- 3 files changed, 131 insertions(+), 35 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 88cdd32dac..21e9134d38 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -34,13 +34,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$; if (followingErr) return rej('invalid following param'); - // Get 'include_replies' parameter - const [includeReplies = true, includeRepliesErr] = $(params.include_replies).optional.boolean().$; - if (includeRepliesErr) return rej('invalid include_replies param'); + // Get 'reply' parameter + const [reply = null, replyErr] = $(params.reply).optional.nullable.boolean().$; + if (replyErr) return rej('invalid reply param'); - // Get 'with_media' parameter - const [withMedia = false, withMediaErr] = $(params.with_media).optional.boolean().$; - if (withMediaErr) return rej('invalid with_media param'); + // Get 'repost' parameter + const [repost = null, repostErr] = $(params.repost).optional.nullable.boolean().$; + if (repostErr) return rej('invalid repost param'); + + // Get 'media' parameter + const [media = null, mediaErr] = $(params.media).optional.nullable.boolean().$; + if (mediaErr) return rej('invalid media param'); // Get 'since_date' parameter const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$; @@ -72,53 +76,119 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // If Elasticsearch is available, search by it // If not, search by MongoDB (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, text, user, following, includeReplies, withMedia, sinceDate, untilDate, offset, limit); + (res, rej, me, text, user, following, reply, repost, media, sinceDate, untilDate, offset, limit); }); // Search by MongoDB -async function byNative(res, rej, me, text, userId, following, includeReplies, withMedia, sinceDate, untilDate, offset, max) { - const q: any = {}; +async function byNative(res, rej, me, text, userId, following, reply, repost, media, sinceDate, untilDate, offset, max) { + const q: any = { + $and: [] + }; + + const push = q.$and.push; if (text) { - q.$and = text.split(' ').map(x => ({ - text: new RegExp(escapeRegexp(x)) - })); + push({ + $and: text.split(' ').map(x => ({ + text: new RegExp(escapeRegexp(x)) + })) + }); } if (userId) { - q.user_id = userId; + push({ + user_id: userId + }); } if (following != null) { const ids = await getFriends(me._id, false); - q.user_id = {}; - if (following) { - q.user_id.$in = ids; + push({ + user_id: following ? { + $in: ids + } : { + $nin: ids + } + }); + } + + if (reply != null) { + if (reply) { + push({ + reply_id: { + $exists: true, + $ne: null + } + }); } else { - q.user_id.$nin = ids; + push({ + $or: [{ + reply_id: { + $exists: false + } + }, { + reply_id: null + }] + }); } } - if (!includeReplies) { - q.reply_id = null; + if (repost != null) { + if (repost) { + push({ + repost_id: { + $exists: true, + $ne: null + } + }); + } else { + push({ + $or: [{ + repost_id: { + $exists: false + } + }, { + repost_id: null + }] + }); + } } - if (withMedia) { - q.media_ids = { - $exists: true, - $ne: null - }; + if (media != null) { + if (media) { + push({ + media_ids: { + $exists: true, + $ne: null + } + }); + } else { + push({ + $or: [{ + media_ids: { + $exists: false + } + }, { + media_ids: null + }] + }); + } } if (sinceDate) { - q.created_at = { - $gt: new Date(sinceDate) - }; + push({ + created_at: { + $gt: new Date(sinceDate) + } + }); } if (untilDate) { - if (q.created_at == undefined) q.created_at = {}; - q.created_at.$lt = new Date(untilDate); + push({ + created_at: { + $lt: new Date(untilDate) + } + }); } // Search posts @@ -137,7 +207,7 @@ async function byNative(res, rej, me, text, userId, following, includeReplies, w } // Search by Elasticsearch -async function byElasticsearch(res, rej, me, text, userId, following, includeReplies, withMedia, sinceDate, untilDate, offset, max) { +async function byElasticsearch(res, rej, me, text, userId, following, reply, repost, media, sinceDate, untilDate, offset, max) { const es = require('../../db/elasticsearch'); es.search({ diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts index 62b2cf51b1..f65e4683a6 100644 --- a/src/web/app/common/scripts/parse-search-query.ts +++ b/src/web/app/common/scripts/parse-search-query.ts @@ -14,10 +14,13 @@ export default function(qs: string) { q['following'] = value == 'null' ? null : value == 'true'; break; case 'reply': - q['include_replies'] = value == 'true'; + q['reply'] = value == 'null' ? null : value == 'true'; + break; + case 'repost': + q['repost'] = value == 'null' ? null : value == 'true'; break; case 'media': - q['with_media'] = value == 'true'; + q['media'] = value == 'null' ? null : value == 'true'; break; case 'until': case 'since': diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 7d4d23fb6a..d46e5f4a04 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -23,13 +23,36 @@ section td ユーザー名。投稿者を限定します。 tr td follow - td フォローしているユーザーのみに限定。(trueかfalse) + td + | true ... フォローしているユーザーに限定。 + br + | false ... フォローしていないユーザーに限定。 + br + | null ... 特に限定しない(デフォルト) tr td reply - td 返信を含めるか否か。(trueかfalse) + td + | true ... 返信に限定。 + br + | false ... 返信でない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) + tr + td repost + td + | true ... Repostに限定。 + br + | false ... Repostでない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) tr td media - td メディアが添付されているか。(trueかfalse) + td + | true ... メディアが添付されている投稿に限定。 + br + | false ... メディアが添付されていない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) tr td until td 上限の日時。(YYYY-MM-DD) From ef08c78b8153e5bc33c0087b18acac505b8956f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 07:35:23 +0900 Subject: [PATCH 120/186] v3424 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4159d025e1..c33ecddb15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3424 (2017/12/21) +----------------- +* 検索にrepost追加 +* など + 3422 (2017/12/21) ----------------- * 検索にfollow追加 #1023 diff --git a/package.json b/package.json index 54fbd9e993..a85ffded04 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3422", + "version": "0.0.3424", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From b2223c19e18ee5884ea13ec0d33f3ddb1ac9ea27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 07:45:45 +0900 Subject: [PATCH 121/186] Fix bug --- src/api/endpoints/posts/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 21e9134d38..a3c44d09ce 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -85,7 +85,7 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me $and: [] }; - const push = q.$and.push; + const push = x => q.$and.push(x); if (text) { push({ From aff76a57c0d123b992d7284faba6c5a146985246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 07:57:31 +0900 Subject: [PATCH 122/186] :v: --- src/api/endpoints/posts/search.ts | 31 +++++++++++++++++-- .../app/common/scripts/parse-search-query.ts | 3 ++ src/web/docs/search.ja.pug | 8 +++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index a3c44d09ce..777cd7909a 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -46,6 +46,10 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [media = null, mediaErr] = $(params.media).optional.nullable.boolean().$; if (mediaErr) return rej('invalid media param'); + // Get 'poll' parameter + const [poll = null, pollErr] = $(params.poll).optional.nullable.boolean().$; + if (pollErr) return rej('invalid poll param'); + // Get 'since_date' parameter const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$; if (sinceDateErr) throw 'invalid since_date param'; @@ -76,11 +80,11 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // If Elasticsearch is available, search by it // If not, search by MongoDB (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, text, user, following, reply, repost, media, sinceDate, untilDate, offset, limit); + (res, rej, me, text, user, following, reply, repost, media, poll, sinceDate, untilDate, offset, limit); }); // Search by MongoDB -async function byNative(res, rej, me, text, userId, following, reply, repost, media, sinceDate, untilDate, offset, max) { +async function byNative(res, rej, me, text, userId, following, reply, repost, media, poll, sinceDate, untilDate, offset, max) { const q: any = { $and: [] }; @@ -175,6 +179,27 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me } } + if (poll != null) { + if (poll) { + push({ + poll: { + $exists: true, + $ne: null + } + }); + } else { + push({ + $or: [{ + poll: { + $exists: false + } + }, { + poll: null + }] + }); + } + } + if (sinceDate) { push({ created_at: { @@ -207,7 +232,7 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me } // Search by Elasticsearch -async function byElasticsearch(res, rej, me, text, userId, following, reply, repost, media, sinceDate, untilDate, offset, max) { +async function byElasticsearch(res, rej, me, text, userId, following, reply, repost, media, poll, sinceDate, untilDate, offset, max) { const es = require('../../db/elasticsearch'); es.search({ diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts index f65e4683a6..c021ee6417 100644 --- a/src/web/app/common/scripts/parse-search-query.ts +++ b/src/web/app/common/scripts/parse-search-query.ts @@ -22,6 +22,9 @@ export default function(qs: string) { case 'media': q['media'] = value == 'null' ? null : value == 'true'; break; + case 'poll': + q['poll'] = value == 'null' ? null : value == 'true'; + break; case 'until': case 'since': // YYYY-MM-DD diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index d46e5f4a04..41e443d746 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -53,6 +53,14 @@ section | false ... メディアが添付されていない投稿に限定。 br | null ... 特に限定しない(デフォルト) + tr + td poll + td + | true ... 投票が添付されている投稿に限定。 + br + | false ... 投票が添付されていない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) tr td until td 上限の日時。(YYYY-MM-DD) From 42cfe26f19a9e3490dd33f18679433c3e80937ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 07:58:04 +0900 Subject: [PATCH 123/186] v3426 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c33ecddb15..ff417fde95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3426 (2017/12/21) +----------------- +* 検索にpoll追加 + 3424 (2017/12/21) ----------------- * 検索にrepost追加 diff --git a/package.json b/package.json index a85ffded04..d3960472dc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3424", + "version": "0.0.3426", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 169142cec3e10f157b43342267e22c11f890ff29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 11:08:17 +0900 Subject: [PATCH 124/186] Fix #1025 --- src/web/app/desktop/tags/search-posts.tag | 13 +++++++------ src/web/app/mobile/tags/search-posts.tag | 10 ++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag index c6b24837d2..2acb675d44 100644 --- a/src/web/app/desktop/tags/search-posts.tag +++ b/src/web/app/desktop/tags/search-posts.tag @@ -41,7 +41,8 @@ this.isLoading = true; this.isEmpty = false; this.moreLoading = false; - this.page = 0; + this.limit = 30; + this.offset = 0; this.on('mount', () => { document.addEventListener('keydown', this.onDocumentKeydown); @@ -72,16 +73,16 @@ this.more = () => { if (this.moreLoading || this.isLoading || this.timeline.posts.length == 0) return; + this.offset += this.limit; this.update({ moreLoading: true }); - this.api('posts/search', { - query: this.query, - page: this.page + 1 + return this.api('posts/search', Object.assign({}, parse(this.query), { + limit: this.limit, + offset: this.offset }).then(posts => { this.update({ - moreLoading: false, - page: page + 1 + moreLoading: false }); this.refs.timeline.prependPosts(posts); }); diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag index 023a35bf62..b37ba69e85 100644 --- a/src/web/app/mobile/tags/search-posts.tag +++ b/src/web/app/mobile/tags/search-posts.tag @@ -19,11 +19,10 @@ this.mixin('api'); - this.max = 30; + this.limit = 30; this.offset = 0; this.query = this.opts.query; - this.withMedia = this.opts.withMedia; this.init = new Promise((res, rej) => { this.api('posts/search', parse(this.query)).then(posts => { @@ -33,10 +32,9 @@ }); this.more = () => { - this.offset += this.max; - return this.api('posts/search', { - query: this.query, - max: this.max, + this.offset += this.limit; + return this.api('posts/search', Object.assign({}, parse(this.query), { + limit: this.limit, offset: this.offset }); }; From 72295b246414dbd29b860f84cab65bb8e137edc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 11:09:39 +0900 Subject: [PATCH 125/186] v3428 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff417fde95..db21a15d4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3428 (2017/12/21) +----------------- +* バグ修正 + 3426 (2017/12/21) ----------------- * 検索にpoll追加 diff --git a/package.json b/package.json index d3960472dc..c3dc9da45d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3426", + "version": "0.0.3428", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From f7d3b2c6ec8b467390bd030ddf7215a09610faad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 11:13:49 +0900 Subject: [PATCH 126/186] oops --- src/web/app/desktop/tags/search-posts.tag | 2 +- src/web/app/mobile/tags/search-posts.tag | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/app/desktop/tags/search-posts.tag b/src/web/app/desktop/tags/search-posts.tag index 2acb675d44..f7ec85a4fe 100644 --- a/src/web/app/desktop/tags/search-posts.tag +++ b/src/web/app/desktop/tags/search-posts.tag @@ -80,7 +80,7 @@ return this.api('posts/search', Object.assign({}, parse(this.query), { limit: this.limit, offset: this.offset - }).then(posts => { + })).then(posts => { this.update({ moreLoading: false }); diff --git a/src/web/app/mobile/tags/search-posts.tag b/src/web/app/mobile/tags/search-posts.tag index b37ba69e85..3e3c034f21 100644 --- a/src/web/app/mobile/tags/search-posts.tag +++ b/src/web/app/mobile/tags/search-posts.tag @@ -36,7 +36,7 @@ return this.api('posts/search', Object.assign({}, parse(this.query), { limit: this.limit, offset: this.offset - }); + })); }; From 52287878b7098c15b18cf2b75be9c526fc88cd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 11:14:16 +0900 Subject: [PATCH 127/186] v3430 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db21a15d4b..c253d1f110 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3430 (2017/12/21) +----------------- +* oops + 3428 (2017/12/21) ----------------- * バグ修正 diff --git a/package.json b/package.json index c3dc9da45d..b43f5be70c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3428", + "version": "0.0.3430", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 0dc97370a34d88c9274f5a89f1714d7ce99f7a25 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2017 15:28:50 +0900 Subject: [PATCH 128/186] Fix bug --- src/api/endpoints/posts/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 777cd7909a..bd3bbfc12e 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -105,7 +105,7 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me }); } - if (following != null) { + if (following != null && me != null) { const ids = await getFriends(me._id, false); push({ user_id: following ? { From fd28d1bcc325ad22afc8584fc9fe6e9091d0524a Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2017 15:30:15 +0900 Subject: [PATCH 129/186] #1026 --- src/api/endpoints/posts/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index bd3bbfc12e..16d54f729f 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -111,7 +111,7 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me user_id: following ? { $in: ids } : { - $nin: ids + $nin: ids.concat(me._id) } }); } From 41623f85901437631707c308e0550b9be8e7b782 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2017 15:37:26 +0900 Subject: [PATCH 130/186] Fix bug --- src/api/endpoints/posts/search.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 16d54f729f..ac25652a0b 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -85,7 +85,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Search by MongoDB async function byNative(res, rej, me, text, userId, following, reply, repost, media, poll, sinceDate, untilDate, offset, max) { - const q: any = { + let q: any = { $and: [] }; @@ -216,6 +216,10 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me }); } + if (q.$and.length == 0) { + q = {}; + } + // Search posts const posts = await Post .find(q, { From 8fd78aebbf01755ffdecb9aa17dff1f842b194ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Fri, 22 Dec 2017 04:50:50 +0900 Subject: [PATCH 131/186] wip --- src/api/endpoints/posts/timeline.ts | 12 +++++++++++- src/api/models/mute.ts | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/api/models/mute.ts diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 91cba0a047..6cc7825e64 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -77,7 +77,17 @@ module.exports = async (params, user, app) => { channel_id: { $in: watchingChannelIds } - }] + }], + // mute + user_id: { + $nin: mutes + }, + '_reply.user_id': { + $nin: mutes + }, + '_repost.user_id': { + $nin: mutes + }, } as any; if (sinceId) { diff --git a/src/api/models/mute.ts b/src/api/models/mute.ts new file mode 100644 index 0000000000..16018b82f7 --- /dev/null +++ b/src/api/models/mute.ts @@ -0,0 +1,3 @@ +import db from '../../db/mongodb'; + +export default db.get('mute') as any; // fuck type definition From 11e05a3a3298ea072f24ece0ad7a5c8c00bb1b23 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 05:41:21 +0900 Subject: [PATCH 132/186] wip --- src/api/endpoints/posts/create.ts | 6 +- tools/migration/node.2017-12-22.hiseikika.js | 67 ++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tools/migration/node.2017-12-22.hiseikika.js diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 7270efaf71..9d791538fe 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -215,7 +215,11 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { poll: poll, text: text, user_id: user._id, - app_id: app ? app._id : null + app_id: app ? app._id : null, + + // 以下非正規化データ + _reply: reply ? { user_id: reply.user_id } : undefined, + _repost: repost ? { user_id: repost.user_id } : undefined, }); // Serialize diff --git a/tools/migration/node.2017-12-22.hiseikika.js b/tools/migration/node.2017-12-22.hiseikika.js new file mode 100644 index 0000000000..ff8294c8d1 --- /dev/null +++ b/tools/migration/node.2017-12-22.hiseikika.js @@ -0,0 +1,67 @@ +// for Node.js interpret + +const { default: Post } = require('../../built/api/models/post') +const { default: zip } = require('@prezzemolo/zip') + +const migrate = async (post) => { + const x = {}; + if (post.reply_id != null) { + const reply = await Post.findOne({ + _id: post.reply_id + }); + x['_reply.user_id'] = reply.user_id; + } + if (post.repost_id != null) { + const repost = await Post.findOne({ + _id: post.repost_id + }); + x['_repost.user_id'] = repost.user_id; + } + if (post.reply_id != null || post.repost_id != null) { + const result = await Post.update(post._id, { + $set: x, + }); + return result.ok === 1; + } else { + return true; + } +} + +async function main() { + const query = { + $or: [{ + reply_id: { + $exists: true, + $ne: null + } + }, { + repost_id: { + $exists: true, + $ne: null + } + }] + } + + const count = await Post.count(query); + + const dop = Number.parseInt(process.argv[2]) || 5 + const idop = ((count - (count % dop)) / dop) + 1 + + return zip( + 1, + async (time) => { + console.log(`${time} / ${idop}`) + const doc = await Post.find(query, { + limit: dop, skip: time * dop + }) + return Promise.all(doc.map(migrate)) + }, + idop + ).then(a => { + const rv = [] + a.forEach(e => rv.push(...e)) + return rv + }) +} + +main().then(console.dir).catch(console.error) From a134aa5a81ea2c443153b3723abf662a8069e36a Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 06:03:54 +0900 Subject: [PATCH 133/186] wip --- src/api/endpoints.ts | 17 +++++++ src/api/endpoints/mute/create.ts | 61 ++++++++++++++++++++++++ src/api/endpoints/mute/delete.ts | 63 +++++++++++++++++++++++++ src/api/endpoints/mute/list.ts | 73 +++++++++++++++++++++++++++++ src/api/endpoints/posts/timeline.ts | 19 ++++++-- 5 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 src/api/endpoints/mute/create.ts create mode 100644 src/api/endpoints/mute/delete.ts create mode 100644 src/api/endpoints/mute/list.ts diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index 1138df193b..e846381578 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -222,6 +222,23 @@ const endpoints: Endpoint[] = [ withCredential: true, kind: 'notification-read' }, + + { + name: 'mute/create', + withCredential: true, + kind: 'account/write' + }, + { + name: 'mute/delete', + withCredential: true, + kind: 'account/write' + }, + { + name: 'mute/list', + withCredential: true, + kind: 'account/read' + }, + { name: 'notifications/get_unread_count', withCredential: true, diff --git a/src/api/endpoints/mute/create.ts b/src/api/endpoints/mute/create.ts new file mode 100644 index 0000000000..f44854ab52 --- /dev/null +++ b/src/api/endpoints/mute/create.ts @@ -0,0 +1,61 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import User from '../../models/user'; +import Mute from '../../models/mute'; + +/** + * Mute a user + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + const muter = user; + + // Get 'user_id' parameter + const [userId, userIdErr] = $(params.user_id).id().$; + if (userIdErr) return rej('invalid user_id param'); + + // 自分自身 + if (user._id.equals(userId)) { + return rej('mutee is yourself'); + } + + // Get mutee + const mutee = await User.findOne({ + _id: userId + }, { + fields: { + data: false, + profile: false + } + }); + + if (mutee === null) { + return rej('user not found'); + } + + // Check if already muting + const exist = await Mute.findOne({ + muter_id: muter._id, + mutee_id: mutee._id, + deleted_at: { $exists: false } + }); + + if (exist !== null) { + return rej('already muting'); + } + + // Create mute + await Mute.insert({ + created_at: new Date(), + muter_id: muter._id, + mutee_id: mutee._id, + }); + + // Send response + res(); +}); diff --git a/src/api/endpoints/mute/delete.ts b/src/api/endpoints/mute/delete.ts new file mode 100644 index 0000000000..d6bff3353a --- /dev/null +++ b/src/api/endpoints/mute/delete.ts @@ -0,0 +1,63 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import User from '../../models/user'; +import Mute from '../../models/mute'; + +/** + * Unmute a user + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + const muter = user; + + // Get 'user_id' parameter + const [userId, userIdErr] = $(params.user_id).id().$; + if (userIdErr) return rej('invalid user_id param'); + + // Check if the mutee is yourself + if (user._id.equals(userId)) { + return rej('mutee is yourself'); + } + + // Get mutee + const mutee = await User.findOne({ + _id: userId + }, { + fields: { + data: false, + profile: false + } + }); + + if (mutee === null) { + return rej('user not found'); + } + + // Check not muting + const exist = await Mute.findOne({ + muter_id: muter._id, + mutee_id: mutee._id, + deleted_at: { $exists: false } + }); + + if (exist === null) { + return rej('already not muting'); + } + + // Delete mute + await Mute.update({ + _id: exist._id + }, { + $set: { + deleted_at: new Date() + } + }); + + // Send response + res(); +}); diff --git a/src/api/endpoints/mute/list.ts b/src/api/endpoints/mute/list.ts new file mode 100644 index 0000000000..740e19f0bb --- /dev/null +++ b/src/api/endpoints/mute/list.ts @@ -0,0 +1,73 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import Mute from '../../models/mute'; +import serialize from '../../serializers/user'; +import getFriends from '../../common/get-friends'; + +/** + * Get muted users of a user + * + * @param {any} params + * @param {any} me + * @return {Promise} + */ +module.exports = (params, me) => new Promise(async (res, rej) => { + // Get 'iknow' parameter + const [iknow = false, iknowErr] = $(params.iknow).optional.boolean().$; + if (iknowErr) return rej('invalid iknow param'); + + // Get 'limit' parameter + const [limit = 30, limitErr] = $(params.limit).optional.number().range(1, 100).$; + if (limitErr) return rej('invalid limit param'); + + // Get 'cursor' parameter + const [cursor = null, cursorErr] = $(params.cursor).optional.id().$; + if (cursorErr) return rej('invalid cursor param'); + + // Construct query + const query = { + muter_id: me._id, + deleted_at: { $exists: false } + } as any; + + if (iknow) { + // Get my friends + const myFriends = await getFriends(me._id); + + query.mutee_id = { + $in: myFriends + }; + } + + // カーソルが指定されている場合 + if (cursor) { + query._id = { + $lt: cursor + }; + } + + // Get mutes + const mutes = await Mute + .find(query, { + limit: limit + 1, + sort: { _id: -1 } + }); + + // 「次のページ」があるかどうか + const inStock = mutes.length === limit + 1; + if (inStock) { + mutes.pop(); + } + + // Serialize + const users = await Promise.all(mutes.map(async m => + await serialize(m.mutee_id, me, { detail: true }))); + + // Response + res({ + users: users, + next: inStock ? mutes[mutes.length - 1]._id : null, + }); +}); diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 6cc7825e64..da7ffd0c14 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -4,6 +4,7 @@ import $ from 'cafy'; import rap from '@prezzemolo/rap'; import Post from '../../models/post'; +import Mute from '../../models/mute'; import ChannelWatching from '../../models/channel-watching'; import getFriends from '../../common/get-friends'; import serialize from '../../serializers/post'; @@ -42,15 +43,23 @@ module.exports = async (params, user, app) => { throw 'only one of since_id, until_id, since_date, until_date can be specified'; } - const { followingIds, watchingChannelIds } = await rap({ + const { followingIds, watchingChannelIds, mutedUserIds } = await rap({ // ID list of the user itself and other users who the user follows followingIds: getFriends(user._id), + // Watchしているチャンネルを取得 watchingChannelIds: ChannelWatching.find({ user_id: user._id, // 削除されたドキュメントは除く deleted_at: { $exists: false } - }).then(watches => watches.map(w => w.channel_id)) + }).then(watches => watches.map(w => w.channel_id)), + + // ミュートしているユーザーを取得 + mutedUserIds: Mute.find({ + muter_id: user._id, + // 削除されたドキュメントは除く + deleted_at: { $exists: false } + }).then(ms => ms.map(m => m.mutee_id)) }); //#region Construct query @@ -80,13 +89,13 @@ module.exports = async (params, user, app) => { }], // mute user_id: { - $nin: mutes + $nin: mutedUserIds }, '_reply.user_id': { - $nin: mutes + $nin: mutedUserIds }, '_repost.user_id': { - $nin: mutes + $nin: mutedUserIds }, } as any; From 26b40d8886ccf87eed5cce2868b14994c29752b9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 06:38:48 +0900 Subject: [PATCH 134/186] wip --- src/api/endpoints/posts/search.ts | 89 +++++++++++++++++++++++++++++-- src/web/docs/search.ja.pug | 16 ++++++ 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index ac25652a0b..f722231d4c 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -6,6 +6,7 @@ import $ from 'cafy'; const escapeRegexp = require('escape-regexp'); import Post from '../../models/post'; import User from '../../models/user'; +import Mute from '../../models/mute'; import getFriends from '../../common/get-friends'; import serialize from '../../serializers/post'; import config from '../../../conf'; @@ -34,6 +35,10 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$; if (followingErr) return rej('invalid following param'); + // Get 'mute' parameter + const [mute = 'mute_all', muteErr] = $(params.mute).optional.string().$; + if (muteErr) return rej('invalid mute param'); + // Get 'reply' parameter const [reply = null, replyErr] = $(params.reply).optional.nullable.boolean().$; if (replyErr) return rej('invalid reply param'); @@ -80,11 +85,11 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // If Elasticsearch is available, search by it // If not, search by MongoDB (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, text, user, following, reply, repost, media, poll, sinceDate, untilDate, offset, limit); + (res, rej, me, text, user, following, mute, reply, repost, media, poll, sinceDate, untilDate, offset, limit); }); // Search by MongoDB -async function byNative(res, rej, me, text, userId, following, reply, repost, media, poll, sinceDate, untilDate, offset, max) { +async function byNative(res, rej, me, text, userId, following, mute, reply, repost, media, poll, sinceDate, untilDate, offset, max) { let q: any = { $and: [] }; @@ -116,6 +121,84 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me }); } + if (me != null) { + const mutes = await Mute.find({ + muter_id: me._id, + deleted_at: { $exists: false } + }); + const mutedUserIds = mutes.map(m => m.mutee_id); + + switch (mute) { + case 'mute_all': + push({ + user_id: { + $nin: mutedUserIds + }, + '_reply.user_id': { + $nin: mutedUserIds + }, + '_repost.user_id': { + $nin: mutedUserIds + } + }); + break; + case 'mute_related': + push({ + '_reply.user_id': { + $nin: mutedUserIds + }, + '_repost.user_id': { + $nin: mutedUserIds + } + }); + break; + case 'mute_direct': + push({ + user_id: { + $nin: mutedUserIds + } + }); + break; + case 'direct_only': + push({ + user_id: { + $in: mutedUserIds + } + }); + break; + case 'related_only': + push({ + $or: [{ + '_reply.user_id': { + $in: mutedUserIds + } + }, { + '_repost.user_id': { + $in: mutedUserIds + } + }] + }); + break; + case 'all_only': + push({ + $or: [{ + user_id: { + $in: mutedUserIds + } + }, { + '_reply.user_id': { + $in: mutedUserIds + } + }, { + '_repost.user_id': { + $in: mutedUserIds + } + }] + }); + break; + } + } + if (reply != null) { if (reply) { push({ @@ -236,7 +319,7 @@ async function byNative(res, rej, me, text, userId, following, reply, repost, me } // Search by Elasticsearch -async function byElasticsearch(res, rej, me, text, userId, following, reply, repost, media, poll, sinceDate, untilDate, offset, max) { +async function byElasticsearch(res, rej, me, text, userId, following, mute, reply, repost, media, poll, sinceDate, untilDate, offset, max) { const es = require('../../db/elasticsearch'); es.search({ diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 41e443d746..552f95c60f 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -29,6 +29,22 @@ section | false ... フォローしていないユーザーに限定。 br | null ... 特に限定しない(デフォルト) + tr + td mute + td + | mute_all ... ミュートしているユーザーの投稿とその投稿に対する返信やRepostを除外する(デフォルト) + br + | mute_related ... ミュートしているユーザーの投稿に対する返信やRepostだけ除外する + br + | mute_direct ... ミュートしているユーザーの投稿だけ除外する + br + | disabled ... ミュートしているユーザーの投稿とその投稿に対する返信やRepostも含める + br + | direct_only ... ミュートしているユーザーの投稿だけに限定 + br + | related_only ... ミュートしているユーザーの投稿に対する返信やRepostだけに限定 + br + | all_only ... ミュートしているユーザーの投稿とその投稿に対する返信やRepostに限定 tr td reply td From 34923888c7f504b95912719e54325cb8633c8cda Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 06:56:37 +0900 Subject: [PATCH 135/186] wip --- locales/en.yml | 5 +++++ locales/ja.yml | 5 +++++ src/api/serializers/user.ts | 15 +++++++++++++-- src/web/app/desktop/tags/user.tag | 27 ++++++++++++++++++++++++++- src/web/docs/api/entities/user.yaml | 6 ++++++ src/web/docs/mute.ja.pug | 3 +++ 6 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/web/docs/mute.ja.pug diff --git a/locales/en.yml b/locales/en.yml index 57e0c4116f..dd3ee2a2a2 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -473,6 +473,11 @@ desktop: mk-user: last-used-at: "Last used at" + follows-you: "Follows you" + mute: "Mute" + muted: "Muting" + unmute: "Unmute" + photos: title: "Photos" loading: "Loading" diff --git a/locales/ja.yml b/locales/ja.yml index ee52f07166..d12eec86d1 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -473,6 +473,11 @@ desktop: mk-user: last-used-at: "最終アクセス" + follows-you: "フォローされています" + mute: "ミュートする" + muted: "ミュートしています" + unmute: "ミュート解除" + photos: title: "フォト" loading: "読み込み中" diff --git a/src/api/serializers/user.ts b/src/api/serializers/user.ts index fe924911c1..ac157097a8 100644 --- a/src/api/serializers/user.ts +++ b/src/api/serializers/user.ts @@ -6,6 +6,7 @@ import deepcopy = require('deepcopy'); import { default as User, IUser } from '../models/user'; import serializePost from './post'; import Following from '../models/following'; +import Mute from '../models/mute'; import getFriends from '../common/get-friends'; import config from '../../conf'; import rap from '@prezzemolo/rap'; @@ -113,7 +114,7 @@ export default ( } if (meId && !meId.equals(_user.id)) { - // If the user is following + // Whether the user is following _user.is_following = (async () => { const follow = await Following.findOne({ follower_id: meId, @@ -123,7 +124,7 @@ export default ( return follow !== null; })(); - // If the user is followed + // Whether the user is followed _user.is_followed = (async () => { const follow2 = await Following.findOne({ follower_id: _user.id, @@ -132,6 +133,16 @@ export default ( }); return follow2 !== null; })(); + + // Whether the user is muted + _user.is_muted = (async () => { + const mute = await Mute.findOne({ + muter_id: meId, + mutee_id: _user.id, + deleted_at: { $exists: false } + }); + return mute !== null; + })(); } if (opts.detail) { diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag index b4db47f9dd..b29d1eaebc 100644 --- a/src/web/app/desktop/tags/user.tag +++ b/src/web/app/desktop/tags/user.tag @@ -226,7 +226,9 @@
-

フォローされています

+

%i18n:desktop.tags.mk-user.follows-you%

+

%i18n:desktop.tags.mk-user.muted% %i18n:desktop.tags.mk-user.unmute%

+

%i18n:desktop.tags.mk-user.mute%

{ user.description }
@@ -311,6 +313,7 @@ this.age = require('s-age'); this.mixin('i'); + this.mixin('api'); this.user = this.opts.user; @@ -325,6 +328,28 @@ user: this.user }); }; + + this.mute = () => { + this.api('mute/create', { + user_id: this.user.id + }).then(() => { + this.user.is_muted = true; + this.update(); + }, e => { + alert('error'); + }); + }; + + this.unmute = () => { + this.api('mute/delete', { + user_id: this.user.id + }).then(() => { + this.user.is_muted = false; + this.update(); + }, e => { + alert('error'); + }); + }; diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml index abc3f300d2..e62ad84db8 100644 --- a/src/web/docs/api/entities/user.yaml +++ b/src/web/docs/api/entities/user.yaml @@ -75,6 +75,12 @@ props: optional: true desc: ja: "自分がこのユーザーにフォローされているか" + - name: "is_muted" + type: "boolean" + optional: true + desc: + ja: "自分がこのユーザーをミュートしているか" + en: "Whether you muted this user" - name: "last_used_at" type: "date" optional: false diff --git a/src/web/docs/mute.ja.pug b/src/web/docs/mute.ja.pug new file mode 100644 index 0000000000..4f5fad8b68 --- /dev/null +++ b/src/web/docs/mute.ja.pug @@ -0,0 +1,3 @@ +h1 ミュート + +p ユーザーをミュートすると、タイムラインや検索結果に対象のユーザーの投稿(およびそれらの投稿に対する返信やRepost)が表示されなくなります。 From 6575a6de5bbcab9a88448e4366feb77f1845a580 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 07:26:23 +0900 Subject: [PATCH 136/186] wip --- src/api/endpoints/i/notifications.ts | 23 ++++++++++++++----- src/api/stream/home.ts | 33 ++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/api/endpoints/i/notifications.ts b/src/api/endpoints/i/notifications.ts index 48254e5e67..fb9be7f61b 100644 --- a/src/api/endpoints/i/notifications.ts +++ b/src/api/endpoints/i/notifications.ts @@ -3,6 +3,7 @@ */ import $ from 'cafy'; import Notification from '../../models/notification'; +import Mute from '../../models/mute'; import serialize from '../../serializers/notification'; import getFriends from '../../common/get-friends'; import read from '../../common/read-notification'; @@ -45,8 +46,18 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('cannot set since_id and until_id'); } + const mute = await Mute.find({ + muter_id: user._id, + deleted_at: { $exists: false } + }); + const query = { - notifiee_id: user._id + notifiee_id: user._id, + $and: [{ + notifier_id: { + $nin: mute.map(m => m.mutee_id) + } + }] } as any; const sort = { @@ -54,12 +65,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }; if (following) { - // ID list of the user $self and other users who the user follows + // ID list of the user itself and other users who the user follows const followingIds = await getFriends(user._id); - query.notifier_id = { - $in: followingIds - }; + query.$and.push({ + notifier_id: { + $in: followingIds + } + }); } if (type) { diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts index 7c8f3bfec8..7dcdb5ed73 100644 --- a/src/api/stream/home.ts +++ b/src/api/stream/home.ts @@ -3,19 +3,48 @@ import * as redis from 'redis'; import * as debug from 'debug'; import User from '../models/user'; +import Mute from '../models/mute'; import serializePost from '../serializers/post'; import readNotification from '../common/read-notification'; const log = debug('misskey'); -export default function homeStream(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { +export default async function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any) { // Subscribe Home stream channel subscriber.subscribe(`misskey:user-stream:${user._id}`); + const mute = await Mute.find({ + muter_id: user._id, + deleted_at: { $exists: false } + }); + const mutedUserIds = mute.map(m => m.mutee_id.toString()); + subscriber.on('message', async (channel, data) => { switch (channel.split(':')[1]) { case 'user-stream': - connection.send(data); + try { + const x = JSON.parse(data); + + if (x.type == 'post') { + if (mutedUserIds.indexOf(x.body.user_id) != -1) { + return; + } + if (x.body.reply != null && mutedUserIds.indexOf(x.body.reply.user_id) != -1) { + return; + } + if (x.body.repost != null && mutedUserIds.indexOf(x.body.repost.user_id) != -1) { + return; + } + } else if (x.type == 'notification') { + if (mutedUserIds.indexOf(x.body.user_id) != -1) { + return; + } + } + + connection.send(data); + } catch (e) { + connection.send(data); + } break; case 'post-stream': const postId = channel.split(':')[2]; From 8b515b4dae8c272257ee8892713fe954f0ff9c4a Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 07:38:57 +0900 Subject: [PATCH 137/186] wip --- src/api/common/notify.ts | 12 ++++++++++++ src/api/endpoints/notifications/get_unread_count.ts | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/api/common/notify.ts b/src/api/common/notify.ts index 4b3e6a5d54..f06622f912 100644 --- a/src/api/common/notify.ts +++ b/src/api/common/notify.ts @@ -1,5 +1,6 @@ import * as mongo from 'mongodb'; import Notification from '../models/notification'; +import Mute from '../models/mute'; import event from '../event'; import serialize from '../serializers/notification'; @@ -32,6 +33,17 @@ export default ( setTimeout(async () => { const fresh = await Notification.findOne({ _id: notification._id }, { is_read: true }); if (!fresh.is_read) { + //#region ただしミュートしているユーザーからの通知なら無視 + const mute = await Mute.find({ + muter_id: notifiee, + deleted_at: { $exists: false } + }); + const mutedUserIds = mute.map(m => m.mutee_id.toString()); + if (mutedUserIds.indexOf(notifier.toHexString()) != -1) { + return; + } + //#endregion + event(notifiee, 'unread_notification', await serialize(notification)); } }, 3000); diff --git a/src/api/endpoints/notifications/get_unread_count.ts b/src/api/endpoints/notifications/get_unread_count.ts index 9514e78713..845d6b29ce 100644 --- a/src/api/endpoints/notifications/get_unread_count.ts +++ b/src/api/endpoints/notifications/get_unread_count.ts @@ -2,6 +2,7 @@ * Module dependencies */ import Notification from '../../models/notification'; +import Mute from '../../models/mute'; /** * Get count of unread notifications @@ -11,9 +12,18 @@ import Notification from '../../models/notification'; * @return {Promise} */ module.exports = (params, user) => new Promise(async (res, rej) => { + const mute = await Mute.find({ + muter_id: user._id, + deleted_at: { $exists: false } + }); + const mutedUserIds = mute.map(m => m.mutee_id); + const count = await Notification .count({ notifiee_id: user._id, + notifier_id: { + $nin: mutedUserIds + }, is_read: false }); From f93bc3a8ec7eae63330193bc87c5b1437bf874ed Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 07:43:56 +0900 Subject: [PATCH 138/186] wip --- src/api/common/notify.ts | 2 +- src/api/endpoints/posts/create.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/api/common/notify.ts b/src/api/common/notify.ts index f06622f912..2b79416a30 100644 --- a/src/api/common/notify.ts +++ b/src/api/common/notify.ts @@ -39,7 +39,7 @@ export default ( deleted_at: { $exists: false } }); const mutedUserIds = mute.map(m => m.mutee_id.toString()); - if (mutedUserIds.indexOf(notifier.toHexString()) != -1) { + if (mutedUserIds.indexOf(notifier.toString()) != -1) { return; } //#endregion diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 9d791538fe..a1d05c67c6 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -8,6 +8,7 @@ import { default as Post, IPost, isValidText } from '../../models/post'; import { default as User, IUser } from '../../models/user'; import { default as Channel, IChannel } from '../../models/channel'; import Following from '../../models/following'; +import Mute from '../../models/mute'; import DriveFile from '../../models/drive-file'; import Watching from '../../models/post-watching'; import ChannelWatching from '../../models/channel-watching'; @@ -240,7 +241,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { const mentions = []; - function addMention(mentionee, reason) { + async function addMention(mentionee, reason) { // Reject if already added if (mentions.some(x => x.equals(mentionee))) return; @@ -249,8 +250,15 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // Publish event if (!user._id.equals(mentionee)) { - event(mentionee, reason, postObj); - pushSw(mentionee, reason, postObj); + const mentioneeMutes = await Mute.find({ + muter_id: mentionee, + deleted_at: { $exists: false } + }); + const mentioneesMutedUserIds = mentioneeMutes.map(m => m.mutee_id.toString()); + if (mentioneesMutedUserIds.indexOf(user._id.toString()) == -1) { + event(mentionee, reason, postObj); + pushSw(mentionee, reason, postObj); + } } } From 4bd694fb59f87a8adcb471dd17874d9aa65d4bc6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 07:57:46 +0900 Subject: [PATCH 139/186] Update mute.ja.pug --- src/web/docs/mute.ja.pug | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/web/docs/mute.ja.pug b/src/web/docs/mute.ja.pug index 4f5fad8b68..a1f3960064 100644 --- a/src/web/docs/mute.ja.pug +++ b/src/web/docs/mute.ja.pug @@ -1,3 +1,7 @@ h1 ミュート -p ユーザーをミュートすると、タイムラインや検索結果に対象のユーザーの投稿(およびそれらの投稿に対する返信やRepost)が表示されなくなります。 +p ユーザーをミュートすると、タイムラインや検索結果に対象のユーザーの投稿(およびそれらの投稿に対する返信やRepost)が表示されなくなります。また、ミュートしているユーザーからの通知も表示されなくなります。 + +p ユーザーページからそのユーザーをミュートすることができます。 + +p ミュートを行ったことは相手に通知されず、ミュートされていることを知ることもできません。 From 2c4d86d8a0fca323b162adb73af60bbf644e7beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Fri, 22 Dec 2017 10:38:59 +0900 Subject: [PATCH 140/186] wip --- locales/en.yml | 4 +++ locales/ja.yml | 4 +++ src/web/app/desktop/tags/settings.tag | 38 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/locales/en.yml b/locales/en.yml index dd3ee2a2a2..e559846772 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -346,6 +346,9 @@ desktop: failed: "Failed to setup. please ensure that the token is correct." info: "From the next sign in, enter the token that is displayed on the device in addition to the password." + mk-mute-setting: + no-users: "No muted users" + mk-post-form: post-placeholder: "What's happening?" reply-placeholder: "Reply to this post..." @@ -379,6 +382,7 @@ desktop: mk-settings: profile: "Profile" + mute: "Mute" drive: "Drive" security: "Security" password: "Password" diff --git a/locales/ja.yml b/locales/ja.yml index d12eec86d1..70ff8739f3 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -346,6 +346,9 @@ desktop: failed: "設定に失敗しました。トークンに誤りがないかご確認ください。" info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。" + mk-mute-setting: + no-users: "ミュートしているユーザーはいません" + mk-post-form: post-placeholder: "いまどうしてる?" reply-placeholder: "この投稿への返信..." @@ -379,6 +382,7 @@ desktop: mk-settings: profile: "プロフィール" + mute: "ミュート" drive: "ドライブ" security: "セキュリティ" password: "パスワード" diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag index 2f36d9b3ec..457b7e2276 100644 --- a/src/web/app/desktop/tags/settings.tag +++ b/src/web/app/desktop/tags/settings.tag @@ -4,6 +4,7 @@

%fa:desktop .fw%Web

%fa:R bell .fw%通知

%fa:cloud .fw%%i18n:desktop.tags.mk-settings.drive%

+

%fa:ban .fw%%i18n:desktop.tags.mk-settings.mute%

%fa:puzzle-piece .fw%アプリ

%fa:B twitter .fw%Twitter

%fa:unlock-alt .fw%%i18n:desktop.tags.mk-settings.security%

@@ -26,6 +27,11 @@ +
+

%i18n:desktop.tags.mk-settings.mute%

+ +
+

アプリケーション

@@ -386,3 +392,35 @@ }); + + +
+

%fa:info-circle%%i18n:desktop.tags.mk-mute-setting.no-users%

+
+
+
+

{ user.name } @{ user.username }

+
+
+ + + +
From a900843b0a7d4a4d771c903fe406ab8741a31185 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 12:59:37 +0900 Subject: [PATCH 141/186] Update mute.ja.pug --- src/web/docs/mute.ja.pug | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/web/docs/mute.ja.pug b/src/web/docs/mute.ja.pug index a1f3960064..176ace5e54 100644 --- a/src/web/docs/mute.ja.pug +++ b/src/web/docs/mute.ja.pug @@ -1,7 +1,14 @@ h1 ミュート -p ユーザーをミュートすると、タイムラインや検索結果に対象のユーザーの投稿(およびそれらの投稿に対する返信やRepost)が表示されなくなります。また、ミュートしているユーザーからの通知も表示されなくなります。 +p ユーザーページから、そのユーザーをミュートすることができます。 -p ユーザーページからそのユーザーをミュートすることができます。 +p ユーザーをミュートすると、そのユーザーに関する次のコンテンツがMisskeyに表示されなくなります: +ul + li タイムラインや投稿の検索結果内の、そのユーザーの +投稿(およびそれらの投稿に対する返信やRepost) + li そのユーザーからの通知 + li メッセージ履歴一覧内の、そのユーザーとのメッセージ履歴 p ミュートを行ったことは相手に通知されず、ミュートされていることを知ることもできません。 + +p 設定>ミュート から、自分がミュートしているユーザー一覧を確認することができます。 From 6e59c822528dab8b011d663b1618b4ab30cd5f3d Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 12:59:59 +0900 Subject: [PATCH 142/186] oops --- src/web/docs/mute.ja.pug | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/web/docs/mute.ja.pug b/src/web/docs/mute.ja.pug index 176ace5e54..5e79af5f8c 100644 --- a/src/web/docs/mute.ja.pug +++ b/src/web/docs/mute.ja.pug @@ -4,8 +4,7 @@ p ユーザーページから、そのユーザーをミュートすることが p ユーザーをミュートすると、そのユーザーに関する次のコンテンツがMisskeyに表示されなくなります: ul - li タイムラインや投稿の検索結果内の、そのユーザーの -投稿(およびそれらの投稿に対する返信やRepost) + li タイムラインや投稿の検索結果内の、そのユーザーの投稿(およびそれらの投稿に対する返信やRepost) li そのユーザーからの通知 li メッセージ履歴一覧内の、そのユーザーとのメッセージ履歴 From e21ab77dd5fc007cc92fffd4362890fbde89db56 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 14:21:40 +0900 Subject: [PATCH 143/186] wip --- src/api/endpoints/messaging/history.ts | 11 ++++++++++- src/api/endpoints/messaging/messages/create.ts | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/api/endpoints/messaging/history.ts b/src/api/endpoints/messaging/history.ts index 5f7c9276dd..f14740dff5 100644 --- a/src/api/endpoints/messaging/history.ts +++ b/src/api/endpoints/messaging/history.ts @@ -3,6 +3,7 @@ */ import $ from 'cafy'; import History from '../../models/messaging-history'; +import Mute from '../../models/mute'; import serialize from '../../serializers/messaging-message'; /** @@ -17,10 +18,18 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; if (limitErr) return rej('invalid limit param'); + const mute = await Mute.find({ + muter_id: user._id, + deleted_at: { $exists: false } + }); + // Get history const history = await History .find({ - user_id: user._id + user_id: user._id, + partner: { + $nin: mute.map(m => m.mutee_id) + } }, { limit: limit, sort: { diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts index 3c7689f967..f69f2e0fb2 100644 --- a/src/api/endpoints/messaging/messages/create.ts +++ b/src/api/endpoints/messaging/messages/create.ts @@ -6,6 +6,7 @@ import Message from '../../../models/messaging-message'; import { isValidText } from '../../../models/messaging-message'; import History from '../../../models/messaging-history'; import User from '../../../models/user'; +import Mute from '../../../models/mute'; import DriveFile from '../../../models/drive-file'; import serialize from '../../../serializers/messaging-message'; import publishUserStream from '../../../event'; @@ -97,6 +98,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => { setTimeout(async () => { const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true }); if (!freshMessage.is_read) { + //#region ただしミュートしているユーザーからの通知なら無視 + const mute = await Mute.find({ + muter_id: recipient._id, + deleted_at: { $exists: false } + }); + const mutedUserIds = mute.map(m => m.mutee_id.toString()); + if (mutedUserIds.indexOf(user._id.toString()) != -1) { + return; + } + //#endregion + publishUserStream(message.recipient_id, 'unread_messaging_message', messageObj); pushSw(message.recipient_id, 'unread_messaging_message', messageObj); } From ef5a963b32afd5842894a2a61fa4c2d078853224 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 14:35:47 +0900 Subject: [PATCH 144/186] wip --- src/api/endpoints/messaging/unread.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/api/endpoints/messaging/unread.ts b/src/api/endpoints/messaging/unread.ts index 40bc83fe1c..c4326e1d22 100644 --- a/src/api/endpoints/messaging/unread.ts +++ b/src/api/endpoints/messaging/unread.ts @@ -2,6 +2,7 @@ * Module dependencies */ import Message from '../../models/messaging-message'; +import Mute from '../../models/mute'; /** * Get count of unread messages @@ -11,8 +12,17 @@ import Message from '../../models/messaging-message'; * @return {Promise} */ module.exports = (params, user) => new Promise(async (res, rej) => { + const mute = await Mute.find({ + muter_id: user._id, + deleted_at: { $exists: false } + }); + const mutedUserIds = mute.map(m => m.mutee_id); + const count = await Message .count({ + user_id: { + $nin: mutedUserIds + }, recipient_id: user._id, is_read: false }); From 09af75a92d94cc59e41e0401da9af59a1a90e29f Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 16:22:33 +0900 Subject: [PATCH 145/186] Update create.ts --- src/api/endpoints/messaging/messages/create.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts index f69f2e0fb2..4e9d10197c 100644 --- a/src/api/endpoints/messaging/messages/create.ts +++ b/src/api/endpoints/messaging/messages/create.ts @@ -98,7 +98,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { setTimeout(async () => { const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true }); if (!freshMessage.is_read) { - //#region ただしミュートしているユーザーからの通知なら無視 + //#region ただしミュートされているなら発行しない const mute = await Mute.find({ muter_id: recipient._id, deleted_at: { $exists: false } From 1ea89fddee13cd6900fbd943d3f4419450693ee5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Dec 2017 17:44:31 +0900 Subject: [PATCH 146/186] v3451 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c253d1f110..bf3a52ccd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3451 (2017/12/22) +----------------- +* ミュート機能 + 3430 (2017/12/21) ----------------- * oops diff --git a/package.json b/package.json index b43f5be70c..eb79e8149a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3430", + "version": "0.0.3451", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 52ea44394aaf9f48340077812ea8357df157ec88 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 00:39:00 +0900 Subject: [PATCH 147/186] Update search.ja.pug --- src/web/docs/search.ja.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 552f95c60f..e94990205b 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -8,7 +8,7 @@ p section h2 オプション p - | オプションを使用して、より高度な検索をすることもできます。 + | オプションを使用して、より高度な検索を行えます。 | オプションを指定するには、「オプション名:値」という形式でクエリに含めます。 p 利用可能なオプション一覧です: From 8376b10b3b93d3c6cc50d69a6f0ae3ceb8c96c74 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 04:21:15 +0900 Subject: [PATCH 148/186] #1035 --- src/api/endpoints/posts/search.ts | 4 +++- src/web/docs/search.ja.pug | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index f722231d4c..4697e6ed0f 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -99,7 +99,9 @@ async function byNative(res, rej, me, text, userId, following, mute, reply, repo if (text) { push({ $and: text.split(' ').map(x => ({ - text: new RegExp(escapeRegexp(x)) + text: x[0] == '-' ? { + $ne: new RegExp(escapeRegexp(x)) + } : new RegExp(escapeRegexp(x)) })) }); } diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index e94990205b..5baac9d400 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -5,6 +5,12 @@ p | キーワードを半角スペースで区切ると、and検索になります。 | 例えば、「git コミット」と検索すると、「gitで編集したファイルの特定の行だけコミットする方法がわからない」などがマッチします。 +section + h2 キーワードの除外 + p キーワードの前に「-」(ハイフン)をプリフィクスすると、そのキーワードを含まない投稿に限定します。 + p 例えば、「gitというキーワードを含むが、コミットというキーワードは含まない投稿」を検索したい場合、クエリは以下のようになります: + code git -コミット + section h2 オプション p From 67c269ddf54d43b68c06b8fb2726f72d87600c11 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 04:21:48 +0900 Subject: [PATCH 149/186] oops --- src/api/endpoints/posts/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 4697e6ed0f..33ef2a0a05 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -100,7 +100,7 @@ async function byNative(res, rej, me, text, userId, following, mute, reply, repo push({ $and: text.split(' ').map(x => ({ text: x[0] == '-' ? { - $ne: new RegExp(escapeRegexp(x)) + $ne: new RegExp(escapeRegexp(x.substr(1))) } : new RegExp(escapeRegexp(x)) })) }); From 3e343814e395a3c4b7374629d3f6082705ea7f8d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 04:22:45 +0900 Subject: [PATCH 150/186] oops --- src/web/docs/search.ja.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 5baac9d400..09173a3503 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -7,7 +7,7 @@ p section h2 キーワードの除外 - p キーワードの前に「-」(ハイフン)をプリフィクスすると、そのキーワードを含まない投稿に限定します。 + p キーワードの前に「-」(ハイフン)をプリフィクスすると、そのキーワードを含まない投稿に限定します。 p 例えば、「gitというキーワードを含むが、コミットというキーワードは含まない投稿」を検索したい場合、クエリは以下のようになります: code git -コミット From 020ce794af9493d3a037bc4cd942c6f0fac75330 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 04:26:37 +0900 Subject: [PATCH 151/186] oops --- src/api/endpoints/posts/search.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 33ef2a0a05..6cea5bdf53 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -99,8 +99,9 @@ async function byNative(res, rej, me, text, userId, following, mute, reply, repo if (text) { push({ $and: text.split(' ').map(x => ({ + // キーワードが-で始まる場合そのキーワードを除外する text: x[0] == '-' ? { - $ne: new RegExp(escapeRegexp(x.substr(1))) + $not: new RegExp(escapeRegexp(x.substr(1))) } : new RegExp(escapeRegexp(x)) })) }); From 7cf4aa9f110cebf1bf3017471b8e96d2522ad462 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 04:38:56 +0900 Subject: [PATCH 152/186] #1034 --- src/api/endpoints/posts/search.ts | 24 ++++++++++++++++-------- src/web/docs/search.ja.pug | 5 +++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 6cea5bdf53..26675989dd 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -97,14 +97,22 @@ async function byNative(res, rej, me, text, userId, following, mute, reply, repo const push = x => q.$and.push(x); if (text) { - push({ - $and: text.split(' ').map(x => ({ - // キーワードが-で始まる場合そのキーワードを除外する - text: x[0] == '-' ? { - $not: new RegExp(escapeRegexp(x.substr(1))) - } : new RegExp(escapeRegexp(x)) - })) - }); + // 完全一致検索 + if (/"""(.+?)"""/.test(text)) { + const x = text.match(/"""(.+?)"""/)[1]; + push({ + text: x + }); + } else { + push({ + $and: text.split(' ').map(x => ({ + // キーワードが-で始まる場合そのキーワードを除外する + text: x[0] == '-' ? { + $not: new RegExp(escapeRegexp(x.substr(1))) + } : new RegExp(escapeRegexp(x)) + })) + }); + } } if (userId) { diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 09173a3503..9e64789488 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -11,6 +11,11 @@ section p 例えば、「gitというキーワードを含むが、コミットというキーワードは含まない投稿」を検索したい場合、クエリは以下のようになります: code git -コミット +section + h2 完全一致 + p テキストを「"""」で囲むと、そのテキストと完全に一致する投稿を検索します。 + p 例えば、「"""にゃーん"""」と検索すると、「にゃーん」という投稿のみがヒットし、「にゃーん…」という投稿はヒットしません。 + section h2 オプション p From f0818edd6e1d566a3d7e2b5495eeb389d728f564 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 07:21:52 +0900 Subject: [PATCH 153/186] #1037 #1038 --- src/api/endpoints/posts/search.ts | 138 +++++++----------- .../app/common/scripts/parse-search-query.ts | 5 +- src/web/docs/search.ja.pug | 19 ++- 3 files changed, 72 insertions(+), 90 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 26675989dd..31c9a8d3c8 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -1,7 +1,6 @@ /** * Module dependencies */ -import * as mongo from 'mongodb'; import $ from 'cafy'; const escapeRegexp = require('escape-regexp'); import Post from '../../models/post'; @@ -9,7 +8,6 @@ import User from '../../models/user'; import Mute from '../../models/mute'; import getFriends from '../../common/get-friends'; import serialize from '../../serializers/post'; -import config from '../../../conf'; /** * Search a post @@ -23,13 +21,21 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [text, textError] = $(params.text).optional.string().$; if (textError) return rej('invalid text param'); - // Get 'user_id' parameter - const [userId, userIdErr] = $(params.user_id).optional.id().$; - if (userIdErr) return rej('invalid user_id param'); + // Get 'include_user_ids' parameter + const [includeUserIds = [], includeUserIdsErr] = $(params.include_user_ids).optional.array('id').$; + if (includeUserIdsErr) return rej('invalid include_user_ids param'); - // Get 'username' parameter - const [username, usernameErr] = $(params.username).optional.string().$; - if (usernameErr) return rej('invalid username param'); + // Get 'exclude_user_ids' parameter + const [excludeUserIds = [], excludeUserIdsErr] = $(params.exclude_user_ids).optional.array('id').$; + if (excludeUserIdsErr) return rej('invalid exclude_user_ids param'); + + // Get 'include_user_usernames' parameter + const [includeUserUsernames = [], includeUserUsernamesErr] = $(params.include_user_usernames).optional.array('string').$; + if (includeUserUsernamesErr) return rej('invalid include_user_usernames param'); + + // Get 'exclude_user_usernames' parameter + const [excludeUserUsernames = [], excludeUserUsernamesErr] = $(params.exclude_user_usernames).optional.array('string').$; + if (excludeUserUsernamesErr) return rej('invalid exclude_user_usernames param'); // Get 'following' parameter const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$; @@ -71,25 +77,36 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 30).$; if (limitErr) return rej('invalid limit param'); - let user = userId; - - if (user == null && username != null) { - const _user = await User.findOne({ - username_lower: username.toLowerCase() - }); - if (_user) { - user = _user._id; - } + let includeUsers = includeUserIds; + if (includeUserUsernames != null) { + const ids = (await Promise.all(includeUserUsernames.map(async (username) => { + const _user = await User.findOne({ + username_lower: username.toLowerCase() + }); + return _user ? _user._id : null; + }))).filter(id => id != null); + includeUsers = includeUsers.concat(ids); } - // If Elasticsearch is available, search by it - // If not, search by MongoDB - (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, text, user, following, mute, reply, repost, media, poll, sinceDate, untilDate, offset, limit); + let excludeUsers = excludeUserIds; + if (excludeUserUsernames != null) { + const ids = (await Promise.all(excludeUserUsernames.map(async (username) => { + const _user = await User.findOne({ + username_lower: username.toLowerCase() + }); + return _user ? _user._id : null; + }))).filter(id => id != null); + excludeUsers = excludeUsers.concat(ids); + } + + search(res, rej, me, text, includeUsers, excludeUsers, following, + mute, reply, repost, media, poll, sinceDate, untilDate, offset, limit); }); -// Search by MongoDB -async function byNative(res, rej, me, text, userId, following, mute, reply, repost, media, poll, sinceDate, untilDate, offset, max) { +async function search( + res, rej, me, text, includeUserIds, excludeUserIds, following, + mute, reply, repost, media, poll, sinceDate, untilDate, offset, max) { + let q: any = { $and: [] }; @@ -115,9 +132,17 @@ async function byNative(res, rej, me, text, userId, following, mute, reply, repo } } - if (userId) { + if (includeUserIds && includeUserIds.length != 0) { push({ - user_id: userId + user_id: { + $in: includeUserIds + } + }); + } else if (excludeUserIds && excludeUserIds.length != 0) { + push({ + user_id: { + $nin: excludeUserIds + } }); } @@ -328,66 +353,3 @@ async function byNative(res, rej, me, text, userId, following, mute, reply, repo res(await Promise.all(posts.map(async post => await serialize(post, me)))); } - -// Search by Elasticsearch -async function byElasticsearch(res, rej, me, text, userId, following, mute, reply, repost, media, poll, sinceDate, untilDate, offset, max) { - const es = require('../../db/elasticsearch'); - - es.search({ - index: 'misskey', - type: 'post', - body: { - size: max, - from: offset, - query: { - simple_query_string: { - fields: ['text'], - query: text, - default_operator: 'and' - } - }, - sort: [ - { _doc: 'desc' } - ], - highlight: { - pre_tags: [''], - post_tags: [''], - encoder: 'html', - fields: { - text: {} - } - } - } - }, async (error, response) => { - if (error) { - console.error(error); - return res(500); - } - - if (response.hits.total === 0) { - return res([]); - } - - const hits = response.hits.hits.map(hit => new mongo.ObjectID(hit._id)); - - // Fetch found posts - const posts = await Post - .find({ - _id: { - $in: hits - } - }, { - sort: { - _id: -1 - } - }); - - posts.map(post => { - post._highlight = response.hits.hits.filter(hit => post._id.equals(hit._id))[0].highlight.text[0]; - }); - - // Serialize - res(await Promise.all(posts.map(async post => - await serialize(post, me)))); - }); -} diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts index c021ee6417..512791ecb0 100644 --- a/src/web/app/common/scripts/parse-search-query.ts +++ b/src/web/app/common/scripts/parse-search-query.ts @@ -8,7 +8,10 @@ export default function(qs: string) { const [key, value] = x.split(':'); switch (key) { case 'user': - q['username'] = value; + q['include_user_usernames'] = value.split(','); + break; + case 'exclude_user': + q['exclude_user_usernames'] = value.split(','); break; case 'follow': q['following'] = value == 'null' ? null : value == 'true'; diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 9e64789488..f33091ee6b 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -31,7 +31,24 @@ section tbody tr td user - td ユーザー名。投稿者を限定します。 + td + | 指定されたユーザー名のユーザーの投稿に限定します。 + | 「,」(カンマ)で区切って、複数ユーザーを指定することもできます。 + br + | 例えば、 + code user:himawari,sakurako + | と検索すると「@himawariまたは@sakurakoの投稿」だけに限定します。 + | (つまりユーザーのホワイトリストです) + tr + td exclude_user + td + | 指定されたユーザー名のユーザーの投稿を除外します。 + | 「,」(カンマ)で区切って、複数ユーザーを指定することもできます。 + br + | 例えば、 + code exclude_user:akari,chinatsu + | と検索すると「@akariまたは@chinatsu以外の投稿」に限定します。 + | (つまりユーザーのブラックリストです) tr td follow td From 84ed78cef7b84353bc1ea48c91b78ecfb2a21f08 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 07:21:57 +0900 Subject: [PATCH 154/186] :art: --- src/web/docs/style.styl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl index 3dcb3e1696..a726d49b16 100644 --- a/src/web/docs/style.styl +++ b/src/web/docs/style.styl @@ -106,6 +106,7 @@ table min-width 128px code + display inline-block padding 8px 10px font-family Consolas, 'Courier New', Courier, Monaco, monospace color #295c92 From f4277b8f9d1d8e3db7f720bcd0872b28162011d1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Dec 2017 07:22:58 +0900 Subject: [PATCH 155/186] v3460 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf3a52ccd5..a05097ff05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3460 (2017/12/23) +----------------- +* 検索で複数のユーザーを指定できるように +* 検索でユーザーを除外できるように +* など + 3451 (2017/12/22) ----------------- * ミュート機能 diff --git a/package.json b/package.json index eb79e8149a..b236051e77 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3451", + "version": "0.0.3460", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From 8b6c30d190b0e37035c6b5c2ce5a028555f5a497 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sat, 23 Dec 2017 02:52:15 +0000 Subject: [PATCH 156/186] fix(package): update ts-node to version 4.1.0 Closes #985 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b236051e77..81588c66f3 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "tcp-port-used": "0.1.2", "textarea-caret": "3.0.2", "tmp": "0.0.33", - "ts-node": "3.3.0", + "ts-node": "4.1.0", "tslint": "5.8.0", "typescript": "2.6.2", "uglify-es": "3.2.0", From 086266cae902ff172d702357682abd8ccc16ac23 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sat, 23 Dec 2017 17:55:00 +0000 Subject: [PATCH 157/186] fix(package): update riot-tag-loader to version 2.0.0 Closes #1042 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 81588c66f3..2607d33a2b 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "request": "2.83.0", "rimraf": "2.6.2", "riot": "3.7.4", - "riot-tag-loader": "1.0.0", + "riot-tag-loader": "2.0.0", "rndstr": "1.0.0", "s-age": "1.1.0", "seedrandom": "2.4.3", From eaf6e83515b219c9c54cd806060fe386caa38165 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sun, 24 Dec 2017 13:50:30 +0000 Subject: [PATCH 158/186] fix(package): update gulp-htmlmin to version 4.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2607d33a2b..33ffb53b4c 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "gm": "1.23.0", "gulp": "3.9.1", "gulp-cssnano": "2.1.2", - "gulp-htmlmin": "3.0.0", + "gulp-htmlmin": "4.0.0", "gulp-imagemin": "4.0.0", "gulp-mocha": "4.3.1", "gulp-pug": "3.3.0", From 3a2e06c06c3359e48a386eca5430ab4eef6f1489 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sun, 24 Dec 2017 23:57:04 +0000 Subject: [PATCH 159/186] fix(package): update mongodb to version 3.0.1 Closes #1046 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2607d33a2b..9649e0b094 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "mkdirp": "^0.5.1", "mocha": "4.0.1", "moji": "0.5.1", - "mongodb": "2.2.33", + "mongodb": "3.0.1", "monk": "6.0.5", "morgan": "1.9.0", "ms": "2.1.1", From 1ba3be5dbe05789bfdc08844288dd9debaeef0ca Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 25 Dec 2017 11:02:15 +0000 Subject: [PATCH 160/186] fix(package): update riot-tag-loader to version 2.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2607d33a2b..d43e967eb5 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "request": "2.83.0", "rimraf": "2.6.2", "riot": "3.7.4", - "riot-tag-loader": "2.0.0", + "riot-tag-loader": "2.0.1", "rndstr": "1.0.0", "s-age": "1.1.0", "seedrandom": "2.4.3", From 7811853be4a85f4ec2a8364fa3f282bbf39d854d Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 27 Dec 2017 10:33:26 +0000 Subject: [PATCH 161/186] fix(package): update uglifyjs-webpack-plugin to version 1.1.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2607d33a2b..c8ab350d4b 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ "tslint": "5.8.0", "typescript": "2.6.2", "uglify-es": "3.2.0", - "uglifyjs-webpack-plugin": "1.1.4", + "uglifyjs-webpack-plugin": "1.1.5", "uuid": "3.1.0", "vhost": "3.0.2", "web-push": "3.2.5", From 9b04c7a32d60d21b87d685034fdb194ad0bdc37b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 27 Dec 2017 17:50:23 +0000 Subject: [PATCH 162/186] fix(package): update qrcode to version 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2607d33a2b..ddb18a2e72 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "prominence": "0.2.0", "proxy-addr": "2.0.2", "pug": "2.0.0-rc.4", - "qrcode": "1.0.0", + "qrcode": "1.0.1", "ratelimiter": "3.0.3", "recaptcha-promise": "0.1.3", "reconnecting-websocket": "3.2.2", From be0d85e1b0f950921ae738e3d3b0f4c8cd027d5c Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 28 Dec 2017 09:49:30 +0900 Subject: [PATCH 163/186] Update .travis.yml --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index ed53af9e20..6e33a2d12c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ # travis file # https://docs.travis-ci.com/user/customizing-the-build +notifications: + email: false + branches: except: - release From 9ff3cccde600b56a8ae3e556521707e1b383631c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 28 Dec 2017 04:49:49 +0000 Subject: [PATCH 164/186] fix(package): update gm to version 1.23.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3be5cdae9..3fbb3f85b9 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "express": "4.16.2", "file-type": "7.4.0", "fuckadblock": "3.2.1", - "gm": "1.23.0", + "gm": "1.23.1", "gulp": "3.9.1", "gulp-cssnano": "2.1.2", "gulp-htmlmin": "4.0.0", From 113ee680246b9b969b73f4a89cdd14c1864530be Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 28 Dec 2017 14:01:33 +0000 Subject: [PATCH 165/186] fix(package): update riot to version 3.8.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3be5cdae9..68d5c27265 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "redis": "2.8.0", "request": "2.83.0", "rimraf": "2.6.2", - "riot": "3.7.4", + "riot": "3.8.0", "riot-tag-loader": "2.0.1", "rndstr": "1.0.0", "s-age": "1.1.0", From 7965e4609e0f4d241b7750b31fbec69fe446bcf3 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 28 Dec 2017 20:40:53 +0000 Subject: [PATCH 166/186] fix(package): update riot to version 3.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68d5c27265..a2d5e3ce1e 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "redis": "2.8.0", "request": "2.83.0", "rimraf": "2.6.2", - "riot": "3.8.0", + "riot": "3.8.1", "riot-tag-loader": "2.0.1", "rndstr": "1.0.0", "s-age": "1.1.0", From 39c7e2ad1cdf9ba63810478414a2808d604c76d6 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 28 Dec 2017 20:50:28 +0000 Subject: [PATCH 167/186] fix(package): update qrcode to version 1.2.0 Closes #1053 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68d5c27265..605f24bf00 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "prominence": "0.2.0", "proxy-addr": "2.0.2", "pug": "2.0.0-rc.4", - "qrcode": "1.0.1", + "qrcode": "1.2.0", "ratelimiter": "3.0.3", "recaptcha-promise": "0.1.3", "reconnecting-websocket": "3.2.2", From 9b4e3d95d15da5c7160dd60985912b6500955b95 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 29 Dec 2017 09:50:12 +0000 Subject: [PATCH 168/186] fix(package): update riot-tag-loader to version 2.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dcd880fbc8..95759fa31e 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "request": "2.83.0", "rimraf": "2.6.2", "riot": "3.8.1", - "riot-tag-loader": "2.0.1", + "riot-tag-loader": "2.0.2", "rndstr": "1.0.0", "s-age": "1.1.0", "seedrandom": "2.4.3", From 4a6b4f7a2b589f53a02979d1a209612cb7629513 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sat, 30 Dec 2017 21:27:41 +0000 Subject: [PATCH 169/186] fix(package): update gulp-imagemin to version 4.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dcd880fbc8..80bfa5f4cb 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "gulp": "3.9.1", "gulp-cssnano": "2.1.2", "gulp-htmlmin": "4.0.0", - "gulp-imagemin": "4.0.0", + "gulp-imagemin": "4.1.0", "gulp-mocha": "4.3.1", "gulp-pug": "3.3.0", "gulp-rename": "1.2.2", From 59c64ba7d91be1fbedba3c7188150e0f81c76818 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 31 Dec 2017 14:38:41 +0900 Subject: [PATCH 170/186] Improve readability --- src/db/mongodb.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts index c978e6460f..be234b3650 100644 --- a/src/db/mongodb.ts +++ b/src/db/mongodb.ts @@ -1,8 +1,8 @@ import config from '../conf'; const uri = config.mongodb.user && config.mongodb.pass -? `mongodb://${config.mongodb.user}:${config.mongodb.pass}@${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}` -: `mongodb://${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}`; + ? `mongodb://${config.mongodb.user}:${config.mongodb.pass}@${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}` + : `mongodb://${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}`; /** * monk From deb86bf6e5fce7d97e449a1f7f2a7db48915a03d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 31 Dec 2017 15:15:19 +0900 Subject: [PATCH 171/186] Fix bug SEE: https://github.com/mongodb/node-mongodb-native/blob/3.0.0/CHANGES_3.0.0.md --- src/db/mongodb.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts index be234b3650..1263ccaacd 100644 --- a/src/db/mongodb.ts +++ b/src/db/mongodb.ts @@ -24,9 +24,9 @@ const nativeDbConn = async (): Promise => { if (mdb) return mdb; const db = await ((): Promise => new Promise((resolve, reject) => { - mongodb.MongoClient.connect(uri, (e, db) => { + (mongodb as any).MongoClient.connect(uri, (e, client) => { if (e) return reject(e); - resolve(db); + resolve(client.db(config.mongodb.db)); }); }))(); From 17369103d7d38e0d96083d331981e00c9565abb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Mon, 1 Jan 2018 00:02:58 +0900 Subject: [PATCH 172/186] LICENSE: Update year to 2018 --- LICENSE | 2 +- src/const.json | 2 +- webpack/plugins/banner.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index e3733b3961..0b6e30e45f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2017 syuilo +Copyright (c) 2014-2018 syuilo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/const.json b/src/const.json index 0ee6ac2068..d8fe4fe6cd 100644 --- a/src/const.json +++ b/src/const.json @@ -1,5 +1,5 @@ { - "copyright": "Copyright (c) 2014-2017 syuilo", + "copyright": "Copyright (c) 2014-2018 syuilo", "themeColor": "#ff4e45", "themeColorForeground": "#fff" } diff --git a/webpack/plugins/banner.ts b/webpack/plugins/banner.ts index 47b8cd3555..a8774e0a39 100644 --- a/webpack/plugins/banner.ts +++ b/webpack/plugins/banner.ts @@ -3,7 +3,7 @@ import * as webpack from 'webpack'; export default version => new webpack.BannerPlugin({ banner: - `Misskey v${version} | MIT Licensed, (c) syuilo 2014-2017\n` + + `Misskey v${version} | MIT Licensed, (c) syuilo 2014-2018\n` + 'https://github.com/syuilo/misskey\n' + `built by ${os.hostname()} at ${new Date()}\n` + 'hash:[hash], chunkhash:[chunkhash]' From 727ecf86b90cb128caa40ea4a3ab6aa36969543a Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 1 Jan 2018 01:58:12 +0900 Subject: [PATCH 173/186] Update dependencies :rocket: --- package.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 4df15d421e..ff9069a42f 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ }, "dependencies": { "@fortawesome/fontawesome": "1.0.1", - "@fortawesome/fontawesome-free-brands": "5.0.1", - "@fortawesome/fontawesome-free-regular": "5.0.1", - "@fortawesome/fontawesome-free-solid": "5.0.1", + "@fortawesome/fontawesome-free-brands": "5.0.2", + "@fortawesome/fontawesome-free-regular": "5.0.2", + "@fortawesome/fontawesome-free-solid": "5.0.2", "@prezzemolo/rap": "0.1.2", "@prezzemolo/zip": "0.0.3", "@types/bcryptjs": "2.4.1", @@ -39,9 +39,9 @@ "@types/deep-equal": "1.0.1", "@types/elasticsearch": "5.0.19", "@types/eventemitter3": "2.0.2", - "@types/express": "4.0.39", + "@types/express": "4.11.0", "@types/gm": "1.17.33", - "@types/gulp": "4.0.3", + "@types/gulp": "3.8.36", "@types/gulp-htmlmin": "1.3.31", "@types/gulp-mocha": "0.0.31", "@types/gulp-rename": "0.0.33", @@ -52,17 +52,17 @@ "@types/is-root": "1.0.0", "@types/is-url": "1.2.28", "@types/js-yaml": "3.10.1", - "@types/mkdirp": "^0.5.2", - "@types/mocha": "2.2.44", - "@types/mongodb": "2.2.17", + "@types/mkdirp": "0.5.2", + "@types/mocha": "2.2.45", + "@types/mongodb": "2.2.18", "@types/monk": "1.0.6", "@types/morgan": "1.7.35", "@types/ms": "0.7.30", "@types/multer": "1.3.6", - "@types/node": "8.5.1", + "@types/node": "8.5.2", "@types/page": "1.5.32", "@types/proxy-addr": "2.0.0", - "@types/pug": "^2.0.4", + "@types/pug": "2.0.4", "@types/qrcode": "0.8.0", "@types/ratelimiter": "2.1.28", "@types/redis": "2.8.3", @@ -108,11 +108,11 @@ "gulp-cssnano": "2.1.2", "gulp-htmlmin": "4.0.0", "gulp-imagemin": "4.1.0", - "gulp-mocha": "4.3.1", + "gulp-mocha": "5.0.0", "gulp-pug": "3.3.0", "gulp-rename": "1.2.2", "gulp-replace": "0.6.1", - "gulp-stylus": "^2.6.0", + "gulp-stylus": "2.6.0", "gulp-tslint": "8.1.2", "gulp-typescript": "3.2.3", "gulp-uglify": "3.0.0", @@ -123,8 +123,8 @@ "is-url": "1.2.2", "js-yaml": "3.10.0", "mecab-async": "0.1.2", - "mkdirp": "^0.5.1", - "mocha": "4.0.1", + "mkdirp": "0.5.1", + "mocha": "4.1.0", "moji": "0.5.1", "mongodb": "3.0.1", "monk": "6.0.5", @@ -166,7 +166,7 @@ "ts-node": "4.1.0", "tslint": "5.8.0", "typescript": "2.6.2", - "uglify-es": "3.2.0", + "uglify-es": "3.3.4", "uglifyjs-webpack-plugin": "1.1.5", "uuid": "3.1.0", "vhost": "3.0.2", From 88e4f1b287e9fa6be12b5a2277073265d6732527 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 1 Jan 2018 02:08:41 +0900 Subject: [PATCH 174/186] :v: --- src/common/build/license.ts | 13 +++++++++++++ src/web/docs/license.en.pug | 3 +++ src/web/docs/license.ja.pug | 3 +++ src/web/docs/vars.ts | 3 +++ webpack/module/rules/license.ts | 9 ++------- 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 src/common/build/license.ts create mode 100644 src/web/docs/license.en.pug create mode 100644 src/web/docs/license.ja.pug diff --git a/src/common/build/license.ts b/src/common/build/license.ts new file mode 100644 index 0000000000..e5c264df8a --- /dev/null +++ b/src/common/build/license.ts @@ -0,0 +1,13 @@ +import * as fs from 'fs'; + +const license = fs.readFileSync(__dirname + '/../../../LICENSE', 'utf-8'); + +const licenseHtml = license + .replace(/\r\n/g, '\n') + .replace(/(.)\n(.)/g, '$1 $2') + .replace(/(^|\n)(.*?)($|\n)/g, '

$2

'); + +export { + license, + licenseHtml +}; diff --git a/src/web/docs/license.en.pug b/src/web/docs/license.en.pug new file mode 100644 index 0000000000..240756e7ea --- /dev/null +++ b/src/web/docs/license.en.pug @@ -0,0 +1,3 @@ +h1 License + +div!= common.license diff --git a/src/web/docs/license.ja.pug b/src/web/docs/license.ja.pug new file mode 100644 index 0000000000..1f44f3f5e7 --- /dev/null +++ b/src/web/docs/license.ja.pug @@ -0,0 +1,3 @@ +h1 ライセンス + +div!= common.license diff --git a/src/web/docs/vars.ts b/src/web/docs/vars.ts index 65b224fbff..95ae9ee629 100644 --- a/src/web/docs/vars.ts +++ b/src/web/docs/vars.ts @@ -4,6 +4,7 @@ import * as yaml from 'js-yaml'; import { fa } from '../../common/build/fa'; import config from '../../conf'; +import { licenseHtml } from '../../common/build/license'; const constants = require('../../const.json'); export default function(): { [key: string]: any } { @@ -42,5 +43,7 @@ export default function(): { [key: string]: any } { vars['facss'] = fa.dom.css(); + vars['license'] = licenseHtml; + return vars; } diff --git a/webpack/module/rules/license.ts b/webpack/module/rules/license.ts index 1795af960d..de8b7d79fb 100644 --- a/webpack/module/rules/license.ts +++ b/webpack/module/rules/license.ts @@ -2,13 +2,8 @@ * Inject license */ -import * as fs from 'fs'; const StringReplacePlugin = require('string-replace-webpack-plugin'); - -const license = fs.readFileSync(__dirname + '/../../../LICENSE', 'utf-8') - .replace(/\r\n/g, '\n') - .replace(/(.)\n(.)/g, '$1 $2') - .replace(/(^|\n)(.*?)($|\n)/g, '

$2

'); +import { licenseHtml } from '../../../src/common/build/license'; export default () => ({ enforce: 'pre', @@ -16,7 +11,7 @@ export default () => ({ exclude: /node_modules/, loader: StringReplacePlugin.replace({ replacements: [{ - pattern: '%license%', replacement: () => license + pattern: '%license%', replacement: () => licenseHtml }] }) }); From 77979ec37b732bb9c0797dc5d6c89330561791b4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 1 Jan 2018 02:09:12 +0900 Subject: [PATCH 175/186] v3493 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a05097ff05..6e69a7319e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ChangeLog (Release Notes) ========================= 主に notable な changes を書いていきます +3493 (2018/01/01) +----------------- +* なんか + 3460 (2017/12/23) ----------------- * 検索で複数のユーザーを指定できるように diff --git a/package.json b/package.json index ff9069a42f..9245a6e2a1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "0.0.3460", + "version": "0.0.3493", "license": "MIT", "description": "A miniblog-based SNS", "bugs": "https://github.com/syuilo/misskey/issues", From e93a2991a96d52f0a6b18f07d92798a4172fbe7f Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 1 Jan 2018 02:14:00 +0900 Subject: [PATCH 176/186] Update backup.md --- docs/backup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backup.md b/docs/backup.md index 484564b314..74ec2678e5 100644 --- a/docs/backup.md +++ b/docs/backup.md @@ -7,7 +7,7 @@ Make sure **mongodb-tools** installed. In your shell: ``` shell -$ mongodump --archive=db-backup +$ mongodump --archive=db-backup -u -p ``` For details, plese see [mongodump docs](https://docs.mongodb.com/manual/reference/program/mongodump/). From f7cae37ce48a51b6d199635a05bb79132b8d5505 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 1 Jan 2018 02:26:25 +0900 Subject: [PATCH 177/186] Fix bug --- src/db/mongodb.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts index 1263ccaacd..bbbe70c34f 100644 --- a/src/db/mongodb.ts +++ b/src/db/mongodb.ts @@ -1,7 +1,10 @@ import config from '../conf'; -const uri = config.mongodb.user && config.mongodb.pass - ? `mongodb://${config.mongodb.user}:${config.mongodb.pass}@${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}` +const u = config.mongodb.user ? encodeURIComponent(config.mongodb.user) : null; +const p = config.mongodb.pass ? encodeURIComponent(config.mongodb.pass) : null; + +const uri = u && p + ? `mongodb://${u}:${p}@${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}` : `mongodb://${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}`; /** From 6b9f6c6e3b2f82ea2a466614626b7bfaa6ad9286 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 8 Jan 2018 01:47:56 +0900 Subject: [PATCH 178/186] Show the licenses in the doc --- package.json | 2 ++ src/web/docs/api/gulpfile.ts | 8 ++++---- src/web/docs/gulpfile.ts | 4 ++-- src/web/docs/license.en.pug | 14 ++++++++++++++ src/web/docs/license.ja.pug | 14 ++++++++++++++ src/web/docs/style.styl | 2 ++ src/web/docs/vars.ts | 17 ++++++++++++++++- 7 files changed, 54 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 9245a6e2a1..69c92efdfd 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@types/is-root": "1.0.0", "@types/is-url": "1.2.28", "@types/js-yaml": "3.10.1", + "@types/license-checker": "^15.0.0", "@types/mkdirp": "0.5.2", "@types/mocha": "2.2.45", "@types/mongodb": "2.2.18", @@ -122,6 +123,7 @@ "is-root": "1.0.0", "is-url": "1.2.2", "js-yaml": "3.10.0", + "license-checker": "^15.0.0", "mecab-async": "0.1.2", "mkdirp": "0.5.1", "mocha": "4.1.0", diff --git a/src/web/docs/api/gulpfile.ts b/src/web/docs/api/gulpfile.ts index 4c30871a0f..cd1bf15307 100644 --- a/src/web/docs/api/gulpfile.ts +++ b/src/web/docs/api/gulpfile.ts @@ -17,8 +17,6 @@ import config from './../../../conf'; import generateVars from '../vars'; -const commonVars = generateVars(); - const langs = Object.keys(locales); const kebab = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); @@ -94,7 +92,8 @@ gulp.task('doc:api', [ 'doc:api:entities' ]); -gulp.task('doc:api:endpoints', () => { +gulp.task('doc:api:endpoints', async () => { + const commonVars = await generateVars(); glob('./src/web/docs/api/endpoints/**/*.yaml', (globErr, files) => { if (globErr) { console.error(globErr); @@ -144,7 +143,8 @@ gulp.task('doc:api:endpoints', () => { }); }); -gulp.task('doc:api:entities', () => { +gulp.task('doc:api:entities', async () => { + const commonVars = await generateVars(); glob('./src/web/docs/api/entities/**/*.yaml', (globErr, files) => { if (globErr) { console.error(globErr); diff --git a/src/web/docs/gulpfile.ts b/src/web/docs/gulpfile.ts index 71033e1bc7..d5ddda108d 100644 --- a/src/web/docs/gulpfile.ts +++ b/src/web/docs/gulpfile.ts @@ -23,9 +23,9 @@ gulp.task('doc', [ 'doc:styles' ]); -const commonVars = generateVars(); +gulp.task('doc:docs', async () => { + const commonVars = await generateVars(); -gulp.task('doc:docs', () => { glob('./src/web/docs/**/*.*.pug', (globErr, files) => { if (globErr) { console.error(globErr); diff --git a/src/web/docs/license.en.pug b/src/web/docs/license.en.pug index 240756e7ea..45d8b76473 100644 --- a/src/web/docs/license.en.pug +++ b/src/web/docs/license.en.pug @@ -1,3 +1,17 @@ h1 License div!= common.license + +details + summary Libraries + + section + h2 Libraries + + each dependency, name in common.dependencies + details + summary= name + + section + h3= name + pre= dependency.licenseText diff --git a/src/web/docs/license.ja.pug b/src/web/docs/license.ja.pug index 1f44f3f5e7..7bd9a62941 100644 --- a/src/web/docs/license.ja.pug +++ b/src/web/docs/license.ja.pug @@ -1,3 +1,17 @@ h1 ライセンス div!= common.license + +details + summary ライブラリ + + section + h2 ライブラリ + + each dependency, name in common.dependencies + details + summary= name + + section + h3= name + pre= dependency.licenseText diff --git a/src/web/docs/style.styl b/src/web/docs/style.styl index a726d49b16..bc165f8728 100644 --- a/src/web/docs/style.styl +++ b/src/web/docs/style.styl @@ -114,5 +114,7 @@ code border-radius 4px pre + overflow auto + > code display block diff --git a/src/web/docs/vars.ts b/src/web/docs/vars.ts index 95ae9ee629..6f713f21d0 100644 --- a/src/web/docs/vars.ts +++ b/src/web/docs/vars.ts @@ -1,13 +1,16 @@ import * as fs from 'fs'; +import * as util from 'util'; import * as glob from 'glob'; import * as yaml from 'js-yaml'; +import * as licenseChecker from 'license-checker'; +import * as tmp from 'tmp'; import { fa } from '../../common/build/fa'; import config from '../../conf'; import { licenseHtml } from '../../common/build/license'; const constants = require('../../const.json'); -export default function(): { [key: string]: any } { +export default async function(): Promise<{ [key: string]: any }> { const vars = {} as { [key: string]: any }; const endpoints = glob.sync('./src/web/docs/api/endpoints/**/*.yaml'); @@ -45,5 +48,17 @@ export default function(): { [key: string]: any } { vars['license'] = licenseHtml; + const tmpObj = tmp.fileSync(); + fs.writeFileSync(tmpObj.name, JSON.stringify({ + licenseText: '' + }), 'utf-8'); + const dependencies = await util.promisify(licenseChecker.init).bind(licenseChecker)({ + start: __dirname + '/../../../', + customPath: tmpObj.name + }); + tmpObj.removeCallback(); + + vars['dependencies'] = dependencies; + return vars; } From d8f8730a7423c2c7a3ccc0365680319c2ff57f14 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 19 Jan 2018 09:22:30 +0900 Subject: [PATCH 179/186] Update api.ts --- src/web/app/common/scripts/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/app/common/scripts/api.ts b/src/web/app/common/scripts/api.ts index 2008e6f5ac..bba838f56b 100644 --- a/src/web/app/common/scripts/api.ts +++ b/src/web/app/common/scripts/api.ts @@ -40,7 +40,7 @@ export default (i, endpoint, data = {}): Promise<{ [x: string]: any }> => { } else { res.json().then(err => { reject(err.error); - }); + }, reject); } }).catch(reject); }); From 50528955189a388ef2ad6f984e786d24c895c09a Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 19 Jan 2018 20:34:01 +0900 Subject: [PATCH 180/186] Refactor --- src/api/common/add-file-to-drive.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index 427b54d72b..23cbc44e61 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -266,11 +266,11 @@ export default (user: any, file: string | stream.Readable, ...args) => new Promi } rej(new Error('un-compatible file.')); }) - .then(([path, remove]): Promise => new Promise((res, rej) => { + .then(([path, shouldCleanup]): Promise => new Promise((res, rej) => { addFile(user, path, ...args) .then(file => { res(file); - if (remove) { + if (shouldCleanup) { fs.unlink(path, (e) => { if (e) log(e.stack); }); From 78e99315241a384dc246a78c399e9a8955ab8eb9 Mon Sep 17 00:00:00 2001 From: Aya Morisawa Date: Sun, 21 Jan 2018 15:49:31 +0900 Subject: [PATCH 181/186] Update text.js --- test/text.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/text.js b/test/text.js index 49e2f02b5d..24800ac448 100644 --- a/test/text.js +++ b/test/text.js @@ -8,7 +8,7 @@ const analyze = require('../built/api/common/text').default; const syntaxhighlighter = require('../built/api/common/text/core/syntax-highlighter').default; describe('Text', () => { - it('is correctly analyzed', () => { + it('can be analyzed', () => { const tokens = analyze('@himawari お腹ペコい :cat: #yryr'); assert.deepEqual([ { type: 'mention', content: '@himawari', username: 'himawari' }, @@ -19,7 +19,7 @@ describe('Text', () => { ], tokens); }); - it('逆関数で正しく復元できる', () => { + it('can be inverted', () => { const text = '@himawari お腹ペコい :cat: #yryr'; assert.equal(analyze(text).map(x => x.content).join(''), text); }); From 1dab37bdaebf54d36085068787890c3983b86191 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 2 Feb 2018 07:34:51 +0900 Subject: [PATCH 182/186] Update dependencies :rocket: --- package.json | 60 +++++++++++++++++++++++------------------------ src/db/mongodb.ts | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 69c92efdfd..bd51144807 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@prezzemolo/zip": "0.0.3", "@types/bcryptjs": "2.4.1", "@types/body-parser": "1.16.8", - "@types/chai": "4.0.10", + "@types/chai": "4.1.2", "@types/chai-http": "3.0.3", "@types/compression": "0.0.35", "@types/cookie": "0.3.1", @@ -39,7 +39,7 @@ "@types/deep-equal": "1.0.1", "@types/elasticsearch": "5.0.19", "@types/eventemitter3": "2.0.2", - "@types/express": "4.11.0", + "@types/express": "4.11.1", "@types/gm": "1.17.33", "@types/gulp": "3.8.36", "@types/gulp-htmlmin": "1.3.31", @@ -54,55 +54,55 @@ "@types/js-yaml": "3.10.1", "@types/license-checker": "^15.0.0", "@types/mkdirp": "0.5.2", - "@types/mocha": "2.2.45", - "@types/mongodb": "2.2.18", - "@types/monk": "1.0.6", + "@types/mocha": "2.2.47", + "@types/mongodb": "3.0.5", + "@types/monk": "6.0.0", "@types/morgan": "1.7.35", "@types/ms": "0.7.30", "@types/multer": "1.3.6", - "@types/node": "8.5.2", + "@types/node": "9.4.0", "@types/page": "1.5.32", "@types/proxy-addr": "2.0.0", "@types/pug": "2.0.4", "@types/qrcode": "0.8.0", "@types/ratelimiter": "2.1.28", - "@types/redis": "2.8.3", - "@types/request": "2.0.9", + "@types/redis": "2.8.5", + "@types/request": "2.47.0", "@types/rimraf": "2.0.2", "@types/riot": "3.6.1", "@types/seedrandom": "2.4.27", "@types/serve-favicon": "2.2.30", - "@types/speakeasy": "2.0.1", + "@types/speakeasy": "2.0.2", "@types/tmp": "0.0.33", "@types/uuid": "3.4.3", - "@types/webpack": "3.8.1", + "@types/webpack": "3.8.4", "@types/webpack-stream": "3.2.8", - "@types/websocket": "0.0.35", + "@types/websocket": "0.0.36", "accesses": "2.5.0", "animejs": "2.2.0", "autwh": "0.0.1", "awesome-typescript-loader": "3.4.1", "bcryptjs": "2.4.3", "body-parser": "1.18.2", - "cafy": "3.2.0", + "cafy": "3.2.1", "chai": "4.1.2", "chai-http": "3.0.0", "chalk": "2.3.0", "compression": "1.7.1", "cookie": "0.3.1", "cors": "2.8.4", - "cropperjs": "1.2.1", - "css-loader": "0.28.7", + "cropperjs": "1.2.2", + "css-loader": "0.28.9", "debug": "3.1.0", "deep-equal": "1.0.1", "deepcopy": "0.6.3", "diskusage": "0.2.4", - "elasticsearch": "14.0.0", + "elasticsearch": "14.1.0", "escape-regexp": "0.0.1", "eventemitter3": "3.0.0", "exif-js": "2.3.0", "express": "4.16.2", - "file-type": "7.4.0", + "file-type": "7.5.0", "fuckadblock": "3.2.1", "gm": "1.23.1", "gulp": "3.9.1", @@ -113,29 +113,29 @@ "gulp-pug": "3.3.0", "gulp-rename": "1.2.2", "gulp-replace": "0.6.1", - "gulp-stylus": "2.6.0", + "gulp-stylus": "2.7.0", "gulp-tslint": "8.1.2", - "gulp-typescript": "3.2.3", + "gulp-typescript": "3.2.4", "gulp-uglify": "3.0.0", "gulp-util": "3.0.8", "highlight.js": "9.12.0", - "inquirer": "4.0.1", + "inquirer": "5.0.1", "is-root": "1.0.0", "is-url": "1.2.2", "js-yaml": "3.10.0", - "license-checker": "^15.0.0", + "license-checker": "16.0.0", "mecab-async": "0.1.2", "mkdirp": "0.5.1", - "mocha": "4.1.0", + "mocha": "5.0.0", "moji": "0.5.1", - "mongodb": "3.0.1", + "mongodb": "3.0.2", "monk": "6.0.5", "morgan": "1.9.0", "ms": "2.1.1", "multer": "1.3.0", "nprogress": "0.2.0", "os-utils": "0.0.14", - "page": "1.7.1", + "page": "1.8.3", "pictograph": "2.1.5", "prominence": "0.2.0", "proxy-addr": "2.0.2", @@ -150,13 +150,13 @@ "riot": "3.8.1", "riot-tag-loader": "2.0.2", "rndstr": "1.0.0", - "s-age": "1.1.0", + "s-age": "1.1.2", "seedrandom": "2.4.3", "serve-favicon": "2.4.5", "sortablejs": "1.7.0", "speakeasy": "2.0.0", "string-replace-webpack-plugin": "0.1.3", - "style-loader": "0.19.1", + "style-loader": "0.20.1", "stylus": "0.54.5", "stylus-loader": "3.0.1", "summaly": "2.0.3", @@ -166,11 +166,11 @@ "textarea-caret": "3.0.2", "tmp": "0.0.33", "ts-node": "4.1.0", - "tslint": "5.8.0", - "typescript": "2.6.2", - "uglify-es": "3.3.4", - "uglifyjs-webpack-plugin": "1.1.5", - "uuid": "3.1.0", + "tslint": "5.9.1", + "typescript": "2.7.1", + "uglify-es": "3.3.9", + "uglifyjs-webpack-plugin": "1.1.8", + "uuid": "3.2.1", "vhost": "3.0.2", "web-push": "3.2.5", "webpack": "3.10.0", diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts index bbbe70c34f..233f2f3d79 100644 --- a/src/db/mongodb.ts +++ b/src/db/mongodb.ts @@ -10,7 +10,7 @@ const uri = u && p /** * monk */ -import * as mongo from 'monk'; +import mongo from 'monk'; const db = mongo(uri); From 9a282e37be5ba847718d198d30eb97f31d11f2a0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 2 Feb 2018 08:06:01 +0900 Subject: [PATCH 183/186] wip --- src/api/models/app.ts | 95 ++++++++++- src/api/models/auth-session.ts | 44 ++++- src/api/models/channel.ts | 66 +++++++- src/api/models/drive-file.ts | 84 +++++++++- src/api/models/drive-folder.ts | 67 +++++++- src/api/models/messaging-message.ts | 66 +++++++- src/api/models/notification.ts | 64 +++++++- src/api/models/post-reaction.ts | 47 +++++- src/api/models/post.ts | 189 +++++++++++++++++++++- src/api/models/signin.ts | 28 +++- src/api/models/user.ts | 196 ++++++++++++++++++++++- src/api/serializers/app.ts | 83 ---------- src/api/serializers/auth-session.ts | 40 ----- src/api/serializers/channel.ts | 66 -------- src/api/serializers/drive-file.ts | 78 --------- src/api/serializers/drive-folder.ts | 64 -------- src/api/serializers/drive-tag.ts | 35 ---- src/api/serializers/messaging-message.ts | 68 -------- src/api/serializers/notification.ts | 65 -------- src/api/serializers/post-reaction.ts | 43 ----- src/api/serializers/post.ts | 192 ---------------------- src/api/serializers/signin.ts | 23 --- src/api/serializers/user.ts | 190 ---------------------- 23 files changed, 920 insertions(+), 973 deletions(-) delete mode 100644 src/api/serializers/app.ts delete mode 100644 src/api/serializers/auth-session.ts delete mode 100644 src/api/serializers/channel.ts delete mode 100644 src/api/serializers/drive-file.ts delete mode 100644 src/api/serializers/drive-folder.ts delete mode 100644 src/api/serializers/drive-tag.ts delete mode 100644 src/api/serializers/messaging-message.ts delete mode 100644 src/api/serializers/notification.ts delete mode 100644 src/api/serializers/post-reaction.ts delete mode 100644 src/api/serializers/post.ts delete mode 100644 src/api/serializers/signin.ts delete mode 100644 src/api/serializers/user.ts diff --git a/src/api/models/app.ts b/src/api/models/app.ts index 68f2f448b0..fe9d49ff67 100644 --- a/src/api/models/app.ts +++ b/src/api/models/app.ts @@ -1,13 +1,96 @@ +import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); +import AccessToken from './access-token'; import db from '../../db/mongodb'; +import config from '../../conf'; -const collection = db.get('apps'); +const App = db.get('apps'); +App.createIndex('name_id'); +App.createIndex('name_id_lower'); +App.createIndex('secret'); +export default App; -(collection as any).createIndex('name_id'); // fuck type definition -(collection as any).createIndex('name_id_lower'); // fuck type definition -(collection as any).createIndex('secret'); // fuck type definition - -export default collection as any; // fuck type definition +export type IApp = { + _id: mongo.ObjectID; + created_at: Date; + user_id: mongo.ObjectID; +}; export function isValidNameId(nameId: string): boolean { return typeof nameId == 'string' && /^[a-zA-Z0-9\-]{3,30}$/.test(nameId); } + +/** + * Pack an app for API response + * + * @param {any} app + * @param {any} me? + * @param {any} options? + * @return {Promise} + */ +export const pack = ( + app: any, + me?: any, + options?: { + includeSecret?: boolean, + includeProfileImageIds?: boolean + } +) => new Promise(async (resolve, reject) => { + const opts = options || { + includeSecret: false, + includeProfileImageIds: false + }; + + let _app: any; + + // Populate the app if 'app' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(app)) { + _app = await App.findOne({ + _id: app + }); + } else if (typeof app === 'string') { + _app = await App.findOne({ + _id: new mongo.ObjectID(app) + }); + } else { + _app = deepcopy(app); + } + + // Me + if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { + if (typeof me === 'string') { + me = new mongo.ObjectID(me); + } else { + me = me._id; + } + } + + // Rename _id to id + _app.id = _app._id; + delete _app._id; + + delete _app.name_id_lower; + + // Visible by only owner + if (!opts.includeSecret) { + delete _app.secret; + } + + _app.icon_url = _app.icon != null + ? `${config.drive_url}/${_app.icon}` + : `${config.drive_url}/app-default.jpg`; + + if (me) { + // 既に連携しているか + const exist = await AccessToken.count({ + app_id: _app.id, + user_id: me, + }, { + limit: 1 + }); + + _app.is_authorized = exist === 1; + } + + resolve(_app); +}); diff --git a/src/api/models/auth-session.ts b/src/api/models/auth-session.ts index b264a133e9..997ec61c20 100644 --- a/src/api/models/auth-session.ts +++ b/src/api/models/auth-session.ts @@ -1,3 +1,45 @@ +import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); import db from '../../db/mongodb'; +import { pack as packApp } from './app'; -export default db.get('auth_sessions') as any; // fuck type definition +const AuthSession = db.get('auth_sessions'); +export default AuthSession; + +export interface IAuthSession { + _id: mongo.ObjectID; +} + +/** + * Pack an auth session for API response + * + * @param {any} session + * @param {any} me? + * @return {Promise} + */ +export const pack = ( + session: any, + me?: any +) => new Promise(async (resolve, reject) => { + let _session: any; + + // TODO: Populate session if it ID + + _session = deepcopy(session); + + // Me + if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { + if (typeof me === 'string') { + me = new mongo.ObjectID(me); + } else { + me = me._id; + } + } + + delete _session._id; + + // Populate app + _session.app = await packApp(_session.app_id, me); + + resolve(_session); +}); diff --git a/src/api/models/channel.ts b/src/api/models/channel.ts index c80e84dbc8..815d53593c 100644 --- a/src/api/models/channel.ts +++ b/src/api/models/channel.ts @@ -1,9 +1,11 @@ import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); +import { IUser } from './user'; +import Watching from './channel-watching'; import db from '../../db/mongodb'; -const collection = db.get('channels'); - -export default collection as any; // fuck type definition +const Channel = db.get('channels'); +export default Channel; export type IChannel = { _id: mongo.ObjectID; @@ -12,3 +14,61 @@ export type IChannel = { user_id: mongo.ObjectID; index: number; }; + +/** + * Pack a channel for API response + * + * @param channel target + * @param me? serializee + * @return response + */ +export const pack = ( + channel: string | mongo.ObjectID | IChannel, + me?: string | mongo.ObjectID | IUser +) => new Promise(async (resolve, reject) => { + + let _channel: any; + + // Populate the channel if 'channel' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(channel)) { + _channel = await Channel.findOne({ + _id: channel + }); + } else if (typeof channel === 'string') { + _channel = await Channel.findOne({ + _id: new mongo.ObjectID(channel) + }); + } else { + _channel = deepcopy(channel); + } + + // Rename _id to id + _channel.id = _channel._id; + delete _channel._id; + + // Remove needless properties + delete _channel.user_id; + + // Me + const meId: mongo.ObjectID = me + ? mongo.ObjectID.prototype.isPrototypeOf(me) + ? me as mongo.ObjectID + : typeof me === 'string' + ? new mongo.ObjectID(me) + : (me as IUser)._id + : null; + + if (me) { + //#region Watchしているかどうか + const watch = await Watching.findOne({ + user_id: meId, + channel_id: _channel.id, + deleted_at: { $exists: false } + }); + + _channel.is_watching = watch !== null; + //#endregion + } + + resolve(_channel); +}); diff --git a/src/api/models/drive-file.ts b/src/api/models/drive-file.ts index 802ee5a5fe..6a8db3ad42 100644 --- a/src/api/models/drive-file.ts +++ b/src/api/models/drive-file.ts @@ -1,9 +1,12 @@ import * as mongodb from 'mongodb'; +import deepcopy = require('deepcopy'); +import { pack as packFolder } from './drive-folder'; +import config from '../../conf'; import monkDb, { nativeDbConn } from '../../db/mongodb'; -const collection = monkDb.get('drive_files.files'); +const DriveFile = monkDb.get('drive_files.files'); -export default collection as any; // fuck type definition +export default DriveFile; const getGridFSBucket = async (): Promise => { const db = await nativeDbConn(); @@ -15,6 +18,12 @@ const getGridFSBucket = async (): Promise => { export { getGridFSBucket }; +export type IDriveFile = { + _id: mongodb.ObjectID; + created_at: Date; + user_id: mongodb.ObjectID; +}; + export function validateFileName(name: string): boolean { return ( (name.trim().length > 0) && @@ -24,3 +33,74 @@ export function validateFileName(name: string): boolean { (name.indexOf('..') === -1) ); } + +/** + * Pack a drive file for API response + * + * @param {any} file + * @param {any} options? + * @return {Promise} + */ +export const pack = ( + file: any, + options?: { + detail: boolean + } +) => new Promise(async (resolve, reject) => { + const opts = Object.assign({ + detail: false + }, options); + + let _file: any; + + // Populate the file if 'file' is ID + if (mongodb.ObjectID.prototype.isPrototypeOf(file)) { + _file = await DriveFile.findOne({ + _id: file + }); + } else if (typeof file === 'string') { + _file = await DriveFile.findOne({ + _id: new mongodb.ObjectID(file) + }); + } else { + _file = deepcopy(file); + } + + if (!_file) return reject('invalid file arg.'); + + // rendered target + let _target: any = {}; + + _target.id = _file._id; + _target.created_at = _file.uploadDate; + _target.name = _file.filename; + _target.type = _file.contentType; + _target.datasize = _file.length; + _target.md5 = _file.md5; + + _target = Object.assign(_target, _file.metadata); + + _target.url = `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`; + + if (_target.properties == null) _target.properties = {}; + + if (opts.detail) { + if (_target.folder_id) { + // Populate folder + _target.folder = await packFolder(_target.folder_id, { + detail: true + }); + } + + /* + if (_target.tags) { + // Populate tags + _target.tags = await _target.tags.map(async (tag: any) => + await serializeDriveTag(tag) + ); + } + */ + } + + resolve(_target); +}); diff --git a/src/api/models/drive-folder.ts b/src/api/models/drive-folder.ts index f81ffe855d..48b26c2bd6 100644 --- a/src/api/models/drive-folder.ts +++ b/src/api/models/drive-folder.ts @@ -1,6 +1,16 @@ +import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); import db from '../../db/mongodb'; +import DriveFile from './drive-file'; -export default db.get('drive_folders') as any; // fuck type definition +const DriveFolder = db.get('drive_folders'); +export default DriveFolder; + +export type IDriveFolder = { + _id: mongo.ObjectID; + created_at: Date; + user_id: mongo.ObjectID; +}; export function isValidFolderName(name: string): boolean { return ( @@ -8,3 +18,58 @@ export function isValidFolderName(name: string): boolean { (name.length <= 200) ); } + +/** + * Pack a drive folder for API response + * + * @param {any} folder + * @param {any} options? + * @return {Promise} + */ +export const pack = ( + folder: any, + options?: { + detail: boolean + } +) => new Promise(async (resolve, reject) => { + const opts = Object.assign({ + detail: false + }, options); + + let _folder: any; + + // Populate the folder if 'folder' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(folder)) { + _folder = await DriveFolder.findOne({ _id: folder }); + } else if (typeof folder === 'string') { + _folder = await DriveFolder.findOne({ _id: new mongo.ObjectID(folder) }); + } else { + _folder = deepcopy(folder); + } + + // Rename _id to id + _folder.id = _folder._id; + delete _folder._id; + + if (opts.detail) { + const childFoldersCount = await DriveFolder.count({ + parent_id: _folder.id + }); + + const childFilesCount = await DriveFile.count({ + 'metadata.folder_id': _folder.id + }); + + _folder.folders_count = childFoldersCount; + _folder.files_count = childFilesCount; + } + + if (opts.detail && _folder.parent_id) { + // Populate parent folder + _folder.parent = await pack(_folder.parent_id, { + detail: true + }); + } + + resolve(_folder); +}); diff --git a/src/api/models/messaging-message.ts b/src/api/models/messaging-message.ts index 18afa57e44..ffdda1db21 100644 --- a/src/api/models/messaging-message.ts +++ b/src/api/models/messaging-message.ts @@ -1,7 +1,12 @@ import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); +import { pack as packUser } from './user'; +import { pack as packFile } from './drive-file'; import db from '../../db/mongodb'; +import parse from '../common/text'; -export default db.get('messaging_messages') as any; // fuck type definition +const MessagingMessage = db.get('messaging_messages'); +export default MessagingMessage; export interface IMessagingMessage { _id: mongo.ObjectID; @@ -10,3 +15,62 @@ export interface IMessagingMessage { export function isValidText(text: string): boolean { return text.length <= 1000 && text.trim() != ''; } + +/** + * Pack a messaging message for API response + * + * @param {any} message + * @param {any} me? + * @param {any} options? + * @return {Promise} + */ +export const pack = ( + message: any, + me?: any, + options?: { + populateRecipient: boolean + } +) => new Promise(async (resolve, reject) => { + const opts = options || { + populateRecipient: true + }; + + let _message: any; + + // Populate the message if 'message' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(message)) { + _message = await MessagingMessage.findOne({ + _id: message + }); + } else if (typeof message === 'string') { + _message = await MessagingMessage.findOne({ + _id: new mongo.ObjectID(message) + }); + } else { + _message = deepcopy(message); + } + + // Rename _id to id + _message.id = _message._id; + delete _message._id; + + // Parse text + if (_message.text) { + _message.ast = parse(_message.text); + } + + // Populate user + _message.user = await packUser(_message.user_id, me); + + if (_message.file) { + // Populate file + _message.file = await packFile(_message.file_id); + } + + if (opts.populateRecipient) { + // Populate recipient + _message.recipient = await packUser(_message.recipient_id, me); + } + + resolve(_message); +}); diff --git a/src/api/models/notification.ts b/src/api/models/notification.ts index e3dc6c70a3..fa7049d312 100644 --- a/src/api/models/notification.ts +++ b/src/api/models/notification.ts @@ -1,8 +1,11 @@ import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); import db from '../../db/mongodb'; -import { IUser } from './user'; +import { IUser, pack as packUser } from './user'; +import { pack as packPost } from './post'; -export default db.get('notifications') as any; // fuck type definition +const Notification = db.get('notifications'); +export default Notification; export interface INotification { _id: mongo.ObjectID; @@ -45,3 +48,60 @@ export interface INotification { */ is_read: Boolean; } + +/** + * Pack a notification for API response + * + * @param {any} notification + * @return {Promise} + */ +export const pack = (notification: any) => new Promise(async (resolve, reject) => { + let _notification: any; + + // Populate the notification if 'notification' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(notification)) { + _notification = await Notification.findOne({ + _id: notification + }); + } else if (typeof notification === 'string') { + _notification = await Notification.findOne({ + _id: new mongo.ObjectID(notification) + }); + } else { + _notification = deepcopy(notification); + } + + // Rename _id to id + _notification.id = _notification._id; + delete _notification._id; + + // Rename notifier_id to user_id + _notification.user_id = _notification.notifier_id; + delete _notification.notifier_id; + + const me = _notification.notifiee_id; + delete _notification.notifiee_id; + + // Populate notifier + _notification.user = await packUser(_notification.user_id, me); + + switch (_notification.type) { + case 'follow': + // nope + break; + case 'mention': + case 'reply': + case 'repost': + case 'quote': + case 'reaction': + case 'poll_vote': + // Populate post + _notification.post = await packPost(_notification.post_id, me); + break; + default: + console.error(`Unknown type: ${_notification.type}`); + break; + } + + resolve(_notification); +}); diff --git a/src/api/models/post-reaction.ts b/src/api/models/post-reaction.ts index 282ae5bd21..568bfc89a2 100644 --- a/src/api/models/post-reaction.ts +++ b/src/api/models/post-reaction.ts @@ -1,3 +1,48 @@ +import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); import db from '../../db/mongodb'; +import Reaction from './post-reaction'; +import { pack as packUser } from './user'; -export default db.get('post_reactions') as any; // fuck type definition +const PostReaction = db.get('post_reactions'); +export default PostReaction; + +export interface IPostReaction { + _id: mongo.ObjectID; +} + +/** + * Pack a reaction for API response + * + * @param {any} reaction + * @param {any} me? + * @return {Promise} + */ +export const pack = ( + reaction: any, + me?: any +) => new Promise(async (resolve, reject) => { + let _reaction: any; + + // Populate the reaction if 'reaction' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(reaction)) { + _reaction = await Reaction.findOne({ + _id: reaction + }); + } else if (typeof reaction === 'string') { + _reaction = await Reaction.findOne({ + _id: new mongo.ObjectID(reaction) + }); + } else { + _reaction = deepcopy(reaction); + } + + // Rename _id to id + _reaction.id = _reaction._id; + delete _reaction._id; + + // Populate user + _reaction.user = await packUser(_reaction.user_id, me); + + resolve(_reaction); +}); diff --git a/src/api/models/post.ts b/src/api/models/post.ts index 7584ce182d..ecc5e1a5e4 100644 --- a/src/api/models/post.ts +++ b/src/api/models/post.ts @@ -1,8 +1,18 @@ import * as mongo from 'mongodb'; - +import deepcopy = require('deepcopy'); +import rap from '@prezzemolo/rap'; import db from '../../db/mongodb'; +import { IUser, pack as packUser } from './user'; +import { pack as packApp } from './app'; +import { pack as packChannel } from './channel'; +import Vote from './poll-vote'; +import Reaction from './post-reaction'; +import { pack as packFile } from './drive-file'; +import parse from '../common/text'; -export default db.get('posts') as any; // fuck type definition +const Post = db.get('posts'); + +export default Post; export function isValidText(text: string): boolean { return text.length <= 1000 && text.trim() != ''; @@ -20,3 +30,178 @@ export type IPost = { user_id: mongo.ObjectID; app_id: mongo.ObjectID; }; + +/** + * Pack a post for API response + * + * @param post target + * @param me? serializee + * @param options? serialize options + * @return response + */ +export const pack = async ( + post: string | mongo.ObjectID | IPost, + me?: string | mongo.ObjectID | IUser, + options?: { + detail: boolean + } +) => { + const opts = options || { + detail: true, + }; + + // Me + const meId: mongo.ObjectID = me + ? mongo.ObjectID.prototype.isPrototypeOf(me) + ? me as mongo.ObjectID + : typeof me === 'string' + ? new mongo.ObjectID(me) + : (me as IUser)._id + : null; + + let _post: any; + + // Populate the post if 'post' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(post)) { + _post = await Post.findOne({ + _id: post + }); + } else if (typeof post === 'string') { + _post = await Post.findOne({ + _id: new mongo.ObjectID(post) + }); + } else { + _post = deepcopy(post); + } + + if (!_post) throw 'invalid post arg.'; + + const id = _post._id; + + // Rename _id to id + _post.id = _post._id; + delete _post._id; + + delete _post.mentions; + + // Parse text + if (_post.text) { + _post.ast = parse(_post.text); + } + + // Populate user + _post.user = packUser(_post.user_id, meId); + + // Populate app + if (_post.app_id) { + _post.app = packApp(_post.app_id); + } + + // Populate channel + if (_post.channel_id) { + _post.channel = packChannel(_post.channel_id); + } + + // Populate media + if (_post.media_ids) { + _post.media = Promise.all(_post.media_ids.map(fileId => + packFile(fileId) + )); + } + + // When requested a detailed post data + if (opts.detail) { + // Get previous post info + _post.prev = (async () => { + const prev = await Post.findOne({ + user_id: _post.user_id, + _id: { + $lt: id + } + }, { + fields: { + _id: true + }, + sort: { + _id: -1 + } + }); + return prev ? prev._id : null; + })(); + + // Get next post info + _post.next = (async () => { + const next = await Post.findOne({ + user_id: _post.user_id, + _id: { + $gt: id + } + }, { + fields: { + _id: true + }, + sort: { + _id: 1 + } + }); + return next ? next._id : null; + })(); + + if (_post.reply_id) { + // Populate reply to post + _post.reply = pack(_post.reply_id, meId, { + detail: false + }); + } + + if (_post.repost_id) { + // Populate repost + _post.repost = pack(_post.repost_id, meId, { + detail: _post.text == null + }); + } + + // Poll + if (meId && _post.poll) { + _post.poll = (async (poll) => { + const vote = await Vote + .findOne({ + user_id: meId, + post_id: id + }); + + if (vote != null) { + const myChoice = poll.choices + .filter(c => c.id == vote.choice)[0]; + + myChoice.is_voted = true; + } + + return poll; + })(_post.poll); + } + + // Fetch my reaction + if (meId) { + _post.my_reaction = (async () => { + const reaction = await Reaction + .findOne({ + user_id: meId, + post_id: id, + deleted_at: { $exists: false } + }); + + if (reaction) { + return reaction.reaction; + } + + return null; + })(); + } + } + + // resolve promises in _post object + _post = await rap(_post); + + return _post; +}; diff --git a/src/api/models/signin.ts b/src/api/models/signin.ts index 385a348f2e..262c8707ed 100644 --- a/src/api/models/signin.ts +++ b/src/api/models/signin.ts @@ -1,3 +1,29 @@ +import * as mongo from 'mongodb'; +import deepcopy = require('deepcopy'); import db from '../../db/mongodb'; -export default db.get('signin') as any; // fuck type definition +const Signin = db.get('signin'); +export default Signin; + +export interface ISignin { + _id: mongo.ObjectID; +} + +/** + * Pack a signin record for API response + * + * @param {any} record + * @return {Promise} + */ +export const pack = ( + record: any +) => new Promise(async (resolve, reject) => { + + const _record = deepcopy(record); + + // Rename _id to id + _record.id = _record._id; + delete _record._id; + + resolve(_record); +}); diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 018979158f..48a45ac2f7 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -1,14 +1,19 @@ import * as mongo from 'mongodb'; - +import deepcopy = require('deepcopy'); +import rap from '@prezzemolo/rap'; import db from '../../db/mongodb'; -import { IPost } from './post'; +import { IPost, pack as packPost } from './post'; +import Following from './following'; +import Mute from './mute'; +import getFriends from '../common/get-friends'; +import config from '../../conf'; -const collection = db.get('users'); +const User = db.get('users'); -(collection as any).createIndex('username'); // fuck type definition -(collection as any).createIndex('token'); // fuck type definition +User.createIndex('username'); +User.createIndex('token'); -export default collection as any; // fuck type definition +export default User; export function validateUsername(username: string): boolean { return typeof username == 'string' && /^[a-zA-Z0-9\-]{3,20}$/.test(username); @@ -83,3 +88,182 @@ export function init(user): IUser { user.pinned_post_id = new mongo.ObjectID(user.pinned_post_id); return user; } + +/** + * Pack a user for API response + * + * @param user target + * @param me? serializee + * @param options? serialize options + * @return Packed user + */ +export const pack = ( + user: string | mongo.ObjectID | IUser, + me?: string | mongo.ObjectID | IUser, + options?: { + detail?: boolean, + includeSecrets?: boolean + } +) => new Promise(async (resolve, reject) => { + + const opts = Object.assign({ + detail: false, + includeSecrets: false + }, options); + + let _user: any; + + const fields = opts.detail ? { + settings: false + } : { + settings: false, + client_settings: false, + profile: false, + keywords: false, + domains: false + }; + + // Populate the user if 'user' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(user)) { + _user = await User.findOne({ + _id: user + }, { fields }); + } else if (typeof user === 'string') { + _user = await User.findOne({ + _id: new mongo.ObjectID(user) + }, { fields }); + } else { + _user = deepcopy(user); + } + + if (!_user) return reject('invalid user arg.'); + + // Me + const meId: mongo.ObjectID = me + ? mongo.ObjectID.prototype.isPrototypeOf(me) + ? me as mongo.ObjectID + : typeof me === 'string' + ? new mongo.ObjectID(me) + : (me as IUser)._id + : null; + + // Rename _id to id + _user.id = _user._id; + delete _user._id; + + // Remove needless properties + delete _user.latest_post; + + // Remove private properties + delete _user.password; + delete _user.token; + delete _user.two_factor_temp_secret; + delete _user.two_factor_secret; + delete _user.username_lower; + if (_user.twitter) { + delete _user.twitter.access_token; + delete _user.twitter.access_token_secret; + } + delete _user.line; + + // Visible via only the official client + if (!opts.includeSecrets) { + delete _user.email; + delete _user.client_settings; + } + + if (!opts.detail) { + delete _user.two_factor_enabled; + } + + _user.avatar_url = _user.avatar_id != null + ? `${config.drive_url}/${_user.avatar_id}` + : `${config.drive_url}/default-avatar.jpg`; + + _user.banner_url = _user.banner_id != null + ? `${config.drive_url}/${_user.banner_id}` + : null; + + if (!meId || !meId.equals(_user.id) || !opts.detail) { + delete _user.avatar_id; + delete _user.banner_id; + + delete _user.drive_capacity; + } + + if (meId && !meId.equals(_user.id)) { + // Whether the user is following + _user.is_following = (async () => { + const follow = await Following.findOne({ + follower_id: meId, + followee_id: _user.id, + deleted_at: { $exists: false } + }); + return follow !== null; + })(); + + // Whether the user is followed + _user.is_followed = (async () => { + const follow2 = await Following.findOne({ + follower_id: _user.id, + followee_id: meId, + deleted_at: { $exists: false } + }); + return follow2 !== null; + })(); + + // Whether the user is muted + _user.is_muted = (async () => { + const mute = await Mute.findOne({ + muter_id: meId, + mutee_id: _user.id, + deleted_at: { $exists: false } + }); + return mute !== null; + })(); + } + + if (opts.detail) { + if (_user.pinned_post_id) { + // Populate pinned post + _user.pinned_post = packPost(_user.pinned_post_id, meId, { + detail: true + }); + } + + if (meId && !meId.equals(_user.id)) { + const myFollowingIds = await getFriends(meId); + + // Get following you know count + _user.following_you_know_count = Following.count({ + followee_id: { $in: myFollowingIds }, + follower_id: _user.id, + deleted_at: { $exists: false } + }); + + // Get followers you know count + _user.followers_you_know_count = Following.count({ + followee_id: _user.id, + follower_id: { $in: myFollowingIds }, + deleted_at: { $exists: false } + }); + } + } + + // resolve promises in _user object + _user = await rap(_user); + + resolve(_user); +}); + +/* +function img(url) { + return { + thumbnail: { + large: `${url}`, + medium: '', + small: '' + } + }; +} +*/ diff --git a/src/api/serializers/app.ts b/src/api/serializers/app.ts deleted file mode 100644 index 9d1c46dca4..0000000000 --- a/src/api/serializers/app.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import App from '../models/app'; -import AccessToken from '../models/access-token'; -import config from '../../conf'; - -/** - * Serialize an app - * - * @param {any} app - * @param {any} me? - * @param {any} options? - * @return {Promise} - */ -export default ( - app: any, - me?: any, - options?: { - includeSecret?: boolean, - includeProfileImageIds?: boolean - } -) => new Promise(async (resolve, reject) => { - const opts = options || { - includeSecret: false, - includeProfileImageIds: false - }; - - let _app: any; - - // Populate the app if 'app' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(app)) { - _app = await App.findOne({ - _id: app - }); - } else if (typeof app === 'string') { - _app = await App.findOne({ - _id: new mongo.ObjectID(app) - }); - } else { - _app = deepcopy(app); - } - - // Me - if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { - if (typeof me === 'string') { - me = new mongo.ObjectID(me); - } else { - me = me._id; - } - } - - // Rename _id to id - _app.id = _app._id; - delete _app._id; - - delete _app.name_id_lower; - - // Visible by only owner - if (!opts.includeSecret) { - delete _app.secret; - } - - _app.icon_url = _app.icon != null - ? `${config.drive_url}/${_app.icon}` - : `${config.drive_url}/app-default.jpg`; - - if (me) { - // 既に連携しているか - const exist = await AccessToken.count({ - app_id: _app.id, - user_id: me, - }, { - limit: 1 - }); - - _app.is_authorized = exist === 1; - } - - resolve(_app); -}); diff --git a/src/api/serializers/auth-session.ts b/src/api/serializers/auth-session.ts deleted file mode 100644 index a9acf1243a..0000000000 --- a/src/api/serializers/auth-session.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import serializeApp from './app'; - -/** - * Serialize an auth session - * - * @param {any} session - * @param {any} me? - * @return {Promise} - */ -export default ( - session: any, - me?: any -) => new Promise(async (resolve, reject) => { - let _session: any; - - // TODO: Populate session if it ID - - _session = deepcopy(session); - - // Me - if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) { - if (typeof me === 'string') { - me = new mongo.ObjectID(me); - } else { - me = me._id; - } - } - - delete _session._id; - - // Populate app - _session.app = await serializeApp(_session.app_id, me); - - resolve(_session); -}); diff --git a/src/api/serializers/channel.ts b/src/api/serializers/channel.ts deleted file mode 100644 index 3cba39aa16..0000000000 --- a/src/api/serializers/channel.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import { IUser } from '../models/user'; -import { default as Channel, IChannel } from '../models/channel'; -import Watching from '../models/channel-watching'; - -/** - * Serialize a channel - * - * @param channel target - * @param me? serializee - * @return response - */ -export default ( - channel: string | mongo.ObjectID | IChannel, - me?: string | mongo.ObjectID | IUser -) => new Promise(async (resolve, reject) => { - - let _channel: any; - - // Populate the channel if 'channel' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(channel)) { - _channel = await Channel.findOne({ - _id: channel - }); - } else if (typeof channel === 'string') { - _channel = await Channel.findOne({ - _id: new mongo.ObjectID(channel) - }); - } else { - _channel = deepcopy(channel); - } - - // Rename _id to id - _channel.id = _channel._id; - delete _channel._id; - - // Remove needless properties - delete _channel.user_id; - - // Me - const meId: mongo.ObjectID = me - ? mongo.ObjectID.prototype.isPrototypeOf(me) - ? me as mongo.ObjectID - : typeof me === 'string' - ? new mongo.ObjectID(me) - : (me as IUser)._id - : null; - - if (me) { - //#region Watchしているかどうか - const watch = await Watching.findOne({ - user_id: meId, - channel_id: _channel.id, - deleted_at: { $exists: false } - }); - - _channel.is_watching = watch !== null; - //#endregion - } - - resolve(_channel); -}); diff --git a/src/api/serializers/drive-file.ts b/src/api/serializers/drive-file.ts deleted file mode 100644 index 003e09ee77..0000000000 --- a/src/api/serializers/drive-file.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFile from '../models/drive-file'; -import serializeDriveFolder from './drive-folder'; -import serializeDriveTag from './drive-tag'; -import deepcopy = require('deepcopy'); -import config from '../../conf'; - -/** - * Serialize a drive file - * - * @param {any} file - * @param {any} options? - * @return {Promise} - */ -export default ( - file: any, - options?: { - detail: boolean - } -) => new Promise(async (resolve, reject) => { - const opts = Object.assign({ - detail: false - }, options); - - let _file: any; - - // Populate the file if 'file' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(file)) { - _file = await DriveFile.findOne({ - _id: file - }); - } else if (typeof file === 'string') { - _file = await DriveFile.findOne({ - _id: new mongo.ObjectID(file) - }); - } else { - _file = deepcopy(file); - } - - if (!_file) return reject('invalid file arg.'); - - // rendered target - let _target: any = {}; - - _target.id = _file._id; - _target.created_at = _file.uploadDate; - _target.name = _file.filename; - _target.type = _file.contentType; - _target.datasize = _file.length; - _target.md5 = _file.md5; - - _target = Object.assign(_target, _file.metadata); - - _target.url = `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`; - - if (_target.properties == null) _target.properties = {}; - - if (opts.detail) { - if (_target.folder_id) { - // Populate folder - _target.folder = await serializeDriveFolder(_target.folder_id, { - detail: true - }); - } - - if (_target.tags) { - // Populate tags - _target.tags = await _target.tags.map(async (tag: any) => - await serializeDriveTag(tag) - ); - } - } - - resolve(_target); -}); diff --git a/src/api/serializers/drive-folder.ts b/src/api/serializers/drive-folder.ts deleted file mode 100644 index 6ebf454a28..0000000000 --- a/src/api/serializers/drive-folder.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../models/drive-folder'; -import DriveFile from '../models/drive-file'; -import deepcopy = require('deepcopy'); - -/** - * Serialize a drive folder - * - * @param {any} folder - * @param {any} options? - * @return {Promise} - */ -const self = ( - folder: any, - options?: { - detail: boolean - } -) => new Promise(async (resolve, reject) => { - const opts = Object.assign({ - detail: false - }, options); - - let _folder: any; - - // Populate the folder if 'folder' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(folder)) { - _folder = await DriveFolder.findOne({ _id: folder }); - } else if (typeof folder === 'string') { - _folder = await DriveFolder.findOne({ _id: new mongo.ObjectID(folder) }); - } else { - _folder = deepcopy(folder); - } - - // Rename _id to id - _folder.id = _folder._id; - delete _folder._id; - - if (opts.detail) { - const childFoldersCount = await DriveFolder.count({ - parent_id: _folder.id - }); - - const childFilesCount = await DriveFile.count({ - 'metadata.folder_id': _folder.id - }); - - _folder.folders_count = childFoldersCount; - _folder.files_count = childFilesCount; - } - - if (opts.detail && _folder.parent_id) { - // Populate parent folder - _folder.parent = await self(_folder.parent_id, { - detail: true - }); - } - - resolve(_folder); -}); - -export default self; diff --git a/src/api/serializers/drive-tag.ts b/src/api/serializers/drive-tag.ts deleted file mode 100644 index 2f152381bd..0000000000 --- a/src/api/serializers/drive-tag.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveTag from '../models/drive-tag'; -import deepcopy = require('deepcopy'); - -/** - * Serialize a drive tag - * - * @param {any} tag - * @return {Promise} - */ -const self = ( - tag: any -) => new Promise(async (resolve, reject) => { - let _tag: any; - - // Populate the tag if 'tag' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(tag)) { - _tag = await DriveTag.findOne({ _id: tag }); - } else if (typeof tag === 'string') { - _tag = await DriveTag.findOne({ _id: new mongo.ObjectID(tag) }); - } else { - _tag = deepcopy(tag); - } - - // Rename _id to id - _tag.id = _tag._id; - delete _tag._id; - - resolve(_tag); -}); - -export default self; diff --git a/src/api/serializers/messaging-message.ts b/src/api/serializers/messaging-message.ts deleted file mode 100644 index 4ab95e42a3..0000000000 --- a/src/api/serializers/messaging-message.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import Message from '../models/messaging-message'; -import serializeUser from './user'; -import serializeDriveFile from './drive-file'; -import parse from '../common/text'; - -/** - * Serialize a message - * - * @param {any} message - * @param {any} me? - * @param {any} options? - * @return {Promise} - */ -export default ( - message: any, - me?: any, - options?: { - populateRecipient: boolean - } -) => new Promise(async (resolve, reject) => { - const opts = options || { - populateRecipient: true - }; - - let _message: any; - - // Populate the message if 'message' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(message)) { - _message = await Message.findOne({ - _id: message - }); - } else if (typeof message === 'string') { - _message = await Message.findOne({ - _id: new mongo.ObjectID(message) - }); - } else { - _message = deepcopy(message); - } - - // Rename _id to id - _message.id = _message._id; - delete _message._id; - - // Parse text - if (_message.text) { - _message.ast = parse(_message.text); - } - - // Populate user - _message.user = await serializeUser(_message.user_id, me); - - if (_message.file) { - // Populate file - _message.file = await serializeDriveFile(_message.file_id); - } - - if (opts.populateRecipient) { - // Populate recipient - _message.recipient = await serializeUser(_message.recipient_id, me); - } - - resolve(_message); -}); diff --git a/src/api/serializers/notification.ts b/src/api/serializers/notification.ts deleted file mode 100644 index ac919dc8b0..0000000000 --- a/src/api/serializers/notification.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import Notification from '../models/notification'; -import serializeUser from './user'; -import serializePost from './post'; -import deepcopy = require('deepcopy'); - -/** - * Serialize a notification - * - * @param {any} notification - * @return {Promise} - */ -export default (notification: any) => new Promise(async (resolve, reject) => { - let _notification: any; - - // Populate the notification if 'notification' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(notification)) { - _notification = await Notification.findOne({ - _id: notification - }); - } else if (typeof notification === 'string') { - _notification = await Notification.findOne({ - _id: new mongo.ObjectID(notification) - }); - } else { - _notification = deepcopy(notification); - } - - // Rename _id to id - _notification.id = _notification._id; - delete _notification._id; - - // Rename notifier_id to user_id - _notification.user_id = _notification.notifier_id; - delete _notification.notifier_id; - - const me = _notification.notifiee_id; - delete _notification.notifiee_id; - - // Populate notifier - _notification.user = await serializeUser(_notification.user_id, me); - - switch (_notification.type) { - case 'follow': - // nope - break; - case 'mention': - case 'reply': - case 'repost': - case 'quote': - case 'reaction': - case 'poll_vote': - // Populate post - _notification.post = await serializePost(_notification.post_id, me); - break; - default: - console.error(`Unknown type: ${_notification.type}`); - break; - } - - resolve(_notification); -}); diff --git a/src/api/serializers/post-reaction.ts b/src/api/serializers/post-reaction.ts deleted file mode 100644 index b8807a741c..0000000000 --- a/src/api/serializers/post-reaction.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import Reaction from '../models/post-reaction'; -import serializeUser from './user'; - -/** - * Serialize a reaction - * - * @param {any} reaction - * @param {any} me? - * @return {Promise} - */ -export default ( - reaction: any, - me?: any -) => new Promise(async (resolve, reject) => { - let _reaction: any; - - // Populate the reaction if 'reaction' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(reaction)) { - _reaction = await Reaction.findOne({ - _id: reaction - }); - } else if (typeof reaction === 'string') { - _reaction = await Reaction.findOne({ - _id: new mongo.ObjectID(reaction) - }); - } else { - _reaction = deepcopy(reaction); - } - - // Rename _id to id - _reaction.id = _reaction._id; - delete _reaction._id; - - // Populate user - _reaction.user = await serializeUser(_reaction.user_id, me); - - resolve(_reaction); -}); diff --git a/src/api/serializers/post.ts b/src/api/serializers/post.ts deleted file mode 100644 index 03fd120772..0000000000 --- a/src/api/serializers/post.ts +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import { default as Post, IPost } from '../models/post'; -import Reaction from '../models/post-reaction'; -import { IUser } from '../models/user'; -import Vote from '../models/poll-vote'; -import serializeApp from './app'; -import serializeChannel from './channel'; -import serializeUser from './user'; -import serializeDriveFile from './drive-file'; -import parse from '../common/text'; -import rap from '@prezzemolo/rap'; - -/** - * Serialize a post - * - * @param post target - * @param me? serializee - * @param options? serialize options - * @return response - */ -const self = async ( - post: string | mongo.ObjectID | IPost, - me?: string | mongo.ObjectID | IUser, - options?: { - detail: boolean - } -) => { - const opts = options || { - detail: true, - }; - - // Me - const meId: mongo.ObjectID = me - ? mongo.ObjectID.prototype.isPrototypeOf(me) - ? me as mongo.ObjectID - : typeof me === 'string' - ? new mongo.ObjectID(me) - : (me as IUser)._id - : null; - - let _post: any; - - // Populate the post if 'post' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(post)) { - _post = await Post.findOne({ - _id: post - }); - } else if (typeof post === 'string') { - _post = await Post.findOne({ - _id: new mongo.ObjectID(post) - }); - } else { - _post = deepcopy(post); - } - - if (!_post) throw 'invalid post arg.'; - - const id = _post._id; - - // Rename _id to id - _post.id = _post._id; - delete _post._id; - - delete _post.mentions; - - // Parse text - if (_post.text) { - _post.ast = parse(_post.text); - } - - // Populate user - _post.user = serializeUser(_post.user_id, meId); - - // Populate app - if (_post.app_id) { - _post.app = serializeApp(_post.app_id); - } - - // Populate channel - if (_post.channel_id) { - _post.channel = serializeChannel(_post.channel_id); - } - - // Populate media - if (_post.media_ids) { - _post.media = Promise.all(_post.media_ids.map(fileId => - serializeDriveFile(fileId) - )); - } - - // When requested a detailed post data - if (opts.detail) { - // Get previous post info - _post.prev = (async () => { - const prev = await Post.findOne({ - user_id: _post.user_id, - _id: { - $lt: id - } - }, { - fields: { - _id: true - }, - sort: { - _id: -1 - } - }); - return prev ? prev._id : null; - })(); - - // Get next post info - _post.next = (async () => { - const next = await Post.findOne({ - user_id: _post.user_id, - _id: { - $gt: id - } - }, { - fields: { - _id: true - }, - sort: { - _id: 1 - } - }); - return next ? next._id : null; - })(); - - if (_post.reply_id) { - // Populate reply to post - _post.reply = self(_post.reply_id, meId, { - detail: false - }); - } - - if (_post.repost_id) { - // Populate repost - _post.repost = self(_post.repost_id, meId, { - detail: _post.text == null - }); - } - - // Poll - if (meId && _post.poll) { - _post.poll = (async (poll) => { - const vote = await Vote - .findOne({ - user_id: meId, - post_id: id - }); - - if (vote != null) { - const myChoice = poll.choices - .filter(c => c.id == vote.choice)[0]; - - myChoice.is_voted = true; - } - - return poll; - })(_post.poll); - } - - // Fetch my reaction - if (meId) { - _post.my_reaction = (async () => { - const reaction = await Reaction - .findOne({ - user_id: meId, - post_id: id, - deleted_at: { $exists: false } - }); - - if (reaction) { - return reaction.reaction; - } - - return null; - })(); - } - } - - // resolve promises in _post object - _post = await rap(_post); - - return _post; -}; - -export default self; diff --git a/src/api/serializers/signin.ts b/src/api/serializers/signin.ts deleted file mode 100644 index 4068067678..0000000000 --- a/src/api/serializers/signin.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Module dependencies - */ -import deepcopy = require('deepcopy'); - -/** - * Serialize a signin record - * - * @param {any} record - * @return {Promise} - */ -export default ( - record: any -) => new Promise(async (resolve, reject) => { - - const _record = deepcopy(record); - - // Rename _id to id - _record.id = _record._id; - delete _record._id; - - resolve(_record); -}); diff --git a/src/api/serializers/user.ts b/src/api/serializers/user.ts deleted file mode 100644 index ac157097a8..0000000000 --- a/src/api/serializers/user.ts +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import deepcopy = require('deepcopy'); -import { default as User, IUser } from '../models/user'; -import serializePost from './post'; -import Following from '../models/following'; -import Mute from '../models/mute'; -import getFriends from '../common/get-friends'; -import config from '../../conf'; -import rap from '@prezzemolo/rap'; - -/** - * Serialize a user - * - * @param user target - * @param me? serializee - * @param options? serialize options - * @return response - */ -export default ( - user: string | mongo.ObjectID | IUser, - me?: string | mongo.ObjectID | IUser, - options?: { - detail?: boolean, - includeSecrets?: boolean - } -) => new Promise(async (resolve, reject) => { - - const opts = Object.assign({ - detail: false, - includeSecrets: false - }, options); - - let _user: any; - - const fields = opts.detail ? { - settings: false - } : { - settings: false, - client_settings: false, - profile: false, - keywords: false, - domains: false - }; - - // Populate the user if 'user' is ID - if (mongo.ObjectID.prototype.isPrototypeOf(user)) { - _user = await User.findOne({ - _id: user - }, { fields }); - } else if (typeof user === 'string') { - _user = await User.findOne({ - _id: new mongo.ObjectID(user) - }, { fields }); - } else { - _user = deepcopy(user); - } - - if (!_user) return reject('invalid user arg.'); - - // Me - const meId: mongo.ObjectID = me - ? mongo.ObjectID.prototype.isPrototypeOf(me) - ? me as mongo.ObjectID - : typeof me === 'string' - ? new mongo.ObjectID(me) - : (me as IUser)._id - : null; - - // Rename _id to id - _user.id = _user._id; - delete _user._id; - - // Remove needless properties - delete _user.latest_post; - - // Remove private properties - delete _user.password; - delete _user.token; - delete _user.two_factor_temp_secret; - delete _user.two_factor_secret; - delete _user.username_lower; - if (_user.twitter) { - delete _user.twitter.access_token; - delete _user.twitter.access_token_secret; - } - delete _user.line; - - // Visible via only the official client - if (!opts.includeSecrets) { - delete _user.email; - delete _user.client_settings; - } - - if (!opts.detail) { - delete _user.two_factor_enabled; - } - - _user.avatar_url = _user.avatar_id != null - ? `${config.drive_url}/${_user.avatar_id}` - : `${config.drive_url}/default-avatar.jpg`; - - _user.banner_url = _user.banner_id != null - ? `${config.drive_url}/${_user.banner_id}` - : null; - - if (!meId || !meId.equals(_user.id) || !opts.detail) { - delete _user.avatar_id; - delete _user.banner_id; - - delete _user.drive_capacity; - } - - if (meId && !meId.equals(_user.id)) { - // Whether the user is following - _user.is_following = (async () => { - const follow = await Following.findOne({ - follower_id: meId, - followee_id: _user.id, - deleted_at: { $exists: false } - }); - return follow !== null; - })(); - - // Whether the user is followed - _user.is_followed = (async () => { - const follow2 = await Following.findOne({ - follower_id: _user.id, - followee_id: meId, - deleted_at: { $exists: false } - }); - return follow2 !== null; - })(); - - // Whether the user is muted - _user.is_muted = (async () => { - const mute = await Mute.findOne({ - muter_id: meId, - mutee_id: _user.id, - deleted_at: { $exists: false } - }); - return mute !== null; - })(); - } - - if (opts.detail) { - if (_user.pinned_post_id) { - // Populate pinned post - _user.pinned_post = serializePost(_user.pinned_post_id, meId, { - detail: true - }); - } - - if (meId && !meId.equals(_user.id)) { - const myFollowingIds = await getFriends(meId); - - // Get following you know count - _user.following_you_know_count = Following.count({ - followee_id: { $in: myFollowingIds }, - follower_id: _user.id, - deleted_at: { $exists: false } - }); - - // Get followers you know count - _user.followers_you_know_count = Following.count({ - followee_id: _user.id, - follower_id: { $in: myFollowingIds }, - deleted_at: { $exists: false } - }); - } - } - - // resolve promises in _user object - _user = await rap(_user); - - resolve(_user); -}); -/* -function img(url) { - return { - thumbnail: { - large: `${url}`, - medium: '', - small: '' - } - }; -} -*/ From 718060dc855e09f270b8e19c089ed3c3743665e0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 2 Feb 2018 08:21:30 +0900 Subject: [PATCH 184/186] wip --- src/api/common/add-file-to-drive.ts | 4 ++-- src/api/common/notify.ts | 6 +++--- src/api/endpoints/app/create.ts | 4 ++-- src/api/endpoints/app/show.ts | 4 ++-- src/api/endpoints/auth/session/show.ts | 4 ++-- src/api/endpoints/auth/session/userkey.ts | 4 ++-- src/api/endpoints/channels.ts | 4 ++-- src/api/endpoints/channels/create.ts | 4 ++-- src/api/endpoints/channels/posts.ts | 4 ++-- src/api/endpoints/channels/show.ts | 4 ++-- src/api/endpoints/drive/files.ts | 4 ++-- src/api/endpoints/drive/files/create.ts | 4 ++-- src/api/endpoints/drive/files/find.ts | 4 ++-- src/api/endpoints/drive/files/show.ts | 4 ++-- src/api/endpoints/drive/files/update.ts | 4 ++-- src/api/endpoints/drive/files/upload_from_url.ts | 4 ++-- src/api/endpoints/drive/folders.ts | 4 ++-- src/api/endpoints/drive/folders/create.ts | 4 ++-- src/api/endpoints/drive/folders/find.ts | 4 ++-- src/api/endpoints/drive/folders/show.ts | 4 ++-- src/api/endpoints/drive/folders/update.ts | 4 ++-- src/api/endpoints/drive/stream.ts | 4 ++-- src/api/endpoints/i.ts | 4 ++-- src/api/endpoints/i/authorized_apps.ts | 4 ++-- src/api/endpoints/i/favorites.ts | 4 ++-- src/api/endpoints/i/notifications.ts | 4 ++-- src/api/endpoints/i/pin.ts | 4 ++-- src/api/endpoints/i/signin_history.ts | 4 ++-- src/api/endpoints/i/update.ts | 4 ++-- src/api/endpoints/messaging/history.ts | 4 ++-- src/api/endpoints/messaging/messages.ts | 4 ++-- src/api/endpoints/messaging/messages/create.ts | 4 ++-- src/api/endpoints/mute/list.ts | 4 ++-- src/api/endpoints/my/apps.ts | 4 ++-- src/api/endpoints/posts.ts | 4 ++-- src/api/endpoints/posts/context.ts | 4 ++-- src/api/endpoints/posts/create.ts | 4 ++-- src/api/endpoints/posts/mentions.ts | 4 ++-- src/api/endpoints/posts/polls/recommendation.ts | 4 ++-- src/api/endpoints/posts/reactions.ts | 4 ++-- src/api/endpoints/posts/replies.ts | 4 ++-- src/api/endpoints/posts/reposts.ts | 4 ++-- src/api/endpoints/posts/search.ts | 4 ++-- src/api/endpoints/posts/show.ts | 4 ++-- src/api/endpoints/posts/timeline.ts | 4 ++-- src/api/endpoints/posts/trend.ts | 4 ++-- src/api/endpoints/users.ts | 4 ++-- src/api/endpoints/users/followers.ts | 4 ++-- src/api/endpoints/users/following.ts | 4 ++-- .../endpoints/users/get_frequently_replied_users.ts | 4 ++-- src/api/endpoints/users/posts.ts | 4 ++-- src/api/endpoints/users/recommendation.ts | 4 ++-- src/api/endpoints/users/search.ts | 4 ++-- src/api/endpoints/users/search_by_username.ts | 4 ++-- src/api/endpoints/users/show.ts | 4 ++-- src/api/models/drive-file.ts | 10 ++++++++-- src/api/models/drive-folder.ts | 2 ++ src/api/models/messaging-message.ts | 5 +++++ src/api/private/signin.ts | 4 ++-- src/api/private/signup.ts | 4 ++-- src/api/service/twitter.ts | 4 ++-- 61 files changed, 132 insertions(+), 119 deletions(-) diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index 23cbc44e61..1ee455c092 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -12,7 +12,7 @@ import prominence = require('prominence'); import DriveFile, { getGridFSBucket } from '../models/drive-file'; import DriveFolder from '../models/drive-folder'; -import serialize from '../serializers/drive-file'; +import { pack } from '../models/drive-file'; import event, { publishDriveStream } from '../event'; import config from '../../conf'; @@ -282,7 +282,7 @@ export default (user: any, file: string | stream.Readable, ...args) => new Promi log(`drive file has been created ${file._id}`); resolve(file); - serialize(file).then(serializedFile => { + pack(file).then(serializedFile => { // Publish drive_file_created event event(user._id, 'drive_file_created', serializedFile); publishDriveStream(user._id, 'file_created', serializedFile); diff --git a/src/api/common/notify.ts b/src/api/common/notify.ts index 2b79416a30..ae5669b84c 100644 --- a/src/api/common/notify.ts +++ b/src/api/common/notify.ts @@ -2,7 +2,7 @@ import * as mongo from 'mongodb'; import Notification from '../models/notification'; import Mute from '../models/mute'; import event from '../event'; -import serialize from '../serializers/notification'; +import { pack } from '../models/notification'; export default ( notifiee: mongo.ObjectID, @@ -27,7 +27,7 @@ export default ( // Publish notification event event(notifiee, 'notification', - await serialize(notification)); + await pack(notification)); // 3秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する setTimeout(async () => { @@ -44,7 +44,7 @@ export default ( } //#endregion - event(notifiee, 'unread_notification', await serialize(notification)); + event(notifiee, 'unread_notification', await pack(notification)); } }, 3000); }); diff --git a/src/api/endpoints/app/create.ts b/src/api/endpoints/app/create.ts index ca684de02d..320163ebd9 100644 --- a/src/api/endpoints/app/create.ts +++ b/src/api/endpoints/app/create.ts @@ -5,7 +5,7 @@ import rndstr from 'rndstr'; import $ from 'cafy'; import App from '../../models/app'; import { isValidNameId } from '../../models/app'; -import serialize from '../../serializers/app'; +import { pack } from '../../models/app'; /** * @swagger @@ -106,5 +106,5 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { }); // Response - res(await serialize(app)); + res(await pack(app)); }); diff --git a/src/api/endpoints/app/show.ts b/src/api/endpoints/app/show.ts index 054aab8596..a3ef24717d 100644 --- a/src/api/endpoints/app/show.ts +++ b/src/api/endpoints/app/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import App from '../../models/app'; -import serialize from '../../serializers/app'; +import { pack } from '../../models/app'; /** * @swagger @@ -67,7 +67,7 @@ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) => } // Send response - res(await serialize(app, user, { + res(await pack(app, user, { includeSecret: isSecure && app.user_id.equals(user._id) })); }); diff --git a/src/api/endpoints/auth/session/show.ts b/src/api/endpoints/auth/session/show.ts index ede8a67634..1fe3b873fe 100644 --- a/src/api/endpoints/auth/session/show.ts +++ b/src/api/endpoints/auth/session/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import AuthSess from '../../../models/auth-session'; -import serialize from '../../../serializers/auth-session'; +import { pack } from '../../../models/auth-session'; /** * @swagger @@ -67,5 +67,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } // Response - res(await serialize(session, user)); + res(await pack(session, user)); }); diff --git a/src/api/endpoints/auth/session/userkey.ts b/src/api/endpoints/auth/session/userkey.ts index afd3250b04..fc989bf8c2 100644 --- a/src/api/endpoints/auth/session/userkey.ts +++ b/src/api/endpoints/auth/session/userkey.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import App from '../../../models/app'; import AuthSess from '../../../models/auth-session'; import AccessToken from '../../../models/access-token'; -import serialize from '../../../serializers/user'; +import { pack } from '../../../models/user'; /** * @swagger @@ -102,7 +102,7 @@ module.exports = (params) => new Promise(async (res, rej) => { // Response res({ access_token: accessToken.token, - user: await serialize(session.user_id, null, { + user: await pack(session.user_id, null, { detail: true }) }); diff --git a/src/api/endpoints/channels.ts b/src/api/endpoints/channels.ts index 14817d9bd8..92dcee83db 100644 --- a/src/api/endpoints/channels.ts +++ b/src/api/endpoints/channels.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Channel from '../models/channel'; -import serialize from '../serializers/channel'; +import { pack } from '../models/channel'; /** * Get all channels @@ -55,5 +55,5 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(channels.map(async channel => - await serialize(channel, me)))); + await pack(channel, me)))); }); diff --git a/src/api/endpoints/channels/create.ts b/src/api/endpoints/channels/create.ts index a8d7c29dc1..695b4515b3 100644 --- a/src/api/endpoints/channels/create.ts +++ b/src/api/endpoints/channels/create.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Channel from '../../models/channel'; import Watching from '../../models/channel-watching'; -import serialize from '../../serializers/channel'; +import { pack } from '../../models/channel'; /** * Create a channel @@ -28,7 +28,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { }); // Response - res(await serialize(channel)); + res(await pack(channel)); // Create Watching await Watching.insert({ diff --git a/src/api/endpoints/channels/posts.ts b/src/api/endpoints/channels/posts.ts index 9c2d607edb..3feee51f76 100644 --- a/src/api/endpoints/channels/posts.ts +++ b/src/api/endpoints/channels/posts.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import { default as Channel, IChannel } from '../../models/channel'; import Post from '../../models/post'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Show a posts of a channel @@ -74,6 +74,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(posts.map(async (post) => - await serialize(post, user) + await pack(post, user) ))); }); diff --git a/src/api/endpoints/channels/show.ts b/src/api/endpoints/channels/show.ts index 8861e54594..89c48379a4 100644 --- a/src/api/endpoints/channels/show.ts +++ b/src/api/endpoints/channels/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import { default as Channel, IChannel } from '../../models/channel'; -import serialize from '../../serializers/channel'; +import { pack } from '../../models/channel'; /** * Show a channel @@ -27,5 +27,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } // Serialize - res(await serialize(channel, user)); + res(await pack(channel, user)); }); diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index 3d5f81339a..3bd80e7282 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFile from '../../models/drive-file'; -import serialize from '../../serializers/drive-file'; +import { pack } from '../../models/drive-file'; /** * Get drive files @@ -69,6 +69,6 @@ module.exports = async (params, user, app) => { }); // Serialize - const _files = await Promise.all(files.map(file => serialize(file))); + const _files = await Promise.all(files.map(file => pack(file))); return _files; }; diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts index 437348a1ef..6fa76d7e95 100644 --- a/src/api/endpoints/drive/files/create.ts +++ b/src/api/endpoints/drive/files/create.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import { validateFileName } from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; +import { pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; /** @@ -43,7 +43,7 @@ module.exports = async (file, params, user): Promise => { const driveFile = await create(user, file.path, name, null, folderId); // Serialize - return serialize(driveFile); + return pack(driveFile); } catch (e) { console.error(e); diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts index a1cdf1643e..571aba81f4 100644 --- a/src/api/endpoints/drive/files/find.ts +++ b/src/api/endpoints/drive/files/find.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFile from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; +import { pack } from '../../../models/drive-file'; /** * Find a file(s) @@ -31,5 +31,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(files.map(async file => - await serialize(file)))); + await pack(file)))); }); diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts index 3c7cf774f9..00f69f1415 100644 --- a/src/api/endpoints/drive/files/show.ts +++ b/src/api/endpoints/drive/files/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFile from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; +import { pack } from '../../../models/drive-file'; /** * Show a file @@ -29,7 +29,7 @@ module.exports = async (params, user) => { } // Serialize - const _file = await serialize(file, { + const _file = await pack(file, { detail: true }); diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index f39a420d6e..9ef8215b1a 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import DriveFile from '../../../models/drive-file'; import { validateFileName } from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; +import { pack } from '../../../models/drive-file'; import { publishDriveStream } from '../../../event'; /** @@ -67,7 +67,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Serialize - const fileObj = await serialize(file); + const fileObj = await pack(file); // Response res(fileObj); diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index 519e0bdf65..f0398bfc5d 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -4,7 +4,7 @@ import * as URL from 'url'; import $ from 'cafy'; import { validateFileName } from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; +import { pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; import * as debug from 'debug'; import * as tmp from 'tmp'; @@ -63,5 +63,5 @@ module.exports = async (params, user): Promise => { if (e) log(e.stack); }); - return serialize(driveFile); + return pack(driveFile); }; diff --git a/src/api/endpoints/drive/folders.ts b/src/api/endpoints/drive/folders.ts index 7944e2c6a6..e650fb74aa 100644 --- a/src/api/endpoints/drive/folders.ts +++ b/src/api/endpoints/drive/folders.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../models/drive-folder'; -import serialize from '../../serializers/drive-folder'; +import { pack } from '../../models/drive-folder'; /** * Get drive folders @@ -63,5 +63,5 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(folders.map(async folder => - await serialize(folder)))); + await pack(folder)))); }); diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts index be847b2153..1953c09ee0 100644 --- a/src/api/endpoints/drive/folders/create.ts +++ b/src/api/endpoints/drive/folders/create.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import { isValidFolderName } from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; +import { pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** @@ -47,7 +47,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Serialize - const folderObj = await serialize(folder); + const folderObj = await pack(folder); // Response res(folderObj); diff --git a/src/api/endpoints/drive/folders/find.ts b/src/api/endpoints/drive/folders/find.ts index a5eb8e015d..caad45d740 100644 --- a/src/api/endpoints/drive/folders/find.ts +++ b/src/api/endpoints/drive/folders/find.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; +import { pack } from '../../../models/drive-folder'; /** * Find a folder(s) @@ -30,5 +30,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Serialize - res(await Promise.all(folders.map(folder => serialize(folder)))); + res(await Promise.all(folders.map(folder => pack(folder)))); }); diff --git a/src/api/endpoints/drive/folders/show.ts b/src/api/endpoints/drive/folders/show.ts index 9b1c04ca3c..fd3061ca54 100644 --- a/src/api/endpoints/drive/folders/show.ts +++ b/src/api/endpoints/drive/folders/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; +import { pack } from '../../../models/drive-folder'; /** * Show a folder @@ -29,7 +29,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } // Serialize - res(await serialize(folder, { + res(await pack(folder, { detail: true })); }); diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts index ff673402ab..8f50a9d009 100644 --- a/src/api/endpoints/drive/folders/update.ts +++ b/src/api/endpoints/drive/folders/update.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import { isValidFolderName } from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; +import { pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** @@ -91,7 +91,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Serialize - const folderObj = await serialize(folder); + const folderObj = await pack(folder); // Response res(folderObj); diff --git a/src/api/endpoints/drive/stream.ts b/src/api/endpoints/drive/stream.ts index 5b0eb0a0d8..3527d70500 100644 --- a/src/api/endpoints/drive/stream.ts +++ b/src/api/endpoints/drive/stream.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import DriveFile from '../../models/drive-file'; -import serialize from '../../serializers/drive-file'; +import { pack } from '../../models/drive-file'; /** * Get drive stream @@ -64,5 +64,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(files.map(async file => - await serialize(file)))); + await pack(file)))); }); diff --git a/src/api/endpoints/i.ts b/src/api/endpoints/i.ts index ae75f11d54..1b6c1e58de 100644 --- a/src/api/endpoints/i.ts +++ b/src/api/endpoints/i.ts @@ -2,7 +2,7 @@ * Module dependencies */ import User from '../models/user'; -import serialize from '../serializers/user'; +import { pack } from '../models/user'; /** * Show myself @@ -15,7 +15,7 @@ import serialize from '../serializers/user'; */ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) => { // Serialize - res(await serialize(user, user, { + res(await pack(user, user, { detail: true, includeSecrets: isSecure })); diff --git a/src/api/endpoints/i/authorized_apps.ts b/src/api/endpoints/i/authorized_apps.ts index 807ca5b1e7..40ce7a68c8 100644 --- a/src/api/endpoints/i/authorized_apps.ts +++ b/src/api/endpoints/i/authorized_apps.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import AccessToken from '../../models/access-token'; -import serialize from '../../serializers/app'; +import { pack } from '../../models/app'; /** * Get authorized apps of my account @@ -39,5 +39,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(tokens.map(async token => - await serialize(token.app_id)))); + await pack(token.app_id)))); }); diff --git a/src/api/endpoints/i/favorites.ts b/src/api/endpoints/i/favorites.ts index a66eaa7546..eb464cf0f0 100644 --- a/src/api/endpoints/i/favorites.ts +++ b/src/api/endpoints/i/favorites.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Favorite from '../../models/favorite'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Get followers of a user @@ -39,6 +39,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(favorites.map(async favorite => - await serialize(favorite.post) + await pack(favorite.post) ))); }); diff --git a/src/api/endpoints/i/notifications.ts b/src/api/endpoints/i/notifications.ts index fb9be7f61b..688039a0dd 100644 --- a/src/api/endpoints/i/notifications.ts +++ b/src/api/endpoints/i/notifications.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Notification from '../../models/notification'; import Mute from '../../models/mute'; -import serialize from '../../serializers/notification'; +import { pack } from '../../models/notification'; import getFriends from '../../common/get-friends'; import read from '../../common/read-notification'; @@ -101,7 +101,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(notifications.map(async notification => - await serialize(notification)))); + await pack(notification)))); // Mark as read all if (notifications.length > 0 && markAsRead) { diff --git a/src/api/endpoints/i/pin.ts b/src/api/endpoints/i/pin.ts index a94950d22b..ff546fc2bd 100644 --- a/src/api/endpoints/i/pin.ts +++ b/src/api/endpoints/i/pin.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import User from '../../models/user'; import Post from '../../models/post'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; /** * Pin post @@ -35,7 +35,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { }); // Serialize - const iObj = await serialize(user, user, { + const iObj = await pack(user, user, { detail: true }); diff --git a/src/api/endpoints/i/signin_history.ts b/src/api/endpoints/i/signin_history.ts index e38bfa4d98..3ab59b694d 100644 --- a/src/api/endpoints/i/signin_history.ts +++ b/src/api/endpoints/i/signin_history.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Signin from '../../models/signin'; -import serialize from '../../serializers/signin'; +import { pack } from '../../models/signin'; /** * Get signin history of my account @@ -58,5 +58,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(history.map(async record => - await serialize(record)))); + await pack(record)))); }); diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index c484c51a96..a138832e54 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import User from '../../models/user'; import { isValidName, isValidDescription, isValidLocation, isValidBirthday } from '../../models/user'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; import event from '../../event'; import config from '../../../conf'; @@ -65,7 +65,7 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re }); // Serialize - const iObj = await serialize(user, user, { + const iObj = await pack(user, user, { detail: true, includeSecrets: isSecure }); diff --git a/src/api/endpoints/messaging/history.ts b/src/api/endpoints/messaging/history.ts index f14740dff5..1683ca7a89 100644 --- a/src/api/endpoints/messaging/history.ts +++ b/src/api/endpoints/messaging/history.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import History from '../../models/messaging-history'; import Mute from '../../models/mute'; -import serialize from '../../serializers/messaging-message'; +import { pack } from '../../models/messaging-message'; /** * Show messaging history @@ -39,5 +39,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(history.map(async h => - await serialize(h.message, user)))); + await pack(h.message, user)))); }); diff --git a/src/api/endpoints/messaging/messages.ts b/src/api/endpoints/messaging/messages.ts index 3d3c6950a1..67ba5e9d6d 100644 --- a/src/api/endpoints/messaging/messages.ts +++ b/src/api/endpoints/messaging/messages.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Message from '../../models/messaging-message'; import User from '../../models/user'; -import serialize from '../../serializers/messaging-message'; +import { pack } from '../../models/messaging-message'; import read from '../../common/read-messaging-message'; /** @@ -87,7 +87,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(messages.map(async message => - await serialize(message, user, { + await pack(message, user, { populateRecipient: false })))); diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts index 4e9d10197c..1b8a5f59e6 100644 --- a/src/api/endpoints/messaging/messages/create.ts +++ b/src/api/endpoints/messaging/messages/create.ts @@ -8,7 +8,7 @@ import History from '../../../models/messaging-history'; import User from '../../../models/user'; import Mute from '../../../models/mute'; import DriveFile from '../../../models/drive-file'; -import serialize from '../../../serializers/messaging-message'; +import { pack } from '../../../models/messaging-message'; import publishUserStream from '../../../event'; import { publishMessagingStream, publishMessagingIndexStream, pushSw } from '../../../event'; import config from '../../../../conf'; @@ -79,7 +79,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Serialize - const messageObj = await serialize(message); + const messageObj = await pack(message); // Reponse res(messageObj); diff --git a/src/api/endpoints/mute/list.ts b/src/api/endpoints/mute/list.ts index 740e19f0bb..19e3b157e6 100644 --- a/src/api/endpoints/mute/list.ts +++ b/src/api/endpoints/mute/list.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Mute from '../../models/mute'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; import getFriends from '../../common/get-friends'; /** @@ -63,7 +63,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize const users = await Promise.all(mutes.map(async m => - await serialize(m.mutee_id, me, { detail: true }))); + await pack(m.mutee_id, me, { detail: true }))); // Response res({ diff --git a/src/api/endpoints/my/apps.ts b/src/api/endpoints/my/apps.ts index eb9c758768..fe583db86a 100644 --- a/src/api/endpoints/my/apps.ts +++ b/src/api/endpoints/my/apps.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import App from '../../models/app'; -import serialize from '../../serializers/app'; +import { pack } from '../../models/app'; /** * Get my apps @@ -37,5 +37,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Reply res(await Promise.all(apps.map(async app => - await serialize(app)))); + await pack(app)))); }); diff --git a/src/api/endpoints/posts.ts b/src/api/endpoints/posts.ts index db166cd67a..d10c6ab408 100644 --- a/src/api/endpoints/posts.ts +++ b/src/api/endpoints/posts.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Post from '../models/post'; -import serialize from '../serializers/post'; +import { pack } from '../models/post'; /** * Lists all posts @@ -85,5 +85,5 @@ module.exports = (params) => new Promise(async (res, rej) => { }); // Serialize - res(await Promise.all(posts.map(async post => await serialize(post)))); + res(await Promise.all(posts.map(async post => await pack(post)))); }); diff --git a/src/api/endpoints/posts/context.ts b/src/api/endpoints/posts/context.ts index bad59a6bee..3051e7af17 100644 --- a/src/api/endpoints/posts/context.ts +++ b/src/api/endpoints/posts/context.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Show a context of a post @@ -60,5 +60,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(context.map(async post => - await serialize(post, user)))); + await pack(post, user)))); }); diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index a1d05c67c6..0fa52221f9 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -12,7 +12,7 @@ import Mute from '../../models/mute'; import DriveFile from '../../models/drive-file'; import Watching from '../../models/post-watching'; import ChannelWatching from '../../models/channel-watching'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; import notify from '../../common/notify'; import watch from '../../common/watch-post'; import event, { pushSw, publishChannelStream } from '../../event'; @@ -224,7 +224,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { }); // Serialize - const postObj = await serialize(post); + const postObj = await pack(post); // Reponse res({ diff --git a/src/api/endpoints/posts/mentions.ts b/src/api/endpoints/posts/mentions.ts index 3bb4ec3fa0..7127db0ad1 100644 --- a/src/api/endpoints/posts/mentions.ts +++ b/src/api/endpoints/posts/mentions.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Post from '../../models/post'; import getFriends from '../../common/get-friends'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Get mentions of myself @@ -73,6 +73,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(mentions.map(async mention => - await serialize(mention, user) + await pack(mention, user) ))); }); diff --git a/src/api/endpoints/posts/polls/recommendation.ts b/src/api/endpoints/posts/polls/recommendation.ts index 9c92d6cac4..5ccb754496 100644 --- a/src/api/endpoints/posts/polls/recommendation.ts +++ b/src/api/endpoints/posts/polls/recommendation.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Vote from '../../../models/poll-vote'; import Post from '../../../models/post'; -import serialize from '../../../serializers/post'; +import { pack } from '../../../models/post'; /** * Get recommended polls @@ -56,5 +56,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(posts.map(async post => - await serialize(post, user, { detail: true })))); + await pack(post, user, { detail: true })))); }); diff --git a/src/api/endpoints/posts/reactions.ts b/src/api/endpoints/posts/reactions.ts index eab5d9b258..f60334df8a 100644 --- a/src/api/endpoints/posts/reactions.ts +++ b/src/api/endpoints/posts/reactions.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Post from '../../models/post'; import Reaction from '../../models/post-reaction'; -import serialize from '../../serializers/post-reaction'; +import { pack } from '../../models/post-reaction'; /** * Show reactions of a post @@ -54,5 +54,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(reactions.map(async reaction => - await serialize(reaction, user)))); + await pack(reaction, user)))); }); diff --git a/src/api/endpoints/posts/replies.ts b/src/api/endpoints/posts/replies.ts index 3fd6a46769..1442b8a4c5 100644 --- a/src/api/endpoints/posts/replies.ts +++ b/src/api/endpoints/posts/replies.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Show a replies of a post @@ -50,5 +50,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(replies.map(async post => - await serialize(post, user)))); + await pack(post, user)))); }); diff --git a/src/api/endpoints/posts/reposts.ts b/src/api/endpoints/posts/reposts.ts index bcc6163a11..0fbb0687b9 100644 --- a/src/api/endpoints/posts/reposts.ts +++ b/src/api/endpoints/posts/reposts.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Show a reposts of a post @@ -70,5 +70,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(reposts.map(async post => - await serialize(post, user)))); + await pack(post, user)))); }); diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 31c9a8d3c8..6e26f55390 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -7,7 +7,7 @@ import Post from '../../models/post'; import User from '../../models/user'; import Mute from '../../models/mute'; import getFriends from '../../common/get-friends'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Search a post @@ -351,5 +351,5 @@ async function search( // Serialize res(await Promise.all(posts.map(async post => - await serialize(post, me)))); + await pack(post, me)))); } diff --git a/src/api/endpoints/posts/show.ts b/src/api/endpoints/posts/show.ts index 5bfe4f6605..c312449710 100644 --- a/src/api/endpoints/posts/show.ts +++ b/src/api/endpoints/posts/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Show a post @@ -27,7 +27,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } // Serialize - res(await serialize(post, user, { + res(await pack(post, user, { detail: true })); }); diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index da7ffd0c14..c41cfdb8bd 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -7,7 +7,7 @@ import Post from '../../models/post'; import Mute from '../../models/mute'; import ChannelWatching from '../../models/channel-watching'; import getFriends from '../../common/get-friends'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Get timeline of myself @@ -128,5 +128,5 @@ module.exports = async (params, user, app) => { }); // Serialize - return await Promise.all(timeline.map(post => serialize(post, user))); + return await Promise.all(timeline.map(post => pack(post, user))); }; diff --git a/src/api/endpoints/posts/trend.ts b/src/api/endpoints/posts/trend.ts index 64a195dff1..b2b1d327a8 100644 --- a/src/api/endpoints/posts/trend.ts +++ b/src/api/endpoints/posts/trend.ts @@ -4,7 +4,7 @@ const ms = require('ms'); import $ from 'cafy'; import Post from '../../models/post'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Get trend posts @@ -76,5 +76,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(posts.map(async post => - await serialize(post, user, { detail: true })))); + await pack(post, user, { detail: true })))); }); diff --git a/src/api/endpoints/users.ts b/src/api/endpoints/users.ts index f3c9b66a5e..ba33b1aeb7 100644 --- a/src/api/endpoints/users.ts +++ b/src/api/endpoints/users.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import User from '../models/user'; -import serialize from '../serializers/user'; +import { pack } from '../models/user'; /** * Lists all users @@ -55,5 +55,5 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(users.map(async user => - await serialize(user, me)))); + await pack(user, me)))); }); diff --git a/src/api/endpoints/users/followers.ts b/src/api/endpoints/users/followers.ts index 4905323ba5..b0fb83c683 100644 --- a/src/api/endpoints/users/followers.ts +++ b/src/api/endpoints/users/followers.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import User from '../../models/user'; import Following from '../../models/following'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; import getFriends from '../../common/get-friends'; /** @@ -82,7 +82,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize const users = await Promise.all(following.map(async f => - await serialize(f.follower_id, me, { detail: true }))); + await pack(f.follower_id, me, { detail: true }))); // Response res({ diff --git a/src/api/endpoints/users/following.ts b/src/api/endpoints/users/following.ts index dc2ff49bbe..8e88431e92 100644 --- a/src/api/endpoints/users/following.ts +++ b/src/api/endpoints/users/following.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import User from '../../models/user'; import Following from '../../models/following'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; import getFriends from '../../common/get-friends'; /** @@ -82,7 +82,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize const users = await Promise.all(following.map(async f => - await serialize(f.followee_id, me, { detail: true }))); + await pack(f.followee_id, me, { detail: true }))); // Response res({ diff --git a/src/api/endpoints/users/get_frequently_replied_users.ts b/src/api/endpoints/users/get_frequently_replied_users.ts index a8add623d4..3cbc761322 100644 --- a/src/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/api/endpoints/users/get_frequently_replied_users.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Post from '../../models/post'; import User from '../../models/user'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'user_id' parameter @@ -91,7 +91,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Make replies object (includes weights) const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({ - user: await serialize(user, me, { detail: true }), + user: await pack(user, me, { detail: true }), weight: repliedUsers[user] / peak }))); diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts index 0d8384a43d..1f3db3cf79 100644 --- a/src/api/endpoints/users/posts.ts +++ b/src/api/endpoints/users/posts.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import Post from '../../models/post'; import User from '../../models/user'; -import serialize from '../../serializers/post'; +import { pack } from '../../models/post'; /** * Get posts of a user @@ -124,6 +124,6 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(posts.map(async (post) => - await serialize(post, me) + await pack(post, me) ))); }); diff --git a/src/api/endpoints/users/recommendation.ts b/src/api/endpoints/users/recommendation.ts index 731d68a7b1..b80fd63ce7 100644 --- a/src/api/endpoints/users/recommendation.ts +++ b/src/api/endpoints/users/recommendation.ts @@ -4,7 +4,7 @@ const ms = require('ms'); import $ from 'cafy'; import User from '../../models/user'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; import getFriends from '../../common/get-friends'; /** @@ -44,5 +44,5 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(users.map(async user => - await serialize(user, me, { detail: true })))); + await pack(user, me, { detail: true })))); }); diff --git a/src/api/endpoints/users/search.ts b/src/api/endpoints/users/search.ts index 73a5db47e2..213038403b 100644 --- a/src/api/endpoints/users/search.ts +++ b/src/api/endpoints/users/search.ts @@ -4,7 +4,7 @@ import * as mongo from 'mongodb'; import $ from 'cafy'; import User from '../../models/user'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; import config from '../../../conf'; const escapeRegexp = require('escape-regexp'); @@ -94,6 +94,6 @@ async function byElasticsearch(res, rej, me, query, offset, max) { // Serialize res(await Promise.all(users.map(async user => - await serialize(user, me, { detail: true })))); + await pack(user, me, { detail: true })))); }); } diff --git a/src/api/endpoints/users/search_by_username.ts b/src/api/endpoints/users/search_by_username.ts index 7f2f42f0a6..63e206b1f2 100644 --- a/src/api/endpoints/users/search_by_username.ts +++ b/src/api/endpoints/users/search_by_username.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import User from '../../models/user'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; /** * Search a user by username @@ -35,5 +35,5 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Serialize res(await Promise.all(users.map(async user => - await serialize(user, me, { detail: true })))); + await pack(user, me, { detail: true })))); }); diff --git a/src/api/endpoints/users/show.ts b/src/api/endpoints/users/show.ts index 8e74b0fe3f..a51cb619d4 100644 --- a/src/api/endpoints/users/show.ts +++ b/src/api/endpoints/users/show.ts @@ -3,7 +3,7 @@ */ import $ from 'cafy'; import User from '../../models/user'; -import serialize from '../../serializers/user'; +import { pack } from '../../models/user'; /** * Show a user @@ -41,7 +41,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { } // Send response - res(await serialize(user, me, { + res(await pack(user, me, { detail: true })); }); diff --git a/src/api/models/drive-file.ts b/src/api/models/drive-file.ts index 6a8db3ad42..9b9df1dac6 100644 --- a/src/api/models/drive-file.ts +++ b/src/api/models/drive-file.ts @@ -20,8 +20,14 @@ export { getGridFSBucket }; export type IDriveFile = { _id: mongodb.ObjectID; - created_at: Date; - user_id: mongodb.ObjectID; + uploadDate: Date; + md5: string; + filename: string; + metadata: { + properties: any; + user_id: mongodb.ObjectID; + folder_id: mongodb.ObjectID; + } }; export function validateFileName(name: string): boolean { diff --git a/src/api/models/drive-folder.ts b/src/api/models/drive-folder.ts index 48b26c2bd6..54b45049b9 100644 --- a/src/api/models/drive-folder.ts +++ b/src/api/models/drive-folder.ts @@ -9,7 +9,9 @@ export default DriveFolder; export type IDriveFolder = { _id: mongo.ObjectID; created_at: Date; + name: string; user_id: mongo.ObjectID; + parent_id: mongo.ObjectID; }; export function isValidFolderName(name: string): boolean { diff --git a/src/api/models/messaging-message.ts b/src/api/models/messaging-message.ts index ffdda1db21..90cf1cd71c 100644 --- a/src/api/models/messaging-message.ts +++ b/src/api/models/messaging-message.ts @@ -10,6 +10,11 @@ export default MessagingMessage; export interface IMessagingMessage { _id: mongo.ObjectID; + created_at: Date; + text: string; + user_id: mongo.ObjectID; + recipient_id: mongo.ObjectID; + is_read: boolean; } export function isValidText(text: string): boolean { diff --git a/src/api/private/signin.ts b/src/api/private/signin.ts index a26c8f6c5a..ab6e93562c 100644 --- a/src/api/private/signin.ts +++ b/src/api/private/signin.ts @@ -3,7 +3,7 @@ import * as bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; import { default as User, IUser } from '../models/user'; import Signin from '../models/signin'; -import serialize from '../serializers/signin'; +import { pack } from '../models/signin'; import event from '../event'; import signin from '../common/signin'; import config from '../../conf'; @@ -85,5 +85,5 @@ export default async (req: express.Request, res: express.Response) => { }); // Publish signin event - event(user._id, 'signin', await serialize(record)); + event(user._id, 'signin', await pack(record)); }; diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 466c6a489f..105fe319a5 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -4,7 +4,7 @@ import * as bcrypt from 'bcryptjs'; import recaptcha = require('recaptcha-promise'); import { default as User, IUser } from '../models/user'; import { validateUsername, validatePassword } from '../models/user'; -import serialize from '../serializers/user'; +import { pack } from '../models/user'; import generateUserToken from '../common/generate-native-user-token'; import config from '../../conf'; @@ -142,7 +142,7 @@ export default async (req: express.Request, res: express.Response) => { }); // Response - res.send(await serialize(account)); + res.send(await pack(account)); // Create search index if (config.elasticsearch.enable) { diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts index 0e75ee0bdb..ca4f8abcca 100644 --- a/src/api/service/twitter.ts +++ b/src/api/service/twitter.ts @@ -6,7 +6,7 @@ import * as uuid from 'uuid'; import autwh from 'autwh'; import redis from '../../db/redis'; import User from '../models/user'; -import serialize from '../serializers/user'; +import { pack } from '../models/user'; import event from '../event'; import config from '../../conf'; import signin from '../common/signin'; @@ -50,7 +50,7 @@ module.exports = (app: express.Application) => { res.send(`Twitterの連携を解除しました :v:`); // Publish i updated event - event(user._id, 'i_updated', await serialize(user, user, { + event(user._id, 'i_updated', await pack(user, user, { detail: true, includeSecrets: true })); From 2cb0511dba7463ad50725fd2dfd1966f0a108a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Fri, 2 Feb 2018 10:31:17 +0900 Subject: [PATCH 185/186] wip --- src/api/endpoints/app/create.ts | 3 +-- src/api/endpoints/app/show.ts | 3 +-- src/api/endpoints/auth/session/show.ts | 3 +-- src/api/endpoints/channels.ts | 3 +-- src/api/endpoints/channels/posts.ts | 3 +-- src/api/endpoints/channels/show.ts | 3 +-- src/api/endpoints/drive/files.ts | 3 +-- src/api/endpoints/drive/files/create.ts | 3 +-- src/api/endpoints/drive/files/find.ts | 3 +-- src/api/endpoints/drive/files/show.ts | 3 +-- src/api/endpoints/drive/files/update.ts | 3 +-- src/api/endpoints/drive/files/upload_from_url.ts | 3 +-- src/api/endpoints/drive/folders.ts | 3 +-- src/api/endpoints/drive/folders/create.ts | 3 +-- src/api/endpoints/drive/folders/find.ts | 3 +-- src/api/endpoints/drive/folders/show.ts | 3 +-- src/api/endpoints/drive/folders/update.ts | 3 +-- src/api/endpoints/drive/stream.ts | 3 +-- src/api/endpoints/i.ts | 3 +-- src/api/endpoints/i/signin_history.ts | 3 +-- src/api/endpoints/i/update.ts | 3 +-- src/api/endpoints/my/apps.ts | 3 +-- src/api/endpoints/posts.ts | 3 +-- src/api/endpoints/posts/context.ts | 3 +-- src/api/endpoints/posts/polls/recommendation.ts | 3 +-- src/api/endpoints/posts/reactions.ts | 3 +-- src/api/endpoints/posts/replies.ts | 3 +-- src/api/endpoints/posts/reposts.ts | 3 +-- src/api/endpoints/posts/show.ts | 3 +-- src/api/endpoints/posts/trend.ts | 3 +-- src/api/endpoints/users.ts | 3 +-- src/api/endpoints/users/get_frequently_replied_users.ts | 3 +-- src/api/endpoints/users/posts.ts | 3 +-- src/api/endpoints/users/recommendation.ts | 3 +-- src/api/endpoints/users/search.ts | 3 +-- src/api/endpoints/users/search_by_username.ts | 3 +-- src/api/endpoints/users/show.ts | 3 +-- src/api/private/signin.ts | 3 +-- src/api/private/signup.ts | 3 +-- src/api/service/twitter.ts | 3 +-- 40 files changed, 40 insertions(+), 80 deletions(-) diff --git a/src/api/endpoints/app/create.ts b/src/api/endpoints/app/create.ts index 320163ebd9..71633f7def 100644 --- a/src/api/endpoints/app/create.ts +++ b/src/api/endpoints/app/create.ts @@ -4,8 +4,7 @@ import rndstr from 'rndstr'; import $ from 'cafy'; import App from '../../models/app'; -import { isValidNameId } from '../../models/app'; -import { pack } from '../../models/app'; +import { isValidNameId }, { pack } from '../../models/app'; /** * @swagger diff --git a/src/api/endpoints/app/show.ts b/src/api/endpoints/app/show.ts index a3ef24717d..8bc3dda42c 100644 --- a/src/api/endpoints/app/show.ts +++ b/src/api/endpoints/app/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import App from '../../models/app'; -import { pack } from '../../models/app'; +import App, { pack } from '../../models/app'; /** * @swagger diff --git a/src/api/endpoints/auth/session/show.ts b/src/api/endpoints/auth/session/show.ts index 1fe3b873fe..73ac3185f6 100644 --- a/src/api/endpoints/auth/session/show.ts +++ b/src/api/endpoints/auth/session/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import AuthSess from '../../../models/auth-session'; -import { pack } from '../../../models/auth-session'; +import AuthSess, { pack } from '../../../models/auth-session'; /** * @swagger diff --git a/src/api/endpoints/channels.ts b/src/api/endpoints/channels.ts index 92dcee83db..b9a7d1b788 100644 --- a/src/api/endpoints/channels.ts +++ b/src/api/endpoints/channels.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Channel from '../models/channel'; -import { pack } from '../models/channel'; +import Channel, { pack } from '../models/channel'; /** * Get all channels diff --git a/src/api/endpoints/channels/posts.ts b/src/api/endpoints/channels/posts.ts index 3feee51f76..d722589c20 100644 --- a/src/api/endpoints/channels/posts.ts +++ b/src/api/endpoints/channels/posts.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import { default as Channel, IChannel } from '../../models/channel'; -import Post from '../../models/post'; -import { pack } from '../../models/post'; +import Post, { pack } from '../../models/post'; /** * Show a posts of a channel diff --git a/src/api/endpoints/channels/show.ts b/src/api/endpoints/channels/show.ts index 89c48379a4..3238616fa5 100644 --- a/src/api/endpoints/channels/show.ts +++ b/src/api/endpoints/channels/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import { default as Channel, IChannel } from '../../models/channel'; -import { pack } from '../../models/channel'; +import { default as Channel, IChannel }, { pack } from '../../models/channel'; /** * Show a channel diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index 3bd80e7282..89915331ea 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFile from '../../models/drive-file'; -import { pack } from '../../models/drive-file'; +import DriveFile, { pack } from '../../models/drive-file'; /** * Get drive files diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts index 6fa76d7e95..7b424f3f5a 100644 --- a/src/api/endpoints/drive/files/create.ts +++ b/src/api/endpoints/drive/files/create.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import { validateFileName } from '../../../models/drive-file'; -import { pack } from '../../../models/drive-file'; +import { validateFileName }, { pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; /** diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts index 571aba81f4..e026afe936 100644 --- a/src/api/endpoints/drive/files/find.ts +++ b/src/api/endpoints/drive/files/find.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFile from '../../../models/drive-file'; -import { pack } from '../../../models/drive-file'; +import DriveFile, { pack } from '../../../models/drive-file'; /** * Find a file(s) diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts index 00f69f1415..21664f7ba4 100644 --- a/src/api/endpoints/drive/files/show.ts +++ b/src/api/endpoints/drive/files/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFile from '../../../models/drive-file'; -import { pack } from '../../../models/drive-file'; +import DriveFile, { pack } from '../../../models/drive-file'; /** * Show a file diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index 9ef8215b1a..ff65a48f71 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -4,8 +4,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import DriveFile from '../../../models/drive-file'; -import { validateFileName } from '../../../models/drive-file'; -import { pack } from '../../../models/drive-file'; +import { validateFileName }, { pack } from '../../../models/drive-file'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index f0398bfc5d..009f06aaaf 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -3,8 +3,7 @@ */ import * as URL from 'url'; import $ from 'cafy'; -import { validateFileName } from '../../../models/drive-file'; -import { pack } from '../../../models/drive-file'; +import { validateFileName }, { pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; import * as debug from 'debug'; import * as tmp from 'tmp'; diff --git a/src/api/endpoints/drive/folders.ts b/src/api/endpoints/drive/folders.ts index e650fb74aa..428bde3507 100644 --- a/src/api/endpoints/drive/folders.ts +++ b/src/api/endpoints/drive/folders.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../models/drive-folder'; -import { pack } from '../../models/drive-folder'; +import DriveFolder, { pack } from '../../models/drive-folder'; /** * Get drive folders diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts index 1953c09ee0..6543b11274 100644 --- a/src/api/endpoints/drive/folders/create.ts +++ b/src/api/endpoints/drive/folders/create.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName } from '../../../models/drive-folder'; -import { pack } from '../../../models/drive-folder'; +import { isValidFolderName }, { pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/folders/find.ts b/src/api/endpoints/drive/folders/find.ts index caad45d740..fc84766bc8 100644 --- a/src/api/endpoints/drive/folders/find.ts +++ b/src/api/endpoints/drive/folders/find.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../../models/drive-folder'; -import { pack } from '../../../models/drive-folder'; +import DriveFolder, { pack } from '../../../models/drive-folder'; /** * Find a folder(s) diff --git a/src/api/endpoints/drive/folders/show.ts b/src/api/endpoints/drive/folders/show.ts index fd3061ca54..e07d14d20d 100644 --- a/src/api/endpoints/drive/folders/show.ts +++ b/src/api/endpoints/drive/folders/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../../models/drive-folder'; -import { pack } from '../../../models/drive-folder'; +import DriveFolder, { pack } from '../../../models/drive-folder'; /** * Show a folder diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts index 8f50a9d009..2adcadcb08 100644 --- a/src/api/endpoints/drive/folders/update.ts +++ b/src/api/endpoints/drive/folders/update.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName } from '../../../models/drive-folder'; -import { pack } from '../../../models/drive-folder'; +import { isValidFolderName }, { pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/stream.ts b/src/api/endpoints/drive/stream.ts index 3527d70500..8352c7dd4c 100644 --- a/src/api/endpoints/drive/stream.ts +++ b/src/api/endpoints/drive/stream.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFile from '../../models/drive-file'; -import { pack } from '../../models/drive-file'; +import DriveFile, { pack } from '../../models/drive-file'; /** * Get drive stream diff --git a/src/api/endpoints/i.ts b/src/api/endpoints/i.ts index 1b6c1e58de..7efdbcd7c9 100644 --- a/src/api/endpoints/i.ts +++ b/src/api/endpoints/i.ts @@ -1,8 +1,7 @@ /** * Module dependencies */ -import User from '../models/user'; -import { pack } from '../models/user'; +import User, { pack } from '../models/user'; /** * Show myself diff --git a/src/api/endpoints/i/signin_history.ts b/src/api/endpoints/i/signin_history.ts index 3ab59b694d..859e81653d 100644 --- a/src/api/endpoints/i/signin_history.ts +++ b/src/api/endpoints/i/signin_history.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Signin from '../../models/signin'; -import { pack } from '../../models/signin'; +import Signin, { pack } from '../../models/signin'; /** * Get signin history of my account diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index a138832e54..cd4b1a13f5 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import User from '../../models/user'; -import { isValidName, isValidDescription, isValidLocation, isValidBirthday } from '../../models/user'; -import { pack } from '../../models/user'; +import { isValidName, isValidDescription, isValidLocation, isValidBirthday }, { pack } from '../../models/user'; import event from '../../event'; import config from '../../../conf'; diff --git a/src/api/endpoints/my/apps.ts b/src/api/endpoints/my/apps.ts index fe583db86a..b236190506 100644 --- a/src/api/endpoints/my/apps.ts +++ b/src/api/endpoints/my/apps.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import App from '../../models/app'; -import { pack } from '../../models/app'; +import App, { pack } from '../../models/app'; /** * Get my apps diff --git a/src/api/endpoints/posts.ts b/src/api/endpoints/posts.ts index d10c6ab408..3b29425927 100644 --- a/src/api/endpoints/posts.ts +++ b/src/api/endpoints/posts.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../models/post'; -import { pack } from '../models/post'; +import Post, { pack } from '../models/post'; /** * Lists all posts diff --git a/src/api/endpoints/posts/context.ts b/src/api/endpoints/posts/context.ts index 3051e7af17..5ba3758975 100644 --- a/src/api/endpoints/posts/context.ts +++ b/src/api/endpoints/posts/context.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../../models/post'; -import { pack } from '../../models/post'; +import Post, { pack } from '../../models/post'; /** * Show a context of a post diff --git a/src/api/endpoints/posts/polls/recommendation.ts b/src/api/endpoints/posts/polls/recommendation.ts index 5ccb754496..4a3fa3f55e 100644 --- a/src/api/endpoints/posts/polls/recommendation.ts +++ b/src/api/endpoints/posts/polls/recommendation.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import Vote from '../../../models/poll-vote'; -import Post from '../../../models/post'; -import { pack } from '../../../models/post'; +import Post, { pack } from '../../../models/post'; /** * Get recommended polls diff --git a/src/api/endpoints/posts/reactions.ts b/src/api/endpoints/posts/reactions.ts index f60334df8a..feb140ab41 100644 --- a/src/api/endpoints/posts/reactions.ts +++ b/src/api/endpoints/posts/reactions.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import Reaction from '../../models/post-reaction'; -import { pack } from '../../models/post-reaction'; +import Reaction, { pack } from '../../models/post-reaction'; /** * Show reactions of a post diff --git a/src/api/endpoints/posts/replies.ts b/src/api/endpoints/posts/replies.ts index 1442b8a4c5..613c4fa24c 100644 --- a/src/api/endpoints/posts/replies.ts +++ b/src/api/endpoints/posts/replies.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../../models/post'; -import { pack } from '../../models/post'; +import Post, { pack } from '../../models/post'; /** * Show a replies of a post diff --git a/src/api/endpoints/posts/reposts.ts b/src/api/endpoints/posts/reposts.ts index 0fbb0687b9..89ab0e3d55 100644 --- a/src/api/endpoints/posts/reposts.ts +++ b/src/api/endpoints/posts/reposts.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../../models/post'; -import { pack } from '../../models/post'; +import Post, { pack } from '../../models/post'; /** * Show a reposts of a post diff --git a/src/api/endpoints/posts/show.ts b/src/api/endpoints/posts/show.ts index c312449710..3839490597 100644 --- a/src/api/endpoints/posts/show.ts +++ b/src/api/endpoints/posts/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../../models/post'; -import { pack } from '../../models/post'; +import Post, { pack } from '../../models/post'; /** * Show a post diff --git a/src/api/endpoints/posts/trend.ts b/src/api/endpoints/posts/trend.ts index b2b1d327a8..caded92bf5 100644 --- a/src/api/endpoints/posts/trend.ts +++ b/src/api/endpoints/posts/trend.ts @@ -3,8 +3,7 @@ */ const ms = require('ms'); import $ from 'cafy'; -import Post from '../../models/post'; -import { pack } from '../../models/post'; +import Post, { pack } from '../../models/post'; /** * Get trend posts diff --git a/src/api/endpoints/users.ts b/src/api/endpoints/users.ts index ba33b1aeb7..095b9fe40d 100644 --- a/src/api/endpoints/users.ts +++ b/src/api/endpoints/users.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../models/user'; -import { pack } from '../models/user'; +import User, { pack } from '../models/user'; /** * Lists all users diff --git a/src/api/endpoints/users/get_frequently_replied_users.ts b/src/api/endpoints/users/get_frequently_replied_users.ts index 3cbc761322..87f4f77a5b 100644 --- a/src/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/api/endpoints/users/get_frequently_replied_users.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import User from '../../models/user'; -import { pack } from '../../models/user'; +import User, { pack } from '../../models/user'; module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'user_id' parameter diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts index 1f3db3cf79..285e5bc46c 100644 --- a/src/api/endpoints/users/posts.ts +++ b/src/api/endpoints/users/posts.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; -import User from '../../models/user'; -import { pack } from '../../models/post'; +import User, { pack } from '../../models/user'; /** * Get posts of a user diff --git a/src/api/endpoints/users/recommendation.ts b/src/api/endpoints/users/recommendation.ts index b80fd63ce7..736233b340 100644 --- a/src/api/endpoints/users/recommendation.ts +++ b/src/api/endpoints/users/recommendation.ts @@ -3,8 +3,7 @@ */ const ms = require('ms'); import $ from 'cafy'; -import User from '../../models/user'; -import { pack } from '../../models/user'; +import User, { pack } from '../../models/user'; import getFriends from '../../common/get-friends'; /** diff --git a/src/api/endpoints/users/search.ts b/src/api/endpoints/users/search.ts index 213038403b..1142db9e9b 100644 --- a/src/api/endpoints/users/search.ts +++ b/src/api/endpoints/users/search.ts @@ -3,8 +3,7 @@ */ import * as mongo from 'mongodb'; import $ from 'cafy'; -import User from '../../models/user'; -import { pack } from '../../models/user'; +import User, { pack } from '../../models/user'; import config from '../../../conf'; const escapeRegexp = require('escape-regexp'); diff --git a/src/api/endpoints/users/search_by_username.ts b/src/api/endpoints/users/search_by_username.ts index 63e206b1f2..9c5e1905aa 100644 --- a/src/api/endpoints/users/search_by_username.ts +++ b/src/api/endpoints/users/search_by_username.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; -import { pack } from '../../models/user'; +import User, { pack } from '../../models/user'; /** * Search a user by username diff --git a/src/api/endpoints/users/show.ts b/src/api/endpoints/users/show.ts index a51cb619d4..7aea59296a 100644 --- a/src/api/endpoints/users/show.ts +++ b/src/api/endpoints/users/show.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; -import { pack } from '../../models/user'; +import User, { pack } from '../../models/user'; /** * Show a user diff --git a/src/api/private/signin.ts b/src/api/private/signin.ts index ab6e93562c..b49d25d99a 100644 --- a/src/api/private/signin.ts +++ b/src/api/private/signin.ts @@ -2,8 +2,7 @@ import * as express from 'express'; import * as bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; import { default as User, IUser } from '../models/user'; -import Signin from '../models/signin'; -import { pack } from '../models/signin'; +import Signin, { pack } from '../models/signin'; import event from '../event'; import signin from '../common/signin'; import config from '../../conf'; diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 105fe319a5..392f3b1fc7 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -3,8 +3,7 @@ import * as express from 'express'; import * as bcrypt from 'bcryptjs'; import recaptcha = require('recaptcha-promise'); import { default as User, IUser } from '../models/user'; -import { validateUsername, validatePassword } from '../models/user'; -import { pack } from '../models/user'; +import { validateUsername, validatePassword }, { pack } from '../models/user'; import generateUserToken from '../common/generate-native-user-token'; import config from '../../conf'; diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts index ca4f8abcca..7d4964eba6 100644 --- a/src/api/service/twitter.ts +++ b/src/api/service/twitter.ts @@ -5,8 +5,7 @@ import * as uuid from 'uuid'; // const Twitter = require('twitter'); import autwh from 'autwh'; import redis from '../../db/redis'; -import User from '../models/user'; -import { pack } from '../models/user'; +import User, { pack } from '../models/user'; import event from '../event'; import config from '../../conf'; import signin from '../common/signin'; From bcd65d290d25219631bb47570478378a698d0fa0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 4 Feb 2018 14:52:33 +0900 Subject: [PATCH 186/186] wip --- src/api/endpoints/aggregation/posts/reactions.ts | 11 +++++++---- src/api/endpoints/aggregation/users.ts | 13 ++++++++----- src/api/endpoints/app/create.ts | 3 +-- src/api/endpoints/channels/show.ts | 2 +- src/api/endpoints/drive/files/create.ts | 2 +- src/api/endpoints/drive/files/update.ts | 3 +-- src/api/endpoints/drive/files/upload_from_url.ts | 2 +- src/api/endpoints/drive/folders/create.ts | 3 +-- src/api/endpoints/drive/folders/update.ts | 3 +-- src/api/endpoints/following/create.ts | 7 +++---- src/api/endpoints/following/delete.ts | 5 ++--- src/api/endpoints/i/update.ts | 3 +-- src/api/endpoints/posts/reactions/create.ts | 9 ++++----- src/api/endpoints/users/posts.ts | 4 ++-- src/api/endpoints/users/search.ts | 2 +- src/api/models/app.ts | 1 + src/api/models/drive-file.ts | 1 + src/api/models/post-reaction.ts | 3 +++ src/api/models/post.ts | 4 +++- src/api/models/user.ts | 1 + src/api/private/signup.ts | 3 +-- src/api/service/twitter.ts | 2 +- src/api/stream/home.ts | 4 ++-- 23 files changed, 48 insertions(+), 43 deletions(-) diff --git a/src/api/endpoints/aggregation/posts/reactions.ts b/src/api/endpoints/aggregation/posts/reactions.ts index 2cd4588ae1..790b523be9 100644 --- a/src/api/endpoints/aggregation/posts/reactions.ts +++ b/src/api/endpoints/aggregation/posts/reactions.ts @@ -35,10 +35,13 @@ module.exports = (params) => new Promise(async (res, rej) => { { deleted_at: { $gt: startTime } } ] }, { - _id: false, - post_id: false - }, { - sort: { created_at: -1 } + sort: { + _id: -1 + }, + fields: { + _id: false, + post_id: false + } }); const graph = []; diff --git a/src/api/endpoints/aggregation/users.ts b/src/api/endpoints/aggregation/users.ts index 9eb2d035ec..e38ce92ff9 100644 --- a/src/api/endpoints/aggregation/users.ts +++ b/src/api/endpoints/aggregation/users.ts @@ -17,11 +17,14 @@ module.exports = params => new Promise(async (res, rej) => { const users = await User .find({}, { - _id: false, - created_at: true, - deleted_at: true - }, { - sort: { created_at: -1 } + sort: { + _id: -1 + }, + fields: { + _id: false, + created_at: true, + deleted_at: true + } }); const graph = []; diff --git a/src/api/endpoints/app/create.ts b/src/api/endpoints/app/create.ts index 71633f7def..0f688792a7 100644 --- a/src/api/endpoints/app/create.ts +++ b/src/api/endpoints/app/create.ts @@ -3,8 +3,7 @@ */ import rndstr from 'rndstr'; import $ from 'cafy'; -import App from '../../models/app'; -import { isValidNameId }, { pack } from '../../models/app'; +import App, { isValidNameId, pack } from '../../models/app'; /** * @swagger diff --git a/src/api/endpoints/channels/show.ts b/src/api/endpoints/channels/show.ts index 3238616fa5..332da64675 100644 --- a/src/api/endpoints/channels/show.ts +++ b/src/api/endpoints/channels/show.ts @@ -2,7 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import { default as Channel, IChannel }, { pack } from '../../models/channel'; +import Channel, { IChannel, pack } from '../../models/channel'; /** * Show a channel diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts index 7b424f3f5a..96bcace886 100644 --- a/src/api/endpoints/drive/files/create.ts +++ b/src/api/endpoints/drive/files/create.ts @@ -2,7 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import { validateFileName }, { pack } from '../../../models/drive-file'; +import { validateFileName, pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; /** diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index ff65a48f71..83da462113 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; -import DriveFile from '../../../models/drive-file'; -import { validateFileName }, { pack } from '../../../models/drive-file'; +import DriveFile, { validateFileName, pack } from '../../../models/drive-file'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index 009f06aaaf..68428747ef 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -3,7 +3,7 @@ */ import * as URL from 'url'; import $ from 'cafy'; -import { validateFileName }, { pack } from '../../../models/drive-file'; +import { validateFileName, pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; import * as debug from 'debug'; import * as tmp from 'tmp'; diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts index 6543b11274..03f396ddc9 100644 --- a/src/api/endpoints/drive/folders/create.ts +++ b/src/api/endpoints/drive/folders/create.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName }, { pack } from '../../../models/drive-folder'; +import DriveFolder, { isValidFolderName, pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts index 2adcadcb08..d3df8bdae5 100644 --- a/src/api/endpoints/drive/folders/update.ts +++ b/src/api/endpoints/drive/folders/update.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName }, { pack } from '../../../models/drive-folder'; +import DriveFolder, { isValidFolderName, pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/following/create.ts b/src/api/endpoints/following/create.ts index b4a2217b16..8e1aa34713 100644 --- a/src/api/endpoints/following/create.ts +++ b/src/api/endpoints/following/create.ts @@ -2,11 +2,10 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; +import User, { pack as packUser } from '../../models/user'; import Following from '../../models/following'; import notify from '../../common/notify'; import event from '../../event'; -import serializeUser from '../../serializers/user'; /** * Follow a user @@ -77,8 +76,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Publish follow event - event(follower._id, 'follow', await serializeUser(followee, follower)); - event(followee._id, 'followed', await serializeUser(follower, followee)); + event(follower._id, 'follow', await packUser(followee, follower)); + event(followee._id, 'followed', await packUser(follower, followee)); // Notify notify(followee._id, follower._id, 'follow'); diff --git a/src/api/endpoints/following/delete.ts b/src/api/endpoints/following/delete.ts index aa1639ef6c..b68cec09dd 100644 --- a/src/api/endpoints/following/delete.ts +++ b/src/api/endpoints/following/delete.ts @@ -2,10 +2,9 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; +import User, { pack as packUser } from '../../models/user'; import Following from '../../models/following'; import event from '../../event'; -import serializeUser from '../../serializers/user'; /** * Unfollow a user @@ -78,5 +77,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Publish follow event - event(follower._id, 'unfollow', await serializeUser(followee, follower)); + event(follower._id, 'unfollow', await packUser(followee, follower)); }); diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index cd4b1a13f5..7bbbf95900 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; -import { isValidName, isValidDescription, isValidLocation, isValidBirthday }, { pack } from '../../models/user'; +import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../models/user'; import event from '../../event'; import config from '../../../conf'; diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts index d537463dfe..0b0e0e294d 100644 --- a/src/api/endpoints/posts/reactions/create.ts +++ b/src/api/endpoints/posts/reactions/create.ts @@ -3,13 +3,12 @@ */ import $ from 'cafy'; import Reaction from '../../../models/post-reaction'; -import Post from '../../../models/post'; +import Post, { pack as packPost } from '../../../models/post'; +import { pack as packUser } from '../../../models/user'; import Watching from '../../../models/post-watching'; import notify from '../../../common/notify'; import watch from '../../../common/watch-post'; import { publishPostStream, pushSw } from '../../../event'; -import serializePost from '../../../serializers/post'; -import serializeUser from '../../../serializers/user'; /** * React to a post @@ -90,8 +89,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); pushSw(post.user_id, 'reaction', { - user: await serializeUser(user, post.user_id), - post: await serializePost(post, post.user_id), + user: await packUser(user, post.user_id), + post: await packPost(post, post.user_id), reaction: reaction }); diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts index 285e5bc46c..0c8bceee3d 100644 --- a/src/api/endpoints/users/posts.ts +++ b/src/api/endpoints/users/posts.ts @@ -2,8 +2,8 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../../models/post'; -import User, { pack } from '../../models/user'; +import Post, { pack } from '../../models/post'; +import User from '../../models/user'; /** * Get posts of a user diff --git a/src/api/endpoints/users/search.ts b/src/api/endpoints/users/search.ts index 1142db9e9b..39e2ff9890 100644 --- a/src/api/endpoints/users/search.ts +++ b/src/api/endpoints/users/search.ts @@ -51,7 +51,7 @@ async function byNative(res, rej, me, query, offset, max) { // Serialize res(await Promise.all(users.map(async user => - await serialize(user, me, { detail: true })))); + await pack(user, me, { detail: true })))); } // Search by Elasticsearch diff --git a/src/api/models/app.ts b/src/api/models/app.ts index fe9d49ff67..34e9867db7 100644 --- a/src/api/models/app.ts +++ b/src/api/models/app.ts @@ -14,6 +14,7 @@ export type IApp = { _id: mongo.ObjectID; created_at: Date; user_id: mongo.ObjectID; + secret: string; }; export function isValidNameId(nameId: string): boolean { diff --git a/src/api/models/drive-file.ts b/src/api/models/drive-file.ts index 9b9df1dac6..2a46d8dc4d 100644 --- a/src/api/models/drive-file.ts +++ b/src/api/models/drive-file.ts @@ -23,6 +23,7 @@ export type IDriveFile = { uploadDate: Date; md5: string; filename: string; + contentType: string; metadata: { properties: any; user_id: mongodb.ObjectID; diff --git a/src/api/models/post-reaction.ts b/src/api/models/post-reaction.ts index 568bfc89a2..639a70e006 100644 --- a/src/api/models/post-reaction.ts +++ b/src/api/models/post-reaction.ts @@ -9,6 +9,9 @@ export default PostReaction; export interface IPostReaction { _id: mongo.ObjectID; + created_at: Date; + deleted_at: Date; + reaction: string; } /** diff --git a/src/api/models/post.ts b/src/api/models/post.ts index ecc5e1a5e4..0bbacebf66 100644 --- a/src/api/models/post.ts +++ b/src/api/models/post.ts @@ -25,10 +25,12 @@ export type IPost = { media_ids: mongo.ObjectID[]; reply_id: mongo.ObjectID; repost_id: mongo.ObjectID; - poll: {}; // todo + poll: any; // todo text: string; user_id: mongo.ObjectID; app_id: mongo.ObjectID; + category: string; + is_category_verified: boolean; }; /** diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 48a45ac2f7..e92f244dd0 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -42,6 +42,7 @@ export function isValidBirthday(birthday: string): boolean { export type IUser = { _id: mongo.ObjectID; created_at: Date; + deleted_at: Date; email: string; followers_count: number; following_count: number; diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 392f3b1fc7..8efdb6db47 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -2,8 +2,7 @@ import * as uuid from 'uuid'; import * as express from 'express'; import * as bcrypt from 'bcryptjs'; import recaptcha = require('recaptcha-promise'); -import { default as User, IUser } from '../models/user'; -import { validateUsername, validatePassword }, { pack } from '../models/user'; +import User, { IUser, validateUsername, validatePassword, pack } from '../models/user'; import generateUserToken from '../common/generate-native-user-token'; import config from '../../conf'; diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts index 7d4964eba6..adcd5ac49b 100644 --- a/src/api/service/twitter.ts +++ b/src/api/service/twitter.ts @@ -163,7 +163,7 @@ module.exports = (app: express.Application) => { res.send(`Twitter: @${result.screenName} を、Misskey: @${user.username} に接続しました!`); // Publish i updated event - event(user._id, 'i_updated', await serialize(user, user, { + event(user._id, 'i_updated', await pack(user, user, { detail: true, includeSecrets: true })); diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts index 7dcdb5ed73..10078337c3 100644 --- a/src/api/stream/home.ts +++ b/src/api/stream/home.ts @@ -4,7 +4,7 @@ import * as debug from 'debug'; import User from '../models/user'; import Mute from '../models/mute'; -import serializePost from '../serializers/post'; +import { pack as packPost } from '../models/post'; import readNotification from '../common/read-notification'; const log = debug('misskey'); @@ -49,7 +49,7 @@ export default async function(request: websocket.request, connection: websocket. case 'post-stream': const postId = channel.split(':')[2]; log(`RECEIVED: ${postId} ${data} by @${user.username}`); - const post = await serializePost(postId, user, { + const post = await packPost(postId, user, { detail: true }); connection.send(JSON.stringify({