From 2b8602bd1b1b114704f87b3cecad1bd4eb73a13a Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 7 Apr 2019 21:50:36 +0900 Subject: [PATCH] Use PostgreSQL instead of MongoDB (#4572) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * Update note.ts * Update timeline.ts * Update core.ts * wip * Update generate-visibility-query.ts * wip * wip * wip * wip * wip * Update global-timeline.ts * wip * wip * wip * Update vote.ts * wip * wip * Update create.ts * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update files.ts * wip * wip * Update CONTRIBUTING.md * wip * wip * wip * wip * wip * wip * wip * wip * Update read-notification.ts * wip * wip * wip * wip * wip * wip * wip * Update cancel.ts * wip * wip * wip * Update show.ts * wip * wip * Update gen-id.ts * Update create.ts * Update id.ts * wip * wip * wip * wip * wip * wip * wip * Docker: Update files about Docker (#4599) * Docker: Use cache if files used by `yarn install` was not updated This patch reduces the number of times to installing node_modules. For example, `yarn install` step will be skipped when only ".config/default.yml" is updated. * Docker: Migrate MongoDB to Postgresql Misskey uses Postgresql as a database instead of Mongodb since version 11. * Docker: Uncomment about data persistence This patch will save a lot of databases. * wip * wip * wip * Update activitypub.ts * wip * wip * wip * Update logs.ts * wip * Update drive-file.ts * Update register.ts * wip * wip * Update mentions.ts * wip * wip * wip * Update recommendation.ts * wip * Update index.ts * wip * Update recommendation.ts * Doc: Update docker.ja.md and docker.en.md (#1) (#4608) Update how to set up misskey. * wip * :v: * wip * Update note.ts * Update postgre.ts * wip * wip * wip * wip * Update add-file.ts * wip * wip * wip * Clean up * Update logs.ts * wip * :pizza: * wip * Ad notes * wip * Update api-visibility.ts * Update note.ts * Update add-file.ts * tests * tests * Update postgre.ts * Update utils.ts * wip * wip * Refactor * wip * Refactor * wip * wip * Update show-users.ts * Update update-instance.ts * wip * Update feed.ts * Update outbox.ts * Update outbox.ts * Update user.ts * wip * Update list.ts * Update update-hashtag.ts * wip * Update update-hashtag.ts * Refactor * Update update.ts * wip * wip * :v: * clean up * docs * Update push.ts * wip * Update api.ts * wip * :v: * Update make-pagination-query.ts * :v: * Delete hashtags.ts * Update instances.ts * Update instances.ts * Update create.ts * Update search.ts * Update reversi-game.ts * Update signup.ts * Update user.ts * id * Update example.yml * :art: * objectid * fix * reversi * reversi * Fix bug of chart engine * Add test of chart engine * Improve test * Better testing * Improve chart engine * Refactor * Add test of chart engine * Refactor * Add chart test * Fix bug * コミットし忘れ * Refactoring * :v: * Add tests * Add test * Extarct note tests * Refactor * 存在しないユーザーにメンションできなくなっていた問題を修正 * Fix bug * Update update-meta.ts * Fix bug * Update mention.vue * Fix bug * Update meta.ts * Update CONTRIBUTING.md * Fix bug * Fix bug * Fix bug * Clean up * Clean up * Update notification.ts * Clean up * Add mute tests * Add test * Refactor * Add test * Fix test * Refactor * Refactor * Add tests * Update utils.ts * Update utils.ts * Fix test * Update package.json * Update update.ts * Update manifest.ts * Fix bug * Fix bug * Add test * :art: * Update endpoint permissions * Updaye permisison * Update person.ts #4299 * データベースと同期しないように * Fix bug * Fix bug * Update reversi-game.ts * Use a feature of Node v11.7.0 to extract a public key (#4644) * wip * wip * :v: * Refactoring #1540 * test * test * test * test * test * test * test * Fix bug * Fix test * :sushi: * wip * #4471 * Add test for #4335 * Refactor * Fix test * Add tests * :clock4: * Fix bug * Add test * Add test * rename * Fix bug --- .config/docker_example.env | 5 + .config/example.yml | 105 +- .config/mongo_initdb_example.js | 13 - .dockerignore | 6 +- .gitignore | 5 +- CONTRIBUTING.md | 58 ++ Dockerfile | 3 +- binding.gyp | 9 - cli/migration/2.0.0.js | 57 -- cli/migration/2.4.0.js | 71 -- cli/migration/5.0.0.js | 9 - cli/migration/7.0.0.js | 134 --- cli/migration/8.0.0.js | 144 --- docker-compose.yml | 24 +- docs/backup.fr.md | 22 - docs/backup.md | 22 - docs/docker.en.md | 34 +- docs/docker.ja.md | 36 +- docs/setup.en.md | 20 +- docs/setup.fr.md | 12 +- docs/setup.ja.md | 20 +- gulpfile.ts | 1 - index.js | 2 +- locales/ja-JP.yml | 5 - package.json | 28 +- src/@types/deepcopy.d.ts | 19 - src/@types/escape-regexp.d.ts | 7 - src/argv.ts | 3 + src/boot/index.ts | 77 ++ src/boot/master.ts | 176 ++++ src/boot/worker.ts | 20 + src/client/app/admin/views/drive.vue | 2 +- src/client/app/admin/views/hashtags.vue | 8 +- src/client/app/admin/views/instance.vue | 19 +- src/client/app/admin/views/logs.vue | 2 +- src/client/app/admin/views/users.vue | 18 +- src/client/app/auth/views/form.vue | 16 +- src/client/app/common/define-widget.ts | 15 +- src/client/app/common/scripts/note-mixin.ts | 4 +- .../app/common/scripts/note-subscriber.ts | 22 +- .../app/common/views/components/avatar.vue | 13 +- .../components/games/reversi/reversi.game.vue | 42 +- .../components/games/reversi/reversi.room.vue | 49 +- .../components/games/reversi/reversi.vue | 2 +- .../app/common/views/components/instance.vue | 2 +- .../app/common/views/components/mention.vue | 2 +- .../app/common/views/components/poll.vue | 8 +- .../views/components/reactions-viewer.vue | 2 +- .../components/settings/notification.vue | 2 +- .../views/components/settings/profile.vue | 8 +- .../views/components/settings/theme.vue | 33 - .../app/common/views/components/signup.vue | 2 +- .../app/common/views/components/trends.vue | 4 +- .../views/components/user-list-editor.vue | 6 +- .../app/common/views/components/user-menu.vue | 2 +- .../common/views/deck/deck.column-core.vue | 2 +- .../app/common/views/deck/deck.hashtag-tl.vue | 2 +- .../common/views/deck/deck.notification.vue | 2 +- .../app/common/views/deck/deck.tl-column.vue | 6 +- src/client/app/common/views/deck/deck.tl.vue | 6 +- src/client/app/common/views/deck/deck.vue | 18 +- src/client/app/common/views/pages/explore.vue | 6 +- .../app/common/views/pages/followers.vue | 26 +- .../app/common/views/pages/following.vue | 27 +- src/client/app/common/views/pages/share.vue | 2 +- .../app/common/views/widgets/server.info.vue | 2 +- .../desktop/views/components/drive.file.vue | 2 +- .../app/desktop/views/components/note.vue | 4 +- .../views/components/notifications.vue | 2 +- .../views/components/user-list-window.vue | 2 +- .../views/components/user-lists-window.vue | 2 +- src/client/app/desktop/views/home/home.vue | 17 +- src/client/app/desktop/views/home/tag.vue | 2 +- .../app/desktop/views/home/timeline.core.vue | 8 +- .../app/desktop/views/home/timeline.vue | 10 +- .../desktop/views/home/user/user.header.vue | 6 +- .../app/desktop/views/pages/welcome.vue | 8 +- src/client/app/dev/views/new-app.vue | 24 +- src/client/app/mios.ts | 15 - .../views/components/drive.file-detail.vue | 2 +- .../mobile/views/components/drive.file.vue | 2 +- .../views/components/notification-preview.vue | 2 +- .../mobile/views/components/notification.vue | 2 +- .../app/mobile/views/pages/home.timeline.vue | 8 +- src/client/app/mobile/views/pages/home.vue | 12 +- src/client/app/mobile/views/pages/tag.vue | 2 +- .../app/mobile/views/pages/user-list.vue | 2 +- .../app/mobile/views/pages/user-lists.vue | 2 +- .../app/mobile/views/pages/user/index.vue | 10 +- src/client/app/mobile/views/pages/welcome.vue | 8 +- src/client/app/mobile/views/pages/widgets.vue | 7 +- src/client/app/store.ts | 118 +-- src/config/types.ts | 4 +- src/crypto_key.cc | 111 --- src/crypto_key.d.ts | 2 - src/daemons/notes-stats-child.ts | 40 +- src/db/mongodb.ts | 39 - src/db/postgre.ts | 137 +++ src/docs/reversi-bot.ja-JP.md | 6 +- src/docs/stream.ja-JP.md | 2 +- src/index.ts | 279 +----- src/init.ts | 16 + src/mfm/toHtml.ts | 4 +- src/misc/aid.ts | 26 + src/misc/aidc.ts | 26 + src/misc/cafy-id.ts | 29 +- src/misc/check-mongodb.ts | 37 - src/misc/fetch-meta.ts | 43 +- src/misc/fetch-proxy-account.ts | 8 + src/misc/gen-id.ts | 22 + src/misc/get-drive-file-url.ts | 31 - src/misc/get-notification-summary.ts | 2 +- src/misc/get-user-name.ts | 4 +- src/misc/get-user-summary.ts | 9 +- src/misc/is-duplicate-key-value-error.ts | 3 + src/misc/is-objectid.ts | 5 - src/misc/is-quote.ts | 6 +- src/misc/nyaize.ts | 9 + src/misc/object-id.ts | 26 + src/misc/reaction-lib.ts | 4 +- src/misc/should-mute-this-note.ts | 13 +- src/models/abuse-user-report.ts | 52 - src/models/access-token.ts | 16 - src/models/app.ts | 102 -- src/models/auth-session.ts | 49 - src/models/blocking.ts | 56 -- src/models/drive-file-thumbnail.ts | 29 - src/models/drive-file-webpublic.ts | 29 - src/models/drive-file.ts | 232 ----- src/models/drive-folder.ts | 75 -- src/models/emoji.ts | 21 - src/models/entities/abuse-user-report.ts | 41 + src/models/entities/access-token.ts | 45 + src/models/entities/app.ts | 60 ++ src/models/entities/auth-session.ts | 39 + src/models/entities/blocking.ts | 42 + src/models/entities/drive-file.ts | 154 +++ src/models/entities/drive-folder.ts | 49 + src/models/entities/emoji.ts | 46 + src/models/entities/follow-request.ts | 85 ++ src/models/entities/following.ts | 80 ++ src/models/entities/games/reversi/game.ts | 133 +++ src/models/entities/games/reversi/matching.ts | 35 + src/models/entities/hashtag.ts | 87 ++ src/models/entities/instance.ts | 132 +++ src/models/entities/log.ts | 46 + src/models/entities/messaging-message.ts | 64 ++ src/models/entities/meta.ts | 264 +++++ src/models/entities/muting.ts | 42 + src/models/entities/note-favorite.ts | 35 + src/models/entities/note-reaction.ts | 42 + src/models/entities/note-unread.ts | 43 + src/models/entities/note-watching.ts | 52 + src/models/entities/note.ts | 236 +++++ src/models/entities/notification.ts | 94 ++ src/models/entities/poll-vote.ts | 40 + src/models/entities/poll.ts | 67 ++ src/models/entities/registration-tickets.ts | 17 + src/models/entities/signin.ts | 35 + src/models/entities/sw-subscription.ts | 37 + src/models/entities/user-keypair.ts | 24 + src/models/entities/user-list-joining.ts | 41 + src/models/entities/user-list.ts | 33 + src/models/entities/user-note-pinings.ts | 35 + src/models/entities/user-publickey.ts | 30 + src/models/entities/user-service-linking.ts | 108 +++ src/models/entities/user.ts | 297 ++++++ src/models/favorite.ts | 65 -- src/models/follow-request.ts | 66 -- src/models/following.ts | 27 - src/models/games/reversi/game.ts | 111 --- src/models/games/reversi/matching.ts | 45 - src/models/hashtag.ts | 63 -- src/models/id.ts | 4 + src/models/index.ts | 74 ++ src/models/instance.ts | 90 -- src/models/log.ts | 19 - src/models/messaging-message.ts | 75 -- src/models/meta.ts | 257 ----- src/models/mute.ts | 56 -- src/models/note-reaction.ts | 51 - src/models/note-unread.ts | 19 - src/models/note-watching.ts | 15 - src/models/note.ts | 418 -------- src/models/notification.ts | 120 --- src/models/poll-vote.ts | 17 - src/models/registration-tickets.ts | 12 - src/models/repositories/abuse-user-report.ts | 32 + src/models/repositories/app.ts | 36 + src/models/repositories/auth-session.ts | 19 + src/models/repositories/blocking.ts | 28 + src/models/repositories/drive-file.ts | 113 +++ src/models/repositories/drive-folder.ts | 49 + src/models/repositories/follow-request.ts | 19 + src/models/repositories/following.ts | 44 + src/models/repositories/games/reversi/game.ts | 49 + .../repositories/games/reversi/matching.ts | 27 + src/models/repositories/messaging-message.ts | 37 + src/models/repositories/muting.ts | 28 + src/models/repositories/note-favorite.ts | 25 + src/models/repositories/note-reaction.ts | 18 + src/models/repositories/note.ts | 210 ++++ src/models/repositories/notification.ts | 47 + src/models/repositories/signin.ts | 11 + src/models/repositories/user-list.ts | 16 + src/models/repositories/user.ts | 198 ++++ src/models/signin.ts | 34 - src/models/sw-subscription.ts | 13 - src/models/user-list.ts | 41 - src/models/user.ts | 438 --------- src/queue/index.ts | 17 +- src/queue/processors/db/delete-drive-files.ts | 34 +- src/queue/processors/db/delete-notes.ts | 55 -- src/queue/processors/db/export-blocking.ts | 36 +- src/queue/processors/db/export-following.ts | 36 +- src/queue/processors/db/export-mute.ts | 36 +- src/queue/processors/db/export-notes.ts | 48 +- src/queue/processors/db/export-user-lists.ts | 29 +- src/queue/processors/db/import-following.ts | 27 +- src/queue/processors/db/import-user-lists.ts | 41 +- src/queue/processors/db/index.ts | 2 - src/queue/processors/deliver.ts | 26 +- src/queue/processors/inbox.ts | 52 +- .../activitypub/kernel/accept/follow.ts | 10 +- src/remote/activitypub/kernel/accept/index.ts | 2 +- src/remote/activitypub/kernel/add/index.ts | 4 +- .../activitypub/kernel/announce/index.ts | 2 +- .../activitypub/kernel/announce/note.ts | 10 +- src/remote/activitypub/kernel/block/index.ts | 10 +- src/remote/activitypub/kernel/create/image.ts | 2 +- src/remote/activitypub/kernel/create/index.ts | 2 +- src/remote/activitypub/kernel/create/note.ts | 2 +- src/remote/activitypub/kernel/delete/index.ts | 6 +- src/remote/activitypub/kernel/delete/note.ts | 8 +- src/remote/activitypub/kernel/follow.ts | 10 +- src/remote/activitypub/kernel/index.ts | 2 +- src/remote/activitypub/kernel/like.ts | 11 +- .../activitypub/kernel/reject/follow.ts | 10 +- src/remote/activitypub/kernel/reject/index.ts | 2 +- src/remote/activitypub/kernel/remove/index.ts | 4 +- src/remote/activitypub/kernel/undo/block.ts | 10 +- src/remote/activitypub/kernel/undo/follow.ts | 24 +- src/remote/activitypub/kernel/undo/index.ts | 2 +- src/remote/activitypub/kernel/undo/like.ts | 11 +- src/remote/activitypub/kernel/update/index.ts | 2 +- src/remote/activitypub/misc/get-note-html.ts | 6 +- src/remote/activitypub/models/image.ts | 25 +- src/remote/activitypub/models/note.ts | 88 +- src/remote/activitypub/models/person.ts | 242 ++--- src/remote/activitypub/models/question.ts | 41 +- src/remote/activitypub/perform.ts | 2 +- src/remote/activitypub/renderer/accept.ts | 4 +- src/remote/activitypub/renderer/add.ts | 4 +- src/remote/activitypub/renderer/announce.ts | 6 +- src/remote/activitypub/renderer/block.ts | 4 +- src/remote/activitypub/renderer/create.ts | 6 +- src/remote/activitypub/renderer/delete.ts | 4 +- src/remote/activitypub/renderer/document.ts | 10 +- src/remote/activitypub/renderer/emoji.ts | 4 +- .../activitypub/renderer/follow-user.ts | 14 +- src/remote/activitypub/renderer/follow.ts | 9 +- src/remote/activitypub/renderer/image.ts | 10 +- src/remote/activitypub/renderer/key.ts | 13 +- src/remote/activitypub/renderer/like.ts | 10 +- src/remote/activitypub/renderer/mention.ts | 9 +- src/remote/activitypub/renderer/note.ts | 89 +- src/remote/activitypub/renderer/person.ts | 41 +- src/remote/activitypub/renderer/question.ts | 19 +- src/remote/activitypub/renderer/reject.ts | 4 +- src/remote/activitypub/renderer/remove.ts | 4 +- src/remote/activitypub/renderer/undo.ts | 6 +- src/remote/activitypub/renderer/update.ts | 6 +- src/remote/activitypub/renderer/vote.ts | 21 +- src/remote/activitypub/request.ts | 17 +- src/remote/activitypub/resolver.ts | 2 +- src/remote/resolve-user.ts | 21 +- src/server/activitypub.ts | 120 +-- src/server/activitypub/featured.ts | 21 +- src/server/activitypub/followers.ts | 38 +- src/server/activitypub/following.ts | 41 +- src/server/activitypub/outbox.ts | 70 +- src/server/api/authenticate.ts | 24 +- src/server/api/call.ts | 6 +- src/server/api/common/generate-mute-query.ts | 36 + .../api/common/generate-native-user-token.ts | 2 +- .../api/common/generate-visibility-query.ts | 40 + src/server/api/common/get-friends.ts | 49 - src/server/api/common/get-hide-users.ts | 25 - src/server/api/common/getters.ts | 42 +- .../api/common/make-pagination-query.ts | 28 + .../api/common/read-messaging-message.ts | 76 +- src/server/api/common/read-notification.ts | 74 +- src/server/api/common/signin.ts | 2 +- src/server/api/define.ts | 8 +- .../api/endpoints/admin/abuse-user-reports.ts | 30 +- src/server/api/endpoints/admin/drive/files.ts | 34 +- .../api/endpoints/admin/drive/show-file.ts | 9 +- src/server/api/endpoints/admin/emoji/add.ts | 8 +- src/server/api/endpoints/admin/emoji/list.ts | 6 +- .../api/endpoints/admin/emoji/remove.ts | 12 +- .../api/endpoints/admin/emoji/update.ts | 24 +- .../admin/federation/remove-all-following.ts | 11 +- .../admin/federation/update-instance.ts | 17 +- src/server/api/endpoints/admin/invite.ts | 6 +- src/server/api/endpoints/admin/logs.ts | 66 +- .../api/endpoints/admin/moderators/add.ts | 19 +- .../api/endpoints/admin/moderators/remove.ts | 19 +- .../admin/remove-abuse-user-report.ts | 15 +- .../api/endpoints/admin/reset-password.ts | 17 +- src/server/api/endpoints/admin/show-user.ts | 9 +- src/server/api/endpoints/admin/show-users.ts | 74 +- .../api/endpoints/admin/silence-user.ts | 19 +- .../api/endpoints/admin/suspend-user.ts | 31 +- .../api/endpoints/admin/unsilence-user.ts | 19 +- .../api/endpoints/admin/unsuspend-user.ts | 19 +- .../api/endpoints/admin/unverify-user.ts | 19 +- src/server/api/endpoints/admin/update-meta.ts | 58 +- .../api/endpoints/admin/update-remote-user.ts | 13 +- src/server/api/endpoints/admin/verify-user.ts | 19 +- .../api/endpoints/aggregation/hashtags.ts | 72 -- src/server/api/endpoints/ap/show.ts | 59 +- src/server/api/endpoints/app/create.ts | 10 +- src/server/api/endpoints/app/show.ts | 13 +- src/server/api/endpoints/auth/accept.ts | 30 +- .../api/endpoints/auth/session/generate.ts | 11 +- src/server/api/endpoints/auth/session/show.ts | 6 +- .../api/endpoints/auth/session/userkey.ts | 34 +- src/server/api/endpoints/blocking/create.ts | 25 +- src/server/api/endpoints/blocking/delete.ts | 22 +- src/server/api/endpoints/blocking/list.ts | 39 +- .../api/endpoints/charts/active-users.ts | 10 +- src/server/api/endpoints/charts/drive.ts | 6 +- src/server/api/endpoints/charts/federation.ts | 10 +- src/server/api/endpoints/charts/hashtag.ts | 10 +- src/server/api/endpoints/charts/instance.ts | 10 +- src/server/api/endpoints/charts/network.ts | 10 +- src/server/api/endpoints/charts/notes.ts | 6 +- src/server/api/endpoints/charts/user/drive.ts | 9 +- .../api/endpoints/charts/user/following.ts | 11 +- src/server/api/endpoints/charts/user/notes.ts | 9 +- .../api/endpoints/charts/user/reactions.ts | 13 +- src/server/api/endpoints/charts/users.ts | 6 +- src/server/api/endpoints/drive.ts | 26 +- src/server/api/endpoints/drive/files.ts | 48 +- .../endpoints/drive/files/attached-notes.ts | 23 +- .../endpoints/drive/files/check-existence.ts | 13 +- .../api/endpoints/drive/files/create.ts | 11 +- .../api/endpoints/drive/files/delete.ts | 21 +- src/server/api/endpoints/drive/files/find.ts | 20 +- src/server/api/endpoints/drive/files/show.ts | 54 +- .../api/endpoints/drive/files/update.ts | 70 +- .../endpoints/drive/files/upload-from-url.ts | 9 +- src/server/api/endpoints/drive/folders.ts | 41 +- .../api/endpoints/drive/folders/create.ts | 32 +- .../api/endpoints/drive/folders/delete.ts | 29 +- .../api/endpoints/drive/folders/find.ts | 20 +- .../api/endpoints/drive/folders/show.ts | 20 +- .../api/endpoints/drive/folders/update.ts | 57 +- src/server/api/endpoints/drive/stream.ts | 44 +- .../api/endpoints/federation/instances.ts | 128 +-- .../api/endpoints/federation/show-instance.ts | 4 +- src/server/api/endpoints/following/create.ts | 20 +- src/server/api/endpoints/following/delete.ts | 20 +- .../endpoints/following/requests/accept.ts | 5 +- .../endpoints/following/requests/cancel.ts | 9 +- .../api/endpoints/following/requests/list.ts | 10 +- .../endpoints/following/requests/reject.ts | 5 +- .../api/endpoints/games/reversi/games.ts | 45 +- .../api/endpoints/games/reversi/games/show.ts | 20 +- .../games/reversi/games/surrender.ts | 29 +- .../endpoints/games/reversi/invitations.ts | 12 +- .../api/endpoints/games/reversi/match.ts | 65 +- .../endpoints/games/reversi/match/cancel.ts | 8 +- src/server/api/endpoints/hashtags/list.ts | 67 +- src/server/api/endpoints/hashtags/search.ts | 21 +- src/server/api/endpoints/hashtags/trend.ts | 135 +-- src/server/api/endpoints/hashtags/users.ts | 55 +- src/server/api/endpoints/i.ts | 4 +- src/server/api/endpoints/i/2fa/done.ts | 12 +- src/server/api/endpoints/i/2fa/register.ts | 8 +- src/server/api/endpoints/i/2fa/unregister.ts | 10 +- src/server/api/endpoints/i/authorized-apps.ts | 25 +- src/server/api/endpoints/i/change-password.ts | 10 +- .../i/clear-follow-request-notification.ts | 23 - src/server/api/endpoints/i/delete-account.ts | 29 +- src/server/api/endpoints/i/export-blocking.ts | 2 - .../api/endpoints/i/export-following.ts | 2 - src/server/api/endpoints/i/export-mute.ts | 2 - src/server/api/endpoints/i/export-notes.ts | 2 - .../api/endpoints/i/export-user-lists.ts | 2 - src/server/api/endpoints/i/favorites.ts | 41 +- .../api/endpoints/i/import-following.ts | 19 +- .../api/endpoints/i/import-user-lists.ts | 19 +- src/server/api/endpoints/i/notifications.ts | 81 +- src/server/api/endpoints/i/pin.ts | 9 +- .../i/read-all-messaging-messages.ts | 25 +- .../api/endpoints/i/read-all-unread-notes.ts | 22 +- .../api/endpoints/i/regenerate-token.ts | 12 +- src/server/api/endpoints/i/signin-history.ts | 35 +- src/server/api/endpoints/i/unpin.ts | 9 +- .../api/endpoints/i/update-client-setting.ts | 22 +- src/server/api/endpoints/i/update-email.ts | 24 +- src/server/api/endpoints/i/update-home.ts | 33 - .../api/endpoints/i/update-mobile-home.ts | 32 - src/server/api/endpoints/i/update-widget.ts | 88 -- src/server/api/endpoints/i/update.ts | 142 +-- src/server/api/endpoints/messaging/history.ts | 52 +- .../api/endpoints/messaging/messages.ts | 45 +- .../endpoints/messaging/messages/create.ts | 56 +- .../endpoints/messaging/messages/delete.ts | 21 +- .../api/endpoints/messaging/messages/read.ts | 15 +- src/server/api/endpoints/meta.ts | 21 +- src/server/api/endpoints/mute/create.ts | 33 +- src/server/api/endpoints/mute/delete.ts | 23 +- src/server/api/endpoints/mute/list.ts | 39 +- src/server/api/endpoints/my/apps.ts | 19 +- src/server/api/endpoints/notes.ts | 58 +- src/server/api/endpoints/notes/children.ts | 106 +- .../api/endpoints/notes/conversation.ts | 12 +- src/server/api/endpoints/notes/create.ts | 67 +- src/server/api/endpoints/notes/delete.ts | 12 +- .../api/endpoints/notes/favorites/create.ts | 23 +- .../api/endpoints/notes/favorites/delete.ts | 19 +- src/server/api/endpoints/notes/featured.ts | 32 +- .../api/endpoints/notes/global-timeline.ts | 91 +- .../api/endpoints/notes/local-timeline.ts | 111 +-- src/server/api/endpoints/notes/mentions.ts | 110 +-- .../endpoints/notes/polls/recommendation.ts | 88 +- src/server/api/endpoints/notes/polls/vote.ts | 98 +- src/server/api/endpoints/notes/reactions.ts | 35 +- .../api/endpoints/notes/reactions/create.ts | 5 +- .../api/endpoints/notes/reactions/delete.ts | 5 +- src/server/api/endpoints/notes/renotes.ts | 39 +- src/server/api/endpoints/notes/replies.ts | 83 +- .../api/endpoints/notes/search-by-tag.ts | 273 +----- src/server/api/endpoints/notes/search.ts | 24 +- src/server/api/endpoints/notes/show.ts | 7 +- ...{hybrid-timeline.ts => social-timeline.ts} | 165 +--- src/server/api/endpoints/notes/state.ts | 24 +- src/server/api/endpoints/notes/timeline.ts | 150 +-- .../api/endpoints/notes/user-list-timeline.ts | 161 +-- .../api/endpoints/notes/watching/create.ts | 7 +- .../api/endpoints/notes/watching/delete.ts | 7 +- .../notifications/mark-all-as-read.ts | 26 +- src/server/api/endpoints/stats.ts | 28 +- src/server/api/endpoints/sw/register.ts | 13 +- .../api/endpoints/username/available.ts | 9 +- src/server/api/endpoints/users.ts | 84 +- src/server/api/endpoints/users/followers.ts | 100 +- src/server/api/endpoints/users/following.ts | 100 +- .../users/get-frequently-replied-users.ts | 52 +- .../api/endpoints/users/lists/create.ts | 18 +- .../api/endpoints/users/lists/delete.ts | 17 +- src/server/api/endpoints/users/lists/list.ts | 10 +- src/server/api/endpoints/users/lists/pull.ts | 23 +- src/server/api/endpoints/users/lists/push.ts | 21 +- src/server/api/endpoints/users/lists/show.ts | 15 +- .../api/endpoints/users/lists/update.ts | 23 +- src/server/api/endpoints/users/notes.ts | 132 +-- .../api/endpoints/users/recommendation.ts | 99 +- src/server/api/endpoints/users/relation.ts | 7 +- .../api/endpoints/users/report-abuse.ts | 24 +- src/server/api/endpoints/users/search.ts | 40 +- src/server/api/endpoints/users/show.ts | 29 +- src/server/api/index.ts | 9 +- src/server/api/limiter.ts | 8 +- src/server/api/openapi/schemas.ts | 40 +- src/server/api/private/signin.ts | 23 +- src/server/api/private/signup.ts | 99 +- src/server/api/service/discord.ts | 86 +- src/server/api/service/github.ts | 55 +- src/server/api/service/twitter.ts | 58 +- src/server/api/stream/channel.ts | 8 + src/server/api/stream/channels/admin.ts | 2 +- src/server/api/stream/channels/drive.ts | 2 +- .../api/stream/channels/games/reversi-game.ts | 168 ++-- .../api/stream/channels/games/reversi.ts | 13 +- .../api/stream/channels/global-timeline.ts | 18 +- src/server/api/stream/channels/hashtag.ts | 48 +- .../api/stream/channels/home-timeline.ts | 45 +- .../api/stream/channels/hybrid-timeline.ts | 55 -- src/server/api/stream/channels/index.ts | 4 +- .../api/stream/channels/local-timeline.ts | 45 +- src/server/api/stream/channels/main.ts | 9 +- .../api/stream/channels/messaging-index.ts | 2 +- src/server/api/stream/channels/messaging.ts | 4 +- .../api/stream/channels/social-timeline.ts | 64 ++ src/server/api/stream/channels/user-list.ts | 72 +- src/server/api/stream/index.ts | 64 +- src/server/api/streaming.ts | 27 - src/server/file/index.ts | 4 +- src/server/file/send-drive-file.ts | 91 +- src/server/index.ts | 16 +- src/server/nodeinfo.ts | 40 +- src/server/web/feed.ts | 35 +- src/server/web/index.ts | 74 +- src/server/web/manifest.ts | 3 +- src/server/web/views/info.pug | 10 +- src/server/well-known.ts | 22 +- src/services/blocking/create.ts | 89 +- src/services/blocking/delete.ts | 18 +- src/services/chart/active-users.ts | 48 - .../chart/charts/classes/active-users.ts | 35 + src/services/chart/charts/classes/drive.ts | 69 ++ .../chart/charts/classes/federation.ts | 51 + src/services/chart/charts/classes/hashtag.ts | 35 + src/services/chart/charts/classes/instance.ts | 160 +++ src/services/chart/charts/classes/network.ts | 34 + src/services/chart/charts/classes/notes.ts | 71 ++ .../chart/charts/classes/per-user-drive.ts | 52 + .../charts/classes/per-user-following.ts | 91 ++ .../chart/charts/classes/per-user-notes.ts | 58 ++ .../charts/classes/per-user-reactions.ts | 32 + .../chart/charts/classes/test-grouped.ts | 47 + .../chart/charts/classes/test-unique.ts | 29 + src/services/chart/charts/classes/test.ts | 45 + src/services/chart/charts/classes/users.ts | 60 ++ .../chart/charts/schemas/active-users.ts | 28 + src/services/chart/charts/schemas/drive.ts | 65 ++ .../chart/charts/schemas/federation.ts | 27 + src/services/chart/charts/schemas/hashtag.ts | 28 + src/services/chart/charts/schemas/instance.ts | 124 +++ src/services/chart/charts/schemas/network.ts | 30 + src/services/chart/charts/schemas/notes.ts | 52 + .../chart/charts/schemas/per-user-drive.ts | 54 ++ .../charts/schemas/per-user-following.ts | 81 ++ .../chart/charts/schemas/per-user-notes.ts | 41 + .../charts/schemas/per-user-reactions.ts | 28 + .../chart/charts/schemas/test-grouped.ts | 26 + .../chart/charts/schemas/test-unique.ts | 11 + src/services/chart/charts/schemas/test.ts | 26 + src/services/chart/charts/schemas/users.ts | 41 + src/services/chart/core.ts | 460 +++++++++ src/services/chart/drive.ts | 150 --- src/services/chart/entities.ts | 8 + src/services/chart/federation.ts | 66 -- src/services/chart/hashtag.ts | 56 -- src/services/chart/index.ts | 387 +------- src/services/chart/instance.ts | 302 ------ src/services/chart/network.ts | 64 -- src/services/chart/notes.ts | 127 --- src/services/chart/per-user-drive.ts | 122 --- src/services/chart/per-user-following.ts | 162 ---- src/services/chart/per-user-notes.ts | 100 -- src/services/chart/per-user-reactions.ts | 45 - src/services/chart/users.ts | 94 -- src/services/create-notification.ts | 82 +- src/services/drive/add-file.ts | 304 +++--- src/services/drive/delete-file.ts | 110 +-- src/services/drive/internal-storage.ts | 27 + src/services/drive/upload-from-url.ts | 20 +- src/services/following/create.ts | 142 ++- src/services/following/delete.ts | 58 +- src/services/following/requests/accept-all.ts | 18 +- src/services/following/requests/accept.ts | 18 +- src/services/following/requests/cancel.ts | 30 +- src/services/following/requests/create.ts | 65 +- src/services/following/requests/reject.ts | 30 +- src/services/i/pin.ts | 95 +- src/services/i/update.ts | 25 +- src/services/logger.ts | 13 +- src/services/note/create.ts | 470 +++------ src/services/note/delete.ts | 94 +- src/services/note/polls/update.ts | 35 +- src/services/note/polls/vote.ts | 89 +- src/services/note/reaction/create.ts | 92 +- src/services/note/reaction/delete.ts | 45 +- src/services/note/read.ts | 56 +- src/services/note/unread.ts | 45 +- src/services/note/unwatch.ts | 11 +- src/services/note/watch.ts | 31 +- src/services/push-notification.ts | 17 +- .../register-or-fetch-instance-doc.ts | 14 +- src/services/stream.ts | 51 +- src/services/update-hashtag.ts | 109 +-- src/services/user-list/push.ts | 25 +- src/tools/add-emoji.ts | 6 +- src/tools/clean-remote-files.ts | 21 +- src/tools/move-drive-files.ts | 83 -- src/tools/show-signin-history.ts | 13 +- test/api-visibility.ts | 271 ++---- test/api.ts | 635 +++--------- test/chart.ts | 323 ++++++ test/mfm.ts | 4 + test/mocha.opts | 3 +- test/mute.ts | 170 ++++ test/note.ts | 361 +++++++ test/reaction-lib.ts | 4 + test/streaming.ts | 917 +++++++++++++++--- test/user-notes.ts | 86 ++ test/utils.ts | 103 +- tsconfig.json | 1 + 592 files changed, 13463 insertions(+), 14147 deletions(-) create mode 100644 .config/docker_example.env delete mode 100644 .config/mongo_initdb_example.js mode change 100755 => 100644 .dockerignore delete mode 100644 binding.gyp delete mode 100644 cli/migration/2.0.0.js delete mode 100644 cli/migration/2.4.0.js delete mode 100644 cli/migration/5.0.0.js delete mode 100644 cli/migration/7.0.0.js delete mode 100644 cli/migration/8.0.0.js delete mode 100644 docs/backup.fr.md delete mode 100644 docs/backup.md delete mode 100644 src/@types/deepcopy.d.ts delete mode 100644 src/@types/escape-regexp.d.ts create mode 100644 src/boot/index.ts create mode 100644 src/boot/master.ts create mode 100644 src/boot/worker.ts delete mode 100644 src/crypto_key.cc delete mode 100644 src/crypto_key.d.ts delete mode 100644 src/db/mongodb.ts create mode 100644 src/db/postgre.ts create mode 100644 src/init.ts create mode 100644 src/misc/aid.ts create mode 100644 src/misc/aidc.ts delete mode 100644 src/misc/check-mongodb.ts create mode 100644 src/misc/fetch-proxy-account.ts create mode 100644 src/misc/gen-id.ts delete mode 100644 src/misc/get-drive-file-url.ts create mode 100644 src/misc/is-duplicate-key-value-error.ts delete mode 100644 src/misc/is-objectid.ts create mode 100644 src/misc/nyaize.ts create mode 100644 src/misc/object-id.ts delete mode 100644 src/models/abuse-user-report.ts delete mode 100644 src/models/access-token.ts delete mode 100644 src/models/app.ts delete mode 100644 src/models/auth-session.ts delete mode 100644 src/models/blocking.ts delete mode 100644 src/models/drive-file-thumbnail.ts delete mode 100644 src/models/drive-file-webpublic.ts delete mode 100644 src/models/drive-file.ts delete mode 100644 src/models/drive-folder.ts delete mode 100644 src/models/emoji.ts create mode 100644 src/models/entities/abuse-user-report.ts create mode 100644 src/models/entities/access-token.ts create mode 100644 src/models/entities/app.ts create mode 100644 src/models/entities/auth-session.ts create mode 100644 src/models/entities/blocking.ts create mode 100644 src/models/entities/drive-file.ts create mode 100644 src/models/entities/drive-folder.ts create mode 100644 src/models/entities/emoji.ts create mode 100644 src/models/entities/follow-request.ts create mode 100644 src/models/entities/following.ts create mode 100644 src/models/entities/games/reversi/game.ts create mode 100644 src/models/entities/games/reversi/matching.ts create mode 100644 src/models/entities/hashtag.ts create mode 100644 src/models/entities/instance.ts create mode 100644 src/models/entities/log.ts create mode 100644 src/models/entities/messaging-message.ts create mode 100644 src/models/entities/meta.ts create mode 100644 src/models/entities/muting.ts create mode 100644 src/models/entities/note-favorite.ts create mode 100644 src/models/entities/note-reaction.ts create mode 100644 src/models/entities/note-unread.ts create mode 100644 src/models/entities/note-watching.ts create mode 100644 src/models/entities/note.ts create mode 100644 src/models/entities/notification.ts create mode 100644 src/models/entities/poll-vote.ts create mode 100644 src/models/entities/poll.ts create mode 100644 src/models/entities/registration-tickets.ts create mode 100644 src/models/entities/signin.ts create mode 100644 src/models/entities/sw-subscription.ts create mode 100644 src/models/entities/user-keypair.ts create mode 100644 src/models/entities/user-list-joining.ts create mode 100644 src/models/entities/user-list.ts create mode 100644 src/models/entities/user-note-pinings.ts create mode 100644 src/models/entities/user-publickey.ts create mode 100644 src/models/entities/user-service-linking.ts create mode 100644 src/models/entities/user.ts delete mode 100644 src/models/favorite.ts delete mode 100644 src/models/follow-request.ts delete mode 100644 src/models/following.ts delete mode 100644 src/models/games/reversi/game.ts delete mode 100644 src/models/games/reversi/matching.ts delete mode 100644 src/models/hashtag.ts create mode 100644 src/models/id.ts create mode 100644 src/models/index.ts delete mode 100644 src/models/instance.ts delete mode 100644 src/models/log.ts delete mode 100644 src/models/messaging-message.ts delete mode 100644 src/models/meta.ts delete mode 100644 src/models/mute.ts delete mode 100644 src/models/note-reaction.ts delete mode 100644 src/models/note-unread.ts delete mode 100644 src/models/note-watching.ts delete mode 100644 src/models/note.ts delete mode 100644 src/models/notification.ts delete mode 100644 src/models/poll-vote.ts delete mode 100644 src/models/registration-tickets.ts create mode 100644 src/models/repositories/abuse-user-report.ts create mode 100644 src/models/repositories/app.ts create mode 100644 src/models/repositories/auth-session.ts create mode 100644 src/models/repositories/blocking.ts create mode 100644 src/models/repositories/drive-file.ts create mode 100644 src/models/repositories/drive-folder.ts create mode 100644 src/models/repositories/follow-request.ts create mode 100644 src/models/repositories/following.ts create mode 100644 src/models/repositories/games/reversi/game.ts create mode 100644 src/models/repositories/games/reversi/matching.ts create mode 100644 src/models/repositories/messaging-message.ts create mode 100644 src/models/repositories/muting.ts create mode 100644 src/models/repositories/note-favorite.ts create mode 100644 src/models/repositories/note-reaction.ts create mode 100644 src/models/repositories/note.ts create mode 100644 src/models/repositories/notification.ts create mode 100644 src/models/repositories/signin.ts create mode 100644 src/models/repositories/user-list.ts create mode 100644 src/models/repositories/user.ts delete mode 100644 src/models/signin.ts delete mode 100644 src/models/sw-subscription.ts delete mode 100644 src/models/user-list.ts delete mode 100644 src/models/user.ts delete mode 100644 src/queue/processors/db/delete-notes.ts create mode 100644 src/server/api/common/generate-mute-query.ts create mode 100644 src/server/api/common/generate-visibility-query.ts delete mode 100644 src/server/api/common/get-friends.ts delete mode 100644 src/server/api/common/get-hide-users.ts create mode 100644 src/server/api/common/make-pagination-query.ts delete mode 100644 src/server/api/endpoints/aggregation/hashtags.ts delete mode 100644 src/server/api/endpoints/i/clear-follow-request-notification.ts delete mode 100644 src/server/api/endpoints/i/update-home.ts delete mode 100644 src/server/api/endpoints/i/update-mobile-home.ts delete mode 100644 src/server/api/endpoints/i/update-widget.ts rename src/server/api/endpoints/notes/{hybrid-timeline.ts => social-timeline.ts} (50%) delete mode 100644 src/server/api/stream/channels/hybrid-timeline.ts create mode 100644 src/server/api/stream/channels/social-timeline.ts delete mode 100644 src/services/chart/active-users.ts create mode 100644 src/services/chart/charts/classes/active-users.ts create mode 100644 src/services/chart/charts/classes/drive.ts create mode 100644 src/services/chart/charts/classes/federation.ts create mode 100644 src/services/chart/charts/classes/hashtag.ts create mode 100644 src/services/chart/charts/classes/instance.ts create mode 100644 src/services/chart/charts/classes/network.ts create mode 100644 src/services/chart/charts/classes/notes.ts create mode 100644 src/services/chart/charts/classes/per-user-drive.ts create mode 100644 src/services/chart/charts/classes/per-user-following.ts create mode 100644 src/services/chart/charts/classes/per-user-notes.ts create mode 100644 src/services/chart/charts/classes/per-user-reactions.ts create mode 100644 src/services/chart/charts/classes/test-grouped.ts create mode 100644 src/services/chart/charts/classes/test-unique.ts create mode 100644 src/services/chart/charts/classes/test.ts create mode 100644 src/services/chart/charts/classes/users.ts create mode 100644 src/services/chart/charts/schemas/active-users.ts create mode 100644 src/services/chart/charts/schemas/drive.ts create mode 100644 src/services/chart/charts/schemas/federation.ts create mode 100644 src/services/chart/charts/schemas/hashtag.ts create mode 100644 src/services/chart/charts/schemas/instance.ts create mode 100644 src/services/chart/charts/schemas/network.ts create mode 100644 src/services/chart/charts/schemas/notes.ts create mode 100644 src/services/chart/charts/schemas/per-user-drive.ts create mode 100644 src/services/chart/charts/schemas/per-user-following.ts create mode 100644 src/services/chart/charts/schemas/per-user-notes.ts create mode 100644 src/services/chart/charts/schemas/per-user-reactions.ts create mode 100644 src/services/chart/charts/schemas/test-grouped.ts create mode 100644 src/services/chart/charts/schemas/test-unique.ts create mode 100644 src/services/chart/charts/schemas/test.ts create mode 100644 src/services/chart/charts/schemas/users.ts create mode 100644 src/services/chart/core.ts delete mode 100644 src/services/chart/drive.ts create mode 100644 src/services/chart/entities.ts delete mode 100644 src/services/chart/federation.ts delete mode 100644 src/services/chart/hashtag.ts delete mode 100644 src/services/chart/instance.ts delete mode 100644 src/services/chart/network.ts delete mode 100644 src/services/chart/notes.ts delete mode 100644 src/services/chart/per-user-drive.ts delete mode 100644 src/services/chart/per-user-following.ts delete mode 100644 src/services/chart/per-user-notes.ts delete mode 100644 src/services/chart/per-user-reactions.ts delete mode 100644 src/services/chart/users.ts create mode 100644 src/services/drive/internal-storage.ts delete mode 100644 src/tools/move-drive-files.ts create mode 100644 test/chart.ts create mode 100644 test/mute.ts create mode 100644 test/note.ts create mode 100644 test/user-notes.ts diff --git a/.config/docker_example.env b/.config/docker_example.env new file mode 100644 index 000000000..411d93659 --- /dev/null +++ b/.config/docker_example.env @@ -0,0 +1,5 @@ +# db settings +POSTGRES_PASSWORD="example-misskey-pass" +POSTGRES_USER="example-misskey-user" +POSTGRES_DB="misskey" + diff --git a/.config/example.yml b/.config/example.yml index 70c096baa..10239f1a7 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -1,8 +1,16 @@ +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Misskey configuration +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# ┌─────┐ +#───┘ URL └───────────────────────────────────────────────────── + # Final accessible URL seen by a user. url: https://example.tld/ +# ┌───────────────────────┐ +#───┘ Port and TLS settings └─────────────────────────────────── -### Port and TLS settings ###################################### # # Misskey supports two deployment options for public. # @@ -30,28 +38,51 @@ url: https://example.tld/ # You need to set Certificate in 'https' section. # To use option 1, uncomment below line. -# port: 3000 # A port that your Misskey server should listen. +#port: 3000 # A port that your Misskey server should listen. # To use option 2, uncomment below lines. -# port: 443 -# -# https: -# # path for certification -# key: /etc/letsencrypt/live/example.tld/privkey.pem -# cert: /etc/letsencrypt/live/example.tld/fullchain.pem +#port: 443 -################################################################ +#https: +# # path for certification +# key: /etc/letsencrypt/live/example.tld/privkey.pem +# cert: /etc/letsencrypt/live/example.tld/fullchain.pem +# ┌──────────────────────────┐ +#───┘ PostgreSQL configuration └──────────────────────────────── -mongodb: +db: host: localhost - port: 27017 + port: 5432 + + # Database name db: misskey + + # Auth user: example-misskey-user pass: example-misskey-pass +# ┌─────────────────────┐ +#───┘ Redis configuration └───────────────────────────────────── + +#redis: +# host: localhost +# port: 6379 +# pass: example-pass + +# ┌─────────────────────────────┐ +#───┘ Elasticsearch configuration └───────────────────────────── + +#elasticsearch: +# host: localhost +# port: 9200 +# pass: null + +# ┌────────────────────────────────────┐ +#───┘ File storage (Drive) configuration └────────────────────── + drive: - storage: 'db' + storage: 'fs' # OR @@ -88,26 +119,44 @@ drive: # accessKey: XXX # secretKey: YYY +# ┌───────────────┐ +#───┘ ID generation └─────────────────────────────────────────── + +# You can select the ID generation method. +# You don't usually need to change this setting, but you can +# change it according to your preferences. + +# Available methods: +# aid1 ... Use AID for ID generation (with random 1 char) +# aid2 ... Use AID for ID generation (with random 2 chars) +# aid3 ... Use AID for ID generation (with random 3 chars) +# aid4 ... Use AID for ID generation (with random 4 chars) +# ulid ... Use ulid for ID generation +# objectid ... This is left for backward compatibility. + +# AID(n) is the original ID generation method. +# The trailing n represents the number of random characters that +# will be suffixed. +# The larger n is the safer. If n is small, the possibility of +# collision at the same time increases, but there are also +# advantages such as shortening of the URL. + +# ULID: Universally Unique Lexicographically Sortable Identifier. +# for more details: https://github.com/ulid/spec +# * Normally, AID should be sufficient. + +# ObjectID is the method used in previous versions of Misskey. +# * Choose this if you are migrating from a previous Misskey. + +id: 'aid2' + +# ┌─────────────────────┐ +#───┘ Other configuration └───────────────────────────────────── + # If enabled: # The first account created is automatically marked as Admin. autoAdmin: true -# -# Below settings are optional -# - -# Redis -#redis: -# host: localhost -# port: 6379 -# pass: example-pass - -# Elasticsearch -#elasticsearch: -# host: localhost -# port: 9200 -# pass: null - # Whether disable HSTS #disableHsts: true diff --git a/.config/mongo_initdb_example.js b/.config/mongo_initdb_example.js deleted file mode 100644 index b7e7321f3..000000000 --- a/.config/mongo_initdb_example.js +++ /dev/null @@ -1,13 +0,0 @@ -var user = { - user: 'example-misskey-user', - pwd: 'example-misskey-pass', - roles: [ - { - role: 'readWrite', - db: 'misskey' - } - ] -}; - -db.createUser(user); - diff --git a/.dockerignore b/.dockerignore old mode 100755 new mode 100644 index a25d4e571..324c4bce5 --- a/.dockerignore +++ b/.dockerignore @@ -5,8 +5,8 @@ .vscode Dockerfile build/ +db/ docker-compose.yml -node_modules/ -mongo/ -redis/ elasticsearch/ +node_modules/ +redis/ diff --git a/.gitignore b/.gitignore index 98ee82cd7..650d4f612 100644 --- a/.gitignore +++ b/.gitignore @@ -8,14 +8,15 @@ built /data /.cache-loader +/db +/elasticsearch npm-debug.log *.pem run.bat api-docs.json *.log /redis -/mongo -/elasticsearch *.code-workspace yarn.lock .DS_Store +/files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1ad1f804..a45ed5cb5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,3 +75,61 @@ src ... Source code test ... Test code ``` + +## Notes +### placeholder +SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない +例えば +``` ts +query.andWhere(new Brackets(qb => { + for (const type of ps.fileType) { + qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type }); + } +})); +``` +と書くと、ループ中で`type`というプレースホルダが複数回使われてしまいおかしくなる +だから次のようにする必要がある +```ts +query.andWhere(new Brackets(qb => { + for (const type of ps.fileType) { + const i = ps.fileType.indexOf(type); + qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type }); + } +})); +``` + +### `null` in SQL +SQLを発行する際、パラメータが`null`になる可能性のある場合はSQL文を出し分けなければならない +例えば +``` ts +query.where('file.folderId = :folderId', { folderId: ps.folderId }); +``` +という処理で、`ps.folderId`が`null`だと結果的に`file.folderId = null`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない +だから次のようにする必要がある +``` ts +if (ps.folderId) { + query.where('file.folderId = :folderId', { folderId: ps.folderId }); +} else { + query.where('file.folderId IS NULL'); +} +``` + +### `[]` in SQL +SQLを発行する際、`IN`のパラメータが`[]`(空の配列)になる可能性のある場合はSQL文を出し分けなければならない +例えば +``` ts +const users = await Users.find({ + id: In(userIds) +}); +``` +という処理で、`userIds`が`[]`だと結果的に`user.id IN ()`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない +だから次のようにする必要がある +``` ts +const users = userIds.length > 0 ? await Users.find({ + id: In(userIds) +}) : []; +``` + +### `undefined`にご用心 +MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 +MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください diff --git a/Dockerfile b/Dockerfile index ad04fb33d..ec7d8a6a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,8 +23,9 @@ RUN apk add --no-cache \ zlib-dev RUN npm i -g yarn -COPY . ./ +COPY package.json ./ RUN yarn install +COPY . ./ RUN yarn build FROM base AS runner diff --git a/binding.gyp b/binding.gyp deleted file mode 100644 index 0349526d5..000000000 --- a/binding.gyp +++ /dev/null @@ -1,9 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'crypto_key', - 'sources': ['src/crypto_key.cc'], - 'include_dirs': [' { - const promise = new Promise(async (res, rej) => { - const file = await DriveFile.findOne(prev ? { - _id: { $gt: prev._id } - } : {}, { - sort: { - _id: 1 - } - }); - - prev = file; - - const user = await User.findOne({ _id: file.metadata.userId }); - - DriveFile.update({ - _id: file._id - }, { - $set: { - 'metadata._user': { - host: user.host - } - } - }).then(() => { - res([i, file]); - }).catch(rej); - }); - - promise.then(([i, file]) => { - console.log(chalk`{gray ${i}} {green done: {bold ${file._id}} ${file.filename}}`); - }); - - return promise; - }); - } - - return await sequential(promiseGens); -} - -main().then(() => { - console.log('ALL DONE'); -}).catch(console.error); diff --git a/cli/migration/2.4.0.js b/cli/migration/2.4.0.js deleted file mode 100644 index aa37849aa..000000000 --- a/cli/migration/2.4.0.js +++ /dev/null @@ -1,71 +0,0 @@ -// for Node.js interpret - -const chalk = require('chalk'); -const sequential = require('promise-sequential'); - -const { default: User } = require('../../built/models/user'); -const { default: DriveFile } = require('../../built/models/drive-file'); - -async function main() { - const promiseGens = []; - - const count = await User.count({}); - - let prev; - - for (let i = 0; i < count; i++) { - promiseGens.push(() => { - const promise = new Promise(async (res, rej) => { - const user = await User.findOne(prev ? { - _id: { $gt: prev._id } - } : {}, { - sort: { - _id: 1 - } - }); - - prev = user; - - const set = {}; - - if (user.avatarId != null) { - const file = await DriveFile.findOne({ _id: user.avatarId }); - - if (file && file.metadata.properties.avgColor) { - set.avatarColor = file.metadata.properties.avgColor; - } - } - - if (user.bannerId != null) { - const file = await DriveFile.findOne({ _id: user.bannerId }); - - if (file && file.metadata.properties.avgColor) { - set.bannerColor = file.metadata.properties.avgColor; - } - } - - if (Object.keys(set).length === 0) return res([i, user]); - - User.update({ - _id: user._id - }, { - $set: set - }).then(() => { - res([i, user]); - }).catch(rej); - }); - - promise.then(([i, user]) => { - console.log(chalk`{gray ${i}} {green done: {bold ${user._id}} @${user.username}}`); - }); - - return promise; - }); - } - - return await sequential(promiseGens); -} - -main().then(() => { - console.log('ALL DONE'); -}).catch(console.error); diff --git a/cli/migration/5.0.0.js b/cli/migration/5.0.0.js deleted file mode 100644 index bef103fe4..000000000 --- a/cli/migration/5.0.0.js +++ /dev/null @@ -1,9 +0,0 @@ -const { default: DriveFile } = require('../../built/models/drive-file'); - -DriveFile.update({}, { - $rename: { - 'metadata.isMetaOnly': 'metadata.withoutChunks' - } -}, { - multi: true -}); diff --git a/cli/migration/7.0.0.js b/cli/migration/7.0.0.js deleted file mode 100644 index fa5e363db..000000000 --- a/cli/migration/7.0.0.js +++ /dev/null @@ -1,134 +0,0 @@ -const { default: Stats } = require('../../built/models/stats'); -const { default: User } = require('../../built/models/user'); -const { default: Note } = require('../../built/models/note'); -const { default: DriveFile } = require('../../built/models/drive-file'); - -const now = new Date(); -const y = now.getFullYear(); -const m = now.getMonth(); -const d = now.getDate(); -const today = new Date(y, m, d); - -async function main() { - const localUsersCount = await User.count({ - host: null - }); - - const remoteUsersCount = await User.count({ - host: { $ne: null } - }); - - const localNotesCount = await Note.count({ - '_user.host': null - }); - - const remoteNotesCount = await Note.count({ - '_user.host': { $ne: null } - }); - - const localDriveFilesCount = await DriveFile.count({ - 'metadata._user.host': null - }); - - const remoteDriveFilesCount = await DriveFile.count({ - 'metadata._user.host': { $ne: null } - }); - - const localDriveFilesSize = await DriveFile - .aggregate([{ - $match: { - 'metadata._user.host': null, - 'metadata.deletedAt': { $exists: false } - } - }, { - $project: { - length: true - } - }, { - $group: { - _id: null, - usage: { $sum: '$length' } - } - }]) - .then(aggregates => { - if (aggregates.length > 0) { - return aggregates[0].usage; - } - return 0; - }); - - const remoteDriveFilesSize = await DriveFile - .aggregate([{ - $match: { - 'metadata._user.host': { $ne: null }, - 'metadata.deletedAt': { $exists: false } - } - }, { - $project: { - length: true - } - }, { - $group: { - _id: null, - usage: { $sum: '$length' } - } - }]) - .then(aggregates => { - if (aggregates.length > 0) { - return aggregates[0].usage; - } - return 0; - }); - - await Stats.insert({ - date: today, - users: { - local: { - total: localUsersCount, - diff: 0 - }, - remote: { - total: remoteUsersCount, - diff: 0 - } - }, - notes: { - local: { - total: localNotesCount, - diff: 0, - diffs: { - normal: 0, - reply: 0, - renote: 0 - } - }, - remote: { - total: remoteNotesCount, - diff: 0, - diffs: { - normal: 0, - reply: 0, - renote: 0 - } - } - }, - drive: { - local: { - totalCount: localDriveFilesCount, - totalSize: localDriveFilesSize, - diffCount: 0, - diffSize: 0 - }, - remote: { - totalCount: remoteDriveFilesCount, - totalSize: remoteDriveFilesSize, - diffCount: 0, - diffSize: 0 - } - } - }); - - console.log('done'); -} - -main(); diff --git a/cli/migration/8.0.0.js b/cli/migration/8.0.0.js deleted file mode 100644 index fd6cb2452..000000000 --- a/cli/migration/8.0.0.js +++ /dev/null @@ -1,144 +0,0 @@ -const { default: Stats } = require('../../built/models/stats'); -const { default: User } = require('../../built/models/user'); -const { default: Note } = require('../../built/models/note'); -const { default: DriveFile } = require('../../built/models/drive-file'); - -const now = new Date(); -const y = now.getFullYear(); -const m = now.getMonth(); -const d = now.getDate(); -const h = now.getHours(); -const date = new Date(y, m, d, h); - -async function main() { - await Stats.update({}, { - $set: { - span: 'day' - } - }, { - multi: true - }); - - const localUsersCount = await User.count({ - host: null - }); - - const remoteUsersCount = await User.count({ - host: { $ne: null } - }); - - const localNotesCount = await Note.count({ - '_user.host': null - }); - - const remoteNotesCount = await Note.count({ - '_user.host': { $ne: null } - }); - - const localDriveFilesCount = await DriveFile.count({ - 'metadata._user.host': null - }); - - const remoteDriveFilesCount = await DriveFile.count({ - 'metadata._user.host': { $ne: null } - }); - - const localDriveFilesSize = await DriveFile - .aggregate([{ - $match: { - 'metadata._user.host': null, - 'metadata.deletedAt': { $exists: false } - } - }, { - $project: { - length: true - } - }, { - $group: { - _id: null, - usage: { $sum: '$length' } - } - }]) - .then(aggregates => { - if (aggregates.length > 0) { - return aggregates[0].usage; - } - return 0; - }); - - const remoteDriveFilesSize = await DriveFile - .aggregate([{ - $match: { - 'metadata._user.host': { $ne: null }, - 'metadata.deletedAt': { $exists: false } - } - }, { - $project: { - length: true - } - }, { - $group: { - _id: null, - usage: { $sum: '$length' } - } - }]) - .then(aggregates => { - if (aggregates.length > 0) { - return aggregates[0].usage; - } - return 0; - }); - - await Stats.insert({ - date: date, - span: 'hour', - users: { - local: { - total: localUsersCount, - diff: 0 - }, - remote: { - total: remoteUsersCount, - diff: 0 - } - }, - notes: { - local: { - total: localNotesCount, - diff: 0, - diffs: { - normal: 0, - reply: 0, - renote: 0 - } - }, - remote: { - total: remoteNotesCount, - diff: 0, - diffs: { - normal: 0, - reply: 0, - renote: 0 - } - } - }, - drive: { - local: { - totalCount: localDriveFilesCount, - totalSize: localDriveFilesSize, - diffCount: 0, - diffSize: 0 - }, - remote: { - totalCount: remoteDriveFilesCount, - totalSize: remoteDriveFilesSize, - diffCount: 0, - diffSize: 0 - } - } - }); - - console.log('done'); -} - -main(); diff --git a/docker-compose.yml b/docker-compose.yml index 7ff8f6a26..184738aa8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: build: . restart: always links: - - mongo + - db # - redis # - es ports: @@ -19,21 +19,18 @@ services: # image: redis:4.0-alpine # networks: # - internal_network -### Uncomment to enable Redis persistance -## volumes: -## - ./redis:/data +# volumes: +# - ./redis:/data - mongo: + db: restart: always - image: mongo:4.1 + image: postgres:11.2-alpine networks: - internal_network - environment: - MONGO_INITDB_DATABASE: "misskey" + env_file: + - .config/docker.env volumes: - - ./.config/mongo_initdb.js:/docker-entrypoint-initdb.d/mongo_initdb.js:ro -### Uncomment to enable MongoDB persistance -# - ./mongo:/data + - ./db:/var/lib/postgresql/data # es: # restart: always @@ -42,9 +39,8 @@ services: # - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # networks: # - internal_network -#### Uncomment to enable ES persistence -## volumes: -## - ./elasticsearch:/usr/share/elasticsearch/data +# volumes: +# - ./elasticsearch:/usr/share/elasticsearch/data networks: internal_network: diff --git a/docs/backup.fr.md b/docs/backup.fr.md deleted file mode 100644 index 19e99068c..000000000 --- a/docs/backup.fr.md +++ /dev/null @@ -1,22 +0,0 @@ -Comment faire une sauvegarde de votre Misskey ? -========================== - -Assurez-vous d'avoir installé **mongodb-tools**. - ---- - -Dans votre terminal : -``` shell -$ mongodump --archive=db-backup -u -p -``` - -Pour plus de détails, merci de consulter [la documentation de mongodump](https://docs.mongodb.com/manual/reference/program/mongodump/). - -Restauration -------- - -``` shell -$ mongorestore --archive=db-backup -``` - -Pour plus de détails, merci de consulter [la documentation de mongorestore](https://docs.mongodb.com/manual/reference/program/mongorestore/). diff --git a/docs/backup.md b/docs/backup.md deleted file mode 100644 index a69af0255..000000000 --- a/docs/backup.md +++ /dev/null @@ -1,22 +0,0 @@ -How to backup your Misskey -========================== - -Make sure **mongodb-tools** installed. - ---- - -In your shell: -``` shell -$ mongodump --archive=db-backup -u -p -``` - -For details, please see [mongodump docs](https://docs.mongodb.com/manual/reference/program/mongodump/). - -Restore -------- - -``` shell -$ mongorestore --archive=db-backup -``` - -For details, please see [mongorestore docs](https://docs.mongodb.com/manual/reference/program/mongorestore/). diff --git a/docs/docker.en.md b/docs/docker.en.md index f0fcdb66d..ee69b6d7a 100644 --- a/docs/docker.en.md +++ b/docs/docker.en.md @@ -15,9 +15,37 @@ This guide describes how to install and setup Misskey with Docker. *2.* Configure Misskey ---------------------------------------------------------------- -1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`. -2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`. -3. Edit `default.yml` and `mongo_initdb.js`. + +Create configuration files with following: + +```bash +cd .config +cp example.yml default.yml +cp docker_example.env docker.env +``` + +### `default.yml` + +Edit this file the same as non-Docker environment. +However hostname of Postgresql, Redis and Elasticsearch are not `localhost`, they are set in `docker-compose.yml`. +The following is default hostname: + +| Service | Hostname | +|---------------|----------| +| Postgresql | `db` | +| Redis | `redis` | +| Elasticsearch | `es` | + +### `docker.env` + +Configure Postgresql in this file. +The minimum required settings are: + +| name | Description | +|---------------------|---------------| +| `POSTGRES_PASSWORD` | Password | +| `POSTGRES_USER` | Username | +| `POSTGRES_DB` | Database name | *3.* Configure Docker ---------------------------------------------------------------- diff --git a/docs/docker.ja.md b/docs/docker.ja.md index 0baf28572..060d4e7bd 100644 --- a/docs/docker.ja.md +++ b/docs/docker.ja.md @@ -13,11 +13,39 @@ Dockerを使ったMisskey構築方法 2. `cd misskey` misskeyディレクトリに移動 3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認 -*2.* 設定ファイルを作成する +*2.* 設定ファイルの作成と編集 ---------------------------------------------------------------- -1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする -2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` `.config/mongo_initdb_example.js`をコピーし名前を`mongo_initdb.js`にする -3. `default.yml`と`mongo_initdb.js`を編集する + +下記コマンドで設定ファイルを作成してください。 + +```bash +cd .config +cp example.yml default.yml +cp docker_example.env docker.env +``` + +### `default.yml`の編集 + +非Docker環境と同じ様に編集してください。 +ただし、Postgresql、RedisとElasticsearchのホストは`localhost`ではなく、`docker-compose.yml`で設定されたサービス名になっています。 +標準設定では次の通りです。 + +| サービス | ホスト名 | +|---------------|---------| +| Postgresql |`db` | +| Redis |`redis` | +| Elasticsearch |`es` | + +### `docker.env`の編集 + +このファイルはPostgresqlの設定を記述します。 +最低限記述する必要がある設定は次の通りです。 + +| 設定 | 内容 | +|---------------------|--------------| +| `POSTGRES_PASSWORD` | パスワード | +| `POSTGRES_USER` | ユーザー名 | +| `POSTGRES_DB` | データベース名 | *3.* Dockerの設定 ---------------------------------------------------------------- diff --git a/docs/setup.en.md b/docs/setup.en.md index 112508144..28de1f32f 100644 --- a/docs/setup.en.md +++ b/docs/setup.en.md @@ -22,8 +22,8 @@ adduser --disabled-password --disabled-login misskey Please install and setup these softwares: #### Dependencies :package: -* **[Node.js](https://nodejs.org/en/)** >= 10.0.0 -* **[MongoDB](https://www.mongodb.com/)** >= 3.6 +* **[Node.js](https://nodejs.org/en/)** >= 11.7.0 +* **[PostgreSQL](https://www.postgresql.org/)** >= 10 ##### Optional * [Redis](https://redis.io/) @@ -31,13 +31,9 @@ Please install and setup these softwares: * [Elasticsearch](https://www.elastic.co/) - required to enable the search feature * [FFmpeg](https://www.ffmpeg.org/) -*3.* Setup MongoDB +*3.* Setup PostgreSQL ---------------------------------------------------------------- -As root: -1. `mongo` Go to the mongo shell -2. `use misskey` Use the misskey database -3. `db.createUser( { user: "misskey", pwd: "", roles: [ { role: "readWrite", db: "misskey" } ] } )` Create the misskey user. -4. `exit` You're done! +:) *4.* Install Misskey ---------------------------------------------------------------- @@ -68,7 +64,13 @@ If you're still encountering errors about some modules, use node-gyp: 3. `node-gyp build` 4. `NODE_ENV=production npm run build` -*7.* That is it. +*7.* Init DB +---------------------------------------------------------------- +``` shell +npm run init +``` + +*8.* That is it. ---------------------------------------------------------------- Well done! Now, you have an environment that run to Misskey. diff --git a/docs/setup.fr.md b/docs/setup.fr.md index 959ec3392..217a4c6a5 100644 --- a/docs/setup.fr.md +++ b/docs/setup.fr.md @@ -22,8 +22,8 @@ adduser --disabled-password --disabled-login misskey Installez les paquets suivants : #### Dépendences :package: -* **[Node.js](https://nodejs.org/en/)** >= 10.0.0 -* **[MongoDB](https://www.mongodb.com/)** >= 3.6 +* **[Node.js](https://nodejs.org/en/)** >= 11.7.0 +* **[PostgreSQL](https://www.postgresql.org/)** >= 10 ##### Optionnels * [Redis](https://redis.io/) @@ -31,13 +31,9 @@ Installez les paquets suivants : * [Elasticsearch](https://www.elastic.co/) - requis pour pouvoir activer la fonctionnalité de recherche * [FFmpeg](https://www.ffmpeg.org/) -*3.* Paramètrage de MongoDB +*3.* Paramètrage de PostgreSQL ---------------------------------------------------------------- -En root : -1. `mongo` Ouvrez le shell mongo -2. `use misskey` Utilisez la base de données misskey -3. `db.createUser( { user: "misskey", pwd: "", roles: [ { role: "readWrite", db: "misskey" } ] } )` Créez l'utilisateur misskey. -4. `exit` Vous avez terminé ! +:) *4.* Installation de Misskey ---------------------------------------------------------------- diff --git a/docs/setup.ja.md b/docs/setup.ja.md index 8a21e104d..1543541ee 100644 --- a/docs/setup.ja.md +++ b/docs/setup.ja.md @@ -22,8 +22,8 @@ adduser --disabled-password --disabled-login misskey これらのソフトウェアをインストール・設定してください: #### 依存関係 :package: -* **[Node.js](https://nodejs.org/en/)** (10.0.0以上) -* **[MongoDB](https://www.mongodb.com/)** (3.6以上) +* **[Node.js](https://nodejs.org/en/)** (11.7.0以上) +* **[PostgreSQL](https://www.postgresql.org/)** (10以上) ##### オプション * [Redis](https://redis.io/) @@ -38,13 +38,9 @@ adduser --disabled-password --disabled-login misskey * 検索機能を有効にするためにはインストールが必要です。 * [FFmpeg](https://www.ffmpeg.org/) -*3.* MongoDBの設定 +*3.* PostgreSQLの設定 ---------------------------------------------------------------- -ルートで: -1. `mongo` mongoシェルを起動 -2. `use misskey` misskeyデータベースを使用 -3. `db.createUser( { user: "misskey", pwd: "", roles: [ { role: "readWrite", db: "misskey" } ] } )` misskeyユーザーを作成 -4. `exit` mongoシェルを終了 +:) *4.* Misskeyのインストール ---------------------------------------------------------------- @@ -74,7 +70,13 @@ Debianをお使いであれば、`build-essential`パッケージをインスト 3. `node-gyp build` 4. `NODE_ENV=production npm run build` -*7.* 以上です! +*7.* データベースを初期化 +---------------------------------------------------------------- +``` shell +npm run init +``` + +*8.* 以上です! ---------------------------------------------------------------- お疲れ様でした。これでMisskeyを動かす準備は整いました。 diff --git a/gulpfile.ts b/gulpfile.ts index b2956c240..bf0b87ef2 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -49,7 +49,6 @@ gulp.task('build:copy:views', () => gulp.task('build:copy', gulp.parallel('build:copy:views', () => gulp.src([ - './build/Release/crypto_key.node', './src/const.json', './src/server/web/views/**/*', './src/**/assets/**/*', diff --git a/index.js b/index.js index 5b7d1347a..bc7e8b2f3 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -require('./built'); +require('./built').default(); diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index d4457b659..43d8cb309 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1238,11 +1238,6 @@ admin/views/instance.vue: save: "保存" saved: "保存しました" user-recommendation-config: "おすすめユーザー" - enable-external-user-recommendation: "外部ユーザーレコメンデーションを有効にする" - external-user-recommendation-engine: "エンジン" - external-user-recommendation-engine-desc: "例: https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}" - external-user-recommendation-timeout: "タイムアウト" - external-user-recommendation-timeout-desc: "ミリ秒単位 (例: 300000)" email-config: "メールサーバーの設定" email-config-info: "メールアドレス確認やパスワードリセットの際に使われます。" enable-email: "メール配信を有効にする" diff --git a/package.json b/package.json index 39e6aa7de..a7c12862f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "misskey", "author": "syuilo ", - "version": "10.99.0", - "codename": "nighthike", + "version": "11.0.0", + "codename": "daybreak", "repository": { "type": "git", "url": "https://github.com/syuilo/misskey.git" @@ -11,6 +11,7 @@ "private": true, "scripts": { "start": "node ./index.js", + "init": "node ./built/init.js", "debug": "DEBUG=misskey:* node ./index.js", "build": "webpack && gulp build", "webpack": "webpack", @@ -62,10 +63,9 @@ "@types/koa-send": "4.1.1", "@types/koa-views": "2.0.3", "@types/koa__cors": "2.2.3", + "@types/lolex": "3.1.1", "@types/minio": "7.0.1", - "@types/mkdirp": "0.5.2", - "@types/mocha": "5.2.5", - "@types/mongodb": "3.1.20", + "@types/mocha": "5.2.6", "@types/node": "11.10.4", "@types/nodemailer": "4.6.6", "@types/nprogress": "0.0.29", @@ -107,6 +107,7 @@ "chai": "4.2.0", "chai-http": "4.2.1", "chalk": "2.4.2", + "cli-highlight": "2.1.0", "commander": "2.20.0", "content-disposition": "0.5.3", "crc-32": "1.2.0", @@ -114,12 +115,10 @@ "cssnano": "4.1.10", "dateformat": "3.0.3", "deep-equal": "1.0.1", - "deepcopy": "0.6.3", "diskusage": "1.0.0", "double-ended-queue": "2.1.0-0", "elasticsearch": "15.4.1", "emojilib": "2.4.0", - "escape-regexp": "0.0.1", "eslint": "5.15.1", "eslint-plugin-vue": "5.2.2", "eventemitter3": "3.1.0", @@ -163,23 +162,22 @@ "koa-views": "6.2.0", "langmap": "0.0.16", "loader-utils": "1.2.3", + "lolex": "3.1.0", "lookup-dns-cache": "2.1.0", "minio": "7.0.5", - "mkdirp": "0.5.1", - "mocha": "5.2.0", + "mocha": "6.0.2", "moji": "0.5.1", "moment": "2.24.0", - "mongodb": "3.2.2", - "monk": "6.0.6", "ms": "2.1.1", - "nan": "2.12.1", "nested-property": "0.0.7", + "node-fetch": "2.3.0", "nodemailer": "5.1.1", "nprogress": "0.2.0", "object-assign-deep": "0.4.0", "os-utils": "0.0.14", "parse5": "5.1.0", "parsimmon": "1.12.0", + "pg": "7.9.0", "portscanner": "2.2.0", "postcss-loader": "3.0.0", "prismjs": "1.16.0", @@ -195,10 +193,12 @@ "recaptcha-promise": "0.1.3", "reconnecting-websocket": "4.1.10", "redis": "2.8.0", + "reflect-metadata": "0.1.13", "rename": "1.0.4", "request": "2.88.0", "request-promise-native": "1.0.7", "request-stats": "3.0.0", + "require-all": "3.0.0", "rimraf": "2.6.3", "rndstr": "1.0.0", "s-age": "1.1.2", @@ -219,12 +219,14 @@ "tinycolor2": "1.4.1", "tmp": "0.0.33", "ts-loader": "5.3.3", - "ts-node": "8.0.3", + "ts-node": "7.0.1", "tslint": "5.13.1", "tslint-sonarts": "1.9.0", + "typeorm": "0.2.16-rc.1", "typescript": "3.3.3333", "typescript-eslint-parser": "22.0.0", "uglify-es": "3.3.9", + "ulid": "2.3.0", "url-loader": "1.1.2", "uuid": "3.3.2", "v-animate-css": "0.0.3", diff --git a/src/@types/deepcopy.d.ts b/src/@types/deepcopy.d.ts deleted file mode 100644 index f276b7e67..000000000 --- a/src/@types/deepcopy.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -declare module 'deepcopy' { - type DeepcopyCustomizerValueType = 'Object'; - - type DeepcopyCustomizer = ( - value: T, - valueType: DeepcopyCustomizerValueType) => T; - - interface IDeepcopyOptions { - customizer: DeepcopyCustomizer; - } - - function deepcopy( - value: T, - options?: IDeepcopyOptions | DeepcopyCustomizer): T; - - namespace deepcopy {} // Hack - - export = deepcopy; -} diff --git a/src/@types/escape-regexp.d.ts b/src/@types/escape-regexp.d.ts deleted file mode 100644 index d68e6048a..000000000 --- a/src/@types/escape-regexp.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare module 'escape-regexp' { - function escapeRegExp(str: string): string; - - namespace escapeRegExp {} // Hack - - export = escapeRegExp; -} diff --git a/src/argv.ts b/src/argv.ts index b5540441c..562852d17 100644 --- a/src/argv.ts +++ b/src/argv.ts @@ -15,5 +15,8 @@ program .parse(process.argv); if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true; +if (process.env.NODE_ENV === 'test') program.disableClustering = true; +if (process.env.NODE_ENV === 'test') program.quiet = true; +if (process.env.NODE_ENV === 'test') program.noDaemons = true; export { program }; diff --git a/src/boot/index.ts b/src/boot/index.ts new file mode 100644 index 000000000..2c86d8ed8 --- /dev/null +++ b/src/boot/index.ts @@ -0,0 +1,77 @@ +import * as cluster from 'cluster'; +import chalk from 'chalk'; +import Xev from 'xev'; + +import Logger from '../services/logger'; +import { program } from '../argv'; + +// for typeorm +import 'reflect-metadata'; +import { masterMain } from './master'; +import { workerMain } from './worker'; + +const logger = new Logger('core', 'cyan'); +const clusterLogger = logger.createSubLogger('cluster', 'orange', false); +const ev = new Xev(); + +/** + * Init process + */ +export default async function() { + process.title = `Misskey (${cluster.isMaster ? 'master' : 'worker'})`; + + if (cluster.isMaster || program.disableClustering) { + await masterMain(); + + if (cluster.isMaster) { + ev.mount(); + } + } + + if (cluster.isWorker || program.disableClustering) { + await workerMain(); + } + + // ユニットテスト時にMisskeyが子プロセスで起動された時のため + // それ以外のときは process.send は使えないので弾く + if (process.send) { + process.send('ok'); + } +} + +//#region Events + +// Listen new workers +cluster.on('fork', worker => { + clusterLogger.debug(`Process forked: [${worker.id}]`); +}); + +// Listen online workers +cluster.on('online', worker => { + clusterLogger.debug(`Process is now online: [${worker.id}]`); +}); + +// Listen for dying workers +cluster.on('exit', worker => { + // Replace the dead worker, + // we're not sentimental + clusterLogger.error(chalk.red(`[${worker.id}] died :(`)); + cluster.fork(); +}); + +// Display detail of unhandled promise rejection +if (!program.quiet) { + process.on('unhandledRejection', console.dir); +} + +// Display detail of uncaught exception +process.on('uncaughtException', err => { + logger.error(err); +}); + +// Dying away... +process.on('exit', code => { + logger.info(`The process is going to exit with code ${code}`); +}); + +//#endregion diff --git a/src/boot/master.ts b/src/boot/master.ts new file mode 100644 index 000000000..2d4080fdb --- /dev/null +++ b/src/boot/master.ts @@ -0,0 +1,176 @@ +import * as os from 'os'; +import * as cluster from 'cluster'; +import chalk from 'chalk'; +import * as portscanner from 'portscanner'; +import * as isRoot from 'is-root'; + +import Logger from '../services/logger'; +import loadConfig from '../config/load'; +import { Config } from '../config/types'; +import { lessThan } from '../prelude/array'; +import * as pkg from '../../package.json'; +import { program } from '../argv'; +import { showMachineInfo } from '../misc/show-machine-info'; +import { initDb } from '../db/postgre'; + +const logger = new Logger('core', 'cyan'); +const bootLogger = logger.createSubLogger('boot', 'magenta', false); + +function greet() { + if (!program.quiet) { + //#region Misskey logo + const v = `v${pkg.version}`; + console.log(' _____ _ _ '); + console.log(' | |_|___ ___| |_ ___ _ _ '); + console.log(' | | | | |_ -|_ -| \'_| -_| | |'); + console.log(' |_|_|_|_|___|___|_,_|___|_ |'); + console.log(' ' + chalk.gray(v) + (' |___|\n'.substr(v.length))); + //#endregion + + console.log(' Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, and @acid-chicken.'); + console.log(chalk.keyword('orange')(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo')); + + console.log(''); + console.log(chalk`< ${os.hostname()} {gray (PID: ${process.pid.toString()})} >`); + } + + bootLogger.info('Welcome to Misskey!'); + bootLogger.info(`Misskey v${pkg.version}`, null, true); +} + +/** + * Init master process + */ +export async function masterMain() { + greet(); + + let config: Config; + + try { + // initialize app + config = await init(); + + if (config.port == null) { + bootLogger.error('The port is not configured. Please configure port.', null, true); + process.exit(1); + } + + if (process.platform === 'linux' && isWellKnownPort(config.port) && !isRoot()) { + bootLogger.error('You need root privileges to listen on well-known port on Linux', null, true); + process.exit(1); + } + + if (!await isPortAvailable(config.port)) { + bootLogger.error(`Port ${config.port} is already in use`, null, true); + process.exit(1); + } + } catch (e) { + bootLogger.error('Fatal error occurred during initialization', null, true); + process.exit(1); + } + + bootLogger.succ('Misskey initialized'); + + if (!program.disableClustering) { + await spawnWorkers(config.clusterLimit); + } + + if (!program.noDaemons) { + require('../daemons/server-stats').default(); + require('../daemons/notes-stats').default(); + require('../daemons/queue-stats').default(); + } + + bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, null, true); +} + +const runningNodejsVersion = process.version.slice(1).split('.').map(x => parseInt(x, 10)); +const requiredNodejsVersion = [11, 7, 0]; +const satisfyNodejsVersion = !lessThan(runningNodejsVersion, requiredNodejsVersion); + +function isWellKnownPort(port: number): boolean { + return port < 1024; +} + +async function isPortAvailable(port: number): Promise { + return await portscanner.checkPortStatus(port, '127.0.0.1') === 'closed'; +} + +function showEnvironment(): void { + const env = process.env.NODE_ENV; + const logger = bootLogger.createSubLogger('env'); + logger.info(typeof env == 'undefined' ? 'NODE_ENV is not set' : `NODE_ENV: ${env}`); + + if (env !== 'production') { + logger.warn('The environment is not in production mode.'); + logger.warn('DO NOT USE FOR PRODUCTION PURPOSE!', null, true); + } + + logger.info(`You ${isRoot() ? '' : 'do not '}have root privileges`); +} + +/** + * Init app + */ +async function init(): Promise { + showEnvironment(); + + const nodejsLogger = bootLogger.createSubLogger('nodejs'); + + nodejsLogger.info(`Version ${runningNodejsVersion.join('.')}`); + + if (!satisfyNodejsVersion) { + nodejsLogger.error(`Node.js version is less than ${requiredNodejsVersion.join('.')}. Please upgrade it.`, null, true); + process.exit(1); + } + + await showMachineInfo(bootLogger); + + const configLogger = bootLogger.createSubLogger('config'); + let config; + + try { + config = loadConfig(); + } catch (exception) { + if (typeof exception === 'string') { + configLogger.error(exception); + process.exit(1); + } + if (exception.code === 'ENOENT') { + configLogger.error('Configuration file not found', null, true); + process.exit(1); + } + throw exception; + } + + configLogger.succ('Loaded'); + + // Try to connect to DB + try { + bootLogger.info('Connecting database...'); + await initDb(); + } catch (e) { + bootLogger.error('Cannot connect to database', null, true); + bootLogger.error(e); + process.exit(1); + } + + return config; +} + +async function spawnWorkers(limit: number = Infinity) { + const workers = Math.min(limit, os.cpus().length); + bootLogger.info(`Starting ${workers} worker${workers === 1 ? '' : 's'}...`); + await Promise.all([...Array(workers)].map(spawnWorker)); + bootLogger.succ('All workers started'); +} + +function spawnWorker(): Promise { + return new Promise(res => { + const worker = cluster.fork(); + worker.on('message', message => { + if (message !== 'ready') return; + res(); + }); + }); +} diff --git a/src/boot/worker.ts b/src/boot/worker.ts new file mode 100644 index 000000000..ca3716972 --- /dev/null +++ b/src/boot/worker.ts @@ -0,0 +1,20 @@ +import * as cluster from 'cluster'; +import { initDb } from '../db/postgre'; + +/** + * Init worker process + */ +export async function workerMain() { + await initDb(); + + // start server + await require('../server').default(); + + // start job queue + require('../queue').default(); + + if (cluster.isWorker) { + // Send a 'ready' message to parent process + process.send('ready'); + } +} diff --git a/src/client/app/admin/views/drive.vue b/src/client/app/admin/views/drive.vue index 7812aadaa..491050b1f 100644 --- a/src/client/app/admin/views/drive.vue +++ b/src/client/app/admin/views/drive.vue @@ -48,7 +48,7 @@
{{ file.type }} - {{ file.datasize | bytes }} + {{ file.size | bytes }}
diff --git a/src/client/app/admin/views/hashtags.vue b/src/client/app/admin/views/hashtags.vue index b3190c29c..e1cc4b494 100644 --- a/src/client/app/admin/views/hashtags.vue +++ b/src/client/app/admin/views/hashtags.vue @@ -3,7 +3,7 @@
- + {{ $t('save') }}
@@ -18,18 +18,18 @@ export default Vue.extend({ i18n: i18n('admin/views/hashtags.vue'), data() { return { - hidedTags: '', + hiddenTags: '', }; }, created() { this.$root.getMeta().then(meta => { - this.hidedTags = meta.hidedTags.join('\n'); + this.hiddenTags = meta.hiddenTags.join('\n'); }); }, methods: { save() { this.$root.api('admin/update-meta', { - hidedTags: this.hidedTags.split('\n') + hiddenTags: this.hiddenTags.split('\n') }).then(() => { //this.$root.os.apis.dialog({ text: `Saved` }); }).catch(e => { diff --git a/src/client/app/admin/views/instance.vue b/src/client/app/admin/views/instance.vue index 2d2a07784..bc2a5fba8 100644 --- a/src/client/app/admin/views/instance.vue +++ b/src/client/app/admin/views/instance.vue @@ -77,12 +77,6 @@
summaly Proxy
URL -
-
{{ $t('user-recommendation-config') }}
- {{ $t('enable-external-user-recommendation') }} - {{ $t('external-user-recommendation-engine') }} - {{ $t('external-user-recommendation-timeout') }} -
{{ $t('save') }}
@@ -184,9 +178,6 @@ export default Vue.extend({ discordClientSecret: null, proxyAccount: null, inviteCode: null, - enableExternalUserRecommendation: false, - externalUserRecommendationEngine: null, - externalUserRecommendationTimeout: null, summalyProxy: null, enableEmail: false, email: null, @@ -205,8 +196,8 @@ export default Vue.extend({ created() { this.$root.getMeta().then(meta => { - this.maintainerName = meta.maintainer.name; - this.maintainerEmail = meta.maintainer.email; + this.maintainerName = meta.maintainerName; + this.maintainerEmail = meta.maintainerEmail; this.disableRegistration = meta.disableRegistration; this.disableLocalTimeline = meta.disableLocalTimeline; this.disableGlobalTimeline = meta.disableGlobalTimeline; @@ -236,9 +227,6 @@ export default Vue.extend({ this.enableDiscordIntegration = meta.enableDiscordIntegration; this.discordClientId = meta.discordClientId; this.discordClientSecret = meta.discordClientSecret; - this.enableExternalUserRecommendation = meta.enableExternalUserRecommendation; - this.externalUserRecommendationEngine = meta.externalUserRecommendationEngine; - this.externalUserRecommendationTimeout = meta.externalUserRecommendationTimeout; this.summalyProxy = meta.summalyProxy; this.enableEmail = meta.enableEmail; this.email = meta.email; @@ -299,9 +287,6 @@ export default Vue.extend({ enableDiscordIntegration: this.enableDiscordIntegration, discordClientId: this.discordClientId, discordClientSecret: this.discordClientSecret, - enableExternalUserRecommendation: this.enableExternalUserRecommendation, - externalUserRecommendationEngine: this.externalUserRecommendationEngine, - externalUserRecommendationTimeout: parseInt(this.externalUserRecommendationTimeout, 10), summalyProxy: this.summalyProxy, enableEmail: this.enableEmail, email: this.email, diff --git a/src/client/app/admin/views/logs.vue b/src/client/app/admin/views/logs.vue index 4a2d957ed..5c2cfdb39 100644 --- a/src/client/app/admin/views/logs.vue +++ b/src/client/app/admin/views/logs.vue @@ -19,7 +19,7 @@
- +
[{{ log.domain.join('.') }}] {{ log.message }} diff --git a/src/client/app/admin/views/users.vue b/src/client/app/admin/views/users.vue index ff485cec8..0f46b564a 100644 --- a/src/client/app/admin/views/users.vue +++ b/src/client/app/admin/views/users.vue @@ -165,7 +165,7 @@ export default Vue.extend({ /** 処理対象ユーザーの情報を更新する */ async refreshUser() { - this.$root.api('admin/show-user', { userId: this.user._id }).then(info => { + this.$root.api('admin/show-user', { userId: this.user.id }).then(info => { this.user = info; }); }, @@ -173,7 +173,7 @@ export default Vue.extend({ async resetPassword() { if (!await this.getConfirmed(this.$t('reset-password-confirm'))) return; - this.$root.api('admin/reset-password', { userId: this.user._id }).then(res => { + this.$root.api('admin/reset-password', { userId: this.user.id }).then(res => { this.$root.dialog({ type: 'success', text: this.$t('password-updated', { password: res.password }) @@ -187,7 +187,7 @@ export default Vue.extend({ this.verifying = true; const process = async () => { - await this.$root.api('admin/verify-user', { userId: this.user._id }); + await this.$root.api('admin/verify-user', { userId: this.user.id }); this.$root.dialog({ type: 'success', text: this.$t('verified') @@ -212,7 +212,7 @@ export default Vue.extend({ this.unverifying = true; const process = async () => { - await this.$root.api('admin/unverify-user', { userId: this.user._id }); + await this.$root.api('admin/unverify-user', { userId: this.user.id }); this.$root.dialog({ type: 'success', text: this.$t('unverified') @@ -233,7 +233,7 @@ export default Vue.extend({ async silenceUser() { const process = async () => { - await this.$root.api('admin/silence-user', { userId: this.user._id }); + await this.$root.api('admin/silence-user', { userId: this.user.id }); this.$root.dialog({ type: 'success', splash: true @@ -252,7 +252,7 @@ export default Vue.extend({ async unsilenceUser() { const process = async () => { - await this.$root.api('admin/unsilence-user', { userId: this.user._id }); + await this.$root.api('admin/unsilence-user', { userId: this.user.id }); this.$root.dialog({ type: 'success', splash: true @@ -275,7 +275,7 @@ export default Vue.extend({ this.suspending = true; const process = async () => { - await this.$root.api('admin/suspend-user', { userId: this.user._id }); + await this.$root.api('admin/suspend-user', { userId: this.user.id }); this.$root.dialog({ type: 'success', text: this.$t('suspended') @@ -300,7 +300,7 @@ export default Vue.extend({ this.unsuspending = true; const process = async () => { - await this.$root.api('admin/unsuspend-user', { userId: this.user._id }); + await this.$root.api('admin/unsuspend-user', { userId: this.user.id }); this.$root.dialog({ type: 'success', text: this.$t('unsuspended') @@ -320,7 +320,7 @@ export default Vue.extend({ }, async updateRemoteUser() { - this.$root.api('admin/update-remote-user', { userId: this.user._id }).then(res => { + this.$root.api('admin/update-remote-user', { userId: this.user.id }).then(res => { this.$root.dialog({ type: 'success', text: this.$t('remote-user-updated') diff --git a/src/client/app/auth/views/form.vue b/src/client/app/auth/views/form.vue index 105af375b..d5d6b25f0 100644 --- a/src/client/app/auth/views/form.vue +++ b/src/client/app/auth/views/form.vue @@ -14,15 +14,15 @@

{{ $t('permission-ask') }}

diff --git a/src/client/app/common/define-widget.ts b/src/client/app/common/define-widget.ts index 1efdbb188..632ddf2ed 100644 --- a/src/client/app/common/define-widget.ts +++ b/src/client/app/common/define-widget.ts @@ -45,15 +45,9 @@ export default function (data: { this.$watch('props', () => { this.mergeProps(); }); - - this.bakeProps(); }, methods: { - bakeProps() { - this.bakedOldProps = JSON.stringify(this.props); - }, - mergeProps() { if (data.props) { const defaultProps = data.props(); @@ -65,17 +59,10 @@ export default function (data: { }, save() { - if (this.bakedOldProps == JSON.stringify(this.props)) return; - - this.bakeProps(); - if (this.platform == 'deck') { this.$store.commit('device/updateDeckColumn', this.column); } else { - this.$root.api('i/update_widget', { - id: this.id, - data: this.props - }); + this.$store.commit('device/updateWidget', this.widget); } } } diff --git a/src/client/app/common/scripts/note-mixin.ts b/src/client/app/common/scripts/note-mixin.ts index 5707d1bb4..67bbe8c0a 100644 --- a/src/client/app/common/scripts/note-mixin.ts +++ b/src/client/app/common/scripts/note-mixin.ts @@ -70,8 +70,8 @@ export default (opts: Opts = {}) => ({ }, reactionsCount(): number { - return this.appearNote.reactionCounts - ? sum(Object.values(this.appearNote.reactionCounts)) + return this.appearNote.reactions + ? sum(Object.values(this.appearNote.reactions)) : 0; }, diff --git a/src/client/app/common/scripts/note-subscriber.ts b/src/client/app/common/scripts/note-subscriber.ts index c2b4dd6df..02d810ded 100644 --- a/src/client/app/common/scripts/note-subscriber.ts +++ b/src/client/app/common/scripts/note-subscriber.ts @@ -87,16 +87,16 @@ export default prop => ({ case 'reacted': { const reaction = body.reaction; - if (this.$_ns_target.reactionCounts == null) { - Vue.set(this.$_ns_target, 'reactionCounts', {}); + if (this.$_ns_target.reactions == null) { + Vue.set(this.$_ns_target, 'reactions', {}); } - if (this.$_ns_target.reactionCounts[reaction] == null) { - Vue.set(this.$_ns_target.reactionCounts, reaction, 0); + if (this.$_ns_target.reactions[reaction] == null) { + Vue.set(this.$_ns_target.reactions, reaction, 0); } // Increment the count - this.$_ns_target.reactionCounts[reaction]++; + this.$_ns_target.reactions[reaction]++; if (body.userId == this.$store.state.i.id) { Vue.set(this.$_ns_target, 'myReaction', reaction); @@ -107,16 +107,16 @@ export default prop => ({ case 'unreacted': { const reaction = body.reaction; - if (this.$_ns_target.reactionCounts == null) { + if (this.$_ns_target.reactions == null) { return; } - if (this.$_ns_target.reactionCounts[reaction] == null) { + if (this.$_ns_target.reactions[reaction] == null) { return; } // Decrement the count - if (this.$_ns_target.reactionCounts[reaction] > 0) this.$_ns_target.reactionCounts[reaction]--; + if (this.$_ns_target.reactions[reaction] > 0) this.$_ns_target.reactions[reaction]--; if (body.userId == this.$store.state.i.id) { Vue.set(this.$_ns_target, 'myReaction', null); @@ -125,9 +125,11 @@ export default prop => ({ } case 'pollVoted': { - if (body.userId == this.$store.state.i.id) return; const choice = body.choice; - this.$_ns_target.poll.choices.find(c => c.id === choice).votes++; + this.$_ns_target.poll.choices[choice].votes++; + if (body.userId == this.$store.state.i.id) { + Vue.set(this.$_ns_target.poll.choices[choice], 'isVoted', true); + } break; } diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue index dce594e70..c074fb600 100644 --- a/src/client/app/common/views/components/avatar.vue +++ b/src/client/app/common/views/components/avatar.vue @@ -55,11 +55,12 @@ export default Vue.extend({ }, icon(): any { return { - backgroundColor: this.lightmode - ? `rgb(${this.user.avatarColor.slice(0, 3).join(',')})` - : this.user.avatarColor && this.user.avatarColor.length == 3 - ? `rgb(${this.user.avatarColor.join(',')})` - : null, + backgroundColor: this.user.avatarColor ? this.lightmode + ? this.user.avatarColor + : this.user.avatarColor.startsWith('rgb(') + ? this.user.avatarColor + : null + : null, backgroundImage: this.lightmode ? null : `url(${this.url})`, borderRadius: this.$store.state.settings.circleIcons ? '100%' : null }; @@ -67,7 +68,7 @@ export default Vue.extend({ }, mounted() { if (this.user.avatarColor) { - this.$el.style.color = `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`; + this.$el.style.color = this.user.avatarColor; } }, methods: { diff --git a/src/client/app/common/views/components/games/reversi/reversi.game.vue b/src/client/app/common/views/components/games/reversi/reversi.game.vue index c6fc36db3..bd0401f78 100644 --- a/src/client/app/common/views/components/games/reversi/reversi.game.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.game.vue @@ -24,11 +24,11 @@
- {{ String.fromCharCode(64 + i) }} + {{ String.fromCharCode(64 + i) }}
-
{{ i }}
+
{{ i }}
-
{{ i }}
+
{{ i }}
- {{ String.fromCharCode(64 + i) }} + {{ String.fromCharCode(64 + i) }}
@@ -71,9 +71,9 @@
-

{{ $t('is-llotheo') }}

-

{{ $t('looped-map') }}

-

{{ $t('can-put-everywhere') }}

+

{{ $t('is-llotheo') }}

+

{{ $t('looped-map') }}

+

{{ $t('can-put-everywhere') }}

@@ -160,8 +160,8 @@ export default Vue.extend({ cellsStyle(): any { return { - 'grid-template-rows': `repeat(${this.game.settings.map.length}, 1fr)`, - 'grid-template-columns': `repeat(${this.game.settings.map[0].length}, 1fr)` + 'grid-template-rows': `repeat(${this.game.map.length}, 1fr)`, + 'grid-template-columns': `repeat(${this.game.map[0].length}, 1fr)` }; } }, @@ -169,10 +169,10 @@ export default Vue.extend({ watch: { logPos(v) { if (!this.game.isEnded) return; - this.o = new Reversi(this.game.settings.map, { - isLlotheo: this.game.settings.isLlotheo, - canPutEverywhere: this.game.settings.canPutEverywhere, - loopedBoard: this.game.settings.loopedBoard + this.o = new Reversi(this.game.map, { + isLlotheo: this.game.isLlotheo, + canPutEverywhere: this.game.canPutEverywhere, + loopedBoard: this.game.loopedBoard }); for (const log of this.logs.slice(0, v)) { this.o.put(log.color, log.pos); @@ -184,10 +184,10 @@ export default Vue.extend({ created() { this.game = this.initGame; - this.o = new Reversi(this.game.settings.map, { - isLlotheo: this.game.settings.isLlotheo, - canPutEverywhere: this.game.settings.canPutEverywhere, - loopedBoard: this.game.settings.loopedBoard + this.o = new Reversi(this.game.map, { + isLlotheo: this.game.isLlotheo, + canPutEverywhere: this.game.canPutEverywhere, + loopedBoard: this.game.loopedBoard }); for (const log of this.game.logs) { @@ -286,10 +286,10 @@ export default Vue.extend({ onRescue(game) { this.game = game; - this.o = new Reversi(this.game.settings.map, { - isLlotheo: this.game.settings.isLlotheo, - canPutEverywhere: this.game.settings.canPutEverywhere, - loopedBoard: this.game.settings.loopedBoard + this.o = new Reversi(this.game.map, { + isLlotheo: this.game.isLlotheo, + canPutEverywhere: this.game.canPutEverywhere, + loopedBoard: this.game.loopedBoard }); for (const log of this.game.logs) { diff --git a/src/client/app/common/views/components/games/reversi/reversi.room.vue b/src/client/app/common/views/components/games/reversi/reversi.room.vue index d5d148790..9ee1a78b8 100644 --- a/src/client/app/common/views/components/games/reversi/reversi.room.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.room.vue @@ -17,9 +17,9 @@
-
-
-
+
+
@@ -35,9 +35,9 @@
- {{ $t('random') }} - {{ this.$t('black-is').split('{}')[0] }}{{ this.$t('black-is').split('{}')[1] }} - {{ this.$t('black-is').split('{}')[0] }}{{ this.$t('black-is').split('{}')[1] }} + {{ $t('random') }} + {{ this.$t('black-is').split('{}')[0] }}{{ this.$t('black-is').split('{}')[1] }} + {{ this.$t('black-is').split('{}')[0] }}{{ this.$t('black-is').split('{}')[1] }}
@@ -47,9 +47,9 @@
- {{ $t('is-llotheo') }} - {{ $t('looped-map') }} - {{ $t('can-put-everywhere') }} + {{ $t('is-llotheo') }} + {{ $t('looped-map') }} + {{ $t('can-put-everywhere') }}
@@ -159,8 +159,8 @@ export default Vue.extend({ this.connection.on('initForm', this.onInitForm); this.connection.on('message', this.onMessage); - if (this.game.user1Id != this.$store.state.i.id && this.game.settings.form1) this.form = this.game.settings.form1; - if (this.game.user2Id != this.$store.state.i.id && this.game.settings.form2) this.form = this.game.settings.form2; + if (this.game.user1Id != this.$store.state.i.id && this.game.form1) this.form = this.game.form1; + if (this.game.user2Id != this.$store.state.i.id && this.game.form2) this.form = this.game.form2; }, beforeDestroy() { @@ -189,18 +189,19 @@ export default Vue.extend({ this.$forceUpdate(); }, - updateSettings() { + updateSettings(key: string) { this.connection.send('updateSettings', { - settings: this.game.settings + key: key, + value: this.game[key] }); }, - onUpdateSettings(settings) { - this.game.settings = settings; - if (this.game.settings.map == null) { + onUpdateSettings({ key, value }) { + this.game[key] = value; + if (this.game.map == null) { this.mapName = null; } else { - const found = Object.values(maps).find(x => x.data.join('') == this.game.settings.map.join('')); + const found = Object.values(maps).find(x => x.data.join('') == this.game.map.join('')); this.mapName = found ? found.name : '-Custom-'; } }, @@ -224,27 +225,27 @@ export default Vue.extend({ onMapChange() { if (this.mapName == null) { - this.game.settings.map = null; + this.game.map = null; } else { - this.game.settings.map = Object.values(maps).find(x => x.name == this.mapName).data; + this.game.map = Object.values(maps).find(x => x.name == this.mapName).data; } this.$forceUpdate(); this.updateSettings(); }, onPixelClick(pos, pixel) { - const x = pos % this.game.settings.map[0].length; - const y = Math.floor(pos / this.game.settings.map[0].length); + const x = pos % this.game.map[0].length; + const y = Math.floor(pos / this.game.map[0].length); const newPixel = pixel == ' ' ? '-' : pixel == '-' ? 'b' : pixel == 'b' ? 'w' : ' '; - const line = this.game.settings.map[y].split(''); + const line = this.game.map[y].split(''); line[x] = newPixel; - this.$set(this.game.settings.map, y, line.join('')); + this.$set(this.game.map, y, line.join('')); this.$forceUpdate(); - this.updateSettings(); + this.updateSettings('map'); } } }); diff --git a/src/client/app/common/views/components/games/reversi/reversi.vue b/src/client/app/common/views/components/games/reversi/reversi.vue index b6803cd7f..d33471a04 100644 --- a/src/client/app/common/views/components/games/reversi/reversi.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.vue @@ -106,7 +106,7 @@ export default Vue.extend({ async nav(game, actualNav = true) { if (this.selfNav) { // 受け取ったゲーム情報が省略されたものなら完全な情報を取得する - if (game != null && (game.settings == null || game.settings.map == null)) { + if (game != null && game.map == null) { game = await this.$root.api('games/reversi/games/show', { gameId: game.id }); diff --git a/src/client/app/common/views/components/instance.vue b/src/client/app/common/views/components/instance.vue index 7b8d4f8e0..497e4976f 100644 --- a/src/client/app/common/views/components/instance.vue +++ b/src/client/app/common/views/components/instance.vue @@ -2,7 +2,7 @@
-

{{ meta.name }}

+

{{ meta.name || 'Misskey' }}

{{ $t('start') }}
diff --git a/src/client/app/common/views/components/mention.vue b/src/client/app/common/views/components/mention.vue index 11dddbd52..e1f67282b 100644 --- a/src/client/app/common/views/components/mention.vue +++ b/src/client/app/common/views/components/mention.vue @@ -33,7 +33,7 @@ export default Vue.extend({ }, computed: { canonical(): string { - return `@${this.username}@${toUnicode(this.host)}`; + return this.host === localHost ? `@${this.username}` : `@${this.username}@${toUnicode(this.host)}`; }, isMe(): boolean { return this.$store.getters.isSignedIn && this.canonical.toLowerCase() === `@${this.$store.state.i.username}@${toUnicode(localHost)}`.toLowerCase(); diff --git a/src/client/app/common/views/components/poll.vue b/src/client/app/common/views/components/poll.vue index ba14ba3a4..dc3aaa34f 100644 --- a/src/client/app/common/views/components/poll.vue +++ b/src/client/app/common/views/components/poll.vue @@ -1,7 +1,7 @@