summaryrefslogtreecommitdiff
path: root/src/server/api/endpoints
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-11-12 02:02:25 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-11-12 02:02:25 +0900
commit0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch)
tree40874799472fa07416f17b50a398ac33b7771905 /src/server/api/endpoints
parentupdate deps (diff)
downloadsharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz
sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2
sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip
refactoring
Resolve #7779
Diffstat (limited to 'src/server/api/endpoints')
-rw-r--r--src/server/api/endpoints/admin/abuse-user-reports.ts134
-rw-r--r--src/server/api/endpoints/admin/accounts/create.ts51
-rw-r--r--src/server/api/endpoints/admin/accounts/delete.ts58
-rw-r--r--src/server/api/endpoints/admin/ad/create.ts49
-rw-r--r--src/server/api/endpoints/admin/ad/delete.ts34
-rw-r--r--src/server/api/endpoints/admin/ad/list.ts36
-rw-r--r--src/server/api/endpoints/admin/ad/update.ts63
-rw-r--r--src/server/api/endpoints/admin/announcements/create.ts71
-rw-r--r--src/server/api/endpoints/admin/announcements/delete.ts34
-rw-r--r--src/server/api/endpoints/admin/announcements/list.ts84
-rw-r--r--src/server/api/endpoints/admin/announcements/update.ts48
-rw-r--r--src/server/api/endpoints/admin/delete-all-files-of-a-user.ts28
-rw-r--r--src/server/api/endpoints/admin/delete-logs.ts13
-rw-r--r--src/server/api/endpoints/admin/drive/clean-remote-files.ts13
-rw-r--r--src/server/api/endpoints/admin/drive/cleanup.ts21
-rw-r--r--src/server/api/endpoints/admin/drive/files.ts81
-rw-r--r--src/server/api/endpoints/admin/drive/show-file.ts180
-rw-r--r--src/server/api/endpoints/admin/emoji/add.ts64
-rw-r--r--src/server/api/endpoints/admin/emoji/copy.ts81
-rw-r--r--src/server/api/endpoints/admin/emoji/list-remote.ts99
-rw-r--r--src/server/api/endpoints/admin/emoji/list.ts98
-rw-r--r--src/server/api/endpoints/admin/emoji/remove.ts42
-rw-r--r--src/server/api/endpoints/admin/emoji/update.ts54
-rw-r--r--src/server/api/endpoints/admin/federation/delete-all-files.ts27
-rw-r--r--src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts28
-rw-r--r--src/server/api/endpoints/admin/federation/remove-all-following.ts32
-rw-r--r--src/server/api/endpoints/admin/federation/update-instance.ts33
-rw-r--r--src/server/api/endpoints/admin/get-index-stats.ts26
-rw-r--r--src/server/api/endpoints/admin/get-table-stats.ts45
-rw-r--r--src/server/api/endpoints/admin/invite.ts44
-rw-r--r--src/server/api/endpoints/admin/moderators/add.ts33
-rw-r--r--src/server/api/endpoints/admin/moderators/remove.ts29
-rw-r--r--src/server/api/endpoints/admin/promo/create.ts57
-rw-r--r--src/server/api/endpoints/admin/queue/clear.ts18
-rw-r--r--src/server/api/endpoints/admin/queue/deliver-delayed.ts55
-rw-r--r--src/server/api/endpoints/admin/queue/inbox-delayed.ts55
-rw-r--r--src/server/api/endpoints/admin/queue/jobs.ts81
-rw-r--r--src/server/api/endpoints/admin/queue/stats.ts44
-rw-r--r--src/server/api/endpoints/admin/relays/add.ts63
-rw-r--r--src/server/api/endpoints/admin/relays/list.ts47
-rw-r--r--src/server/api/endpoints/admin/relays/remove.ts20
-rw-r--r--src/server/api/endpoints/admin/reset-password.ts59
-rw-r--r--src/server/api/endpoints/admin/resolve-abuse-user-report.ts30
-rw-r--r--src/server/api/endpoints/admin/resync-chart.ts21
-rw-r--r--src/server/api/endpoints/admin/send-email.ts26
-rw-r--r--src/server/api/endpoints/admin/server-info.ts119
-rw-r--r--src/server/api/endpoints/admin/show-moderation-logs.ts74
-rw-r--r--src/server/api/endpoints/admin/show-user.ts177
-rw-r--r--src/server/api/endpoints/admin/show-users.ts119
-rw-r--r--src/server/api/endpoints/admin/silence-user.ts38
-rw-r--r--src/server/api/endpoints/admin/suspend-user.ts84
-rw-r--r--src/server/api/endpoints/admin/unsilence-user.ts34
-rw-r--r--src/server/api/endpoints/admin/unsuspend-user.ts37
-rw-r--r--src/server/api/endpoints/admin/update-meta.ts608
-rw-r--r--src/server/api/endpoints/admin/vacuum.ts36
-rw-r--r--src/server/api/endpoints/announcements.ts92
-rw-r--r--src/server/api/endpoints/antennas/create.ts127
-rw-r--r--src/server/api/endpoints/antennas/delete.ts43
-rw-r--r--src/server/api/endpoints/antennas/list.ts28
-rw-r--r--src/server/api/endpoints/antennas/notes.ts93
-rw-r--r--src/server/api/endpoints/antennas/show.ts47
-rw-r--r--src/server/api/endpoints/antennas/update.ts143
-rw-r--r--src/server/api/endpoints/ap/get.ts36
-rw-r--r--src/server/api/endpoints/ap/show.ts190
-rw-r--r--src/server/api/endpoints/app/create.ts63
-rw-r--r--src/server/api/endpoints/app/show.ts51
-rw-r--r--src/server/api/endpoints/auth/accept.ts76
-rw-r--r--src/server/api/endpoints/auth/session/generate.ts70
-rw-r--r--src/server/api/endpoints/auth/session/show.ts58
-rw-r--r--src/server/api/endpoints/auth/session/userkey.ts98
-rw-r--r--src/server/api/endpoints/blocking/create.ts89
-rw-r--r--src/server/api/endpoints/blocking/delete.ts85
-rw-r--r--src/server/api/endpoints/blocking/list.ts49
-rw-r--r--src/server/api/endpoints/channels/create.ts68
-rw-r--r--src/server/api/endpoints/channels/featured.ts28
-rw-r--r--src/server/api/endpoints/channels/follow.ts48
-rw-r--r--src/server/api/endpoints/channels/followed.ts49
-rw-r--r--src/server/api/endpoints/channels/owned.ts49
-rw-r--r--src/server/api/endpoints/channels/pin-note.ts0
-rw-r--r--src/server/api/endpoints/channels/show.ts43
-rw-r--r--src/server/api/endpoints/channels/timeline.ts85
-rw-r--r--src/server/api/endpoints/channels/unfollow.ts45
-rw-r--r--src/server/api/endpoints/channels/update.ts94
-rw-r--r--src/server/api/endpoints/charts/active-users.ts30
-rw-r--r--src/server/api/endpoints/charts/drive.ts30
-rw-r--r--src/server/api/endpoints/charts/federation.ts30
-rw-r--r--src/server/api/endpoints/charts/hashtag.ts34
-rw-r--r--src/server/api/endpoints/charts/instance.ts34
-rw-r--r--src/server/api/endpoints/charts/network.ts30
-rw-r--r--src/server/api/endpoints/charts/notes.ts30
-rw-r--r--src/server/api/endpoints/charts/user/drive.ts35
-rw-r--r--src/server/api/endpoints/charts/user/following.ts35
-rw-r--r--src/server/api/endpoints/charts/user/notes.ts35
-rw-r--r--src/server/api/endpoints/charts/user/reactions.ts35
-rw-r--r--src/server/api/endpoints/charts/users.ts30
-rw-r--r--src/server/api/endpoints/clips/add-note.ts76
-rw-r--r--src/server/api/endpoints/clips/create.ts45
-rw-r--r--src/server/api/endpoints/clips/delete.ts40
-rw-r--r--src/server/api/endpoints/clips/list.ts28
-rw-r--r--src/server/api/endpoints/clips/notes.ts93
-rw-r--r--src/server/api/endpoints/clips/show.ts50
-rw-r--r--src/server/api/endpoints/clips/update.ts65
-rw-r--r--src/server/api/endpoints/drive.ts38
-rw-r--r--src/server/api/endpoints/drive/files.ts70
-rw-r--r--src/server/api/endpoints/drive/files/attached-notes.ts57
-rw-r--r--src/server/api/endpoints/drive/files/check-existence.ts31
-rw-r--r--src/server/api/endpoints/drive/files/create.ts89
-rw-r--r--src/server/api/endpoints/drive/files/delete.ts53
-rw-r--r--src/server/api/endpoints/drive/files/find-by-hash.ts36
-rw-r--r--src/server/api/endpoints/drive/files/find.ts43
-rw-r--r--src/server/api/endpoints/drive/files/show.ts84
-rw-r--r--src/server/api/endpoints/drive/files/update.ts116
-rw-r--r--src/server/api/endpoints/drive/files/upload-from-url.ts64
-rw-r--r--src/server/api/endpoints/drive/folders.ts58
-rw-r--r--src/server/api/endpoints/drive/folders/create.ts72
-rw-r--r--src/server/api/endpoints/drive/folders/delete.ts60
-rw-r--r--src/server/api/endpoints/drive/folders/find.ts43
-rw-r--r--src/server/api/endpoints/drive/folders/show.ts49
-rw-r--r--src/server/api/endpoints/drive/folders/update.ts123
-rw-r--r--src/server/api/endpoints/drive/stream.ts59
-rw-r--r--src/server/api/endpoints/email-address/available.ts34
-rw-r--r--src/server/api/endpoints/endpoint.ts26
-rw-r--r--src/server/api/endpoints/endpoints.ts30
-rw-r--r--src/server/api/endpoints/federation/dns.ts43
-rw-r--r--src/server/api/endpoints/federation/followers.ts51
-rw-r--r--src/server/api/endpoints/federation/following.ts51
-rw-r--r--src/server/api/endpoints/federation/instances.ts149
-rw-r--r--src/server/api/endpoints/federation/show-instance.ts29
-rw-r--r--src/server/api/endpoints/federation/update-remote-user.ts22
-rw-r--r--src/server/api/endpoints/federation/users.ts51
-rw-r--r--src/server/api/endpoints/following/create.ts100
-rw-r--r--src/server/api/endpoints/following/delete.ts82
-rw-r--r--src/server/api/endpoints/following/requests/accept.ts48
-rw-r--r--src/server/api/endpoints/following/requests/cancel.ts58
-rw-r--r--src/server/api/endpoints/following/requests/list.ts44
-rw-r--r--src/server/api/endpoints/following/requests/reject.ts40
-rw-r--r--src/server/api/endpoints/gallery/featured.ts29
-rw-r--r--src/server/api/endpoints/gallery/popular.ts28
-rw-r--r--src/server/api/endpoints/gallery/posts.ts43
-rw-r--r--src/server/api/endpoints/gallery/posts/create.ts77
-rw-r--r--src/server/api/endpoints/gallery/posts/delete.ts40
-rw-r--r--src/server/api/endpoints/gallery/posts/like.ts71
-rw-r--r--src/server/api/endpoints/gallery/posts/show.ts43
-rw-r--r--src/server/api/endpoints/gallery/posts/unlike.ts54
-rw-r--r--src/server/api/endpoints/gallery/posts/update.ts82
-rw-r--r--src/server/api/endpoints/games/reversi/games.ts156
-rw-r--r--src/server/api/endpoints/games/reversi/games/show.ts168
-rw-r--r--src/server/api/endpoints/games/reversi/games/surrender.ts67
-rw-r--r--src/server/api/endpoints/games/reversi/invitations.ts58
-rw-r--r--src/server/api/endpoints/games/reversi/match.ts108
-rw-r--r--src/server/api/endpoints/games/reversi/match/cancel.ts14
-rw-r--r--src/server/api/endpoints/get-online-users-count.ts23
-rw-r--r--src/server/api/endpoints/hashtags/list.ts95
-rw-r--r--src/server/api/endpoints/hashtags/search.ts46
-rw-r--r--src/server/api/endpoints/hashtags/show.ts40
-rw-r--r--src/server/api/endpoints/hashtags/trend.ts146
-rw-r--r--src/server/api/endpoints/hashtags/users.ts89
-rw-r--r--src/server/api/endpoints/i.ts26
-rw-r--r--src/server/api/endpoints/i/2fa/done.ts41
-rw-r--r--src/server/api/endpoints/i/2fa/key-done.ts150
-rw-r--r--src/server/api/endpoints/i/2fa/password-less.ts21
-rw-r--r--src/server/api/endpoints/i/2fa/register-key.ts59
-rw-r--r--src/server/api/endpoints/i/2fa/register.ts54
-rw-r--r--src/server/api/endpoints/i/2fa/remove-key.ts45
-rw-r--r--src/server/api/endpoints/i/2fa/unregister.ts32
-rw-r--r--src/server/api/endpoints/i/apps.ts43
-rw-r--r--src/server/api/endpoints/i/authorized-apps.ts44
-rw-r--r--src/server/api/endpoints/i/change-password.ts39
-rw-r--r--src/server/api/endpoints/i/delete-account.ts48
-rw-r--r--src/server/api/endpoints/i/export-blocking.ts16
-rw-r--r--src/server/api/endpoints/i/export-following.ts16
-rw-r--r--src/server/api/endpoints/i/export-mute.ts16
-rw-r--r--src/server/api/endpoints/i/export-notes.ts16
-rw-r--r--src/server/api/endpoints/i/export-user-lists.ts16
-rw-r--r--src/server/api/endpoints/i/favorites.ts50
-rw-r--r--src/server/api/endpoints/i/gallery/likes.ts57
-rw-r--r--src/server/api/endpoints/i/gallery/posts.ts49
-rw-r--r--src/server/api/endpoints/i/get-word-muted-notes-count.ts33
-rw-r--r--src/server/api/endpoints/i/import-blocking.ts60
-rw-r--r--src/server/api/endpoints/i/import-following.ts59
-rw-r--r--src/server/api/endpoints/i/import-muting.ts60
-rw-r--r--src/server/api/endpoints/i/import-user-lists.ts59
-rw-r--r--src/server/api/endpoints/i/notifications.ts138
-rw-r--r--src/server/api/endpoints/i/page-likes.ts57
-rw-r--r--src/server/api/endpoints/i/pages.ts49
-rw-r--r--src/server/api/endpoints/i/pin.ts59
-rw-r--r--src/server/api/endpoints/i/read-all-messaging-messages.ts37
-rw-r--r--src/server/api/endpoints/i/read-all-unread-notes.ts25
-rw-r--r--src/server/api/endpoints/i/read-announcement.ts60
-rw-r--r--src/server/api/endpoints/i/regenerate-token.ts44
-rw-r--r--src/server/api/endpoints/i/registry/get-all.ts33
-rw-r--r--src/server/api/endpoints/i/registry/get-detail.ts48
-rw-r--r--src/server/api/endpoints/i/registry/get.ts45
-rw-r--r--src/server/api/endpoints/i/registry/keys-with-type.ts41
-rw-r--r--src/server/api/endpoints/i/registry/keys.ts28
-rw-r--r--src/server/api/endpoints/i/registry/remove.ts45
-rw-r--r--src/server/api/endpoints/i/registry/scopes.ts29
-rw-r--r--src/server/api/endpoints/i/registry/set.ts61
-rw-r--r--src/server/api/endpoints/i/revoke-token.ts31
-rw-r--r--src/server/api/endpoints/i/signin-history.ts35
-rw-r--r--src/server/api/endpoints/i/unpin.ts45
-rw-r--r--src/server/api/endpoints/i/update-email.ts94
-rw-r--r--src/server/api/endpoints/i/update.ts294
-rw-r--r--src/server/api/endpoints/i/user-group-invites.ts61
-rw-r--r--src/server/api/endpoints/messaging/history.ts94
-rw-r--r--src/server/api/endpoints/messaging/messages.ts148
-rw-r--r--src/server/api/endpoints/messaging/messages/create.ts148
-rw-r--r--src/server/api/endpoints/messaging/messages/delete.ts48
-rw-r--r--src/server/api/endpoints/messaging/messages/read.ts48
-rw-r--r--src/server/api/endpoints/meta.ts598
-rw-r--r--src/server/api/endpoints/miauth/gen-token.ts72
-rw-r--r--src/server/api/endpoints/mute/create.ts83
-rw-r--r--src/server/api/endpoints/mute/delete.ts73
-rw-r--r--src/server/api/endpoints/mute/list.ts49
-rw-r--r--src/server/api/endpoints/my/apps.ts86
-rw-r--r--src/server/api/endpoints/notes.ts94
-rw-r--r--src/server/api/endpoints/notes/children.ts72
-rw-r--r--src/server/api/endpoints/notes/clips.ts55
-rw-r--r--src/server/api/endpoints/notes/conversation.ts81
-rw-r--r--src/server/api/endpoints/notes/create.ts299
-rw-r--r--src/server/api/endpoints/notes/delete.ts56
-rw-r--r--src/server/api/endpoints/notes/favorites/create.ts61
-rw-r--r--src/server/api/endpoints/notes/favorites/delete.ts55
-rw-r--r--src/server/api/endpoints/notes/featured.ts64
-rw-r--r--src/server/api/endpoints/notes/global-timeline.ts101
-rw-r--r--src/server/api/endpoints/notes/hybrid-timeline.ts158
-rw-r--r--src/server/api/endpoints/notes/local-timeline.ts129
-rw-r--r--src/server/api/endpoints/notes/mentions.ts88
-rw-r--r--src/server/api/endpoints/notes/polls/recommendation.ts77
-rw-r--r--src/server/api/endpoints/notes/polls/vote.ts170
-rw-r--r--src/server/api/endpoints/notes/reactions.ts90
-rw-r--r--src/server/api/endpoints/notes/reactions/create.ts57
-rw-r--r--src/server/api/endpoints/notes/reactions/delete.ts52
-rw-r--r--src/server/api/endpoints/notes/renotes.ts76
-rw-r--r--src/server/api/endpoints/notes/replies.ts61
-rw-r--r--src/server/api/endpoints/notes/search-by-tag.ts134
-rw-r--r--src/server/api/endpoints/notes/search.ts152
-rw-r--r--src/server/api/endpoints/notes/show.ts43
-rw-r--r--src/server/api/endpoints/notes/state.ts69
-rw-r--r--src/server/api/endpoints/notes/thread-muting/create.ts54
-rw-r--r--src/server/api/endpoints/notes/thread-muting/delete.ts40
-rw-r--r--src/server/api/endpoints/notes/timeline.ts150
-rw-r--r--src/server/api/endpoints/notes/translate.ts89
-rw-r--r--src/server/api/endpoints/notes/unrenote.ts52
-rw-r--r--src/server/api/endpoints/notes/user-list-timeline.ts147
-rw-r--r--src/server/api/endpoints/notes/watching/create.ts37
-rw-r--r--src/server/api/endpoints/notes/watching/delete.ts37
-rw-r--r--src/server/api/endpoints/notifications/create.ts37
-rw-r--r--src/server/api/endpoints/notifications/mark-all-as-read.ts24
-rw-r--r--src/server/api/endpoints/notifications/read.ts42
-rw-r--r--src/server/api/endpoints/page-push.ts50
-rw-r--r--src/server/api/endpoints/pages/create.ts128
-rw-r--r--src/server/api/endpoints/pages/delete.ts45
-rw-r--r--src/server/api/endpoints/pages/featured.ts29
-rw-r--r--src/server/api/endpoints/pages/like.ts71
-rw-r--r--src/server/api/endpoints/pages/show.ts65
-rw-r--r--src/server/api/endpoints/pages/unlike.ts54
-rw-r--r--src/server/api/endpoints/pages/update.ts141
-rw-r--r--src/server/api/endpoints/ping.ts27
-rw-r--r--src/server/api/endpoints/pinned-users.ts32
-rw-r--r--src/server/api/endpoints/promo/read.ts50
-rw-r--r--src/server/api/endpoints/request-reset-password.ts73
-rw-r--r--src/server/api/endpoints/reset-db.ts23
-rw-r--r--src/server/api/endpoints/reset-password.ts45
-rw-r--r--src/server/api/endpoints/room/show.ts159
-rw-r--r--src/server/api/endpoints/room/update.ts51
-rw-r--r--src/server/api/endpoints/server-info.ts35
-rw-r--r--src/server/api/endpoints/stats.ts83
-rw-r--r--src/server/api/endpoints/sw/register.ts74
-rw-r--r--src/server/api/endpoints/sw/unregister.ts22
-rw-r--r--src/server/api/endpoints/username/available.ts40
-rw-r--r--src/server/api/endpoints/users.ts101
-rw-r--r--src/server/api/endpoints/users/clips.ts40
-rw-r--r--src/server/api/endpoints/users/followers.ts104
-rw-r--r--src/server/api/endpoints/users/following.ts104
-rw-r--r--src/server/api/endpoints/users/gallery/posts.ts39
-rw-r--r--src/server/api/endpoints/users/get-frequently-replied-users.ts105
-rw-r--r--src/server/api/endpoints/users/groups/create.ts45
-rw-r--r--src/server/api/endpoints/users/groups/delete.ts40
-rw-r--r--src/server/api/endpoints/users/groups/invitations/accept.ts54
-rw-r--r--src/server/api/endpoints/users/groups/invitations/reject.ts44
-rw-r--r--src/server/api/endpoints/users/groups/invite.ts102
-rw-r--r--src/server/api/endpoints/users/groups/joined.ts36
-rw-r--r--src/server/api/endpoints/users/groups/leave.ts50
-rw-r--r--src/server/api/endpoints/users/groups/owned.ts28
-rw-r--r--src/server/api/endpoints/users/groups/pull.ts69
-rw-r--r--src/server/api/endpoints/users/groups/show.ts55
-rw-r--r--src/server/api/endpoints/users/groups/transfer.ts83
-rw-r--r--src/server/api/endpoints/users/groups/update.ts55
-rw-r--r--src/server/api/endpoints/users/lists/create.ts36
-rw-r--r--src/server/api/endpoints/users/lists/delete.ts40
-rw-r--r--src/server/api/endpoints/users/lists/list.ts28
-rw-r--r--src/server/api/endpoints/users/lists/pull.ts62
-rw-r--r--src/server/api/endpoints/users/lists/push.ts92
-rw-r--r--src/server/api/endpoints/users/lists/show.ts47
-rw-r--r--src/server/api/endpoints/users/lists/update.ts55
-rw-r--r--src/server/api/endpoints/users/notes.ts144
-rw-r--r--src/server/api/endpoints/users/pages.ts40
-rw-r--r--src/server/api/endpoints/users/reactions.ts79
-rw-r--r--src/server/api/endpoints/users/recommendation.ts63
-rw-r--r--src/server/api/endpoints/users/relation.ts111
-rw-r--r--src/server/api/endpoints/users/report-abuse.ts90
-rw-r--r--src/server/api/endpoints/users/search-by-username-and-host.ts116
-rw-r--r--src/server/api/endpoints/users/search.ts127
-rw-r--r--src/server/api/endpoints/users/show.ts105
-rw-r--r--src/server/api/endpoints/users/stats.ts144
306 files changed, 0 insertions, 20595 deletions
diff --git a/src/server/api/endpoints/admin/abuse-user-reports.ts b/src/server/api/endpoints/admin/abuse-user-reports.ts
deleted file mode 100644
index 403eb24191..0000000000
--- a/src/server/api/endpoints/admin/abuse-user-reports.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { AbuseUserReports } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- state: {
- validator: $.optional.nullable.str,
- default: null,
- },
-
- reporterOrigin: {
- validator: $.optional.str.or([
- 'combined',
- 'local',
- 'remote',
- ]),
- default: 'combined'
- },
-
- targetUserOrigin: {
- validator: $.optional.str.or([
- 'combined',
- 'local',
- 'remote',
- ]),
- default: 'combined'
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- createdAt: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- format: 'date-time',
- },
- comment: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- },
- resolved: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const,
- example: false
- },
- reporterId: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- format: 'id',
- },
- targetUserId: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- format: 'id',
- },
- assigneeId: {
- type: 'string' as const,
- nullable: true as const, optional: false as const,
- format: 'id',
- },
- reporter: {
- type: 'object' as const,
- nullable: false as const, optional: false as const,
- ref: 'User'
- },
- targetUser: {
- type: 'object' as const,
- nullable: false as const, optional: false as const,
- ref: 'User'
- },
- assignee: {
- type: 'object' as const,
- nullable: true as const, optional: true as const,
- ref: 'User'
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId);
-
- switch (ps.state) {
- case 'resolved': query.andWhere('report.resolved = TRUE'); break;
- case 'unresolved': query.andWhere('report.resolved = FALSE'); break;
- }
-
- switch (ps.reporterOrigin) {
- case 'local': query.andWhere('report.reporterHost IS NULL'); break;
- case 'remote': query.andWhere('report.reporterHost IS NOT NULL'); break;
- }
-
- switch (ps.targetUserOrigin) {
- case 'local': query.andWhere('report.targetUserHost IS NULL'); break;
- case 'remote': query.andWhere('report.targetUserHost IS NOT NULL'); break;
- }
-
- const reports = await query.take(ps.limit!).getMany();
-
- return await AbuseUserReports.packMany(reports);
-});
diff --git a/src/server/api/endpoints/admin/accounts/create.ts b/src/server/api/endpoints/admin/accounts/create.ts
deleted file mode 100644
index fa15e84f77..0000000000
--- a/src/server/api/endpoints/admin/accounts/create.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import define from '../../../define';
-import { Users } from '@/models/index';
-import { signup } from '../../../common/signup';
-
-export const meta = {
- tags: ['admin'],
-
- params: {
- username: {
- validator: Users.validateLocalUsername,
- },
-
- password: {
- validator: Users.validatePassword,
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- properties: {
- token: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
-};
-
-export default define(meta, async (ps, _me) => {
- const me = _me ? await Users.findOneOrFail(_me.id) : null;
- const noUsers = (await Users.count({
- host: null,
- })) === 0;
- if (!noUsers && !me?.isAdmin) throw new Error('access denied');
-
- const { account, secret } = await signup({
- username: ps.username,
- password: ps.password,
- });
-
- const res = await Users.pack(account, account, {
- detail: true,
- includeSecrets: true
- });
-
- (res as any).token = secret;
-
- return res;
-});
diff --git a/src/server/api/endpoints/admin/accounts/delete.ts b/src/server/api/endpoints/admin/accounts/delete.ts
deleted file mode 100644
index 4e8a559805..0000000000
--- a/src/server/api/endpoints/admin/accounts/delete.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Users } from '@/models/index';
-import { doPostSuspend } from '@/services/suspend-user';
-import { publishUserEvent } from '@/services/stream';
-import { createDeleteAccountJob } from '@/queue';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- if (user.isAdmin) {
- throw new Error('cannot suspend admin');
- }
-
- if (user.isModerator) {
- throw new Error('cannot suspend moderator');
- }
-
- if (Users.isLocalUser(user)) {
- // 物理削除する前にDelete activityを送信する
- await doPostSuspend(user).catch(e => {});
-
- createDeleteAccountJob(user, {
- soft: false
- });
- } else {
- createDeleteAccountJob(user, {
- soft: true // リモートユーザーの削除は、完全にDBから物理削除してしまうと再度連合してきてアカウントが復活する可能性があるため、soft指定する
- });
- }
-
- await Users.update(user.id, {
- isDeleted: true,
- });
-
- if (Users.isLocalUser(user)) {
- // Terminate streaming
- publishUserEvent(user.id, 'terminate', {});
- }
-});
diff --git a/src/server/api/endpoints/admin/ad/create.ts b/src/server/api/endpoints/admin/ad/create.ts
deleted file mode 100644
index 27c7b5d318..0000000000
--- a/src/server/api/endpoints/admin/ad/create.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Ads } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- url: {
- validator: $.str.min(1)
- },
- memo: {
- validator: $.str
- },
- place: {
- validator: $.str
- },
- priority: {
- validator: $.str
- },
- ratio: {
- validator: $.num.int().min(0)
- },
- expiresAt: {
- validator: $.num.int()
- },
- imageUrl: {
- validator: $.str.min(1)
- }
- },
-};
-
-export default define(meta, async (ps) => {
- await Ads.insert({
- id: genId(),
- createdAt: new Date(),
- expiresAt: new Date(ps.expiresAt),
- url: ps.url,
- imageUrl: ps.imageUrl,
- priority: ps.priority,
- ratio: ps.ratio,
- place: ps.place,
- memo: ps.memo,
- });
-});
diff --git a/src/server/api/endpoints/admin/ad/delete.ts b/src/server/api/endpoints/admin/ad/delete.ts
deleted file mode 100644
index 91934e1aab..0000000000
--- a/src/server/api/endpoints/admin/ad/delete.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { Ads } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- id: {
- validator: $.type(ID)
- }
- },
-
- errors: {
- noSuchAd: {
- message: 'No such ad.',
- code: 'NO_SUCH_AD',
- id: 'ccac9863-3a03-416e-b899-8a64041118b1'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const ad = await Ads.findOne(ps.id);
-
- if (ad == null) throw new ApiError(meta.errors.noSuchAd);
-
- await Ads.delete(ad.id);
-});
diff --git a/src/server/api/endpoints/admin/ad/list.ts b/src/server/api/endpoints/admin/ad/list.ts
deleted file mode 100644
index 000aaaba9d..0000000000
--- a/src/server/api/endpoints/admin/ad/list.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { Ads } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-};
-
-export default define(meta, async (ps) => {
- const query = makePaginationQuery(Ads.createQueryBuilder('ad'), ps.sinceId, ps.untilId)
- .andWhere('ad.expiresAt > :now', { now: new Date() });
-
- const ads = await query.take(ps.limit!).getMany();
-
- return ads;
-});
diff --git a/src/server/api/endpoints/admin/ad/update.ts b/src/server/api/endpoints/admin/ad/update.ts
deleted file mode 100644
index 36c87895c2..0000000000
--- a/src/server/api/endpoints/admin/ad/update.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { Ads } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- id: {
- validator: $.type(ID)
- },
- memo: {
- validator: $.str
- },
- url: {
- validator: $.str.min(1)
- },
- imageUrl: {
- validator: $.str.min(1)
- },
- place: {
- validator: $.str
- },
- priority: {
- validator: $.str
- },
- ratio: {
- validator: $.num.int().min(0)
- },
- expiresAt: {
- validator: $.num.int()
- },
- },
-
- errors: {
- noSuchAd: {
- message: 'No such ad.',
- code: 'NO_SUCH_AD',
- id: 'b7aa1727-1354-47bc-a182-3a9c3973d300'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const ad = await Ads.findOne(ps.id);
-
- if (ad == null) throw new ApiError(meta.errors.noSuchAd);
-
- await Ads.update(ad.id, {
- url: ps.url,
- place: ps.place,
- priority: ps.priority,
- ratio: ps.ratio,
- memo: ps.memo,
- imageUrl: ps.imageUrl,
- expiresAt: new Date(ps.expiresAt),
- });
-});
diff --git a/src/server/api/endpoints/admin/announcements/create.ts b/src/server/api/endpoints/admin/announcements/create.ts
deleted file mode 100644
index f1c07745f9..0000000000
--- a/src/server/api/endpoints/admin/announcements/create.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Announcements } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- title: {
- validator: $.str.min(1)
- },
- text: {
- validator: $.str.min(1)
- },
- imageUrl: {
- validator: $.nullable.str.min(1)
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time',
- },
- updatedAt: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'date-time',
- },
- title: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- text: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- imageUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const announcement = await Announcements.save({
- id: genId(),
- createdAt: new Date(),
- updatedAt: null,
- title: ps.title,
- text: ps.text,
- imageUrl: ps.imageUrl,
- });
-
- return announcement;
-});
diff --git a/src/server/api/endpoints/admin/announcements/delete.ts b/src/server/api/endpoints/admin/announcements/delete.ts
deleted file mode 100644
index 7dbc05b4c9..0000000000
--- a/src/server/api/endpoints/admin/announcements/delete.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { Announcements } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- id: {
- validator: $.type(ID)
- }
- },
-
- errors: {
- noSuchAnnouncement: {
- message: 'No such announcement.',
- code: 'NO_SUCH_ANNOUNCEMENT',
- id: 'ecad8040-a276-4e85-bda9-015a708d291e'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const announcement = await Announcements.findOne(ps.id);
-
- if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
-
- await Announcements.delete(announcement.id);
-});
diff --git a/src/server/api/endpoints/admin/announcements/list.ts b/src/server/api/endpoints/admin/announcements/list.ts
deleted file mode 100644
index 4039bcd88f..0000000000
--- a/src/server/api/endpoints/admin/announcements/list.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { Announcements, AnnouncementReads } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time',
- },
- updatedAt: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'date-time',
- },
- text: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- title: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- imageUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- reads: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId);
-
- const announcements = await query.take(ps.limit!).getMany();
-
- for (const announcement of announcements) {
- (announcement as any).reads = await AnnouncementReads.count({
- announcementId: announcement.id
- });
- }
-
- return announcements;
-});
diff --git a/src/server/api/endpoints/admin/announcements/update.ts b/src/server/api/endpoints/admin/announcements/update.ts
deleted file mode 100644
index 343f37d626..0000000000
--- a/src/server/api/endpoints/admin/announcements/update.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { Announcements } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- id: {
- validator: $.type(ID)
- },
- title: {
- validator: $.str.min(1)
- },
- text: {
- validator: $.str.min(1)
- },
- imageUrl: {
- validator: $.nullable.str.min(1)
- }
- },
-
- errors: {
- noSuchAnnouncement: {
- message: 'No such announcement.',
- code: 'NO_SUCH_ANNOUNCEMENT',
- id: 'd3aae5a7-6372-4cb4-b61c-f511ffc2d7cc'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const announcement = await Announcements.findOne(ps.id);
-
- if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
-
- await Announcements.update(announcement.id, {
- updatedAt: new Date(),
- title: ps.title,
- text: ps.text,
- imageUrl: ps.imageUrl,
- });
-});
diff --git a/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts b/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts
deleted file mode 100644
index 988ab29558..0000000000
--- a/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { deleteFile } from '@/services/drive/delete-file';
-import { DriveFiles } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const files = await DriveFiles.find({
- userId: ps.userId
- });
-
- for (const file of files) {
- deleteFile(file);
- }
-});
diff --git a/src/server/api/endpoints/admin/delete-logs.ts b/src/server/api/endpoints/admin/delete-logs.ts
deleted file mode 100644
index 9d37ceb434..0000000000
--- a/src/server/api/endpoints/admin/delete-logs.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import define from '../../define';
-import { Logs } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-};
-
-export default define(meta, async (ps) => {
- await Logs.clear(); // TRUNCATE
-});
diff --git a/src/server/api/endpoints/admin/drive/clean-remote-files.ts b/src/server/api/endpoints/admin/drive/clean-remote-files.ts
deleted file mode 100644
index 76a6acff59..0000000000
--- a/src/server/api/endpoints/admin/drive/clean-remote-files.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import define from '../../../define';
-import { createCleanRemoteFilesJob } from '@/queue/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-};
-
-export default define(meta, async (ps, me) => {
- createCleanRemoteFilesJob();
-});
diff --git a/src/server/api/endpoints/admin/drive/cleanup.ts b/src/server/api/endpoints/admin/drive/cleanup.ts
deleted file mode 100644
index 8497478da9..0000000000
--- a/src/server/api/endpoints/admin/drive/cleanup.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { IsNull } from 'typeorm';
-import define from '../../../define';
-import { deleteFile } from '@/services/drive/delete-file';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-};
-
-export default define(meta, async (ps, me) => {
- const files = await DriveFiles.find({
- userId: IsNull()
- });
-
- for (const file of files) {
- deleteFile(file);
- }
-});
diff --git a/src/server/api/endpoints/admin/drive/files.ts b/src/server/api/endpoints/admin/drive/files.ts
deleted file mode 100644
index fe1c799805..0000000000
--- a/src/server/api/endpoints/admin/drive/files.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { DriveFiles } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: false as const,
- requireModerator: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- type: {
- validator: $.optional.nullable.str.match(/^[a-zA-Z0-9\/\-*]+$/)
- },
-
- origin: {
- validator: $.optional.str.or([
- 'combined',
- 'local',
- 'remote',
- ]),
- default: 'local'
- },
-
- hostname: {
- validator: $.optional.nullable.str,
- default: null
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId);
-
- if (ps.origin === 'local') {
- query.andWhere('file.userHost IS NULL');
- } else if (ps.origin === 'remote') {
- query.andWhere('file.userHost IS NOT NULL');
- }
-
- if (ps.hostname) {
- query.andWhere('file.userHost = :hostname', { hostname: ps.hostname });
- }
-
- if (ps.type) {
- if (ps.type.endsWith('/*')) {
- query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' });
- } else {
- query.andWhere('file.type = :type', { type: ps.type });
- }
- }
-
- const files = await query.take(ps.limit!).getMany();
-
- return await DriveFiles.packMany(files, { detail: true, withUser: true, self: true });
-});
diff --git a/src/server/api/endpoints/admin/drive/show-file.ts b/src/server/api/endpoints/admin/drive/show-file.ts
deleted file mode 100644
index 270b89c4fa..0000000000
--- a/src/server/api/endpoints/admin/drive/show-file.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- fileId: {
- validator: $.optional.type(ID),
- },
-
- url: {
- validator: $.optional.str,
- },
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'caf3ca38-c6e5-472e-a30c-b05377dcc240'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time',
- },
- userId: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- userHost: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- md5: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'md5',
- example: '15eca7fba0480996e2245f5185bf39f2'
- },
- name: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- example: 'lenna.jpg'
- },
- type: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- example: 'image/jpeg'
- },
- size: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- example: 51469
- },
- comment: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- blurhash: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- properties: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- width: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- example: 1280
- },
- height: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- example: 720
- },
- avgColor: {
- type: 'string' as const,
- optional: true as const, nullable: false as const,
- example: 'rgb(40,65,87)'
- }
- }
- },
- storedInternal: {
- type: 'boolean' as const,
- optional: false as const, nullable: true as const,
- example: true
- },
- url: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'url',
- },
- thumbnailUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'url',
- },
- webpublicUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'url',
- },
- accessKey: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- thumbnailAccessKey: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- webpublicAccessKey: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- uri: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- src: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- folderId: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- isSensitive: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- isLink: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const file = ps.fileId ? await DriveFiles.findOne(ps.fileId) : await DriveFiles.findOne({
- where: [{
- url: ps.url
- }, {
- thumbnailUrl: ps.url
- }, {
- webpublicUrl: ps.url
- }]
- });
-
- if (file == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
-
- return file;
-});
diff --git a/src/server/api/endpoints/admin/emoji/add.ts b/src/server/api/endpoints/admin/emoji/add.ts
deleted file mode 100644
index 1af81fe46d..0000000000
--- a/src/server/api/endpoints/admin/emoji/add.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Emojis, DriveFiles } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { getConnection } from 'typeorm';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-import { ApiError } from '../../../error';
-import { ID } from '@/misc/cafy-id';
-import rndstr from 'rndstr';
-import { publishBroadcastStream } from '@/services/stream';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- fileId: {
- validator: $.type(ID)
- },
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'MO_SUCH_FILE',
- id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) throw new ApiError(meta.errors.noSuchFile);
-
- const name = file.name.split('.')[0].match(/^[a-z0-9_]+$/) ? file.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`;
-
- const emoji = await Emojis.save({
- id: genId(),
- updatedAt: new Date(),
- name: name,
- category: null,
- host: null,
- aliases: [],
- url: file.url,
- type: file.type,
- });
-
- await getConnection().queryResultCache!.remove(['meta_emojis']);
-
- publishBroadcastStream('emojiAdded', {
- emoji: await Emojis.pack(emoji.id)
- });
-
- insertModerationLog(me, 'addEmoji', {
- emojiId: emoji.id
- });
-
- return {
- id: emoji.id
- };
-});
diff --git a/src/server/api/endpoints/admin/emoji/copy.ts b/src/server/api/endpoints/admin/emoji/copy.ts
deleted file mode 100644
index 4c8ab99f7c..0000000000
--- a/src/server/api/endpoints/admin/emoji/copy.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Emojis } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { getConnection } from 'typeorm';
-import { ApiError } from '../../../error';
-import { DriveFile } from '@/models/entities/drive-file';
-import { ID } from '@/misc/cafy-id';
-import uploadFromUrl from '@/services/drive/upload-from-url';
-import { publishBroadcastStream } from '@/services/stream';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- emojiId: {
- validator: $.type(ID)
- },
- },
-
- errors: {
- noSuchEmoji: {
- message: 'No such emoji.',
- code: 'NO_SUCH_EMOJI',
- id: 'e2785b66-dca3-4087-9cac-b93c541cc425'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- }
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const emoji = await Emojis.findOne(ps.emojiId);
-
- if (emoji == null) {
- throw new ApiError(meta.errors.noSuchEmoji);
- }
-
- let driveFile: DriveFile;
-
- try {
- // Create file
- driveFile = await uploadFromUrl(emoji.url, null, null, null, false, true);
- } catch (e) {
- throw new ApiError();
- }
-
- const copied = await Emojis.insert({
- id: genId(),
- updatedAt: new Date(),
- name: emoji.name,
- host: null,
- aliases: [],
- url: driveFile.url,
- type: driveFile.type,
- fileId: driveFile.id,
- }).then(x => Emojis.findOneOrFail(x.identifiers[0]));
-
- await getConnection().queryResultCache!.remove(['meta_emojis']);
-
- publishBroadcastStream('emojiAdded', {
- emoji: await Emojis.pack(copied.id)
- });
-
- return {
- id: copied.id
- };
-});
diff --git a/src/server/api/endpoints/admin/emoji/list-remote.ts b/src/server/api/endpoints/admin/emoji/list-remote.ts
deleted file mode 100644
index 3c8ca22170..0000000000
--- a/src/server/api/endpoints/admin/emoji/list-remote.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Emojis } from '@/models/index';
-import { toPuny } from '@/misc/convert-host';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- query: {
- validator: $.optional.nullable.str,
- default: null
- },
-
- host: {
- validator: $.optional.nullable.str,
- default: null
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- },
- aliases: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- name: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- category: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- host: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- url: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId);
-
- if (ps.host == null) {
- q.andWhere(`emoji.host IS NOT NULL`);
- } else {
- q.andWhere(`emoji.host = :host`, { host: toPuny(ps.host) });
- }
-
- if (ps.query) {
- q.andWhere('emoji.name like :query', { query: '%' + ps.query + '%' });
- }
-
- const emojis = await q
- .orderBy('emoji.id', 'DESC')
- .take(ps.limit!)
- .getMany();
-
- return Emojis.packMany(emojis);
-});
diff --git a/src/server/api/endpoints/admin/emoji/list.ts b/src/server/api/endpoints/admin/emoji/list.ts
deleted file mode 100644
index cb1e79e0fe..0000000000
--- a/src/server/api/endpoints/admin/emoji/list.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Emojis } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-import { ID } from '@/misc/cafy-id';
-import { Emoji } from '@/models/entities/emoji';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- query: {
- validator: $.optional.nullable.str,
- default: null
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- },
- aliases: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- name: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- category: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- host: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- url: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId)
- .andWhere(`emoji.host IS NULL`);
-
- let emojis: Emoji[];
-
- if (ps.query) {
- //q.andWhere('emoji.name ILIKE :q', { q: `%${ps.query}%` });
- //const emojis = await q.take(ps.limit!).getMany();
-
- emojis = await q.getMany();
-
- emojis = emojis.filter(emoji =>
- emoji.name.includes(ps.query!) ||
- emoji.aliases.some(a => a.includes(ps.query!)) ||
- emoji.category?.includes(ps.query!));
-
- emojis.splice(ps.limit! + 1);
- } else {
- emojis = await q.take(ps.limit!).getMany();
- }
-
- return Emojis.packMany(emojis);
-});
diff --git a/src/server/api/endpoints/admin/emoji/remove.ts b/src/server/api/endpoints/admin/emoji/remove.ts
deleted file mode 100644
index 259950e362..0000000000
--- a/src/server/api/endpoints/admin/emoji/remove.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { Emojis } from '@/models/index';
-import { getConnection } from 'typeorm';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- id: {
- validator: $.type(ID)
- }
- },
-
- errors: {
- noSuchEmoji: {
- message: 'No such emoji.',
- code: 'NO_SUCH_EMOJI',
- id: 'be83669b-773a-44b7-b1f8-e5e5170ac3c2'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const emoji = await Emojis.findOne(ps.id);
-
- if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji);
-
- await Emojis.delete(emoji.id);
-
- await getConnection().queryResultCache!.remove(['meta_emojis']);
-
- insertModerationLog(me, 'removeEmoji', {
- emoji: emoji
- });
-});
diff --git a/src/server/api/endpoints/admin/emoji/update.ts b/src/server/api/endpoints/admin/emoji/update.ts
deleted file mode 100644
index 3fd547d7e5..0000000000
--- a/src/server/api/endpoints/admin/emoji/update.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { Emojis } from '@/models/index';
-import { getConnection } from 'typeorm';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- id: {
- validator: $.type(ID)
- },
-
- name: {
- validator: $.str
- },
-
- category: {
- validator: $.optional.nullable.str
- },
-
- aliases: {
- validator: $.arr($.str)
- }
- },
-
- errors: {
- noSuchEmoji: {
- message: 'No such emoji.',
- code: 'NO_SUCH_EMOJI',
- id: '684dec9d-a8c2-4364-9aa8-456c49cb1dc8'
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const emoji = await Emojis.findOne(ps.id);
-
- if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji);
-
- await Emojis.update(emoji.id, {
- updatedAt: new Date(),
- name: ps.name,
- category: ps.category,
- aliases: ps.aliases,
- });
-
- await getConnection().queryResultCache!.remove(['meta_emojis']);
-});
diff --git a/src/server/api/endpoints/admin/federation/delete-all-files.ts b/src/server/api/endpoints/admin/federation/delete-all-files.ts
deleted file mode 100644
index 82540c5447..0000000000
--- a/src/server/api/endpoints/admin/federation/delete-all-files.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { deleteFile } from '@/services/drive/delete-file';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- host: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const files = await DriveFiles.find({
- userHost: ps.host
- });
-
- for (const file of files) {
- deleteFile(file);
- }
-});
diff --git a/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts b/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts
deleted file mode 100644
index 65a6947ba0..0000000000
--- a/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Instances } from '@/models/index';
-import { toPuny } from '@/misc/convert-host';
-import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- host: {
- validator: $.str
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const instance = await Instances.findOne({ host: toPuny(ps.host) });
-
- if (instance == null) {
- throw new Error('instance not found');
- }
-
- fetchInstanceMetadata(instance, true);
-});
diff --git a/src/server/api/endpoints/admin/federation/remove-all-following.ts b/src/server/api/endpoints/admin/federation/remove-all-following.ts
deleted file mode 100644
index 7935eaa631..0000000000
--- a/src/server/api/endpoints/admin/federation/remove-all-following.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import deleteFollowing from '@/services/following/delete';
-import { Followings, Users } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- host: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const followings = await Followings.find({
- followerHost: ps.host
- });
-
- const pairs = await Promise.all(followings.map(f => Promise.all([
- Users.findOneOrFail(f.followerId),
- Users.findOneOrFail(f.followeeId)
- ])));
-
- for (const pair of pairs) {
- deleteFollowing(pair[0], pair[1]);
- }
-});
diff --git a/src/server/api/endpoints/admin/federation/update-instance.ts b/src/server/api/endpoints/admin/federation/update-instance.ts
deleted file mode 100644
index 34eab27c78..0000000000
--- a/src/server/api/endpoints/admin/federation/update-instance.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Instances } from '@/models/index';
-import { toPuny } from '@/misc/convert-host';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- host: {
- validator: $.str
- },
-
- isSuspended: {
- validator: $.bool
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const instance = await Instances.findOne({ host: toPuny(ps.host) });
-
- if (instance == null) {
- throw new Error('instance not found');
- }
-
- Instances.update({ host: toPuny(ps.host) }, {
- isSuspended: ps.isSuspended
- });
-});
diff --git a/src/server/api/endpoints/admin/get-index-stats.ts b/src/server/api/endpoints/admin/get-index-stats.ts
deleted file mode 100644
index f2b06d0ef2..0000000000
--- a/src/server/api/endpoints/admin/get-index-stats.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import define from '../../define';
-import { getConnection } from 'typeorm';
-
-export const meta = {
- requireCredential: true as const,
- requireModerator: true,
-
- tags: ['admin'],
-
- params: {
- },
-};
-
-export default define(meta, async () => {
- const stats = await
- getConnection().query(`SELECT * FROM pg_indexes;`)
- .then(recs => {
- const res = [] as { tablename: string; indexname: string; }[];
- for (const rec of recs) {
- res.push(rec);
- }
- return res;
- });
-
- return stats;
-});
diff --git a/src/server/api/endpoints/admin/get-table-stats.ts b/src/server/api/endpoints/admin/get-table-stats.ts
deleted file mode 100644
index bce813232b..0000000000
--- a/src/server/api/endpoints/admin/get-table-stats.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import define from '../../define';
-import { getConnection } from 'typeorm';
-
-export const meta = {
- requireCredential: true as const,
- requireModerator: true,
-
- tags: ['admin'],
-
- params: {
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- example: {
- migrations: {
- count: 66,
- size: 32768
- },
- }
- }
-};
-
-export default define(meta, async () => {
- const sizes = await
- getConnection().query(`
- SELECT relname AS "table", reltuples as "count", pg_total_relation_size(C.oid) AS "size"
- FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
- WHERE nspname NOT IN ('pg_catalog', 'information_schema')
- AND C.relkind <> 'i'
- AND nspname !~ '^pg_toast';`)
- .then(recs => {
- const res = {} as Record<string, { count: number; size: number; }>;
- for (const rec of recs) {
- res[rec.table] = {
- count: parseInt(rec.count, 10),
- size: parseInt(rec.size, 10),
- };
- }
- return res;
- });
-
- return sizes;
-});
diff --git a/src/server/api/endpoints/admin/invite.ts b/src/server/api/endpoints/admin/invite.ts
deleted file mode 100644
index 2c69eec535..0000000000
--- a/src/server/api/endpoints/admin/invite.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import rndstr from 'rndstr';
-import define from '../../define';
-import { RegistrationTickets } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {},
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- code: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- example: '2ERUA5VR',
- maxLength: 8,
- minLength: 8
- }
- }
- }
-};
-
-export default define(meta, async () => {
- const code = rndstr({
- length: 8,
- chars: '2-9A-HJ-NP-Z', // [0-9A-Z] w/o [01IO] (32 patterns)
- });
-
- await RegistrationTickets.insert({
- id: genId(),
- createdAt: new Date(),
- code,
- });
-
- return {
- code,
- };
-});
diff --git a/src/server/api/endpoints/admin/moderators/add.ts b/src/server/api/endpoints/admin/moderators/add.ts
deleted file mode 100644
index 2b87fc217f..0000000000
--- a/src/server/api/endpoints/admin/moderators/add.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireAdmin: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- if (user.isAdmin) {
- throw new Error('cannot mark as moderator if admin user');
- }
-
- await Users.update(user.id, {
- isModerator: true
- });
-});
diff --git a/src/server/api/endpoints/admin/moderators/remove.ts b/src/server/api/endpoints/admin/moderators/remove.ts
deleted file mode 100644
index cbb0625224..0000000000
--- a/src/server/api/endpoints/admin/moderators/remove.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireAdmin: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- await Users.update(user.id, {
- isModerator: false
- });
-});
diff --git a/src/server/api/endpoints/admin/promo/create.ts b/src/server/api/endpoints/admin/promo/create.ts
deleted file mode 100644
index 3bdaaad4d9..0000000000
--- a/src/server/api/endpoints/admin/promo/create.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getNote } from '../../../common/getters';
-import { PromoNotes } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- expiresAt: {
- validator: $.num.int()
- },
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'ee449fbe-af2a-453b-9cae-cf2fe7c895fc'
- },
-
- alreadyPromoted: {
- message: 'The note has already promoted.',
- code: 'ALREADY_PROMOTED',
- id: 'ae427aa2-7a41-484f-a18c-2c1104051604'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const exist = await PromoNotes.findOne(note.id);
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyPromoted);
- }
-
- await PromoNotes.insert({
- noteId: note.id,
- createdAt: new Date(),
- expiresAt: new Date(ps.expiresAt),
- userId: note.userId,
- });
-});
diff --git a/src/server/api/endpoints/admin/queue/clear.ts b/src/server/api/endpoints/admin/queue/clear.ts
deleted file mode 100644
index fedb7065ab..0000000000
--- a/src/server/api/endpoints/admin/queue/clear.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import define from '../../../define';
-import { destroy } from '@/queue/index';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {}
-};
-
-export default define(meta, async (ps, me) => {
- destroy();
-
- insertModerationLog(me, 'clearQueue');
-});
diff --git a/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/src/server/api/endpoints/admin/queue/deliver-delayed.ts
deleted file mode 100644
index cd7b640983..0000000000
--- a/src/server/api/endpoints/admin/queue/deliver-delayed.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { deliverQueue } from '@/queue/queues';
-import { URL } from 'url';
-import define from '../../../define';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- anyOf: [
- {
- type: 'string' as const,
- },
- {
- type: 'number' as const,
- }
- ]
- }
- },
- example: [[
- 'example.com',
- 12
- ]]
- }
-};
-
-export default define(meta, async (ps) => {
- const jobs = await deliverQueue.getJobs(['delayed']);
-
- const res = [] as [string, number][];
-
- for (const job of jobs) {
- const host = new URL(job.data.to).host;
- if (res.find(x => x[0] === host)) {
- res.find(x => x[0] === host)![1]++;
- } else {
- res.push([host, 1]);
- }
- }
-
- res.sort((a, b) => b[1] - a[1]);
-
- return res;
-});
diff --git a/src/server/api/endpoints/admin/queue/inbox-delayed.ts b/src/server/api/endpoints/admin/queue/inbox-delayed.ts
deleted file mode 100644
index 1925906c28..0000000000
--- a/src/server/api/endpoints/admin/queue/inbox-delayed.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { URL } from 'url';
-import define from '../../../define';
-import { inboxQueue } from '@/queue/queues';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- anyOf: [
- {
- type: 'string' as const,
- },
- {
- type: 'number' as const,
- }
- ]
- }
- },
- example: [[
- 'example.com',
- 12
- ]]
- }
-};
-
-export default define(meta, async (ps) => {
- const jobs = await inboxQueue.getJobs(['delayed']);
-
- const res = [] as [string, number][];
-
- for (const job of jobs) {
- const host = new URL(job.data.signature.keyId).host;
- if (res.find(x => x[0] === host)) {
- res.find(x => x[0] === host)![1]++;
- } else {
- res.push([host, 1]);
- }
- }
-
- res.sort((a, b) => b[1] - a[1]);
-
- return res;
-});
diff --git a/src/server/api/endpoints/admin/queue/jobs.ts b/src/server/api/endpoints/admin/queue/jobs.ts
deleted file mode 100644
index c426e5f39b..0000000000
--- a/src/server/api/endpoints/admin/queue/jobs.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues';
-import $ from 'cafy';
-import define from '../../../define';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- domain: {
- validator: $.str.or(['deliver', 'inbox', 'db', 'objectStorage']),
- },
-
- state: {
- validator: $.str.or(['active', 'waiting', 'delayed']),
- },
-
- limit: {
- validator: $.optional.num,
- default: 50
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- data: {
- type: 'object' as const,
- optional: false as const, nullable: false as const
- },
- attempts: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- maxAttempts: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- timestamp: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const queue =
- ps.domain === 'deliver' ? deliverQueue :
- ps.domain === 'inbox' ? inboxQueue :
- ps.domain === 'db' ? dbQueue :
- ps.domain === 'objectStorage' ? objectStorageQueue :
- null as never;
-
- const jobs = await queue.getJobs([ps.state], 0, ps.limit!);
-
- return jobs.map(job => {
- const data = job.data;
- delete data.content;
- delete data.user;
- return {
- id: job.id,
- data,
- attempts: job.attemptsMade,
- maxAttempts: job.opts ? job.opts.attempts : 0,
- timestamp: job.timestamp,
- };
- });
-});
diff --git a/src/server/api/endpoints/admin/queue/stats.ts b/src/server/api/endpoints/admin/queue/stats.ts
deleted file mode 100644
index 38f18459dd..0000000000
--- a/src/server/api/endpoints/admin/queue/stats.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues';
-import define from '../../../define';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {},
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- deliver: {
- ref: 'QueueCount'
- },
- inbox: {
- ref: 'QueueCount'
- },
- db: {
- ref: 'QueueCount'
- },
- objectStorage: {
- ref: 'QueueCount'
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const deliverJobCounts = await deliverQueue.getJobCounts();
- const inboxJobCounts = await inboxQueue.getJobCounts();
- const dbJobCounts = await dbQueue.getJobCounts();
- const objectStorageJobCounts = await objectStorageQueue.getJobCounts();
-
- return {
- deliver: deliverJobCounts,
- inbox: inboxJobCounts,
- db: dbJobCounts,
- objectStorage: objectStorageJobCounts,
- };
-});
diff --git a/src/server/api/endpoints/admin/relays/add.ts b/src/server/api/endpoints/admin/relays/add.ts
deleted file mode 100644
index 567035fd3a..0000000000
--- a/src/server/api/endpoints/admin/relays/add.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { URL } from 'url';
-import $ from 'cafy';
-import define from '../../../define';
-import { addRelay } from '@/services/relay';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true as const,
-
- params: {
- inbox: {
- validator: $.str
- },
- },
-
- errors: {
- invalidUrl: {
- message: 'Invalid URL',
- code: 'INVALID_URL',
- id: 'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- inbox: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url'
- },
- status: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- default: 'requesting',
- enum: [
- 'requesting',
- 'accepted',
- 'rejected'
- ]
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- try {
- if (new URL(ps.inbox).protocol !== 'https:') throw 'https only';
- } catch {
- throw new ApiError(meta.errors.invalidUrl);
- }
-
- return await addRelay(ps.inbox);
-});
diff --git a/src/server/api/endpoints/admin/relays/list.ts b/src/server/api/endpoints/admin/relays/list.ts
deleted file mode 100644
index 031ebe85d0..0000000000
--- a/src/server/api/endpoints/admin/relays/list.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import define from '../../../define';
-import { listRelay } from '@/services/relay';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true as const,
-
- params: {
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- inbox: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url'
- },
- status: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- default: 'requesting',
- enum: [
- 'requesting',
- 'accepted',
- 'rejected'
- ]
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- return await listRelay();
-});
diff --git a/src/server/api/endpoints/admin/relays/remove.ts b/src/server/api/endpoints/admin/relays/remove.ts
deleted file mode 100644
index c1c50f5dc0..0000000000
--- a/src/server/api/endpoints/admin/relays/remove.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { removeRelay } from '@/services/relay';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true as const,
-
- params: {
- inbox: {
- validator: $.str
- },
- },
-};
-
-export default define(meta, async (ps, user) => {
- return await removeRelay(ps.inbox);
-});
diff --git a/src/server/api/endpoints/admin/reset-password.ts b/src/server/api/endpoints/admin/reset-password.ts
deleted file mode 100644
index 0fc2c6a868..0000000000
--- a/src/server/api/endpoints/admin/reset-password.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import * as bcrypt from 'bcryptjs';
-import rndstr from 'rndstr';
-import { Users, UserProfiles } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- password: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- minLength: 8,
- maxLength: 8
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- if (user.isAdmin) {
- throw new Error('cannot reset password of admin');
- }
-
- const passwd = rndstr('a-zA-Z0-9', 8);
-
- // Generate hash of password
- const hash = bcrypt.hashSync(passwd);
-
- await UserProfiles.update({
- userId: user.id
- }, {
- password: hash
- });
-
- return {
- password: passwd
- };
-});
diff --git a/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
deleted file mode 100644
index 7b71f8e000..0000000000
--- a/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { AbuseUserReports } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- reportId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const report = await AbuseUserReports.findOne(ps.reportId);
-
- if (report == null) {
- throw new Error('report not found');
- }
-
- await AbuseUserReports.update(report.id, {
- resolved: true,
- assigneeId: me.id,
- });
-});
diff --git a/src/server/api/endpoints/admin/resync-chart.ts b/src/server/api/endpoints/admin/resync-chart.ts
deleted file mode 100644
index e01dfce1b6..0000000000
--- a/src/server/api/endpoints/admin/resync-chart.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import define from '../../define';
-import { driveChart, notesChart, usersChart } from '@/services/chart/index';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-};
-
-export default define(meta, async (ps, me) => {
- insertModerationLog(me, 'chartResync');
-
- driveChart.resync();
- notesChart.resync();
- usersChart.resync();
-
- // TODO: ユーザーごとのチャートもキューに入れて更新する
- // TODO: インスタンスごとのチャートもキューに入れて更新する
-});
diff --git a/src/server/api/endpoints/admin/send-email.ts b/src/server/api/endpoints/admin/send-email.ts
deleted file mode 100644
index 6f67b78542..0000000000
--- a/src/server/api/endpoints/admin/send-email.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { sendEmail } from '@/services/send-email';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- to: {
- validator: $.str,
- },
- subject: {
- validator: $.str,
- },
- text: {
- validator: $.str,
- },
- }
-};
-
-export default define(meta, async (ps) => {
- await sendEmail(ps.to, ps.subject, ps.text, ps.text);
-});
diff --git a/src/server/api/endpoints/admin/server-info.ts b/src/server/api/endpoints/admin/server-info.ts
deleted file mode 100644
index bb2d35e397..0000000000
--- a/src/server/api/endpoints/admin/server-info.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import * as os from 'os';
-import * as si from 'systeminformation';
-import { getConnection } from 'typeorm';
-import define from '../../define';
-import { redisClient } from '../../../../db/redis';
-
-export const meta = {
- requireCredential: true as const,
- requireModerator: true,
-
- tags: ['admin', 'meta'],
-
- params: {
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- machine: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- os: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- example: 'linux'
- },
- node: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- psql: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- cpu: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- model: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- cores: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- }
- }
- },
- mem: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- total: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- format: 'bytes',
- }
- }
- },
- fs: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- total: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- format: 'bytes',
- },
- used: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- format: 'bytes',
- }
- }
- },
- net: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- interface: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- example: 'eth0'
- }
- }
- }
- }
- }
-};
-
-export default define(meta, async () => {
- const memStats = await si.mem();
- const fsStats = await si.fsSize();
- const netInterface = await si.networkInterfaceDefault();
-
- return {
- machine: os.hostname(),
- os: os.platform(),
- node: process.version,
- psql: await getConnection().query('SHOW server_version').then(x => x[0].server_version),
- redis: redisClient.server_info.redis_version,
- cpu: {
- model: os.cpus()[0].model,
- cores: os.cpus().length
- },
- mem: {
- total: memStats.total
- },
- fs: {
- total: fsStats[0].size,
- used: fsStats[0].used,
- },
- net: {
- interface: netInterface
- }
- };
-});
diff --git a/src/server/api/endpoints/admin/show-moderation-logs.ts b/src/server/api/endpoints/admin/show-moderation-logs.ts
deleted file mode 100644
index e9509568d0..0000000000
--- a/src/server/api/endpoints/admin/show-moderation-logs.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ModerationLogs } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time'
- },
- type: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- info: {
- type: 'object' as const,
- optional: false as const, nullable: false as const
- },
- userId: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- user: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const query = makePaginationQuery(ModerationLogs.createQueryBuilder('report'), ps.sinceId, ps.untilId);
-
- const reports = await query.take(ps.limit!).getMany();
-
- return await ModerationLogs.packMany(reports);
-});
diff --git a/src/server/api/endpoints/admin/show-user.ts b/src/server/api/endpoints/admin/show-user.ts
deleted file mode 100644
index 963c123255..0000000000
--- a/src/server/api/endpoints/admin/show-user.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- nullable: false as const, optional: false as const,
- properties: {
- id: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- format: 'id'
- },
- createdAt: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- format: 'date-time'
- },
- updatedAt: {
- type: 'string' as const,
- nullable: true as const, optional: false as const,
- format: 'date-time'
- },
- lastFetchedAt: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- username: {
- type: 'string' as const,
- nullable: false as const, optional: false as const
- },
- name: {
- type: 'string' as const,
- nullable: false as const, optional: false as const
- },
- folowersCount: {
- type: 'number' as const,
- nullable: false as const, optional: false as const
- },
- followingCount: {
- type: 'number' as const,
- nullable: false as const, optional: false as const
- },
- notesCount: {
- type: 'number' as const,
- nullable: false as const, optional: false as const
- },
- avatarId: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- bannerId: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- tags: {
- type: 'array' as const,
- nullable: false as const, optional: false as const,
- items: {
- type: 'string' as const,
- nullable: false as const, optional: false as const
- }
- },
- avatarUrl: {
- type: 'string' as const,
- nullable: true as const, optional: false as const,
- format: 'url'
- },
- bannerUrl: {
- type: 'string' as const,
- nullable: true as const, optional: false as const,
- format: 'url'
- },
- avatarBlurhash: {
- type: 'any' as const,
- nullable: true as const, optional: false as const,
- default: null
- },
- bannerBlurhash: {
- type: 'any' as const,
- nullable: true as const, optional: false as const,
- default: null
- },
- isSuspended: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const
- },
- isSilenced: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const
- },
- isLocked: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const,
- },
- isBot: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const
- },
- isCat: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const
- },
- isAdmin: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const
- },
- isModerator: {
- type: 'boolean' as const,
- nullable: false as const, optional: false as const
- },
- emojis: {
- type: 'array' as const,
- nullable: false as const, optional: false as const,
- items: {
- type: 'string' as const,
- nullable: false as const, optional: false as const
- }
- },
- host: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- inbox: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- sharedInbox: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- featured: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- uri: {
- type: 'string' as const,
- nullable: true as const, optional: false as const
- },
- token: {
- type: 'string' as const,
- nullable: false as const, optional: false as const,
- default: '<MASKED>'
- }
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- if ((me.isModerator && !me.isAdmin) && user.isAdmin) {
- throw new Error('cannot show info of admin');
- }
-
- return {
- ...user,
- token: user.token != null ? '<MASKED>' : user.token,
- };
-});
diff --git a/src/server/api/endpoints/admin/show-users.ts b/src/server/api/endpoints/admin/show-users.ts
deleted file mode 100644
index 20b63e7be6..0000000000
--- a/src/server/api/endpoints/admin/show-users.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- },
-
- sort: {
- validator: $.optional.str.or([
- '+follower',
- '-follower',
- '+createdAt',
- '-createdAt',
- '+updatedAt',
- '-updatedAt',
- ]),
- },
-
- state: {
- validator: $.optional.str.or([
- 'all',
- 'available',
- 'admin',
- 'moderator',
- 'adminOrModerator',
- 'silenced',
- 'suspended',
- ]),
- default: 'all'
- },
-
- origin: {
- validator: $.optional.str.or([
- 'combined',
- 'local',
- 'remote',
- ]),
- default: 'local'
- },
-
- username: {
- validator: $.optional.str,
- default: null
- },
-
- hostname: {
- validator: $.optional.str,
- default: null
- }
- },
-
- res: {
- type: 'array' as const,
- nullable: false as const, optional: false as const,
- items: {
- type: 'object' as const,
- nullable: false as const, optional: false as const,
- ref: 'User'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const query = Users.createQueryBuilder('user');
-
- switch (ps.state) {
- case 'available': query.where('user.isSuspended = FALSE'); break;
- case 'admin': query.where('user.isAdmin = TRUE'); break;
- case 'moderator': query.where('user.isModerator = TRUE'); break;
- case 'adminOrModerator': query.where('user.isAdmin = TRUE OR user.isModerator = TRUE'); break;
- case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break;
- case 'silenced': query.where('user.isSilenced = TRUE'); break;
- case 'suspended': query.where('user.isSuspended = TRUE'); break;
- }
-
- switch (ps.origin) {
- case 'local': query.andWhere('user.host IS NULL'); break;
- case 'remote': query.andWhere('user.host IS NOT NULL'); break;
- }
-
- if (ps.username) {
- query.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' });
- }
-
- if (ps.hostname) {
- query.andWhere('user.host like :hostname', { hostname: '%' + ps.hostname.toLowerCase() + '%' });
- }
-
- switch (ps.sort) {
- case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
- case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
- case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
- case '+updatedAt': query.orderBy('user.updatedAt', 'DESC', 'NULLS LAST'); break;
- case '-updatedAt': query.orderBy('user.updatedAt', 'ASC', 'NULLS FIRST'); break;
- default: query.orderBy('user.id', 'ASC'); break;
- }
-
- query.take(ps.limit!);
- query.skip(ps.offset);
-
- const users = await query.getMany();
-
- return await Users.packMany(users, me, { detail: true });
-});
diff --git a/src/server/api/endpoints/admin/silence-user.ts b/src/server/api/endpoints/admin/silence-user.ts
deleted file mode 100644
index 9bfed2310a..0000000000
--- a/src/server/api/endpoints/admin/silence-user.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Users } from '@/models/index';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- if (user.isAdmin) {
- throw new Error('cannot silence admin');
- }
-
- await Users.update(user.id, {
- isSilenced: true
- });
-
- insertModerationLog(me, 'silence', {
- targetId: user.id,
- });
-});
diff --git a/src/server/api/endpoints/admin/suspend-user.ts b/src/server/api/endpoints/admin/suspend-user.ts
deleted file mode 100644
index 364f258ce8..0000000000
--- a/src/server/api/endpoints/admin/suspend-user.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import deleteFollowing from '@/services/following/delete';
-import { Users, Followings, Notifications } from '@/models/index';
-import { User } from '@/models/entities/user';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-import { doPostSuspend } from '@/services/suspend-user';
-import { publishUserEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- if (user.isAdmin) {
- throw new Error('cannot suspend admin');
- }
-
- if (user.isModerator) {
- throw new Error('cannot suspend moderator');
- }
-
- await Users.update(user.id, {
- isSuspended: true
- });
-
- insertModerationLog(me, 'suspend', {
- targetId: user.id,
- });
-
- // Terminate streaming
- if (Users.isLocalUser(user)) {
- publishUserEvent(user.id, 'terminate', {});
- }
-
- (async () => {
- await doPostSuspend(user).catch(e => {});
- await unFollowAll(user).catch(e => {});
- await readAllNotify(user).catch(e => {});
- })();
-});
-
-async function unFollowAll(follower: User) {
- const followings = await Followings.find({
- followerId: follower.id
- });
-
- for (const following of followings) {
- const followee = await Users.findOne({
- id: following.followeeId
- });
-
- if (followee == null) {
- throw `Cant find followee ${following.followeeId}`;
- }
-
- await deleteFollowing(follower, followee, true);
- }
-}
-
-async function readAllNotify(notifier: User) {
- await Notifications.update({
- notifierId: notifier.id,
- isRead: false,
- }, {
- isRead: true
- });
-}
diff --git a/src/server/api/endpoints/admin/unsilence-user.ts b/src/server/api/endpoints/admin/unsilence-user.ts
deleted file mode 100644
index 9994fbf462..0000000000
--- a/src/server/api/endpoints/admin/unsilence-user.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Users } from '@/models/index';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- await Users.update(user.id, {
- isSilenced: false
- });
-
- insertModerationLog(me, 'unsilence', {
- targetId: user.id,
- });
-});
diff --git a/src/server/api/endpoints/admin/unsuspend-user.ts b/src/server/api/endpoints/admin/unsuspend-user.ts
deleted file mode 100644
index ab4c2d3dfe..0000000000
--- a/src/server/api/endpoints/admin/unsuspend-user.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Users } from '@/models/index';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-import { doPostUnsuspend } from '@/services/unsuspend-user';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId as string);
-
- if (user == null) {
- throw new Error('user not found');
- }
-
- await Users.update(user.id, {
- isSuspended: false
- });
-
- insertModerationLog(me, 'unsuspend', {
- targetId: user.id,
- });
-
- doPostUnsuspend(user);
-});
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
deleted file mode 100644
index 55447098dc..0000000000
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ /dev/null
@@ -1,608 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { getConnection } from 'typeorm';
-import { Meta } from '@/models/entities/meta';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireAdmin: true,
-
- params: {
- disableRegistration: {
- validator: $.optional.nullable.bool,
- },
-
- disableLocalTimeline: {
- validator: $.optional.nullable.bool,
- },
-
- disableGlobalTimeline: {
- validator: $.optional.nullable.bool,
- },
-
- useStarForReactionFallback: {
- validator: $.optional.nullable.bool,
- },
-
- pinnedUsers: {
- validator: $.optional.nullable.arr($.str),
- },
-
- hiddenTags: {
- validator: $.optional.nullable.arr($.str),
- },
-
- blockedHosts: {
- validator: $.optional.nullable.arr($.str),
- },
-
- mascotImageUrl: {
- validator: $.optional.nullable.str,
- },
-
- bannerUrl: {
- validator: $.optional.nullable.str,
- },
-
- errorImageUrl: {
- validator: $.optional.nullable.str,
- },
-
- iconUrl: {
- validator: $.optional.nullable.str,
- },
-
- backgroundImageUrl: {
- validator: $.optional.nullable.str,
- },
-
- logoImageUrl: {
- validator: $.optional.nullable.str,
- },
-
- name: {
- validator: $.optional.nullable.str,
- },
-
- description: {
- validator: $.optional.nullable.str,
- },
-
- maxNoteTextLength: {
- validator: $.optional.num.min(0).max(DB_MAX_NOTE_TEXT_LENGTH),
- },
-
- localDriveCapacityMb: {
- validator: $.optional.num.min(0),
- },
-
- remoteDriveCapacityMb: {
- validator: $.optional.num.min(0),
- },
-
- cacheRemoteFiles: {
- validator: $.optional.bool,
- },
-
- proxyRemoteFiles: {
- validator: $.optional.bool,
- },
-
- emailRequiredForSignup: {
- validator: $.optional.bool,
- },
-
- enableHcaptcha: {
- validator: $.optional.bool,
- },
-
- hcaptchaSiteKey: {
- validator: $.optional.nullable.str,
- },
-
- hcaptchaSecretKey: {
- validator: $.optional.nullable.str,
- },
-
- enableRecaptcha: {
- validator: $.optional.bool,
- },
-
- recaptchaSiteKey: {
- validator: $.optional.nullable.str,
- },
-
- recaptchaSecretKey: {
- validator: $.optional.nullable.str,
- },
-
- proxyAccountId: {
- validator: $.optional.nullable.type(ID),
- },
-
- maintainerName: {
- validator: $.optional.nullable.str,
- },
-
- maintainerEmail: {
- validator: $.optional.nullable.str,
- },
-
- pinnedPages: {
- validator: $.optional.arr($.str),
- },
-
- pinnedClipId: {
- validator: $.optional.nullable.type(ID),
- },
-
- langs: {
- validator: $.optional.arr($.str),
- },
-
- summalyProxy: {
- validator: $.optional.nullable.str,
- },
-
- deeplAuthKey: {
- validator: $.optional.nullable.str,
- },
-
- deeplIsPro: {
- validator: $.optional.bool,
- },
-
- enableTwitterIntegration: {
- validator: $.optional.bool,
- },
-
- twitterConsumerKey: {
- validator: $.optional.nullable.str,
- },
-
- twitterConsumerSecret: {
- validator: $.optional.nullable.str,
- },
-
- enableGithubIntegration: {
- validator: $.optional.bool,
- },
-
- githubClientId: {
- validator: $.optional.nullable.str,
- },
-
- githubClientSecret: {
- validator: $.optional.nullable.str,
- },
-
- enableDiscordIntegration: {
- validator: $.optional.bool,
- },
-
- discordClientId: {
- validator: $.optional.nullable.str,
- },
-
- discordClientSecret: {
- validator: $.optional.nullable.str,
- },
-
- enableEmail: {
- validator: $.optional.bool,
- },
-
- email: {
- validator: $.optional.nullable.str,
- },
-
- smtpSecure: {
- validator: $.optional.bool,
- },
-
- smtpHost: {
- validator: $.optional.nullable.str,
- },
-
- smtpPort: {
- validator: $.optional.nullable.num,
- },
-
- smtpUser: {
- validator: $.optional.nullable.str,
- },
-
- smtpPass: {
- validator: $.optional.nullable.str,
- },
-
- enableServiceWorker: {
- validator: $.optional.bool,
- },
-
- swPublicKey: {
- validator: $.optional.nullable.str,
- },
-
- swPrivateKey: {
- validator: $.optional.nullable.str,
- },
-
- tosUrl: {
- validator: $.optional.nullable.str,
- },
-
- repositoryUrl: {
- validator: $.optional.str,
- },
-
- feedbackUrl: {
- validator: $.optional.str,
- },
-
- useObjectStorage: {
- validator: $.optional.bool
- },
-
- objectStorageBaseUrl: {
- validator: $.optional.nullable.str
- },
-
- objectStorageBucket: {
- validator: $.optional.nullable.str
- },
-
- objectStoragePrefix: {
- validator: $.optional.nullable.str
- },
-
- objectStorageEndpoint: {
- validator: $.optional.nullable.str
- },
-
- objectStorageRegion: {
- validator: $.optional.nullable.str
- },
-
- objectStoragePort: {
- validator: $.optional.nullable.num
- },
-
- objectStorageAccessKey: {
- validator: $.optional.nullable.str
- },
-
- objectStorageSecretKey: {
- validator: $.optional.nullable.str
- },
-
- objectStorageUseSSL: {
- validator: $.optional.bool
- },
-
- objectStorageUseProxy: {
- validator: $.optional.bool
- },
-
- objectStorageSetPublicRead: {
- validator: $.optional.bool
- },
-
- objectStorageS3ForcePathStyle: {
- validator: $.optional.bool
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const set = {} as Partial<Meta>;
-
- if (typeof ps.disableRegistration === 'boolean') {
- set.disableRegistration = ps.disableRegistration;
- }
-
- if (typeof ps.disableLocalTimeline === 'boolean') {
- set.disableLocalTimeline = ps.disableLocalTimeline;
- }
-
- if (typeof ps.disableGlobalTimeline === 'boolean') {
- set.disableGlobalTimeline = ps.disableGlobalTimeline;
- }
-
- if (typeof ps.useStarForReactionFallback === 'boolean') {
- set.useStarForReactionFallback = ps.useStarForReactionFallback;
- }
-
- if (Array.isArray(ps.pinnedUsers)) {
- set.pinnedUsers = ps.pinnedUsers.filter(Boolean);
- }
-
- if (Array.isArray(ps.hiddenTags)) {
- set.hiddenTags = ps.hiddenTags.filter(Boolean);
- }
-
- if (Array.isArray(ps.blockedHosts)) {
- set.blockedHosts = ps.blockedHosts.filter(Boolean);
- }
-
- if (ps.mascotImageUrl !== undefined) {
- set.mascotImageUrl = ps.mascotImageUrl;
- }
-
- if (ps.bannerUrl !== undefined) {
- set.bannerUrl = ps.bannerUrl;
- }
-
- if (ps.iconUrl !== undefined) {
- set.iconUrl = ps.iconUrl;
- }
-
- if (ps.backgroundImageUrl !== undefined) {
- set.backgroundImageUrl = ps.backgroundImageUrl;
- }
-
- if (ps.logoImageUrl !== undefined) {
- set.logoImageUrl = ps.logoImageUrl;
- }
-
- if (ps.name !== undefined) {
- set.name = ps.name;
- }
-
- if (ps.description !== undefined) {
- set.description = ps.description;
- }
-
- if (ps.maxNoteTextLength) {
- set.maxNoteTextLength = ps.maxNoteTextLength;
- }
-
- if (ps.localDriveCapacityMb !== undefined) {
- set.localDriveCapacityMb = ps.localDriveCapacityMb;
- }
-
- if (ps.remoteDriveCapacityMb !== undefined) {
- set.remoteDriveCapacityMb = ps.remoteDriveCapacityMb;
- }
-
- if (ps.cacheRemoteFiles !== undefined) {
- set.cacheRemoteFiles = ps.cacheRemoteFiles;
- }
-
- if (ps.proxyRemoteFiles !== undefined) {
- set.proxyRemoteFiles = ps.proxyRemoteFiles;
- }
-
- if (ps.emailRequiredForSignup !== undefined) {
- set.emailRequiredForSignup = ps.emailRequiredForSignup;
- }
-
- if (ps.enableHcaptcha !== undefined) {
- set.enableHcaptcha = ps.enableHcaptcha;
- }
-
- if (ps.hcaptchaSiteKey !== undefined) {
- set.hcaptchaSiteKey = ps.hcaptchaSiteKey;
- }
-
- if (ps.hcaptchaSecretKey !== undefined) {
- set.hcaptchaSecretKey = ps.hcaptchaSecretKey;
- }
-
- if (ps.enableRecaptcha !== undefined) {
- set.enableRecaptcha = ps.enableRecaptcha;
- }
-
- if (ps.recaptchaSiteKey !== undefined) {
- set.recaptchaSiteKey = ps.recaptchaSiteKey;
- }
-
- if (ps.recaptchaSecretKey !== undefined) {
- set.recaptchaSecretKey = ps.recaptchaSecretKey;
- }
-
- if (ps.proxyAccountId !== undefined) {
- set.proxyAccountId = ps.proxyAccountId;
- }
-
- if (ps.maintainerName !== undefined) {
- set.maintainerName = ps.maintainerName;
- }
-
- if (ps.maintainerEmail !== undefined) {
- set.maintainerEmail = ps.maintainerEmail;
- }
-
- if (Array.isArray(ps.langs)) {
- set.langs = ps.langs.filter(Boolean);
- }
-
- if (Array.isArray(ps.pinnedPages)) {
- set.pinnedPages = ps.pinnedPages.filter(Boolean);
- }
-
- if (ps.pinnedClipId !== undefined) {
- set.pinnedClipId = ps.pinnedClipId;
- }
-
- if (ps.summalyProxy !== undefined) {
- set.summalyProxy = ps.summalyProxy;
- }
-
- if (ps.enableTwitterIntegration !== undefined) {
- set.enableTwitterIntegration = ps.enableTwitterIntegration;
- }
-
- if (ps.twitterConsumerKey !== undefined) {
- set.twitterConsumerKey = ps.twitterConsumerKey;
- }
-
- if (ps.twitterConsumerSecret !== undefined) {
- set.twitterConsumerSecret = ps.twitterConsumerSecret;
- }
-
- if (ps.enableGithubIntegration !== undefined) {
- set.enableGithubIntegration = ps.enableGithubIntegration;
- }
-
- if (ps.githubClientId !== undefined) {
- set.githubClientId = ps.githubClientId;
- }
-
- if (ps.githubClientSecret !== undefined) {
- set.githubClientSecret = ps.githubClientSecret;
- }
-
- if (ps.enableDiscordIntegration !== undefined) {
- set.enableDiscordIntegration = ps.enableDiscordIntegration;
- }
-
- if (ps.discordClientId !== undefined) {
- set.discordClientId = ps.discordClientId;
- }
-
- if (ps.discordClientSecret !== undefined) {
- set.discordClientSecret = ps.discordClientSecret;
- }
-
- if (ps.enableEmail !== undefined) {
- set.enableEmail = ps.enableEmail;
- }
-
- if (ps.email !== undefined) {
- set.email = ps.email;
- }
-
- if (ps.smtpSecure !== undefined) {
- set.smtpSecure = ps.smtpSecure;
- }
-
- if (ps.smtpHost !== undefined) {
- set.smtpHost = ps.smtpHost;
- }
-
- if (ps.smtpPort !== undefined) {
- set.smtpPort = ps.smtpPort;
- }
-
- if (ps.smtpUser !== undefined) {
- set.smtpUser = ps.smtpUser;
- }
-
- if (ps.smtpPass !== undefined) {
- set.smtpPass = ps.smtpPass;
- }
-
- if (ps.errorImageUrl !== undefined) {
- set.errorImageUrl = ps.errorImageUrl;
- }
-
- if (ps.enableServiceWorker !== undefined) {
- set.enableServiceWorker = ps.enableServiceWorker;
- }
-
- if (ps.swPublicKey !== undefined) {
- set.swPublicKey = ps.swPublicKey;
- }
-
- if (ps.swPrivateKey !== undefined) {
- set.swPrivateKey = ps.swPrivateKey;
- }
-
- if (ps.tosUrl !== undefined) {
- set.ToSUrl = ps.tosUrl;
- }
-
- if (ps.repositoryUrl !== undefined) {
- set.repositoryUrl = ps.repositoryUrl;
- }
-
- if (ps.feedbackUrl !== undefined) {
- set.feedbackUrl = ps.feedbackUrl;
- }
-
- if (ps.useObjectStorage !== undefined) {
- set.useObjectStorage = ps.useObjectStorage;
- }
-
- if (ps.objectStorageBaseUrl !== undefined) {
- set.objectStorageBaseUrl = ps.objectStorageBaseUrl;
- }
-
- if (ps.objectStorageBucket !== undefined) {
- set.objectStorageBucket = ps.objectStorageBucket;
- }
-
- if (ps.objectStoragePrefix !== undefined) {
- set.objectStoragePrefix = ps.objectStoragePrefix;
- }
-
- if (ps.objectStorageEndpoint !== undefined) {
- set.objectStorageEndpoint = ps.objectStorageEndpoint;
- }
-
- if (ps.objectStorageRegion !== undefined) {
- set.objectStorageRegion = ps.objectStorageRegion;
- }
-
- if (ps.objectStoragePort !== undefined) {
- set.objectStoragePort = ps.objectStoragePort;
- }
-
- if (ps.objectStorageAccessKey !== undefined) {
- set.objectStorageAccessKey = ps.objectStorageAccessKey;
- }
-
- if (ps.objectStorageSecretKey !== undefined) {
- set.objectStorageSecretKey = ps.objectStorageSecretKey;
- }
-
- if (ps.objectStorageUseSSL !== undefined) {
- set.objectStorageUseSSL = ps.objectStorageUseSSL;
- }
-
- if (ps.objectStorageUseProxy !== undefined) {
- set.objectStorageUseProxy = ps.objectStorageUseProxy;
- }
-
- if (ps.objectStorageSetPublicRead !== undefined) {
- set.objectStorageSetPublicRead = ps.objectStorageSetPublicRead;
- }
-
- if (ps.objectStorageS3ForcePathStyle !== undefined) {
- set.objectStorageS3ForcePathStyle = ps.objectStorageS3ForcePathStyle;
- }
-
- if (ps.deeplAuthKey !== undefined) {
- if (ps.deeplAuthKey === '') {
- set.deeplAuthKey = null;
- } else {
- set.deeplAuthKey = ps.deeplAuthKey;
- }
- }
-
- if (ps.deeplIsPro !== undefined) {
- set.deeplIsPro = ps.deeplIsPro;
- }
-
- await getConnection().transaction(async transactionalEntityManager => {
- const meta = await transactionalEntityManager.findOne(Meta, {
- order: {
- id: 'DESC'
- }
- });
-
- if (meta) {
- await transactionalEntityManager.update(Meta, meta.id, set);
- } else {
- await transactionalEntityManager.save(Meta, set);
- }
- });
-
- insertModerationLog(me, 'updateMeta');
-});
diff --git a/src/server/api/endpoints/admin/vacuum.ts b/src/server/api/endpoints/admin/vacuum.ts
deleted file mode 100644
index 9a80d88c44..0000000000
--- a/src/server/api/endpoints/admin/vacuum.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { getConnection } from 'typeorm';
-import { insertModerationLog } from '@/services/insert-moderation-log';
-
-export const meta = {
- tags: ['admin'],
-
- requireCredential: true as const,
- requireModerator: true,
-
- params: {
- full: {
- validator: $.bool,
- },
- analyze: {
- validator: $.bool,
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const params: string[] = [];
-
- if (ps.full) {
- params.push('FULL');
- }
-
- if (ps.analyze) {
- params.push('ANALYZE');
- }
-
- getConnection().query('VACUUM ' + params.join(' '));
-
- insertModerationLog(me, 'vacuum', ps);
-});
diff --git a/src/server/api/endpoints/announcements.ts b/src/server/api/endpoints/announcements.ts
deleted file mode 100644
index a67737b2ff..0000000000
--- a/src/server/api/endpoints/announcements.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../define';
-import { Announcements, AnnouncementReads } from '@/models/index';
-import { makePaginationQuery } from '../common/make-pagination-query';
-
-export const meta = {
- tags: ['meta'],
-
- requireCredential: false as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- withUnreads: {
- validator: $.optional.boolean,
- default: false
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id',
- example: 'xxxxxxxxxx',
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time',
- },
- updatedAt: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'date-time',
- },
- text: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- title: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- imageUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- isRead: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId);
-
- const announcements = await query.take(ps.limit!).getMany();
-
- if (user) {
- const reads = (await AnnouncementReads.find({
- userId: user.id
- })).map(x => x.announcementId);
-
- for (const announcement of announcements) {
- (announcement as any).isRead = reads.includes(announcement.id);
- }
- }
-
- return ps.withUnreads ? announcements.filter((a: any) => !a.isRead) : announcements;
-});
diff --git a/src/server/api/endpoints/antennas/create.ts b/src/server/api/endpoints/antennas/create.ts
deleted file mode 100644
index 4bdae8cc33..0000000000
--- a/src/server/api/endpoints/antennas/create.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { genId } from '@/misc/gen-id';
-import { Antennas, UserLists, UserGroupJoinings } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-import { ApiError } from '../../error';
-import { publishInternalEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['antennas'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- name: {
- validator: $.str.range(1, 100)
- },
-
- src: {
- validator: $.str.or(['home', 'all', 'users', 'list', 'group'])
- },
-
- userListId: {
- validator: $.nullable.optional.type(ID),
- },
-
- userGroupId: {
- validator: $.nullable.optional.type(ID),
- },
-
- keywords: {
- validator: $.arr($.arr($.str))
- },
-
- excludeKeywords: {
- validator: $.arr($.arr($.str))
- },
-
- users: {
- validator: $.arr($.str)
- },
-
- caseSensitive: {
- validator: $.bool
- },
-
- withReplies: {
- validator: $.bool
- },
-
- withFile: {
- validator: $.bool
- },
-
- notify: {
- validator: $.bool
- }
- },
-
- errors: {
- noSuchUserList: {
- message: 'No such user list.',
- code: 'NO_SUCH_USER_LIST',
- id: '95063e93-a283-4b8b-9aa5-bcdb8df69a7f'
- },
-
- noSuchUserGroup: {
- message: 'No such user group.',
- code: 'NO_SUCH_USER_GROUP',
- id: 'aa3c0b9a-8cae-47c0-92ac-202ce5906682'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Antenna'
- }
-};
-
-export default define(meta, async (ps, user) => {
- let userList;
- let userGroupJoining;
-
- if (ps.src === 'list' && ps.userListId) {
- userList = await UserLists.findOne({
- id: ps.userListId,
- userId: user.id,
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchUserList);
- }
- } else if (ps.src === 'group' && ps.userGroupId) {
- userGroupJoining = await UserGroupJoinings.findOne({
- userGroupId: ps.userGroupId,
- userId: user.id,
- });
-
- if (userGroupJoining == null) {
- throw new ApiError(meta.errors.noSuchUserGroup);
- }
- }
-
- const antenna = await Antennas.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- name: ps.name,
- src: ps.src,
- userListId: userList ? userList.id : null,
- userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
- keywords: ps.keywords,
- excludeKeywords: ps.excludeKeywords,
- users: ps.users,
- caseSensitive: ps.caseSensitive,
- withReplies: ps.withReplies,
- withFile: ps.withFile,
- notify: ps.notify,
- }).then(x => Antennas.findOneOrFail(x.identifiers[0]));
-
- publishInternalEvent('antennaCreated', antenna);
-
- return await Antennas.pack(antenna);
-});
diff --git a/src/server/api/endpoints/antennas/delete.ts b/src/server/api/endpoints/antennas/delete.ts
deleted file mode 100644
index 1cd136183e..0000000000
--- a/src/server/api/endpoints/antennas/delete.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Antennas } from '@/models/index';
-import { publishInternalEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['antennas'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- antennaId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchAntenna: {
- message: 'No such antenna.',
- code: 'NO_SUCH_ANTENNA',
- id: 'b34dcf9d-348f-44bb-99d0-6c9314cfe2df'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const antenna = await Antennas.findOne({
- id: ps.antennaId,
- userId: user.id
- });
-
- if (antenna == null) {
- throw new ApiError(meta.errors.noSuchAntenna);
- }
-
- await Antennas.delete(antenna.id);
-
- publishInternalEvent('antennaDeleted', antenna);
-});
diff --git a/src/server/api/endpoints/antennas/list.ts b/src/server/api/endpoints/antennas/list.ts
deleted file mode 100644
index 8baae8435b..0000000000
--- a/src/server/api/endpoints/antennas/list.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import define from '../../define';
-import { Antennas } from '@/models/index';
-
-export const meta = {
- tags: ['antennas', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Antenna'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const antennas = await Antennas.find({
- userId: me.id,
- });
-
- return await Promise.all(antennas.map(x => Antennas.pack(x)));
-});
diff --git a/src/server/api/endpoints/antennas/notes.ts b/src/server/api/endpoints/antennas/notes.ts
deleted file mode 100644
index 1759e95b4c..0000000000
--- a/src/server/api/endpoints/antennas/notes.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import readNote from '@/services/note/read';
-import { Antennas, Notes, AntennaNotes } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { ApiError } from '../../error';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['antennas', 'account', 'notes'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- params: {
- antennaId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- errors: {
- noSuchAntenna: {
- message: 'No such antenna.',
- code: 'NO_SUCH_ANTENNA',
- id: '850926e0-fd3b-49b6-b69a-b28a5dbd82fe'
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const antenna = await Antennas.findOne({
- id: ps.antennaId,
- userId: user.id
- });
-
- if (antenna == null) {
- throw new ApiError(meta.errors.noSuchAntenna);
- }
-
- const antennaQuery = AntennaNotes.createQueryBuilder('joining')
- .select('joining.noteId')
- .where('joining.antennaId = :antennaId', { antennaId: antenna.id });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.id IN (${ antennaQuery.getQuery() })`)
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .setParameters(antennaQuery.getParameters());
-
- generateVisibilityQuery(query, user);
- generateMutedUserQuery(query, user);
- generateBlockedUserQuery(query, user);
-
- const notes = await query
- .take(ps.limit!)
- .getMany();
-
- if (notes.length > 0) {
- readNote(user.id, notes);
- }
-
- return await Notes.packMany(notes, user);
-});
diff --git a/src/server/api/endpoints/antennas/show.ts b/src/server/api/endpoints/antennas/show.ts
deleted file mode 100644
index 3cdf4dcb61..0000000000
--- a/src/server/api/endpoints/antennas/show.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Antennas } from '@/models/index';
-
-export const meta = {
- tags: ['antennas', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- params: {
- antennaId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchAntenna: {
- message: 'No such antenna.',
- code: 'NO_SUCH_ANTENNA',
- id: 'c06569fb-b025-4f23-b22d-1fcd20d2816b'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Antenna'
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the antenna
- const antenna = await Antennas.findOne({
- id: ps.antennaId,
- userId: me.id,
- });
-
- if (antenna == null) {
- throw new ApiError(meta.errors.noSuchAntenna);
- }
-
- return await Antennas.pack(antenna);
-});
diff --git a/src/server/api/endpoints/antennas/update.ts b/src/server/api/endpoints/antennas/update.ts
deleted file mode 100644
index d69b4feee6..0000000000
--- a/src/server/api/endpoints/antennas/update.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Antennas, UserLists, UserGroupJoinings } from '@/models/index';
-import { publishInternalEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['antennas'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- antennaId: {
- validator: $.type(ID),
- },
-
- name: {
- validator: $.str.range(1, 100)
- },
-
- src: {
- validator: $.str.or(['home', 'all', 'users', 'list', 'group'])
- },
-
- userListId: {
- validator: $.nullable.optional.type(ID),
- },
-
- userGroupId: {
- validator: $.nullable.optional.type(ID),
- },
-
- keywords: {
- validator: $.arr($.arr($.str))
- },
-
- excludeKeywords: {
- validator: $.arr($.arr($.str))
- },
-
- users: {
- validator: $.arr($.str)
- },
-
- caseSensitive: {
- validator: $.bool
- },
-
- withReplies: {
- validator: $.bool
- },
-
- withFile: {
- validator: $.bool
- },
-
- notify: {
- validator: $.bool
- }
- },
-
- errors: {
- noSuchAntenna: {
- message: 'No such antenna.',
- code: 'NO_SUCH_ANTENNA',
- id: '10c673ac-8852-48eb-aa1f-f5b67f069290'
- },
-
- noSuchUserList: {
- message: 'No such user list.',
- code: 'NO_SUCH_USER_LIST',
- id: '1c6b35c9-943e-48c2-81e4-2844989407f7'
- },
-
- noSuchUserGroup: {
- message: 'No such user group.',
- code: 'NO_SUCH_USER_GROUP',
- id: '109ed789-b6eb-456e-b8a9-6059d567d385'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Antenna'
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch the antenna
- const antenna = await Antennas.findOne({
- id: ps.antennaId,
- userId: user.id
- });
-
- if (antenna == null) {
- throw new ApiError(meta.errors.noSuchAntenna);
- }
-
- let userList;
- let userGroupJoining;
-
- if (ps.src === 'list' && ps.userListId) {
- userList = await UserLists.findOne({
- id: ps.userListId,
- userId: user.id,
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchUserList);
- }
- } else if (ps.src === 'group' && ps.userGroupId) {
- userGroupJoining = await UserGroupJoinings.findOne({
- userGroupId: ps.userGroupId,
- userId: user.id,
- });
-
- if (userGroupJoining == null) {
- throw new ApiError(meta.errors.noSuchUserGroup);
- }
- }
-
- await Antennas.update(antenna.id, {
- name: ps.name,
- src: ps.src,
- userListId: userList ? userList.id : null,
- userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
- keywords: ps.keywords,
- excludeKeywords: ps.excludeKeywords,
- users: ps.users,
- caseSensitive: ps.caseSensitive,
- withReplies: ps.withReplies,
- withFile: ps.withFile,
- notify: ps.notify,
- });
-
- publishInternalEvent('antennaUpdated', await Antennas.findOneOrFail(antenna.id));
-
- return await Antennas.pack(antenna.id);
-});
diff --git a/src/server/api/endpoints/ap/get.ts b/src/server/api/endpoints/ap/get.ts
deleted file mode 100644
index 78919f43b0..0000000000
--- a/src/server/api/endpoints/ap/get.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import Resolver from '@/remote/activitypub/resolver';
-import { ApiError } from '../../error';
-import * as ms from 'ms';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: true as const,
-
- limit: {
- duration: ms('1hour'),
- max: 30
- },
-
- params: {
- uri: {
- validator: $.str,
- },
- },
-
- errors: {
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- }
-};
-
-export default define(meta, async (ps) => {
- const resolver = new Resolver();
- const object = await resolver.resolve(ps.uri);
- return object;
-});
diff --git a/src/server/api/endpoints/ap/show.ts b/src/server/api/endpoints/ap/show.ts
deleted file mode 100644
index 2280d93724..0000000000
--- a/src/server/api/endpoints/ap/show.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import config from '@/config/index';
-import { createPerson } from '@/remote/activitypub/models/person';
-import { createNote } from '@/remote/activitypub/models/note';
-import Resolver from '@/remote/activitypub/resolver';
-import { ApiError } from '../../error';
-import { extractDbHost } from '@/misc/convert-host';
-import { Users, Notes } from '@/models/index';
-import { Note } from '@/models/entities/note';
-import { User } from '@/models/entities/user';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { isActor, isPost, getApId } from '@/remote/activitypub/type';
-import * as ms from 'ms';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: true as const,
-
- limit: {
- duration: ms('1hour'),
- max: 30
- },
-
- params: {
- uri: {
- validator: $.str,
- },
- },
-
- errors: {
- noSuchObject: {
- message: 'No such object.',
- code: 'NO_SUCH_OBJECT',
- id: 'dc94d745-1262-4e63-a17d-fecaa57efc82'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- type: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- enum: ['User', 'Note']
- },
- object: {
- type: 'object' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- const object = await fetchAny(ps.uri);
- if (object) {
- return object;
- } else {
- throw new ApiError(meta.errors.noSuchObject);
- }
-});
-
-/***
- * URIからUserかNoteを解決する
- */
-async function fetchAny(uri: string) {
- // URIがこのサーバーを指しているなら、ローカルユーザーIDとしてDBからフェッチ
- if (uri.startsWith(config.url + '/')) {
- const parts = uri.split('/');
- const id = parts.pop();
- const type = parts.pop();
-
- if (type === 'notes') {
- const note = await Notes.findOne(id);
-
- if (note) {
- return {
- type: 'Note',
- object: await Notes.pack(note, null, { detail: true })
- };
- }
- } else if (type === 'users') {
- const user = await Users.findOne(id);
-
- if (user) {
- return {
- type: 'User',
- object: await Users.pack(user, null, { detail: true })
- };
- }
- }
- }
-
- // ブロックしてたら中断
- const meta = await fetchMeta();
- if (meta.blockedHosts.includes(extractDbHost(uri))) return null;
-
- // URI(AP Object id)としてDB検索
- {
- const [user, note] = await Promise.all([
- Users.findOne({ uri: uri }),
- Notes.findOne({ uri: uri })
- ]);
-
- const packed = await mergePack(user, note);
- if (packed !== null) return packed;
- }
-
- // リモートから一旦オブジェクトフェッチ
- const resolver = new Resolver();
- const object = await resolver.resolve(uri) as any;
-
- // /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する
- // これはDBに存在する可能性があるため再度DB検索
- if (uri !== object.id) {
- if (object.id.startsWith(config.url + '/')) {
- const parts = object.id.split('/');
- const id = parts.pop();
- const type = parts.pop();
-
- if (type === 'notes') {
- const note = await Notes.findOne(id);
-
- if (note) {
- return {
- type: 'Note',
- object: await Notes.pack(note, null, { detail: true })
- };
- }
- } else if (type === 'users') {
- const user = await Users.findOne(id);
-
- if (user) {
- return {
- type: 'User',
- object: await Users.pack(user, null, { detail: true })
- };
- }
- }
- }
-
- const [user, note] = await Promise.all([
- Users.findOne({ uri: object.id }),
- Notes.findOne({ uri: object.id })
- ]);
-
- const packed = await mergePack(user, note);
- if (packed !== null) return packed;
- }
-
- // それでもみつからなければ新規であるため登録
- if (isActor(object)) {
- const user = await createPerson(getApId(object));
- return {
- type: 'User',
- object: await Users.pack(user, null, { detail: true })
- };
- }
-
- if (isPost(object)) {
- const note = await createNote(getApId(object), undefined, true);
- return {
- type: 'Note',
- object: await Notes.pack(note!, null, { detail: true })
- };
- }
-
- return null;
-}
-
-async function mergePack(user: User | null | undefined, note: Note | null | undefined) {
- if (user != null) {
- return {
- type: 'User',
- object: await Users.pack(user, null, { detail: true })
- };
- }
-
- if (note != null) {
- return {
- type: 'Note',
- object: await Notes.pack(note, null, { detail: true })
- };
- }
-
- return null;
-}
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
deleted file mode 100644
index c2ce943dcc..0000000000
--- a/src/server/api/endpoints/app/create.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Apps } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { unique } from '@/prelude/array';
-import { secureRndstr } from '@/misc/secure-rndstr';
-
-export const meta = {
- tags: ['app'],
-
- requireCredential: false as const,
-
- params: {
- name: {
- validator: $.str,
- },
-
- description: {
- validator: $.str,
- },
-
- permission: {
- validator: $.arr($.str).unique(),
- },
-
- // TODO: Check it is valid url
- callbackUrl: {
- validator: $.optional.nullable.str,
- default: null,
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'App',
- },
-};
-
-export default define(meta, async (ps, user) => {
- // Generate secret
- const secret = secureRndstr(32, true);
-
- // for backward compatibility
- const permission = unique(ps.permission.map(v => v.replace(/^(.+)(\/|-)(read|write)$/, '$3:$1')));
-
- // Create account
- const app = await Apps.save({
- id: genId(),
- createdAt: new Date(),
- userId: user ? user.id : null,
- name: ps.name,
- description: ps.description,
- permission,
- callbackUrl: ps.callbackUrl,
- secret: secret
- });
-
- return await Apps.pack(app, null, {
- detail: true,
- includeSecret: true
- });
-});
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
deleted file mode 100644
index 27f12eb44f..0000000000
--- a/src/server/api/endpoints/app/show.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Apps } from '@/models/index';
-
-export const meta = {
- tags: ['app'],
-
- params: {
- appId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'App',
- },
-
- errors: {
- noSuchApp: {
- message: 'No such app.',
- code: 'NO_SUCH_APP',
- id: 'dce83913-2dc6-4093-8a7b-71dbb11718a3'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'App'
- }
-};
-
-export default define(meta, async (ps, user, token) => {
- const isSecure = user != null && token == null;
-
- // Lookup app
- const ap = await Apps.findOne(ps.appId);
-
- if (ap == null) {
- throw new ApiError(meta.errors.noSuchApp);
- }
-
- return await Apps.pack(ap, user, {
- detail: true,
- includeSecret: isSecure && (ap.userId === user!.id)
- });
-});
diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts
deleted file mode 100644
index 1d1d8ac227..0000000000
--- a/src/server/api/endpoints/auth/accept.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import * as crypto from 'crypto';
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { AuthSessions, AccessTokens, Apps } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { secureRndstr } from '@/misc/secure-rndstr';
-
-export const meta = {
- tags: ['auth'],
-
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- token: {
- validator: $.str
- }
- },
-
- errors: {
- noSuchSession: {
- message: 'No such session.',
- code: 'NO_SUCH_SESSION',
- id: '9c72d8de-391a-43c1-9d06-08d29efde8df'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch token
- const session = await AuthSessions
- .findOne({ token: ps.token });
-
- if (session == null) {
- throw new ApiError(meta.errors.noSuchSession);
- }
-
- // Generate access token
- const accessToken = secureRndstr(32, true);
-
- // Fetch exist access token
- const exist = await AccessTokens.findOne({
- appId: session.appId,
- userId: user.id,
- });
-
- if (exist == null) {
- // Lookup app
- const app = await Apps.findOneOrFail(session.appId);
-
- // Generate Hash
- const sha256 = crypto.createHash('sha256');
- sha256.update(accessToken + app.secret);
- const hash = sha256.digest('hex');
-
- const now = new Date();
-
- // Insert access token doc
- await AccessTokens.insert({
- id: genId(),
- createdAt: now,
- lastUsedAt: now,
- appId: session.appId,
- userId: user.id,
- token: accessToken,
- hash: hash
- });
- }
-
- // Update session
- await AuthSessions.update(session.id, {
- userId: user.id
- });
-});
diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts
deleted file mode 100644
index 859cf52ed3..0000000000
--- a/src/server/api/endpoints/auth/session/generate.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { v4 as uuid } from 'uuid';
-import $ from 'cafy';
-import config from '@/config/index';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { Apps, AuthSessions } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['auth'],
-
- requireCredential: false as const,
-
- params: {
- appSecret: {
- validator: $.str,
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- token: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- url: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url',
- },
- }
- },
-
- errors: {
- noSuchApp: {
- message: 'No such app.',
- code: 'NO_SUCH_APP',
- id: '92f93e63-428e-4f2f-a5a4-39e1407fe998'
- }
- }
-};
-
-export default define(meta, async (ps) => {
- // Lookup app
- const app = await Apps.findOne({
- secret: ps.appSecret
- });
-
- if (app == null) {
- throw new ApiError(meta.errors.noSuchApp);
- }
-
- // Generate token
- const token = uuid();
-
- // Create session token document
- const doc = await AuthSessions.save({
- id: genId(),
- createdAt: new Date(),
- appId: app.id,
- token: token
- });
-
- return {
- token: doc.token,
- url: `${config.authUrl}/${doc.token}`
- };
-});
diff --git a/src/server/api/endpoints/auth/session/show.ts b/src/server/api/endpoints/auth/session/show.ts
deleted file mode 100644
index 23f1a56a37..0000000000
--- a/src/server/api/endpoints/auth/session/show.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { AuthSessions } from '@/models/index';
-
-export const meta = {
- tags: ['auth'],
-
- requireCredential: false as const,
-
- params: {
- token: {
- validator: $.str,
- }
- },
-
- errors: {
- noSuchSession: {
- message: 'No such session.',
- code: 'NO_SUCH_SESSION',
- id: 'bd72c97d-eba7-4adb-a467-f171b8847250'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- app: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'App'
- },
- token: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Lookup session
- const session = await AuthSessions.findOne({
- token: ps.token
- });
-
- if (session == null) {
- throw new ApiError(meta.errors.noSuchSession);
- }
-
- return await AuthSessions.pack(session, user);
-});
diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts
deleted file mode 100644
index 72201cb207..0000000000
--- a/src/server/api/endpoints/auth/session/userkey.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { Apps, AuthSessions, AccessTokens, Users } from '@/models/index';
-
-export const meta = {
- tags: ['auth'],
-
- requireCredential: false as const,
-
- params: {
- appSecret: {
- validator: $.str,
- },
-
- token: {
- validator: $.str,
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- accessToken: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
-
- user: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- },
- }
- },
-
- errors: {
- noSuchApp: {
- message: 'No such app.',
- code: 'NO_SUCH_APP',
- id: 'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d'
- },
-
- noSuchSession: {
- message: 'No such session.',
- code: 'NO_SUCH_SESSION',
- id: '5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3'
- },
-
- pendingSession: {
- message: 'This session is not completed yet.',
- code: 'PENDING_SESSION',
- id: '8c8a4145-02cc-4cca-8e66-29ba60445a8e'
- }
- }
-};
-
-export default define(meta, async (ps) => {
- // Lookup app
- const app = await Apps.findOne({
- secret: ps.appSecret
- });
-
- if (app == null) {
- throw new ApiError(meta.errors.noSuchApp);
- }
-
- // Fetch token
- const session = await AuthSessions.findOne({
- token: ps.token,
- appId: app.id
- });
-
- if (session == null) {
- throw new ApiError(meta.errors.noSuchSession);
- }
-
- if (session.userId == null) {
- throw new ApiError(meta.errors.pendingSession);
- }
-
- // Lookup access token
- const accessToken = await AccessTokens.findOneOrFail({
- appId: app.id,
- userId: session.userId
- });
-
- // Delete session
- AuthSessions.delete(session.id);
-
- return {
- accessToken: accessToken.token,
- user: await Users.pack(session.userId, null, {
- detail: true
- })
- };
-});
diff --git a/src/server/api/endpoints/blocking/create.ts b/src/server/api/endpoints/blocking/create.ts
deleted file mode 100644
index 2953252394..0000000000
--- a/src/server/api/endpoints/blocking/create.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import * as ms from 'ms';
-import create from '@/services/blocking/create';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { Blockings, NoteWatchings, Users } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- limit: {
- duration: ms('1hour'),
- max: 100
- },
-
- requireCredential: true as const,
-
- kind: 'write:blocks',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '7cc4f851-e2f1-4621-9633-ec9e1d00c01e'
- },
-
- blockeeIsYourself: {
- message: 'Blockee is yourself.',
- code: 'BLOCKEE_IS_YOURSELF',
- id: '88b19138-f28d-42c0-8499-6a31bbd0fdc6'
- },
-
- alreadyBlocking: {
- message: 'You are already blocking that user.',
- code: 'ALREADY_BLOCKING',
- id: '787fed64-acb9-464a-82eb-afbd745b9614'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, user) => {
- const blocker = await Users.findOneOrFail(user.id);
-
- // 自分自身
- if (user.id === ps.userId) {
- throw new ApiError(meta.errors.blockeeIsYourself);
- }
-
- // Get blockee
- const blockee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check if already blocking
- const exist = await Blockings.findOne({
- blockerId: blocker.id,
- blockeeId: blockee.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyBlocking);
- }
-
- await create(blocker, blockee);
-
- NoteWatchings.delete({
- userId: blocker.id,
- noteUserId: blockee.id
- });
-
- return await Users.pack(blockee.id, blocker, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/blocking/delete.ts b/src/server/api/endpoints/blocking/delete.ts
deleted file mode 100644
index a66e46fdf0..0000000000
--- a/src/server/api/endpoints/blocking/delete.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import * as ms from 'ms';
-import deleteBlocking from '@/services/blocking/delete';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { Blockings, Users } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- limit: {
- duration: ms('1hour'),
- max: 100
- },
-
- requireCredential: true as const,
-
- kind: 'write:blocks',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '8621d8bf-c358-4303-a066-5ea78610eb3f'
- },
-
- blockeeIsYourself: {
- message: 'Blockee is yourself.',
- code: 'BLOCKEE_IS_YOURSELF',
- id: '06f6fac6-524b-473c-a354-e97a40ae6eac'
- },
-
- notBlocking: {
- message: 'You are not blocking that user.',
- code: 'NOT_BLOCKING',
- id: '291b2efa-60c6-45c0-9f6a-045c8f9b02cd'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- },
-};
-
-export default define(meta, async (ps, user) => {
- const blocker = await Users.findOneOrFail(user.id);
-
- // Check if the blockee is yourself
- if (user.id === ps.userId) {
- throw new ApiError(meta.errors.blockeeIsYourself);
- }
-
- // Get blockee
- const blockee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check not blocking
- const exist = await Blockings.findOne({
- blockerId: blocker.id,
- blockeeId: blockee.id
- });
-
- if (exist == null) {
- throw new ApiError(meta.errors.notBlocking);
- }
-
- // Delete blocking
- await deleteBlocking(blocker, blockee);
-
- return await Users.pack(blockee.id, blocker, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/blocking/list.ts b/src/server/api/endpoints/blocking/list.ts
deleted file mode 100644
index fe25fdaba1..0000000000
--- a/src/server/api/endpoints/blocking/list.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Blockings } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'read:blocks',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 30
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Blocking',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Blockings.createQueryBuilder('blocking'), ps.sinceId, ps.untilId)
- .andWhere(`blocking.blockerId = :meId`, { meId: me.id });
-
- const blockings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Blockings.packMany(blockings, me);
-});
diff --git a/src/server/api/endpoints/channels/create.ts b/src/server/api/endpoints/channels/create.ts
deleted file mode 100644
index 0cedfd6c6a..0000000000
--- a/src/server/api/endpoints/channels/create.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Channels, DriveFiles } from '@/models/index';
-import { Channel } from '@/models/entities/channel';
-import { genId } from '@/misc/gen-id';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['channels'],
-
- requireCredential: true as const,
-
- kind: 'write:channels',
-
- params: {
- name: {
- validator: $.str.range(1, 128)
- },
-
- description: {
- validator: $.nullable.optional.str.range(1, 2048)
- },
-
- bannerId: {
- validator: $.nullable.optional.type(ID),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Channel',
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- let banner = null;
- if (ps.bannerId != null) {
- banner = await DriveFiles.findOne({
- id: ps.bannerId,
- userId: user.id
- });
-
- if (banner == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- }
-
- const channel = await Channels.save({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- name: ps.name,
- description: ps.description || null,
- bannerId: banner ? banner.id : null,
- } as Channel);
-
- return await Channels.pack(channel, user);
-});
diff --git a/src/server/api/endpoints/channels/featured.ts b/src/server/api/endpoints/channels/featured.ts
deleted file mode 100644
index dc1f49f960..0000000000
--- a/src/server/api/endpoints/channels/featured.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import define from '../../define';
-import { Channels } from '@/models/index';
-
-export const meta = {
- tags: ['channels'],
-
- requireCredential: false as const,
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Channel',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = Channels.createQueryBuilder('channel')
- .where('channel.lastNotedAt IS NOT NULL')
- .orderBy('channel.lastNotedAt', 'DESC');
-
- const channels = await query.take(10).getMany();
-
- return await Promise.all(channels.map(x => Channels.pack(x, me)));
-});
diff --git a/src/server/api/endpoints/channels/follow.ts b/src/server/api/endpoints/channels/follow.ts
deleted file mode 100644
index d4664e6996..0000000000
--- a/src/server/api/endpoints/channels/follow.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Channels, ChannelFollowings } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { publishUserEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['channels'],
-
- requireCredential: true as const,
-
- kind: 'write:channels',
-
- params: {
- channelId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchChannel: {
- message: 'No such channel.',
- code: 'NO_SUCH_CHANNEL',
- id: 'c0031718-d573-4e85-928e-10039f1fbb68'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const channel = await Channels.findOne({
- id: ps.channelId,
- });
-
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
-
- await ChannelFollowings.insert({
- id: genId(),
- createdAt: new Date(),
- followerId: user.id,
- followeeId: channel.id,
- });
-
- publishUserEvent(user.id, 'followChannel', channel);
-});
diff --git a/src/server/api/endpoints/channels/followed.ts b/src/server/api/endpoints/channels/followed.ts
deleted file mode 100644
index be239a01d6..0000000000
--- a/src/server/api/endpoints/channels/followed.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Channels, ChannelFollowings } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['channels', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:channels',
-
- params: {
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 5
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Channel',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(ChannelFollowings.createQueryBuilder(), ps.sinceId, ps.untilId)
- .andWhere({ followerId: me.id });
-
- const followings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Promise.all(followings.map(x => Channels.pack(x.followeeId, me)));
-});
diff --git a/src/server/api/endpoints/channels/owned.ts b/src/server/api/endpoints/channels/owned.ts
deleted file mode 100644
index 4a2e9db17b..0000000000
--- a/src/server/api/endpoints/channels/owned.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Channels } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['channels', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:channels',
-
- params: {
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 5
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Channel',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Channels.createQueryBuilder(), ps.sinceId, ps.untilId)
- .andWhere({ userId: me.id });
-
- const channels = await query
- .take(ps.limit!)
- .getMany();
-
- return await Promise.all(channels.map(x => Channels.pack(x, me)));
-});
diff --git a/src/server/api/endpoints/channels/pin-note.ts b/src/server/api/endpoints/channels/pin-note.ts
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/server/api/endpoints/channels/pin-note.ts
+++ /dev/null
diff --git a/src/server/api/endpoints/channels/show.ts b/src/server/api/endpoints/channels/show.ts
deleted file mode 100644
index 803ce6363d..0000000000
--- a/src/server/api/endpoints/channels/show.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Channels } from '@/models/index';
-
-export const meta = {
- tags: ['channels'],
-
- requireCredential: false as const,
-
- params: {
- channelId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Channel',
- },
-
- errors: {
- noSuchChannel: {
- message: 'No such channel.',
- code: 'NO_SUCH_CHANNEL',
- id: '6f6c314b-7486-4897-8966-c04a66a02923'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const channel = await Channels.findOne({
- id: ps.channelId,
- });
-
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
-
- return await Channels.pack(channel, me);
-});
diff --git a/src/server/api/endpoints/channels/timeline.ts b/src/server/api/endpoints/channels/timeline.ts
deleted file mode 100644
index 0ed057a11e..0000000000
--- a/src/server/api/endpoints/channels/timeline.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Notes, Channels } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { activeUsersChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['notes', 'channels'],
-
- requireCredential: false as const,
-
- params: {
- channelId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchChannel: {
- message: 'No such channel.',
- code: 'NO_SUCH_CHANNEL',
- id: '4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const channel = await Channels.findOne({
- id: ps.channelId,
- });
-
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
-
- //#region Construct query
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere('note.channelId = :channelId', { channelId: channel.id })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .leftJoinAndSelect('note.channel', 'channel');
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- if (user) activeUsersChart.update(user);
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/channels/unfollow.ts b/src/server/api/endpoints/channels/unfollow.ts
deleted file mode 100644
index 700f8e93ba..0000000000
--- a/src/server/api/endpoints/channels/unfollow.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Channels, ChannelFollowings } from '@/models/index';
-import { publishUserEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['channels'],
-
- requireCredential: true as const,
-
- kind: 'write:channels',
-
- params: {
- channelId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchChannel: {
- message: 'No such channel.',
- code: 'NO_SUCH_CHANNEL',
- id: '19959ee9-0153-4c51-bbd9-a98c49dc59d6'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const channel = await Channels.findOne({
- id: ps.channelId,
- });
-
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
-
- await ChannelFollowings.delete({
- followerId: user.id,
- followeeId: channel.id,
- });
-
- publishUserEvent(user.id, 'unfollowChannel', channel);
-});
diff --git a/src/server/api/endpoints/channels/update.ts b/src/server/api/endpoints/channels/update.ts
deleted file mode 100644
index 9b447bd04b..0000000000
--- a/src/server/api/endpoints/channels/update.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Channels, DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['channels'],
-
- requireCredential: true as const,
-
- kind: 'write:channels',
-
- params: {
- channelId: {
- validator: $.type(ID),
- },
-
- name: {
- validator: $.optional.str.range(1, 128)
- },
-
- description: {
- validator: $.nullable.optional.str.range(1, 2048)
- },
-
- bannerId: {
- validator: $.nullable.optional.type(ID),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Channel',
- },
-
- errors: {
- noSuchChannel: {
- message: 'No such channel.',
- code: 'NO_SUCH_CHANNEL',
- id: 'f9c5467f-d492-4c3c-9a8d-a70dacc86512'
- },
-
- accessDenied: {
- message: 'You do not have edit privilege of the channel.',
- code: 'ACCESS_DENIED',
- id: '1fb7cb09-d46a-4fdf-b8df-057788cce513'
- },
-
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'e86c14a4-0da2-4032-8df3-e737a04c7f3b'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const channel = await Channels.findOne({
- id: ps.channelId,
- });
-
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
-
- if (channel.userId !== me.id) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- // tslint:disable-next-line:no-unnecessary-initializer
- let banner = undefined;
- if (ps.bannerId != null) {
- banner = await DriveFiles.findOne({
- id: ps.bannerId,
- userId: me.id
- });
-
- if (banner == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- } else if (ps.bannerId === null) {
- banner = null;
- }
-
- await Channels.update(channel.id, {
- ...(ps.name !== undefined ? { name: ps.name } : {}),
- ...(ps.description !== undefined ? { description: ps.description } : {}),
- ...(banner ? { bannerId: banner.id } : {}),
- });
-
- return await Channels.pack(channel.id, me);
-});
diff --git a/src/server/api/endpoints/charts/active-users.ts b/src/server/api/endpoints/charts/active-users.ts
deleted file mode 100644
index c4878f7d61..0000000000
--- a/src/server/api/endpoints/charts/active-users.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { activeUsersChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'users'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
- },
-
- res: convertLog(activeUsersChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await activeUsersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
-});
diff --git a/src/server/api/endpoints/charts/drive.ts b/src/server/api/endpoints/charts/drive.ts
deleted file mode 100644
index 07bff82cf4..0000000000
--- a/src/server/api/endpoints/charts/drive.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { driveChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'drive'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
- },
-
- res: convertLog(driveChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await driveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
-});
diff --git a/src/server/api/endpoints/charts/federation.ts b/src/server/api/endpoints/charts/federation.ts
deleted file mode 100644
index 9575f9a7b7..0000000000
--- a/src/server/api/endpoints/charts/federation.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { federationChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
- },
-
- res: convertLog(federationChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await federationChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
-});
diff --git a/src/server/api/endpoints/charts/hashtag.ts b/src/server/api/endpoints/charts/hashtag.ts
deleted file mode 100644
index 53dc61e51e..0000000000
--- a/src/server/api/endpoints/charts/hashtag.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { hashtagChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'hashtags'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
-
- tag: {
- validator: $.str,
- },
- },
-
- res: convertLog(hashtagChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.tag);
-});
diff --git a/src/server/api/endpoints/charts/instance.ts b/src/server/api/endpoints/charts/instance.ts
deleted file mode 100644
index 1835023188..0000000000
--- a/src/server/api/endpoints/charts/instance.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { instanceChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
-
- host: {
- validator: $.str,
- }
- },
-
- res: convertLog(instanceChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await instanceChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.host);
-});
diff --git a/src/server/api/endpoints/charts/network.ts b/src/server/api/endpoints/charts/network.ts
deleted file mode 100644
index b524df93be..0000000000
--- a/src/server/api/endpoints/charts/network.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { networkChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
- },
-
- res: convertLog(networkChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await networkChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
-});
diff --git a/src/server/api/endpoints/charts/notes.ts b/src/server/api/endpoints/charts/notes.ts
deleted file mode 100644
index 676f302939..0000000000
--- a/src/server/api/endpoints/charts/notes.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { notesChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'notes'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
- },
-
- res: convertLog(notesChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await notesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
-});
diff --git a/src/server/api/endpoints/charts/user/drive.ts b/src/server/api/endpoints/charts/user/drive.ts
deleted file mode 100644
index f2770e2df8..0000000000
--- a/src/server/api/endpoints/charts/user/drive.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { convertLog } from '@/services/chart/core';
-import { perUserDriveChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'drive', 'users'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
-
- userId: {
- validator: $.type(ID),
- }
- },
-
- res: convertLog(perUserDriveChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
-});
diff --git a/src/server/api/endpoints/charts/user/following.ts b/src/server/api/endpoints/charts/user/following.ts
deleted file mode 100644
index 8c97b63e89..0000000000
--- a/src/server/api/endpoints/charts/user/following.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { convertLog } from '@/services/chart/core';
-import { perUserFollowingChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'users', 'following'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
-
- userId: {
- validator: $.type(ID),
- }
- },
-
- res: convertLog(perUserFollowingChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
-});
diff --git a/src/server/api/endpoints/charts/user/notes.ts b/src/server/api/endpoints/charts/user/notes.ts
deleted file mode 100644
index 0d5f5a8b6a..0000000000
--- a/src/server/api/endpoints/charts/user/notes.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { convertLog } from '@/services/chart/core';
-import { perUserNotesChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'users', 'notes'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
-
- userId: {
- validator: $.type(ID),
- }
- },
-
- res: convertLog(perUserNotesChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
-});
diff --git a/src/server/api/endpoints/charts/user/reactions.ts b/src/server/api/endpoints/charts/user/reactions.ts
deleted file mode 100644
index 3cabe40d56..0000000000
--- a/src/server/api/endpoints/charts/user/reactions.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ID } from '@/misc/cafy-id';
-import { convertLog } from '@/services/chart/core';
-import { perUserReactionsChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'users', 'reactions'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
-
- userId: {
- validator: $.type(ID),
- }
- },
-
- res: convertLog(perUserReactionsChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
-});
diff --git a/src/server/api/endpoints/charts/users.ts b/src/server/api/endpoints/charts/users.ts
deleted file mode 100644
index deac89b59d..0000000000
--- a/src/server/api/endpoints/charts/users.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { convertLog } from '@/services/chart/core';
-import { usersChart } from '@/services/chart/index';
-
-export const meta = {
- tags: ['charts', 'users'],
-
- params: {
- span: {
- validator: $.str.or(['day', 'hour']),
- },
-
- limit: {
- validator: $.optional.num.range(1, 500),
- default: 30,
- },
-
- offset: {
- validator: $.optional.nullable.num,
- default: null,
- },
- },
-
- res: convertLog(usersChart.schema),
-};
-
-export default define(meta, async (ps) => {
- return await usersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
-});
diff --git a/src/server/api/endpoints/clips/add-note.ts b/src/server/api/endpoints/clips/add-note.ts
deleted file mode 100644
index 79d7b8adde..0000000000
--- a/src/server/api/endpoints/clips/add-note.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ClipNotes, Clips } from '@/models/index';
-import { ApiError } from '../../error';
-import { genId } from '@/misc/gen-id';
-import { getNote } from '../../common/getters';
-
-export const meta = {
- tags: ['account', 'notes', 'clips'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- clipId: {
- validator: $.type(ID),
- },
-
- noteId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchClip: {
- message: 'No such clip.',
- code: 'NO_SUCH_CLIP',
- id: 'd6e76cc0-a1b5-4c7c-a287-73fa9c716dcf'
- },
-
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b'
- },
-
- alreadyClipped: {
- message: 'The note has already been clipped.',
- code: 'ALREADY_CLIPPED',
- id: '734806c4-542c-463a-9311-15c512803965'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const clip = await Clips.findOne({
- id: ps.clipId,
- userId: user.id
- });
-
- if (clip == null) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const exist = await ClipNotes.findOne({
- noteId: note.id,
- clipId: clip.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyClipped);
- }
-
- await ClipNotes.insert({
- id: genId(),
- noteId: note.id,
- clipId: clip.id
- });
-});
diff --git a/src/server/api/endpoints/clips/create.ts b/src/server/api/endpoints/clips/create.ts
deleted file mode 100644
index 02d2773709..0000000000
--- a/src/server/api/endpoints/clips/create.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { genId } from '@/misc/gen-id';
-import { Clips } from '@/models/index';
-
-export const meta = {
- tags: ['clips'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- name: {
- validator: $.str.range(1, 100)
- },
-
- isPublic: {
- validator: $.optional.bool
- },
-
- description: {
- validator: $.optional.nullable.str.range(1, 2048)
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Clip'
- }
-};
-
-export default define(meta, async (ps, user) => {
- const clip = await Clips.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- name: ps.name,
- isPublic: ps.isPublic,
- description: ps.description,
- }).then(x => Clips.findOneOrFail(x.identifiers[0]));
-
- return await Clips.pack(clip);
-});
diff --git a/src/server/api/endpoints/clips/delete.ts b/src/server/api/endpoints/clips/delete.ts
deleted file mode 100644
index ca489af3bf..0000000000
--- a/src/server/api/endpoints/clips/delete.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Clips } from '@/models/index';
-
-export const meta = {
- tags: ['clips'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- clipId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchClip: {
- message: 'No such clip.',
- code: 'NO_SUCH_CLIP',
- id: '70ca08ba-6865-4630-b6fb-8494759aa754'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const clip = await Clips.findOne({
- id: ps.clipId,
- userId: user.id
- });
-
- if (clip == null) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- await Clips.delete(clip.id);
-});
diff --git a/src/server/api/endpoints/clips/list.ts b/src/server/api/endpoints/clips/list.ts
deleted file mode 100644
index 1f6db9b979..0000000000
--- a/src/server/api/endpoints/clips/list.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import define from '../../define';
-import { Clips } from '@/models/index';
-
-export const meta = {
- tags: ['clips', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Clip'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const clips = await Clips.find({
- userId: me.id,
- });
-
- return await Promise.all(clips.map(x => Clips.pack(x)));
-});
diff --git a/src/server/api/endpoints/clips/notes.ts b/src/server/api/endpoints/clips/notes.ts
deleted file mode 100644
index 5a9fed52fa..0000000000
--- a/src/server/api/endpoints/clips/notes.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ClipNotes, Clips, Notes } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { ApiError } from '../../error';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['account', 'notes', 'clips'],
-
- requireCredential: false as const,
-
- kind: 'read:account',
-
- params: {
- clipId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- errors: {
- noSuchClip: {
- message: 'No such clip.',
- code: 'NO_SUCH_CLIP',
- id: '1d7645e6-2b6d-4635-b0fe-fe22b0e72e00'
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const clip = await Clips.findOne({
- id: ps.clipId,
- });
-
- if (clip == null) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- if (!clip.isPublic && (user == null || (clip.userId !== user.id))) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- const clipQuery = ClipNotes.createQueryBuilder('joining')
- .select('joining.noteId')
- .where('joining.clipId = :clipId', { clipId: clip.id });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.id IN (${ clipQuery.getQuery() })`)
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .setParameters(clipQuery.getParameters());
-
- if (user) {
- generateVisibilityQuery(query, user);
- generateMutedUserQuery(query, user);
- generateBlockedUserQuery(query, user);
- }
-
- const notes = await query
- .take(ps.limit!)
- .getMany();
-
- return await Notes.packMany(notes, user);
-});
diff --git a/src/server/api/endpoints/clips/show.ts b/src/server/api/endpoints/clips/show.ts
deleted file mode 100644
index 8f245cd18e..0000000000
--- a/src/server/api/endpoints/clips/show.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Clips } from '@/models/index';
-
-export const meta = {
- tags: ['clips', 'account'],
-
- requireCredential: false as const,
-
- kind: 'read:account',
-
- params: {
- clipId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchClip: {
- message: 'No such clip.',
- code: 'NO_SUCH_CLIP',
- id: 'c3c5fe33-d62c-44d2-9ea5-d997703f5c20'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Clip'
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the clip
- const clip = await Clips.findOne({
- id: ps.clipId,
- });
-
- if (clip == null) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- if (!clip.isPublic && (me == null || (clip.userId !== me.id))) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- return await Clips.pack(clip);
-});
diff --git a/src/server/api/endpoints/clips/update.ts b/src/server/api/endpoints/clips/update.ts
deleted file mode 100644
index 7f645560bb..0000000000
--- a/src/server/api/endpoints/clips/update.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Clips } from '@/models/index';
-
-export const meta = {
- tags: ['clips'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- clipId: {
- validator: $.type(ID),
- },
-
- name: {
- validator: $.str.range(1, 100),
- },
-
- isPublic: {
- validator: $.optional.bool
- },
-
- description: {
- validator: $.optional.nullable.str.range(1, 2048)
- }
- },
-
- errors: {
- noSuchClip: {
- message: 'No such clip.',
- code: 'NO_SUCH_CLIP',
- id: 'b4d92d70-b216-46fa-9a3f-a8c811699257'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Clip'
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch the clip
- const clip = await Clips.findOne({
- id: ps.clipId,
- userId: user.id
- });
-
- if (clip == null) {
- throw new ApiError(meta.errors.noSuchClip);
- }
-
- await Clips.update(clip.id, {
- name: ps.name,
- description: ps.description,
- isPublic: ps.isPublic,
- });
-
- return await Clips.pack(clip.id);
-});
diff --git a/src/server/api/endpoints/drive.ts b/src/server/api/endpoints/drive.ts
deleted file mode 100644
index 2974ccfab9..0000000000
--- a/src/server/api/endpoints/drive.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import define from '../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- capacity: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- usage: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const instance = await fetchMeta(true);
-
- // Calculate drive usage
- const usage = await DriveFiles.calcDriveUsageOf(user.id);
-
- return {
- capacity: 1024 * 1024 * instance.localDriveCapacityMb,
- usage: usage
- };
-});
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
deleted file mode 100644
index 95435e1e43..0000000000
--- a/src/server/api/endpoints/drive/files.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { DriveFiles } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- folderId: {
- validator: $.optional.nullable.type(ID),
- default: null,
- },
-
- type: {
- validator: $.optional.nullable.str.match(/^[a-zA-Z\/\-*]+$/)
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
- .andWhere('file.userId = :userId', { userId: user.id });
-
- if (ps.folderId) {
- query.andWhere('file.folderId = :folderId', { folderId: ps.folderId });
- } else {
- query.andWhere('file.folderId IS NULL');
- }
-
- if (ps.type) {
- if (ps.type.endsWith('/*')) {
- query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' });
- } else {
- query.andWhere('file.type = :type', { type: ps.type });
- }
- }
-
- const files = await query.take(ps.limit!).getMany();
-
- return await DriveFiles.packMany(files, { detail: false, self: true });
-});
diff --git a/src/server/api/endpoints/drive/files/attached-notes.ts b/src/server/api/endpoints/drive/files/attached-notes.ts
deleted file mode 100644
index eec7d7877e..0000000000
--- a/src/server/api/endpoints/drive/files/attached-notes.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFiles, Notes } from '@/models/index';
-
-export const meta = {
- tags: ['drive', 'notes'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- fileId: {
- validator: $.type(ID),
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'c118ece3-2e4b-4296-99d1-51756e32d232',
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch file
- const file = await DriveFiles.findOne({
- id: ps.fileId,
- userId: user.id,
- });
-
- if (file == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
-
- const notes = await Notes.createQueryBuilder('note')
- .where(':file = ANY(note.fileIds)', { file: file.id })
- .getMany();
-
- return await Notes.packMany(notes, user, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/drive/files/check-existence.ts b/src/server/api/endpoints/drive/files/check-existence.ts
deleted file mode 100644
index 2c36078421..0000000000
--- a/src/server/api/endpoints/drive/files/check-existence.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- md5: {
- validator: $.str,
- }
- },
-
- res: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne({
- md5: ps.md5,
- userId: user.id,
- });
-
- return file != null;
-});
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
deleted file mode 100644
index 2abc104e6c..0000000000
--- a/src/server/api/endpoints/drive/files/create.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import * as ms from 'ms';
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import create from '@/services/drive/add-file';
-import define from '../../../define';
-import { apiLogger } from '../../../logger';
-import { ApiError } from '../../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- limit: {
- duration: ms('1hour'),
- max: 120
- },
-
- requireFile: true,
-
- kind: 'write:drive',
-
- params: {
- folderId: {
- validator: $.optional.nullable.type(ID),
- default: null,
- },
-
- name: {
- validator: $.optional.nullable.str,
- default: null,
- },
-
- isSensitive: {
- validator: $.optional.either($.bool, $.str),
- default: false,
- transform: (v: any): boolean => v === true || v === 'true',
- },
-
- force: {
- validator: $.optional.either($.bool, $.str),
- default: false,
- transform: (v: any): boolean => v === true || v === 'true',
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile',
- },
-
- errors: {
- invalidFileName: {
- message: 'Invalid file name.',
- code: 'INVALID_FILE_NAME',
- id: 'f449b209-0c60-4e51-84d5-29486263bfd4'
- }
- }
-};
-
-export default define(meta, async (ps, user, _, file, cleanup) => {
- // Get 'name' parameter
- let name = ps.name || file.originalname;
- if (name !== undefined && name !== null) {
- name = name.trim();
- if (name.length === 0) {
- name = null;
- } else if (name === 'blob') {
- name = null;
- } else if (!DriveFiles.validateFileName(name)) {
- throw new ApiError(meta.errors.invalidFileName);
- }
- } else {
- name = null;
- }
-
- try {
- // Create file
- const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive);
- return await DriveFiles.pack(driveFile, { self: true });
- } catch (e) {
- apiLogger.error(e);
- throw new ApiError();
- } finally {
- cleanup!();
- }
-});
diff --git a/src/server/api/endpoints/drive/files/delete.ts b/src/server/api/endpoints/drive/files/delete.ts
deleted file mode 100644
index 038325694d..0000000000
--- a/src/server/api/endpoints/drive/files/delete.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { deleteFile } from '@/services/drive/delete-file';
-import { publishDriveStream } from '@/services/stream';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'write:drive',
-
- params: {
- fileId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: '908939ec-e52b-4458-b395-1025195cea58'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: '5eb8d909-2540-4970-90b8-dd6f86088121'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
-
- if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- // Delete
- await deleteFile(file);
-
- // Publish fileDeleted event
- publishDriveStream(user.id, 'fileDeleted', file.id);
-});
diff --git a/src/server/api/endpoints/drive/files/find-by-hash.ts b/src/server/api/endpoints/drive/files/find-by-hash.ts
deleted file mode 100644
index 5fea7bbbb0..0000000000
--- a/src/server/api/endpoints/drive/files/find-by-hash.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- md5: {
- validator: $.str,
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const files = await DriveFiles.find({
- md5: ps.md5,
- userId: user.id,
- });
-
- return await DriveFiles.packMany(files, { self: true });
-});
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
deleted file mode 100644
index dd419f4c04..0000000000
--- a/src/server/api/endpoints/drive/files/find.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- tags: ['drive'],
-
- kind: 'read:drive',
-
- params: {
- name: {
- validator: $.str
- },
-
- folderId: {
- validator: $.optional.nullable.type(ID),
- default: null,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const files = await DriveFiles.find({
- name: ps.name,
- userId: user.id,
- folderId: ps.folderId
- });
-
- return await Promise.all(files.map(file => DriveFiles.pack(file, { self: true })));
-});
diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts
deleted file mode 100644
index a96ebaa123..0000000000
--- a/src/server/api/endpoints/drive/files/show.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFile } from '@/models/entities/drive-file';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- fileId: {
- validator: $.optional.type(ID),
- },
-
- url: {
- validator: $.optional.str,
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile',
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: '067bc436-2718-4795-b0fb-ecbe43949e31'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: '25b73c73-68b1-41d0-bad1-381cfdf6579f'
- },
-
- fileIdOrUrlRequired: {
- message: 'fileId or url required.',
- code: 'INVALID_PARAM',
- id: '89674805-722c-440c-8d88-5641830dc3e4'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- let file: DriveFile | undefined;
-
- if (ps.fileId) {
- file = await DriveFiles.findOne(ps.fileId);
- } else if (ps.url) {
- file = await DriveFiles.findOne({
- where: [{
- url: ps.url
- }, {
- webpublicUrl: ps.url
- }, {
- thumbnailUrl: ps.url
- }],
- });
- } else {
- throw new ApiError(meta.errors.fileIdOrUrlRequired);
- }
-
- if (file == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
-
- if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- return await DriveFiles.pack(file, {
- detail: true,
- withUser: true,
- self: true
- });
-});
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
deleted file mode 100644
index f277a9c3dc..0000000000
--- a/src/server/api/endpoints/drive/files/update.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishDriveStream } from '@/services/stream';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFiles, DriveFolders } from '@/models/index';
-import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'write:drive',
-
- params: {
- fileId: {
- validator: $.type(ID),
- },
-
- folderId: {
- validator: $.optional.nullable.type(ID),
- default: undefined as any,
- },
-
- name: {
- validator: $.optional.str.pipe(DriveFiles.validateFileName),
- default: undefined as any,
- },
-
- isSensitive: {
- validator: $.optional.bool,
- default: undefined as any,
- },
-
- comment: {
- validator: $.optional.nullable.str.max(DB_MAX_IMAGE_COMMENT_LENGTH),
- default: undefined as any,
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: '01a53b27-82fc-445b-a0c1-b558465a8ed2'
- },
-
- noSuchFolder: {
- message: 'No such folder.',
- code: 'NO_SUCH_FOLDER',
- id: 'ea8fb7a5-af77-4a08-b608-c0218176cd73'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile'
- }
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
-
- if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- if (ps.name) file.name = ps.name;
-
- if (ps.comment !== undefined) file.comment = ps.comment;
-
- if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive;
-
- if (ps.folderId !== undefined) {
- if (ps.folderId === null) {
- file.folderId = null;
- } else {
- const folder = await DriveFolders.findOne({
- id: ps.folderId,
- userId: user.id
- });
-
- if (folder == null) {
- throw new ApiError(meta.errors.noSuchFolder);
- }
-
- file.folderId = folder.id;
- }
- }
-
- await DriveFiles.update(file.id, {
- name: file.name,
- comment: file.comment,
- folderId: file.folderId,
- isSensitive: file.isSensitive
- });
-
- const fileObj = await DriveFiles.pack(file, { self: true });
-
- // Publish fileUpdated event
- publishDriveStream(user.id, 'fileUpdated', fileObj);
-
- return fileObj;
-});
diff --git a/src/server/api/endpoints/drive/files/upload-from-url.ts b/src/server/api/endpoints/drive/files/upload-from-url.ts
deleted file mode 100644
index 9f10a42d24..0000000000
--- a/src/server/api/endpoints/drive/files/upload-from-url.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import * as ms from 'ms';
-import uploadFromUrl from '@/services/drive/upload-from-url';
-import define from '../../../define';
-import { DriveFiles } from '@/models/index';
-import { publishMainStream } from '@/services/stream';
-import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits';
-
-export const meta = {
- tags: ['drive'],
-
- limit: {
- duration: ms('1hour'),
- max: 60
- },
-
- requireCredential: true as const,
-
- kind: 'write:drive',
-
- params: {
- url: {
- // TODO: Validate this url
- validator: $.str,
- },
-
- folderId: {
- validator: $.optional.nullable.type(ID),
- default: null,
- },
-
- isSensitive: {
- validator: $.optional.bool,
- default: false,
- },
-
- comment: {
- validator: $.optional.nullable.str.max(DB_MAX_IMAGE_COMMENT_LENGTH),
- default: null,
- },
-
- marker: {
- validator: $.optional.nullable.str,
- default: null,
- },
-
- force: {
- validator: $.optional.bool,
- default: false,
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force, false, ps.comment).then(file => {
- DriveFiles.pack(file, { self: true }).then(packedFile => {
- publishMainStream(user.id, 'urlUploadFinished', {
- marker: ps.marker,
- file: packedFile
- });
- });
- });
-});
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
deleted file mode 100644
index 6f16878b13..0000000000
--- a/src/server/api/endpoints/drive/folders.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { DriveFolders } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- folderId: {
- validator: $.optional.nullable.type(ID),
- default: null,
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFolder',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(DriveFolders.createQueryBuilder('folder'), ps.sinceId, ps.untilId)
- .andWhere('folder.userId = :userId', { userId: user.id });
-
- if (ps.folderId) {
- query.andWhere('folder.parentId = :parentId', { parentId: ps.folderId });
- } else {
- query.andWhere('folder.parentId IS NULL');
- }
-
- const folders = await query.take(ps.limit!).getMany();
-
- return await Promise.all(folders.map(folder => DriveFolders.pack(folder)));
-});
diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts
deleted file mode 100644
index 80f96bd641..0000000000
--- a/src/server/api/endpoints/drive/folders/create.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishDriveStream } from '@/services/stream';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFolders } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'write:drive',
-
- params: {
- name: {
- validator: $.optional.str.pipe(DriveFolders.validateFolderName),
- default: 'Untitled',
- },
-
- parentId: {
- validator: $.optional.nullable.type(ID),
- }
- },
-
- errors: {
- noSuchFolder: {
- message: 'No such folder.',
- code: 'NO_SUCH_FOLDER',
- id: '53326628-a00d-40a6-a3cd-8975105c0f95'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFolder'
- }
-};
-
-export default define(meta, async (ps, user) => {
- // If the parent folder is specified
- let parent = null;
- if (ps.parentId) {
- // Fetch parent folder
- parent = await DriveFolders.findOne({
- id: ps.parentId,
- userId: user.id
- });
-
- if (parent == null) {
- throw new ApiError(meta.errors.noSuchFolder);
- }
- }
-
- // Create folder
- const folder = await DriveFolders.insert({
- id: genId(),
- createdAt: new Date(),
- name: ps.name,
- parentId: parent !== null ? parent.id : null,
- userId: user.id
- }).then(x => DriveFolders.findOneOrFail(x.identifiers[0]));
-
- const folderObj = await DriveFolders.pack(folder);
-
- // Publish folderCreated event
- publishDriveStream(user.id, 'folderCreated', folderObj);
-
- return folderObj;
-});
diff --git a/src/server/api/endpoints/drive/folders/delete.ts b/src/server/api/endpoints/drive/folders/delete.ts
deleted file mode 100644
index 38b4aef103..0000000000
--- a/src/server/api/endpoints/drive/folders/delete.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { publishDriveStream } from '@/services/stream';
-import { ApiError } from '../../../error';
-import { DriveFolders, DriveFiles } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'write:drive',
-
- params: {
- folderId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchFolder: {
- message: 'No such folder.',
- code: 'NO_SUCH_FOLDER',
- id: '1069098f-c281-440f-b085-f9932edbe091'
- },
-
- hasChildFilesOrFolders: {
- message: 'This folder has child files or folders.',
- code: 'HAS_CHILD_FILES_OR_FOLDERS',
- id: 'b0fc8a17-963c-405d-bfbc-859a487295e1'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Get folder
- const folder = await DriveFolders.findOne({
- id: ps.folderId,
- userId: user.id
- });
-
- if (folder == null) {
- throw new ApiError(meta.errors.noSuchFolder);
- }
-
- const [childFoldersCount, childFilesCount] = await Promise.all([
- DriveFolders.count({ parentId: folder.id }),
- DriveFiles.count({ folderId: folder.id })
- ]);
-
- if (childFoldersCount !== 0 || childFilesCount !== 0) {
- throw new ApiError(meta.errors.hasChildFilesOrFolders);
- }
-
- await DriveFolders.delete(folder.id);
-
- // Publish folderCreated event
- publishDriveStream(user.id, 'folderDeleted', folder.id);
-});
diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts
deleted file mode 100644
index a6c5a49988..0000000000
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { DriveFolders } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- name: {
- validator: $.str
- },
-
- parentId: {
- validator: $.optional.nullable.type(ID),
- default: null,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFolder',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const folders = await DriveFolders.find({
- name: ps.name,
- userId: user.id,
- parentId: ps.parentId
- });
-
- return await Promise.all(folders.map(folder => DriveFolders.pack(folder)));
-});
diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts
deleted file mode 100644
index e907a24f05..0000000000
--- a/src/server/api/endpoints/drive/folders/show.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFolders } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- folderId: {
- validator: $.type(ID),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFolder',
- },
-
- errors: {
- noSuchFolder: {
- message: 'No such folder.',
- code: 'NO_SUCH_FOLDER',
- id: 'd74ab9eb-bb09-4bba-bf24-fb58f761e1e9'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Get folder
- const folder = await DriveFolders.findOne({
- id: ps.folderId,
- userId: user.id
- });
-
- if (folder == null) {
- throw new ApiError(meta.errors.noSuchFolder);
- }
-
- return await DriveFolders.pack(folder, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
deleted file mode 100644
index 612252e6df..0000000000
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishDriveStream } from '@/services/stream';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { DriveFolders } from '@/models/index';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'write:drive',
-
- params: {
- folderId: {
- validator: $.type(ID),
- },
-
- name: {
- validator: $.optional.str.pipe(DriveFolders.validateFolderName),
- },
-
- parentId: {
- validator: $.optional.nullable.type(ID),
- }
- },
-
- errors: {
- noSuchFolder: {
- message: 'No such folder.',
- code: 'NO_SUCH_FOLDER',
- id: 'f7974dac-2c0d-4a27-926e-23583b28e98e'
- },
-
- noSuchParentFolder: {
- message: 'No such parent folder.',
- code: 'NO_SUCH_PARENT_FOLDER',
- id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1'
- },
-
- recursiveNesting: {
- message: 'It can not be structured like nesting folders recursively.',
- code: 'NO_SUCH_PARENT_FOLDER',
- id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFolder'
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch folder
- const folder = await DriveFolders.findOne({
- id: ps.folderId,
- userId: user.id
- });
-
- if (folder == null) {
- throw new ApiError(meta.errors.noSuchFolder);
- }
-
- if (ps.name) folder.name = ps.name;
-
- if (ps.parentId !== undefined) {
- if (ps.parentId === folder.id) {
- throw new ApiError(meta.errors.recursiveNesting);
- } else if (ps.parentId === null) {
- folder.parentId = null;
- } else {
- // Get parent folder
- const parent = await DriveFolders.findOne({
- id: ps.parentId,
- userId: user.id
- });
-
- if (parent == null) {
- throw new ApiError(meta.errors.noSuchParentFolder);
- }
-
- // Check if the circular reference will occur
- async function checkCircle(folderId: any): Promise<boolean> {
- // Fetch folder
- const folder2 = await DriveFolders.findOne({
- id: folderId
- });
-
- if (folder2!.id === folder!.id) {
- return true;
- } else if (folder2!.parentId) {
- return await checkCircle(folder2!.parentId);
- } else {
- return false;
- }
- }
-
- if (parent.parentId !== null) {
- if (await checkCircle(parent.parentId)) {
- throw new ApiError(meta.errors.recursiveNesting);
- }
- }
-
- folder.parentId = parent.id;
- }
- }
-
- // Update
- DriveFolders.update(folder.id, {
- name: folder.name,
- parentId: folder.parentId
- });
-
- const folderObj = await DriveFolders.pack(folder);
-
- // Publish folderUpdated event
- publishDriveStream(user.id, 'folderUpdated', folderObj);
-
- return folderObj;
-});
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
deleted file mode 100644
index 141e02f748..0000000000
--- a/src/server/api/endpoints/drive/stream.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { DriveFiles } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['drive'],
-
- requireCredential: true as const,
-
- kind: 'read:drive',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- type: {
- validator: $.optional.str.match(/^[a-zA-Z\/\-*]+$/)
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'DriveFile',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
- .andWhere('file.userId = :userId', { userId: user.id });
-
- if (ps.type) {
- if (ps.type.endsWith('/*')) {
- query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' });
- } else {
- query.andWhere('file.type = :type', { type: ps.type });
- }
- }
-
- const files = await query.take(ps.limit!).getMany();
-
- return await DriveFiles.packMany(files, { detail: false, self: true });
-});
diff --git a/src/server/api/endpoints/email-address/available.ts b/src/server/api/endpoints/email-address/available.ts
deleted file mode 100644
index f6fccd59b0..0000000000
--- a/src/server/api/endpoints/email-address/available.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { validateEmailForAccount } from '@/services/validate-email-for-account';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- emailAddress: {
- validator: $.str
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- available: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- reason: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- }
- }
-};
-
-export default define(meta, async (ps) => {
- return await validateEmailForAccount(ps.emailAddress);
-});
diff --git a/src/server/api/endpoints/endpoint.ts b/src/server/api/endpoints/endpoint.ts
deleted file mode 100644
index 1a04d8bee8..0000000000
--- a/src/server/api/endpoints/endpoint.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import $ from 'cafy';
-import define from '../define';
-import endpoints from '../endpoints';
-
-export const meta = {
- requireCredential: false as const,
-
- tags: ['meta'],
-
- params: {
- endpoint: {
- validator: $.str,
- }
- },
-};
-
-export default define(meta, async (ps) => {
- const ep = endpoints.find(x => x.name === ps.endpoint);
- if (ep == null) return null;
- return {
- params: Object.entries(ep.meta.params || {}).map(([k, v]) => ({
- name: k,
- type: v.validator.name === 'ID' ? 'String' : v.validator.name
- }))
- };
-});
diff --git a/src/server/api/endpoints/endpoints.ts b/src/server/api/endpoints/endpoints.ts
deleted file mode 100644
index f7b9757d8d..0000000000
--- a/src/server/api/endpoints/endpoints.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import define from '../define';
-import endpoints from '../endpoints';
-
-export const meta = {
- requireCredential: false as const,
-
- tags: ['meta'],
-
- params: {
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- example: [
- 'admin/abuse-user-reports',
- 'admin/accounts/create',
- 'admin/announcements/create',
- '...'
- ]
- }
-};
-
-export default define(meta, async () => {
- return endpoints.map(x => x.name);
-});
diff --git a/src/server/api/endpoints/federation/dns.ts b/src/server/api/endpoints/federation/dns.ts
deleted file mode 100644
index 7ba566301a..0000000000
--- a/src/server/api/endpoints/federation/dns.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { promises as dns } from 'dns';
-import $ from 'cafy';
-import define from '../../define';
-import { Instances } from '@/models/index';
-import { toPuny } from '@/misc/convert-host';
-
-const resolver = new dns.Resolver();
-resolver.setServers(['1.1.1.1']);
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: false as const,
-
- params: {
- host: {
- validator: $.str
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const instance = await Instances.findOneOrFail({ host: toPuny(ps.host) });
-
- const [
- resolved4,
- resolved6,
- resolvedCname,
- resolvedTxt,
- ] = await Promise.all([
- resolver.resolve4(instance.host).catch(() => []),
- resolver.resolve6(instance.host).catch(() => []),
- resolver.resolveCname(instance.host).catch(() => []),
- resolver.resolveTxt(instance.host).catch(() => []),
- ]);
-
- return {
- a: resolved4,
- aaaa: resolved6,
- cname: resolvedCname,
- txt: resolvedTxt,
- };
-});
diff --git a/src/server/api/endpoints/federation/followers.ts b/src/server/api/endpoints/federation/followers.ts
deleted file mode 100644
index 655e7b7b9a..0000000000
--- a/src/server/api/endpoints/federation/followers.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Followings } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: false as const,
-
- params: {
- host: {
- validator: $.str
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Following',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId)
- .andWhere(`following.followeeHost = :host`, { host: ps.host });
-
- const followings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Followings.packMany(followings, me, { populateFollowee: true });
-});
diff --git a/src/server/api/endpoints/federation/following.ts b/src/server/api/endpoints/federation/following.ts
deleted file mode 100644
index 5b283581a6..0000000000
--- a/src/server/api/endpoints/federation/following.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Followings } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: false as const,
-
- params: {
- host: {
- validator: $.str
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Following',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId)
- .andWhere(`following.followerHost = :host`, { host: ps.host });
-
- const followings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Followings.packMany(followings, me, { populateFollowee: true });
-});
diff --git a/src/server/api/endpoints/federation/instances.ts b/src/server/api/endpoints/federation/instances.ts
deleted file mode 100644
index cf5e44ebd5..0000000000
--- a/src/server/api/endpoints/federation/instances.ts
+++ /dev/null
@@ -1,149 +0,0 @@
-import $ from 'cafy';
-import config from '@/config/index';
-import define from '../../define';
-import { Instances } from '@/models/index';
-import { fetchMeta } from '@/misc/fetch-meta';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: false as const,
-
- params: {
- host: {
- validator: $.optional.nullable.str,
- },
-
- blocked: {
- validator: $.optional.nullable.bool,
- },
-
- notResponding: {
- validator: $.optional.nullable.bool,
- },
-
- suspended: {
- validator: $.optional.nullable.bool,
- },
-
- federating: {
- validator: $.optional.nullable.bool,
- },
-
- subscribing: {
- validator: $.optional.nullable.bool,
- },
-
- publishing: {
- validator: $.optional.nullable.bool,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 30
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- },
-
- sort: {
- validator: $.optional.str,
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'FederationInstance'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const query = Instances.createQueryBuilder('instance');
-
- switch (ps.sort) {
- case '+pubSub': query.orderBy('instance.followingCount', 'DESC').orderBy('instance.followersCount', 'DESC'); break;
- case '-pubSub': query.orderBy('instance.followingCount', 'ASC').orderBy('instance.followersCount', 'ASC'); break;
- case '+notes': query.orderBy('instance.notesCount', 'DESC'); break;
- case '-notes': query.orderBy('instance.notesCount', 'ASC'); break;
- case '+users': query.orderBy('instance.usersCount', 'DESC'); break;
- case '-users': query.orderBy('instance.usersCount', 'ASC'); break;
- case '+following': query.orderBy('instance.followingCount', 'DESC'); break;
- case '-following': query.orderBy('instance.followingCount', 'ASC'); break;
- case '+followers': query.orderBy('instance.followersCount', 'DESC'); break;
- case '-followers': query.orderBy('instance.followersCount', 'ASC'); break;
- case '+caughtAt': query.orderBy('instance.caughtAt', 'DESC'); break;
- case '-caughtAt': query.orderBy('instance.caughtAt', 'ASC'); break;
- case '+lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'DESC'); break;
- case '-lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'ASC'); break;
- case '+driveUsage': query.orderBy('instance.driveUsage', 'DESC'); break;
- case '-driveUsage': query.orderBy('instance.driveUsage', 'ASC'); break;
- case '+driveFiles': query.orderBy('instance.driveFiles', 'DESC'); break;
- case '-driveFiles': query.orderBy('instance.driveFiles', 'ASC'); break;
-
- default: query.orderBy('instance.id', 'DESC'); break;
- }
-
- if (typeof ps.blocked === 'boolean') {
- const meta = await fetchMeta(true);
- if (ps.blocked) {
- query.andWhere('instance.host IN (:...blocks)', { blocks: meta.blockedHosts });
- } else {
- query.andWhere('instance.host NOT IN (:...blocks)', { blocks: meta.blockedHosts });
- }
- }
-
- if (typeof ps.notResponding === 'boolean') {
- if (ps.notResponding) {
- query.andWhere('instance.isNotResponding = TRUE');
- } else {
- query.andWhere('instance.isNotResponding = FALSE');
- }
- }
-
- if (typeof ps.suspended === 'boolean') {
- if (ps.suspended) {
- query.andWhere('instance.isSuspended = TRUE');
- } else {
- query.andWhere('instance.isSuspended = FALSE');
- }
- }
-
- if (typeof ps.federating === 'boolean') {
- if (ps.federating) {
- query.andWhere('((instance.followingCount > 0) OR (instance.followersCount > 0))');
- } else {
- query.andWhere('((instance.followingCount = 0) AND (instance.followersCount = 0))');
- }
- }
-
- if (typeof ps.subscribing === 'boolean') {
- if (ps.subscribing) {
- query.andWhere('instance.followersCount > 0');
- } else {
- query.andWhere('instance.followersCount = 0');
- }
- }
-
- if (typeof ps.publishing === 'boolean') {
- if (ps.publishing) {
- query.andWhere('instance.followingCount > 0');
- } else {
- query.andWhere('instance.followingCount = 0');
- }
- }
-
- if (ps.host) {
- query.andWhere('instance.host like :host', { host: '%' + ps.host.toLowerCase() + '%' });
- }
-
- const instances = await query.take(ps.limit!).skip(ps.offset).getMany();
-
- return instances;
-});
diff --git a/src/server/api/endpoints/federation/show-instance.ts b/src/server/api/endpoints/federation/show-instance.ts
deleted file mode 100644
index f8352aefb3..0000000000
--- a/src/server/api/endpoints/federation/show-instance.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Instances } from '@/models/index';
-import { toPuny } from '@/misc/convert-host';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: false as const,
-
- params: {
- host: {
- validator: $.str
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'FederationInstance'
- }
-};
-
-export default define(meta, async (ps, me) => {
- const instance = await Instances
- .findOne({ host: toPuny(ps.host) });
-
- return instance;
-});
diff --git a/src/server/api/endpoints/federation/update-remote-user.ts b/src/server/api/endpoints/federation/update-remote-user.ts
deleted file mode 100644
index 580c3cb3d9..0000000000
--- a/src/server/api/endpoints/federation/update-remote-user.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { getRemoteUser } from '../../common/getters';
-import { updatePerson } from '@/remote/activitypub/models/person';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: true as const,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps) => {
- const user = await getRemoteUser(ps.userId);
- await updatePerson(user.uri!);
-});
diff --git a/src/server/api/endpoints/federation/users.ts b/src/server/api/endpoints/federation/users.ts
deleted file mode 100644
index 0e35df3e1c..0000000000
--- a/src/server/api/endpoints/federation/users.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Users } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['federation'],
-
- requireCredential: false as const,
-
- params: {
- host: {
- validator: $.str
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Users.createQueryBuilder('user'), ps.sinceId, ps.untilId)
- .andWhere(`user.host = :host`, { host: ps.host });
-
- const users = await query
- .take(ps.limit!)
- .getMany();
-
- return await Users.packMany(users, me, { detail: true });
-});
diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts
deleted file mode 100644
index ba9ca1092d..0000000000
--- a/src/server/api/endpoints/following/create.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import * as ms from 'ms';
-import create from '@/services/following/create';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { Followings, Users } from '@/models/index';
-
-export const meta = {
- tags: ['following', 'users'],
-
- limit: {
- duration: ms('1hour'),
- max: 100
- },
-
- requireCredential: true as const,
-
- kind: 'write:following',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'
- },
-
- followeeIsYourself: {
- message: 'Followee is yourself.',
- code: 'FOLLOWEE_IS_YOURSELF',
- id: '26fbe7bb-a331-4857-af17-205b426669a9'
- },
-
- alreadyFollowing: {
- message: 'You are already following that user.',
- code: 'ALREADY_FOLLOWING',
- id: '35387507-38c7-4cb9-9197-300b93783fa0'
- },
-
- blocking: {
- message: 'You are blocking that user.',
- code: 'BLOCKING',
- id: '4e2206ec-aa4f-4960-b865-6c23ac38e2d9'
- },
-
- blocked: {
- message: 'You are blocked by that user.',
- code: 'BLOCKED',
- id: 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, user) => {
- const follower = user;
-
- // 自分自身
- if (user.id === ps.userId) {
- throw new ApiError(meta.errors.followeeIsYourself);
- }
-
- // Get followee
- const followee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check if already following
- const exist = await Followings.findOne({
- followerId: follower.id,
- followeeId: followee.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyFollowing);
- }
-
- try {
- await create(follower, followee);
- } catch (e) {
- if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking);
- if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError(meta.errors.blocked);
- throw e;
- }
-
- return await Users.pack(followee.id, user);
-});
diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts
deleted file mode 100644
index 0b0158b86e..0000000000
--- a/src/server/api/endpoints/following/delete.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import * as ms from 'ms';
-import deleteFollowing from '@/services/following/delete';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { Followings, Users } from '@/models/index';
-
-export const meta = {
- tags: ['following', 'users'],
-
- limit: {
- duration: ms('1hour'),
- max: 100
- },
-
- requireCredential: true as const,
-
- kind: 'write:following',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8'
- },
-
- followeeIsYourself: {
- message: 'Followee is yourself.',
- code: 'FOLLOWEE_IS_YOURSELF',
- id: 'd9e400b9-36b0-4808-b1d8-79e707f1296c'
- },
-
- notFollowing: {
- message: 'You are not following that user.',
- code: 'NOT_FOLLOWING',
- id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, user) => {
- const follower = user;
-
- // Check if the followee is yourself
- if (user.id === ps.userId) {
- throw new ApiError(meta.errors.followeeIsYourself);
- }
-
- // Get followee
- const followee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check not following
- const exist = await Followings.findOne({
- followerId: follower.id,
- followeeId: followee.id
- });
-
- if (exist == null) {
- throw new ApiError(meta.errors.notFollowing);
- }
-
- await deleteFollowing(follower, followee);
-
- return await Users.pack(followee.id, user);
-});
diff --git a/src/server/api/endpoints/following/requests/accept.ts b/src/server/api/endpoints/following/requests/accept.ts
deleted file mode 100644
index af39ea1d90..0000000000
--- a/src/server/api/endpoints/following/requests/accept.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import acceptFollowRequest from '@/services/following/requests/accept';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-
-export const meta = {
- tags: ['following', 'account'],
-
- requireCredential: true as const,
-
- kind: 'write:following',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '66ce1645-d66c-46bb-8b79-96739af885bd'
- },
- noFollowRequest: {
- message: 'No follow request.',
- code: 'NO_FOLLOW_REQUEST',
- id: 'bcde4f8b-0913-4614-8881-614e522fb041'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch follower
- const follower = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- await acceptFollowRequest(user, follower).catch(e => {
- if (e.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError(meta.errors.noFollowRequest);
- throw e;
- });
-
- return;
-});
diff --git a/src/server/api/endpoints/following/requests/cancel.ts b/src/server/api/endpoints/following/requests/cancel.ts
deleted file mode 100644
index b69c9d2fe1..0000000000
--- a/src/server/api/endpoints/following/requests/cancel.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import cancelFollowRequest from '@/services/following/requests/cancel';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['following', 'account'],
-
- requireCredential: true as const,
-
- kind: 'write:following',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab'
- },
-
- followRequestNotFound: {
- message: 'Follow request not found.',
- code: 'FOLLOW_REQUEST_NOT_FOUND',
- id: '089b125b-d338-482a-9a09-e2622ac9f8d4'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch followee
- const followee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- try {
- await cancelFollowRequest(followee, user);
- } catch (e) {
- if (e.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError(meta.errors.followRequestNotFound);
- throw e;
- }
-
- return await Users.pack(followee.id, user);
-});
diff --git a/src/server/api/endpoints/following/requests/list.ts b/src/server/api/endpoints/following/requests/list.ts
deleted file mode 100644
index 84440ccac7..0000000000
--- a/src/server/api/endpoints/following/requests/list.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import define from '../../../define';
-import { FollowRequests } from '@/models/index';
-
-export const meta = {
- tags: ['following', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:following',
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- follower: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- },
- followee: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const reqs = await FollowRequests.find({
- followeeId: user.id
- });
-
- return await Promise.all(reqs.map(req => FollowRequests.pack(req)));
-});
diff --git a/src/server/api/endpoints/following/requests/reject.ts b/src/server/api/endpoints/following/requests/reject.ts
deleted file mode 100644
index 620324361f..0000000000
--- a/src/server/api/endpoints/following/requests/reject.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import rejectFollowRequest from '@/services/following/requests/reject';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-
-export const meta = {
- tags: ['following', 'account'],
-
- requireCredential: true as const,
-
- kind: 'write:following',
-
- params: {
- userId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: 'abc2ffa6-25b2-4380-ba99-321ff3a94555'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch follower
- const follower = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- await rejectFollowRequest(user, follower);
-
- return;
-});
diff --git a/src/server/api/endpoints/gallery/featured.ts b/src/server/api/endpoints/gallery/featured.ts
deleted file mode 100644
index 30ef8cedec..0000000000
--- a/src/server/api/endpoints/gallery/featured.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import define from '../../define';
-import { GalleryPosts } from '@/models/index';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: false as const,
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = GalleryPosts.createQueryBuilder('post')
- .andWhere('post.createdAt > :date', { date: new Date(Date.now() - (1000 * 60 * 60 * 24 * 3)) })
- .andWhere('post.likedCount > 0')
- .orderBy('post.likedCount', 'DESC');
-
- const posts = await query.take(10).getMany();
-
- return await GalleryPosts.packMany(posts, me);
-});
diff --git a/src/server/api/endpoints/gallery/popular.ts b/src/server/api/endpoints/gallery/popular.ts
deleted file mode 100644
index 18449b9654..0000000000
--- a/src/server/api/endpoints/gallery/popular.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import define from '../../define';
-import { GalleryPosts } from '@/models/index';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: false as const,
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = GalleryPosts.createQueryBuilder('post')
- .andWhere('post.likedCount > 0')
- .orderBy('post.likedCount', 'DESC');
-
- const posts = await query.take(10).getMany();
-
- return await GalleryPosts.packMany(posts, me);
-});
diff --git a/src/server/api/endpoints/gallery/posts.ts b/src/server/api/endpoints/gallery/posts.ts
deleted file mode 100644
index 53d3236d2d..0000000000
--- a/src/server/api/endpoints/gallery/posts.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { GalleryPosts } from '@/models/index';
-
-export const meta = {
- tags: ['gallery'],
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
- .innerJoinAndSelect('post.user', 'user');
-
- const posts = await query.take(ps.limit!).getMany();
-
- return await GalleryPosts.packMany(posts, me);
-});
diff --git a/src/server/api/endpoints/gallery/posts/create.ts b/src/server/api/endpoints/gallery/posts/create.ts
deleted file mode 100644
index 38b487e6ea..0000000000
--- a/src/server/api/endpoints/gallery/posts/create.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import $ from 'cafy';
-import * as ms from 'ms';
-import define from '../../../define';
-import { ID } from '../../../../../misc/cafy-id';
-import { DriveFiles, GalleryPosts } from '@/models/index';
-import { genId } from '../../../../../misc/gen-id';
-import { GalleryPost } from '@/models/entities/gallery-post';
-import { ApiError } from '../../../error';
-import { DriveFile } from '@/models/entities/drive-file';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: true as const,
-
- kind: 'write:gallery',
-
- limit: {
- duration: ms('1hour'),
- max: 300
- },
-
- params: {
- title: {
- validator: $.str.min(1),
- },
-
- description: {
- validator: $.optional.nullable.str,
- },
-
- fileIds: {
- validator: $.arr($.type(ID)).unique().range(1, 32),
- },
-
- isSensitive: {
- validator: $.optional.bool,
- default: false,
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost',
- },
-
- errors: {
-
- }
-};
-
-export default define(meta, async (ps, user) => {
- const files = (await Promise.all(ps.fileIds.map(fileId =>
- DriveFiles.findOne({
- id: fileId,
- userId: user.id
- })
- ))).filter((file): file is DriveFile => file != null);
-
- if (files.length === 0) {
- throw new Error();
- }
-
- const post = await GalleryPosts.insert(new GalleryPost({
- id: genId(),
- createdAt: new Date(),
- updatedAt: new Date(),
- title: ps.title,
- description: ps.description,
- userId: user.id,
- isSensitive: ps.isSensitive,
- fileIds: files.map(file => file.id)
- })).then(x => GalleryPosts.findOneOrFail(x.identifiers[0]));
-
- return await GalleryPosts.pack(post, user);
-});
diff --git a/src/server/api/endpoints/gallery/posts/delete.ts b/src/server/api/endpoints/gallery/posts/delete.ts
deleted file mode 100644
index e5b7c07f2f..0000000000
--- a/src/server/api/endpoints/gallery/posts/delete.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { GalleryPosts } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: true as const,
-
- kind: 'write:gallery',
-
- params: {
- postId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchPost: {
- message: 'No such post.',
- code: 'NO_SUCH_POST',
- id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const post = await GalleryPosts.findOne({
- id: ps.postId,
- userId: user.id,
- });
-
- if (post == null) {
- throw new ApiError(meta.errors.noSuchPost);
- }
-
- await GalleryPosts.delete(post.id);
-});
diff --git a/src/server/api/endpoints/gallery/posts/like.ts b/src/server/api/endpoints/gallery/posts/like.ts
deleted file mode 100644
index 81a25c0ad1..0000000000
--- a/src/server/api/endpoints/gallery/posts/like.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { GalleryPosts, GalleryLikes } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: true as const,
-
- kind: 'write:gallery-likes',
-
- params: {
- postId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchPost: {
- message: 'No such post.',
- code: 'NO_SUCH_POST',
- id: '56c06af3-1287-442f-9701-c93f7c4a62ff'
- },
-
- yourPost: {
- message: 'You cannot like your post.',
- code: 'YOUR_POST',
- id: 'f78f1511-5ebc-4478-a888-1198d752da68'
- },
-
- alreadyLiked: {
- message: 'The post has already been liked.',
- code: 'ALREADY_LIKED',
- id: '40e9ed56-a59c-473a-bf3f-f289c54fb5a7'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const post = await GalleryPosts.findOne(ps.postId);
- if (post == null) {
- throw new ApiError(meta.errors.noSuchPost);
- }
-
- if (post.userId === user.id) {
- throw new ApiError(meta.errors.yourPost);
- }
-
- // if already liked
- const exist = await GalleryLikes.findOne({
- postId: post.id,
- userId: user.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyLiked);
- }
-
- // Create like
- await GalleryLikes.insert({
- id: genId(),
- createdAt: new Date(),
- postId: post.id,
- userId: user.id
- });
-
- GalleryPosts.increment({ id: post.id }, 'likedCount', 1);
-});
diff --git a/src/server/api/endpoints/gallery/posts/show.ts b/src/server/api/endpoints/gallery/posts/show.ts
deleted file mode 100644
index 93852a5f8d..0000000000
--- a/src/server/api/endpoints/gallery/posts/show.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { GalleryPosts } from '@/models/index';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: false as const,
-
- params: {
- postId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchPost: {
- message: 'No such post.',
- code: 'NO_SUCH_POST',
- id: '1137bf14-c5b0-4604-85bb-5b5371b1cd45'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost'
- }
-};
-
-export default define(meta, async (ps, me) => {
- const post = await GalleryPosts.findOne({
- id: ps.postId,
- });
-
- if (post == null) {
- throw new ApiError(meta.errors.noSuchPost);
- }
-
- return await GalleryPosts.pack(post, me);
-});
diff --git a/src/server/api/endpoints/gallery/posts/unlike.ts b/src/server/api/endpoints/gallery/posts/unlike.ts
deleted file mode 100644
index 0347cdf79e..0000000000
--- a/src/server/api/endpoints/gallery/posts/unlike.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { GalleryPosts, GalleryLikes } from '@/models/index';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: true as const,
-
- kind: 'write:gallery-likes',
-
- params: {
- postId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchPost: {
- message: 'No such post.',
- code: 'NO_SUCH_POST',
- id: 'c32e6dd0-b555-4413-925e-b3757d19ed84'
- },
-
- notLiked: {
- message: 'You have not liked that post.',
- code: 'NOT_LIKED',
- id: 'e3e8e06e-be37-41f7-a5b4-87a8250288f0'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const post = await GalleryPosts.findOne(ps.postId);
- if (post == null) {
- throw new ApiError(meta.errors.noSuchPost);
- }
-
- const exist = await GalleryLikes.findOne({
- postId: post.id,
- userId: user.id
- });
-
- if (exist == null) {
- throw new ApiError(meta.errors.notLiked);
- }
-
- // Delete like
- await GalleryLikes.delete(exist.id);
-
- GalleryPosts.decrement({ id: post.id }, 'likedCount', 1);
-});
diff --git a/src/server/api/endpoints/gallery/posts/update.ts b/src/server/api/endpoints/gallery/posts/update.ts
deleted file mode 100644
index 54eea130d3..0000000000
--- a/src/server/api/endpoints/gallery/posts/update.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import $ from 'cafy';
-import * as ms from 'ms';
-import define from '../../../define';
-import { ID } from '../../../../../misc/cafy-id';
-import { DriveFiles, GalleryPosts } from '@/models/index';
-import { GalleryPost } from '@/models/entities/gallery-post';
-import { ApiError } from '../../../error';
-import { DriveFile } from '@/models/entities/drive-file';
-
-export const meta = {
- tags: ['gallery'],
-
- requireCredential: true as const,
-
- kind: 'write:gallery',
-
- limit: {
- duration: ms('1hour'),
- max: 300
- },
-
- params: {
- postId: {
- validator: $.type(ID),
- },
-
- title: {
- validator: $.str.min(1),
- },
-
- description: {
- validator: $.optional.nullable.str,
- },
-
- fileIds: {
- validator: $.arr($.type(ID)).unique().range(1, 32),
- },
-
- isSensitive: {
- validator: $.optional.bool,
- default: false,
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost',
- },
-
- errors: {
-
- }
-};
-
-export default define(meta, async (ps, user) => {
- const files = (await Promise.all(ps.fileIds.map(fileId =>
- DriveFiles.findOne({
- id: fileId,
- userId: user.id
- })
- ))).filter((file): file is DriveFile => file != null);
-
- if (files.length === 0) {
- throw new Error();
- }
-
- await GalleryPosts.update({
- id: ps.postId,
- userId: user.id,
- }, {
- updatedAt: new Date(),
- title: ps.title,
- description: ps.description,
- isSensitive: ps.isSensitive,
- fileIds: files.map(file => file.id)
- });
-
- const post = await GalleryPosts.findOneOrFail(ps.postId);
-
- return await GalleryPosts.pack(post, user);
-});
diff --git a/src/server/api/endpoints/games/reversi/games.ts b/src/server/api/endpoints/games/reversi/games.ts
deleted file mode 100644
index 4db9ecb69f..0000000000
--- a/src/server/api/endpoints/games/reversi/games.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ReversiGames } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-import { Brackets } from 'typeorm';
-
-export const meta = {
- tags: ['games'],
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- my: {
- validator: $.optional.bool,
- default: false
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time'
- },
- startedAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time'
- },
- isStarted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isEnded: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- form1: {
- type: 'any' as const,
- optional: false as const, nullable: true as const
- },
- form2: {
- type: 'any' as const,
- optional: false as const, nullable: true as const
- },
- user1Accepted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- default: false
- },
- user2Accepted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- default: false
- },
- user1Id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- user2Id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- user1: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- },
- user2: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- },
- winnerId: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'id'
- },
- winner: {
- type: 'object' as const,
- optional: false as const, nullable: true as const,
- ref: 'User'
- },
- surrendered: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'id'
- },
- black: {
- type: 'number' as const,
- optional: false as const, nullable: true as const
- },
- bw: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- isLlotheo: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- canPutEverywhere: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- loopedBoard: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(ReversiGames.createQueryBuilder('game'), ps.sinceId, ps.untilId)
- .andWhere('game.isStarted = TRUE');
-
- if (ps.my && user) {
- query.andWhere(new Brackets(qb => { qb
- .where('game.user1Id = :userId', { userId: user.id })
- .orWhere('game.user2Id = :userId', { userId: user.id });
- }));
- }
-
- // Fetch games
- const games = await query.take(ps.limit!).getMany();
-
- return await Promise.all(games.map((g) => ReversiGames.pack(g, user, {
- detail: false
- })));
-});
diff --git a/src/server/api/endpoints/games/reversi/games/show.ts b/src/server/api/endpoints/games/reversi/games/show.ts
deleted file mode 100644
index 93afffdb1f..0000000000
--- a/src/server/api/endpoints/games/reversi/games/show.ts
+++ /dev/null
@@ -1,168 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import Reversi from '../../../../../../games/reversi/core';
-import define from '../../../../define';
-import { ApiError } from '../../../../error';
-import { ReversiGames } from '@/models/index';
-
-export const meta = {
- tags: ['games'],
-
- params: {
- gameId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchGame: {
- message: 'No such game.',
- code: 'NO_SUCH_GAME',
- id: 'f13a03db-fae1-46c9-87f3-43c8165419e1'
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time'
- },
- startedAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time'
- },
- isStarted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isEnded: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- form1: {
- type: 'any' as const,
- optional: false as const, nullable: true as const
- },
- form2: {
- type: 'any' as const,
- optional: false as const, nullable: true as const
- },
- user1Accepted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- default: false
- },
- user2Accepted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- default: false
- },
- user1Id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- user2Id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- user1: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- },
- user2: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- },
- winnerId: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'id'
- },
- winner: {
- type: 'object' as const,
- optional: false as const, nullable: true as const,
- ref: 'User'
- },
- surrendered: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- format: 'id'
- },
- black: {
- type: 'number' as const,
- optional: false as const, nullable: true as const
- },
- bw: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- isLlotheo: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- canPutEverywhere: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- loopedBoard: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- board: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'any' as const,
- optional: false as const, nullable: false as const
- }
- },
- turn: {
- type: 'any' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const game = await ReversiGames.findOne(ps.gameId);
-
- if (game == null) {
- throw new ApiError(meta.errors.noSuchGame);
- }
-
- const o = new Reversi(game.map, {
- isLlotheo: game.isLlotheo,
- canPutEverywhere: game.canPutEverywhere,
- loopedBoard: game.loopedBoard
- });
-
- for (const log of game.logs) {
- o.put(log.color, log.pos);
- }
-
- const packed = await ReversiGames.pack(game, user);
-
- return Object.assign({
- board: o.board,
- turn: o.turn
- }, packed);
-});
diff --git a/src/server/api/endpoints/games/reversi/games/surrender.ts b/src/server/api/endpoints/games/reversi/games/surrender.ts
deleted file mode 100644
index 00d58b19e3..0000000000
--- a/src/server/api/endpoints/games/reversi/games/surrender.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishReversiGameStream } from '@/services/stream';
-import define from '../../../../define';
-import { ApiError } from '../../../../error';
-import { ReversiGames } from '@/models/index';
-
-export const meta = {
- tags: ['games'],
-
- requireCredential: true as const,
-
- params: {
- gameId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchGame: {
- message: 'No such game.',
- code: 'NO_SUCH_GAME',
- id: 'ace0b11f-e0a6-4076-a30d-e8284c81b2df'
- },
-
- alreadyEnded: {
- message: 'That game has already ended.',
- code: 'ALREADY_ENDED',
- id: '6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: '6e04164b-a992-4c93-8489-2123069973e1'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const game = await ReversiGames.findOne(ps.gameId);
-
- if (game == null) {
- throw new ApiError(meta.errors.noSuchGame);
- }
-
- if (game.isEnded) {
- throw new ApiError(meta.errors.alreadyEnded);
- }
-
- if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- const winnerId = game.user1Id === user.id ? game.user2Id : game.user1Id;
-
- await ReversiGames.update(game.id, {
- surrendered: user.id,
- isEnded: true,
- winnerId: winnerId
- });
-
- publishReversiGameStream(game.id, 'ended', {
- winnerId: winnerId,
- game: await ReversiGames.pack(game.id, user)
- });
-});
diff --git a/src/server/api/endpoints/games/reversi/invitations.ts b/src/server/api/endpoints/games/reversi/invitations.ts
deleted file mode 100644
index c8629377b2..0000000000
--- a/src/server/api/endpoints/games/reversi/invitations.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import define from '../../../define';
-import { ReversiMatchings } from '@/models/index';
-
-export const meta = {
- tags: ['games'],
-
- requireCredential: true as const,
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- createdAt: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'date-time'
- },
- parentId: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- parent: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- },
- childId: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- child: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Find session
- const invitations = await ReversiMatchings.find({
- childId: user.id
- });
-
- return await Promise.all(invitations.map((i) => ReversiMatchings.pack(i, user)));
-});
diff --git a/src/server/api/endpoints/games/reversi/match.ts b/src/server/api/endpoints/games/reversi/match.ts
deleted file mode 100644
index 5ceb16c7d7..0000000000
--- a/src/server/api/endpoints/games/reversi/match.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishMainStream, publishReversiStream } from '@/services/stream';
-import { eighteight } from '../../../../../games/reversi/maps';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { genId } from '@/misc/gen-id';
-import { ReversiMatchings, ReversiGames } from '@/models/index';
-import { ReversiGame } from '@/models/entities/games/reversi/game';
-import { ReversiMatching } from '@/models/entities/games/reversi/matching';
-
-export const meta = {
- tags: ['games'],
-
- requireCredential: true as const,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '0b4f0559-b484-4e31-9581-3f73cee89b28'
- },
-
- isYourself: {
- message: 'Target user is yourself.',
- code: 'TARGET_IS_YOURSELF',
- id: '96fd7bd6-d2bc-426c-a865-d055dcd2828e'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Myself
- if (ps.userId === user.id) {
- throw new ApiError(meta.errors.isYourself);
- }
-
- // Find session
- const exist = await ReversiMatchings.findOne({
- parentId: ps.userId,
- childId: user.id
- });
-
- if (exist) {
- // Destroy session
- ReversiMatchings.delete(exist.id);
-
- // Create game
- const game = await ReversiGames.save({
- id: genId(),
- createdAt: new Date(),
- user1Id: exist.parentId,
- user2Id: user.id,
- user1Accepted: false,
- user2Accepted: false,
- isStarted: false,
- isEnded: false,
- logs: [],
- map: eighteight.data,
- bw: 'random',
- isLlotheo: false
- } as Partial<ReversiGame>);
-
- publishReversiStream(exist.parentId, 'matched', await ReversiGames.pack(game, { id: exist.parentId }));
-
- const other = await ReversiMatchings.count({
- childId: user.id
- });
-
- if (other == 0) {
- publishMainStream(user.id, 'reversiNoInvites');
- }
-
- return await ReversiGames.pack(game, user);
- } else {
- // Fetch child
- const child = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // 以前のセッションはすべて削除しておく
- await ReversiMatchings.delete({
- parentId: user.id
- });
-
- // セッションを作成
- const matching = await ReversiMatchings.save({
- id: genId(),
- createdAt: new Date(),
- parentId: user.id,
- childId: child.id
- } as ReversiMatching);
-
- const packed = await ReversiMatchings.pack(matching, child);
- publishReversiStream(child.id, 'invited', packed);
- publishMainStream(child.id, 'reversiInvited', packed);
-
- return;
- }
-});
diff --git a/src/server/api/endpoints/games/reversi/match/cancel.ts b/src/server/api/endpoints/games/reversi/match/cancel.ts
deleted file mode 100644
index e4a138bb87..0000000000
--- a/src/server/api/endpoints/games/reversi/match/cancel.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import define from '../../../../define';
-import { ReversiMatchings } from '@/models/index';
-
-export const meta = {
- tags: ['games'],
-
- requireCredential: true as const
-};
-
-export default define(meta, async (ps, user) => {
- await ReversiMatchings.delete({
- parentId: user.id
- });
-});
diff --git a/src/server/api/endpoints/get-online-users-count.ts b/src/server/api/endpoints/get-online-users-count.ts
deleted file mode 100644
index 5c80d588d3..0000000000
--- a/src/server/api/endpoints/get-online-users-count.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { USER_ONLINE_THRESHOLD } from '@/const';
-import { Users } from '@/models/index';
-import { MoreThan } from 'typeorm';
-import define from '../define';
-
-export const meta = {
- tags: ['meta'],
-
- requireCredential: false as const,
-
- params: {
- }
-};
-
-export default define(meta, async () => {
- const count = await Users.count({
- lastActiveDate: MoreThan(new Date(Date.now() - USER_ONLINE_THRESHOLD))
- });
-
- return {
- count
- };
-});
diff --git a/src/server/api/endpoints/hashtags/list.ts b/src/server/api/endpoints/hashtags/list.ts
deleted file mode 100644
index 821016a50c..0000000000
--- a/src/server/api/endpoints/hashtags/list.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Hashtags } from '@/models/index';
-
-export const meta = {
- tags: ['hashtags'],
-
- requireCredential: false as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- attachedToUserOnly: {
- validator: $.optional.bool,
- default: false
- },
-
- attachedToLocalUserOnly: {
- validator: $.optional.bool,
- default: false
- },
-
- attachedToRemoteUserOnly: {
- validator: $.optional.bool,
- default: false
- },
-
- sort: {
- validator: $.str.or([
- '+mentionedUsers',
- '-mentionedUsers',
- '+mentionedLocalUsers',
- '-mentionedLocalUsers',
- '+mentionedRemoteUsers',
- '-mentionedRemoteUsers',
- '+attachedUsers',
- '-attachedUsers',
- '+attachedLocalUsers',
- '-attachedLocalUsers',
- '+attachedRemoteUsers',
- '-attachedRemoteUsers',
- ]),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Hashtag',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = Hashtags.createQueryBuilder('tag');
-
- if (ps.attachedToUserOnly) query.andWhere('tag.attachedUsersCount != 0');
- if (ps.attachedToLocalUserOnly) query.andWhere('tag.attachedLocalUsersCount != 0');
- if (ps.attachedToRemoteUserOnly) query.andWhere('tag.attachedRemoteUsersCount != 0');
-
- switch (ps.sort) {
- case '+mentionedUsers': query.orderBy('tag.mentionedUsersCount', 'DESC'); break;
- case '-mentionedUsers': query.orderBy('tag.mentionedUsersCount', 'ASC'); break;
- case '+mentionedLocalUsers': query.orderBy('tag.mentionedLocalUsersCount', 'DESC'); break;
- case '-mentionedLocalUsers': query.orderBy('tag.mentionedLocalUsersCount', 'ASC'); break;
- case '+mentionedRemoteUsers': query.orderBy('tag.mentionedRemoteUsersCount', 'DESC'); break;
- case '-mentionedRemoteUsers': query.orderBy('tag.mentionedRemoteUsersCount', 'ASC'); break;
- case '+attachedUsers': query.orderBy('tag.attachedUsersCount', 'DESC'); break;
- case '-attachedUsers': query.orderBy('tag.attachedUsersCount', 'ASC'); break;
- case '+attachedLocalUsers': query.orderBy('tag.attachedLocalUsersCount', 'DESC'); break;
- case '-attachedLocalUsers': query.orderBy('tag.attachedLocalUsersCount', 'ASC'); break;
- case '+attachedRemoteUsers': query.orderBy('tag.attachedRemoteUsersCount', 'DESC'); break;
- case '-attachedRemoteUsers': query.orderBy('tag.attachedRemoteUsersCount', 'ASC'); break;
- }
-
- query.select([
- 'tag.name',
- 'tag.mentionedUsersCount',
- 'tag.mentionedLocalUsersCount',
- 'tag.mentionedRemoteUsersCount',
- 'tag.attachedUsersCount',
- 'tag.attachedLocalUsersCount',
- 'tag.attachedRemoteUsersCount',
- ]);
-
- const tags = await query.take(ps.limit!).getMany();
-
- return Hashtags.packMany(tags);
-});
diff --git a/src/server/api/endpoints/hashtags/search.ts b/src/server/api/endpoints/hashtags/search.ts
deleted file mode 100644
index fd0cac3983..0000000000
--- a/src/server/api/endpoints/hashtags/search.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Hashtags } from '@/models/index';
-
-export const meta = {
- tags: ['hashtags'],
-
- requireCredential: false as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- query: {
- validator: $.str,
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0,
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- }
- },
-};
-
-export default define(meta, async (ps) => {
- const hashtags = await Hashtags.createQueryBuilder('tag')
- .where('tag.name like :q', { q: ps.query.toLowerCase() + '%' })
- .orderBy('tag.count', 'DESC')
- .groupBy('tag.id')
- .take(ps.limit!)
- .skip(ps.offset)
- .getMany();
-
- return hashtags.map(tag => tag.name);
-});
diff --git a/src/server/api/endpoints/hashtags/show.ts b/src/server/api/endpoints/hashtags/show.ts
deleted file mode 100644
index f22edbfffd..0000000000
--- a/src/server/api/endpoints/hashtags/show.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Hashtags } from '@/models/index';
-import { normalizeForSearch } from '@/misc/normalize-for-search';
-
-export const meta = {
- tags: ['hashtags'],
-
- requireCredential: false as const,
-
- params: {
- tag: {
- validator: $.str,
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Hashtag',
- },
-
- errors: {
- noSuchHashtag: {
- message: 'No such hashtag.',
- code: 'NO_SUCH_HASHTAG',
- id: '110ee688-193e-4a3a-9ecf-c167b2e6981e'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const hashtag = await Hashtags.findOne({ name: normalizeForSearch(ps.tag) });
- if (hashtag == null) {
- throw new ApiError(meta.errors.noSuchHashtag);
- }
-
- return await Hashtags.pack(hashtag);
-});
diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts
deleted file mode 100644
index 3d67241ab6..0000000000
--- a/src/server/api/endpoints/hashtags/trend.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-import { Brackets } from 'typeorm';
-import define from '../../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { Notes } from '@/models/index';
-import { Note } from '@/models/entities/note';
-import { safeForSql } from '@/misc/safe-for-sql';
-import { normalizeForSearch } from '@/misc/normalize-for-search';
-
-/*
-トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
-ユニーク投稿数とはそのハッシュタグと投稿ユーザーのペアのカウントで、例えば同じユーザーが複数回同じハッシュタグを投稿してもそのハッシュタグのユニーク投稿数は1とカウントされる
-
-..が理想だけどPostgreSQLでどうするのか分からないので単に「直近Aの内に投稿されたユニーク投稿数が多いハッシュタグ」で妥協する
-*/
-
-const rangeA = 1000 * 60 * 60; // 60分
-//const rangeB = 1000 * 60 * 120; // 2時間
-//const coefficient = 1.25; // 「n倍」の部分
-//const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか
-
-const max = 5;
-
-export const meta = {
- tags: ['hashtags'],
-
- requireCredential: false as const,
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- tag: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- chart: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- }
- },
- usersCount: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
- }
-};
-
-export default define(meta, async () => {
- const instance = await fetchMeta(true);
- const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
-
- const now = new Date(); // 5分単位で丸めた現在日時
- now.setMinutes(Math.round(now.getMinutes() / 5) * 5, 0, 0);
-
- const tagNotes = await Notes.createQueryBuilder('note')
- .where(`note.createdAt > :date`, { date: new Date(now.getTime() - rangeA) })
- .andWhere(new Brackets(qb => { qb
- .where(`note.visibility = 'public'`)
- .orWhere(`note.visibility = 'home'`);
- }))
- .andWhere(`note.tags != '{}'`)
- .select(['note.tags', 'note.userId'])
- .cache(60000) // 1 min
- .getMany();
-
- if (tagNotes.length === 0) {
- return [];
- }
-
- const tags: {
- name: string;
- users: Note['userId'][];
- }[] = [];
-
- for (const note of tagNotes) {
- for (const tag of note.tags) {
- if (hiddenTags.includes(tag)) continue;
-
- const x = tags.find(x => x.name === tag);
- if (x) {
- if (!x.users.includes(note.userId)) {
- x.users.push(note.userId);
- }
- } else {
- tags.push({
- name: tag,
- users: [note.userId]
- });
- }
- }
- }
-
- // タグを人気順に並べ替え
- const hots = tags
- .sort((a, b) => b.users.length - a.users.length)
- .map(tag => tag.name)
- .slice(0, max);
-
- //#region 2(または3)で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得する
- const countPromises: Promise<number[]>[] = [];
-
- const range = 20;
-
- // 10分
- const interval = 1000 * 60 * 10;
-
- for (let i = 0; i < range; i++) {
- countPromises.push(Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
- .select('count(distinct note.userId)')
- .where(`'{"${safeForSql(tag) ? tag : 'aichan_kawaii'}"}' <@ note.tags`)
- .andWhere('note.createdAt < :lt', { lt: new Date(now.getTime() - (interval * i)) })
- .andWhere('note.createdAt > :gt', { gt: new Date(now.getTime() - (interval * (i + 1))) })
- .cache(60000) // 1 min
- .getRawOne()
- .then(x => parseInt(x.count, 10))
- )));
- }
-
- const countsLog = await Promise.all(countPromises);
- //#endregion
-
- const totalCounts = await Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
- .select('count(distinct note.userId)')
- .where(`'{"${safeForSql(tag) ? tag : 'aichan_kawaii'}"}' <@ note.tags`)
- .andWhere('note.createdAt > :gt', { gt: new Date(now.getTime() - rangeA) })
- .cache(60000 * 60) // 60 min
- .getRawOne()
- .then(x => parseInt(x.count, 10))
- ));
-
- const stats = hots.map((tag, i) => ({
- tag,
- chart: countsLog.map(counts => counts[i]),
- usersCount: totalCounts[i]
- }));
-
- return stats;
-});
diff --git a/src/server/api/endpoints/hashtags/users.ts b/src/server/api/endpoints/hashtags/users.ts
deleted file mode 100644
index 8c8cd1510b..0000000000
--- a/src/server/api/endpoints/hashtags/users.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Users } from '@/models/index';
-import { normalizeForSearch } from '@/misc/normalize-for-search';
-
-export const meta = {
- requireCredential: false as const,
-
- tags: ['hashtags', 'users'],
-
- params: {
- tag: {
- validator: $.str,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sort: {
- validator: $.str.or([
- '+follower',
- '-follower',
- '+createdAt',
- '-createdAt',
- '+updatedAt',
- '-updatedAt',
- ]),
- },
-
- state: {
- validator: $.optional.str.or([
- 'all',
- 'alive'
- ]),
- default: 'all'
- },
-
- origin: {
- validator: $.optional.str.or([
- 'combined',
- 'local',
- 'remote',
- ]),
- default: 'local'
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = Users.createQueryBuilder('user')
- .where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) });
-
- const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5));
-
- if (ps.state === 'alive') {
- query.andWhere('user.updatedAt > :date', { date: recent });
- }
-
- if (ps.origin === 'local') {
- query.andWhere('user.host IS NULL');
- } else if (ps.origin === 'remote') {
- query.andWhere('user.host IS NOT NULL');
- }
-
- switch (ps.sort) {
- case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
- case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
- case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
- case '+updatedAt': query.orderBy('user.updatedAt', 'DESC'); break;
- case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
- }
-
- const users = await query.take(ps.limit!).getMany();
-
- return await Users.packMany(users, me, { detail: true });
-});
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
deleted file mode 100644
index 0568a962d8..0000000000
--- a/src/server/api/endpoints/i.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import define from '../define';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- params: {},
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- },
-};
-
-export default define(meta, async (ps, user, token) => {
- const isSecure = token == null;
-
- // ここで渡ってきている user はキャッシュされていて古い可能性もあるので id だけ渡す
- return await Users.pack(user.id, user, {
- detail: true,
- includeSecrets: isSecure
- });
-});
diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts
deleted file mode 100644
index 2bd2128cce..0000000000
--- a/src/server/api/endpoints/i/2fa/done.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import $ from 'cafy';
-import * as speakeasy from 'speakeasy';
-import define from '../../../define';
-import { UserProfiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- token: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const token = ps.token.replace(/\s/g, '');
-
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- if (profile.twoFactorTempSecret == null) {
- throw new Error('二段階認証の設定が開始されていません');
- }
-
- const verified = (speakeasy as any).totp.verify({
- secret: profile.twoFactorTempSecret,
- encoding: 'base32',
- token: token
- });
-
- if (!verified) {
- throw new Error('not verified');
- }
-
- await UserProfiles.update(user.id, {
- twoFactorSecret: profile.twoFactorTempSecret,
- twoFactorEnabled: true
- });
-});
diff --git a/src/server/api/endpoints/i/2fa/key-done.ts b/src/server/api/endpoints/i/2fa/key-done.ts
deleted file mode 100644
index b4d3af235a..0000000000
--- a/src/server/api/endpoints/i/2fa/key-done.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import { promisify } from 'util';
-import * as cbor from 'cbor';
-import define from '../../../define';
-import {
- UserProfiles,
- UserSecurityKeys,
- AttestationChallenges,
- Users
-} from '@/models/index';
-import config from '@/config/index';
-import { procedures, hash } from '../../../2fa';
-import { publishMainStream } from '@/services/stream';
-
-const cborDecodeFirst = promisify(cbor.decodeFirst) as any;
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- clientDataJSON: {
- validator: $.str
- },
- attestationObject: {
- validator: $.str
- },
- password: {
- validator: $.str
- },
- challengeId: {
- validator: $.str
- },
- name: {
- validator: $.str
- }
- }
-};
-
-const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8'));
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- if (!profile.twoFactorEnabled) {
- throw new Error('2fa not enabled');
- }
-
- const clientData = JSON.parse(ps.clientDataJSON);
-
- if (clientData.type != 'webauthn.create') {
- throw new Error('not a creation attestation');
- }
- if (clientData.origin != config.scheme + '://' + config.host) {
- throw new Error('origin mismatch');
- }
-
- const clientDataJSONHash = hash(Buffer.from(ps.clientDataJSON, 'utf-8'));
-
- const attestation = await cborDecodeFirst(ps.attestationObject);
-
- const rpIdHash = attestation.authData.slice(0, 32);
- if (!rpIdHashReal.equals(rpIdHash)) {
- throw new Error('rpIdHash mismatch');
- }
-
- const flags = attestation.authData[32];
-
- // tslint:disable-next-line:no-bitwise
- if (!(flags & 1)) {
- throw new Error('user not present');
- }
-
- const authData = Buffer.from(attestation.authData);
- const credentialIdLength = authData.readUInt16BE(53);
- const credentialId = authData.slice(55, 55 + credentialIdLength);
- const publicKeyData = authData.slice(55 + credentialIdLength);
- const publicKey: Map<number, any> = await cborDecodeFirst(publicKeyData);
- if (publicKey.get(3) != -7) {
- throw new Error('alg mismatch');
- }
-
- if (!(procedures as any)[attestation.fmt]) {
- throw new Error('unsupported fmt');
- }
-
- const verificationData = (procedures as any)[attestation.fmt].verify({
- attStmt: attestation.attStmt,
- authenticatorData: authData,
- clientDataHash: clientDataJSONHash,
- credentialId,
- publicKey,
- rpIdHash
- });
- if (!verificationData.valid) throw new Error('signature invalid');
-
- const attestationChallenge = await AttestationChallenges.findOne({
- userId: user.id,
- id: ps.challengeId,
- registrationChallenge: true,
- challenge: hash(clientData.challenge).toString('hex')
- });
-
- if (!attestationChallenge) {
- throw new Error('non-existent challenge');
- }
-
- await AttestationChallenges.delete({
- userId: user.id,
- id: ps.challengeId
- });
-
- // Expired challenge (> 5min old)
- if (
- new Date().getTime() - attestationChallenge.createdAt.getTime() >=
- 5 * 60 * 1000
- ) {
- throw new Error('expired challenge');
- }
-
- const credentialIdString = credentialId.toString('hex');
-
- await UserSecurityKeys.save({
- userId: user.id,
- id: credentialIdString,
- lastUsed: new Date(),
- name: ps.name,
- publicKey: verificationData.publicKey.toString('hex')
- });
-
- // Publish meUpdated event
- publishMainStream(user.id, 'meUpdated', await Users.pack(user.id, user, {
- detail: true,
- includeSecrets: true
- }));
-
- return {
- id: credentialIdString,
- name: ps.name
- };
-});
diff --git a/src/server/api/endpoints/i/2fa/password-less.ts b/src/server/api/endpoints/i/2fa/password-less.ts
deleted file mode 100644
index 064828b638..0000000000
--- a/src/server/api/endpoints/i/2fa/password-less.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { UserProfiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- value: {
- validator: $.boolean
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- await UserProfiles.update(user.id, {
- usePasswordLessLogin: ps.value
- });
-});
diff --git a/src/server/api/endpoints/i/2fa/register-key.ts b/src/server/api/endpoints/i/2fa/register-key.ts
deleted file mode 100644
index 1b385a10ee..0000000000
--- a/src/server/api/endpoints/i/2fa/register-key.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import define from '../../../define';
-import { UserProfiles, AttestationChallenges } from '@/models/index';
-import { promisify } from 'util';
-import * as crypto from 'crypto';
-import { genId } from '@/misc/gen-id';
-import { hash } from '../../../2fa';
-
-const randomBytes = promisify(crypto.randomBytes);
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- if (!profile.twoFactorEnabled) {
- throw new Error('2fa not enabled');
- }
-
- // 32 byte challenge
- const entropy = await randomBytes(32);
- const challenge = entropy.toString('base64')
- .replace(/=/g, '')
- .replace(/\+/g, '-')
- .replace(/\//g, '_');
-
- const challengeId = genId();
-
- await AttestationChallenges.save({
- userId: user.id,
- id: challengeId,
- challenge: hash(Buffer.from(challenge, 'utf-8')).toString('hex'),
- createdAt: new Date(),
- registrationChallenge: true
- });
-
- return {
- challengeId,
- challenge
- };
-});
diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts
deleted file mode 100644
index b03b98188a..0000000000
--- a/src/server/api/endpoints/i/2fa/register.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import * as speakeasy from 'speakeasy';
-import * as QRCode from 'qrcode';
-import config from '@/config/index';
-import define from '../../../define';
-import { UserProfiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- // Generate user's secret key
- const secret = speakeasy.generateSecret({
- length: 32
- });
-
- await UserProfiles.update(user.id, {
- twoFactorTempSecret: secret.base32
- });
-
- // Get the data URL of the authenticator URL
- const dataUrl = await QRCode.toDataURL(speakeasy.otpauthURL({
- secret: secret.base32,
- encoding: 'base32',
- label: user.username,
- issuer: config.host
- }));
-
- return {
- qr: dataUrl,
- secret: secret.base32,
- label: user.username,
- issuer: config.host
- };
-});
diff --git a/src/server/api/endpoints/i/2fa/remove-key.ts b/src/server/api/endpoints/i/2fa/remove-key.ts
deleted file mode 100644
index dea56301ab..0000000000
--- a/src/server/api/endpoints/i/2fa/remove-key.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import define from '../../../define';
-import { UserProfiles, UserSecurityKeys, Users } from '@/models/index';
-import { publishMainStream } from '@/services/stream';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- },
- credentialId: {
- validator: $.str
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- // Make sure we only delete the user's own creds
- await UserSecurityKeys.delete({
- userId: user.id,
- id: ps.credentialId
- });
-
- // Publish meUpdated event
- publishMainStream(user.id, 'meUpdated', await Users.pack(user.id, user, {
- detail: true,
- includeSecrets: true
- }));
-
- return {};
-});
diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts
deleted file mode 100644
index af53033daa..0000000000
--- a/src/server/api/endpoints/i/2fa/unregister.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import define from '../../../define';
-import { UserProfiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- await UserProfiles.update(user.id, {
- twoFactorSecret: null,
- twoFactorEnabled: false
- });
-});
diff --git a/src/server/api/endpoints/i/apps.ts b/src/server/api/endpoints/i/apps.ts
deleted file mode 100644
index 994528e5c9..0000000000
--- a/src/server/api/endpoints/i/apps.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { AccessTokens } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- sort: {
- validator: $.optional.str.or([
- '+createdAt',
- '-createdAt',
- '+lastUsedAt',
- '-lastUsedAt',
- ]),
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = AccessTokens.createQueryBuilder('token')
- .where('token.userId = :userId', { userId: user.id });
-
- switch (ps.sort) {
- case '+createdAt': query.orderBy('token.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('token.createdAt', 'ASC'); break;
- case '+lastUsedAt': query.orderBy('token.lastUsedAt', 'DESC'); break;
- case '-lastUsedAt': query.orderBy('token.lastUsedAt', 'ASC'); break;
- default: query.orderBy('token.id', 'ASC'); break;
- }
-
- const tokens = await query.getMany();
-
- return await Promise.all(tokens.map(token => ({
- id: token.id,
- name: token.name,
- createdAt: token.createdAt,
- lastUsedAt: token.lastUsedAt,
- permission: token.permission,
- })));
-});
diff --git a/src/server/api/endpoints/i/authorized-apps.ts b/src/server/api/endpoints/i/authorized-apps.ts
deleted file mode 100644
index 042fcd14e8..0000000000
--- a/src/server/api/endpoints/i/authorized-apps.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { AccessTokens, Apps } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0,
- },
-
- sort: {
- validator: $.optional.str.or('desc|asc'),
- default: 'desc',
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Get tokens
- const tokens = await AccessTokens.find({
- where: {
- userId: user.id
- },
- take: ps.limit!,
- skip: ps.offset,
- order: {
- id: ps.sort == 'asc' ? 1 : -1
- }
- });
-
- return await Promise.all(tokens.map(token => Apps.pack(token.appId, user, {
- detail: true
- })));
-});
diff --git a/src/server/api/endpoints/i/change-password.ts b/src/server/api/endpoints/i/change-password.ts
deleted file mode 100644
index 7ea5f8c488..0000000000
--- a/src/server/api/endpoints/i/change-password.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import define from '../../define';
-import { UserProfiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- currentPassword: {
- validator: $.str
- },
-
- newPassword: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.currentPassword, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- // Generate hash of password
- const salt = await bcrypt.genSalt(8);
- const hash = await bcrypt.hash(ps.newPassword, salt);
-
- await UserProfiles.update(user.id, {
- password: hash
- });
-});
diff --git a/src/server/api/endpoints/i/delete-account.ts b/src/server/api/endpoints/i/delete-account.ts
deleted file mode 100644
index 10e5adf64a..0000000000
--- a/src/server/api/endpoints/i/delete-account.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import define from '../../define';
-import { UserProfiles, Users } from '@/models/index';
-import { doPostSuspend } from '@/services/suspend-user';
-import { publishUserEvent } from '@/services/stream';
-import { createDeleteAccountJob } from '@/queue';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
- const userDetailed = await Users.findOneOrFail(user.id);
- if (userDetailed.isDeleted) {
- return;
- }
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- // 物理削除する前にDelete activityを送信する
- await doPostSuspend(user).catch(e => {});
-
- createDeleteAccountJob(user, {
- soft: false
- });
-
- await Users.update(user.id, {
- isDeleted: true,
- });
-
- // Terminate streaming
- publishUserEvent(user.id, 'terminate', {});
-});
diff --git a/src/server/api/endpoints/i/export-blocking.ts b/src/server/api/endpoints/i/export-blocking.ts
deleted file mode 100644
index e4797da0c1..0000000000
--- a/src/server/api/endpoints/i/export-blocking.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import define from '../../define';
-import { createExportBlockingJob } from '@/queue/index';
-import * as ms from 'ms';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-};
-
-export default define(meta, async (ps, user) => {
- createExportBlockingJob(user);
-});
diff --git a/src/server/api/endpoints/i/export-following.ts b/src/server/api/endpoints/i/export-following.ts
deleted file mode 100644
index b0f154cda8..0000000000
--- a/src/server/api/endpoints/i/export-following.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import define from '../../define';
-import { createExportFollowingJob } from '@/queue/index';
-import * as ms from 'ms';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-};
-
-export default define(meta, async (ps, user) => {
- createExportFollowingJob(user);
-});
diff --git a/src/server/api/endpoints/i/export-mute.ts b/src/server/api/endpoints/i/export-mute.ts
deleted file mode 100644
index 46d547fa53..0000000000
--- a/src/server/api/endpoints/i/export-mute.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import define from '../../define';
-import { createExportMuteJob } from '@/queue/index';
-import * as ms from 'ms';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-};
-
-export default define(meta, async (ps, user) => {
- createExportMuteJob(user);
-});
diff --git a/src/server/api/endpoints/i/export-notes.ts b/src/server/api/endpoints/i/export-notes.ts
deleted file mode 100644
index 441bf16896..0000000000
--- a/src/server/api/endpoints/i/export-notes.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import define from '../../define';
-import { createExportNotesJob } from '@/queue/index';
-import * as ms from 'ms';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1day'),
- max: 1,
- },
-};
-
-export default define(meta, async (ps, user) => {
- createExportNotesJob(user);
-});
diff --git a/src/server/api/endpoints/i/export-user-lists.ts b/src/server/api/endpoints/i/export-user-lists.ts
deleted file mode 100644
index 24043a862a..0000000000
--- a/src/server/api/endpoints/i/export-user-lists.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import define from '../../define';
-import { createExportUserListsJob } from '@/queue/index';
-import * as ms from 'ms';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1min'),
- max: 1,
- },
-};
-
-export default define(meta, async (ps, user) => {
- createExportUserListsJob(user);
-});
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
deleted file mode 100644
index b79d68ae73..0000000000
--- a/src/server/api/endpoints/i/favorites.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { NoteFavorites } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account', 'notes', 'favorites'],
-
- requireCredential: true as const,
-
- kind: 'read:favorites',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'NoteFavorite',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(NoteFavorites.createQueryBuilder('favorite'), ps.sinceId, ps.untilId)
- .andWhere(`favorite.userId = :meId`, { meId: user.id })
- .leftJoinAndSelect('favorite.note', 'note');
-
- const favorites = await query
- .take(ps.limit!)
- .getMany();
-
- return await NoteFavorites.packMany(favorites, user);
-});
diff --git a/src/server/api/endpoints/i/gallery/likes.ts b/src/server/api/endpoints/i/gallery/likes.ts
deleted file mode 100644
index 7a2935a5ec..0000000000
--- a/src/server/api/endpoints/i/gallery/likes.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { GalleryLikes } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account', 'gallery'],
-
- requireCredential: true as const,
-
- kind: 'read:gallery-likes',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- page: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost'
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(GalleryLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId)
- .andWhere(`like.userId = :meId`, { meId: user.id })
- .leftJoinAndSelect('like.post', 'post');
-
- const likes = await query
- .take(ps.limit!)
- .getMany();
-
- return await GalleryLikes.packMany(likes, user);
-});
diff --git a/src/server/api/endpoints/i/gallery/posts.ts b/src/server/api/endpoints/i/gallery/posts.ts
deleted file mode 100644
index 21bb8759fc..0000000000
--- a/src/server/api/endpoints/i/gallery/posts.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { GalleryPosts } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account', 'gallery'],
-
- requireCredential: true as const,
-
- kind: 'read:gallery',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'GalleryPost'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
- .andWhere(`post.userId = :meId`, { meId: user.id });
-
- const posts = await query
- .take(ps.limit!)
- .getMany();
-
- return await GalleryPosts.packMany(posts, user);
-});
diff --git a/src/server/api/endpoints/i/get-word-muted-notes-count.ts b/src/server/api/endpoints/i/get-word-muted-notes-count.ts
deleted file mode 100644
index 6b9be98582..0000000000
--- a/src/server/api/endpoints/i/get-word-muted-notes-count.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import define from '../../define';
-import { MutedNotes } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- params: {
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- count: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- return {
- count: await MutedNotes.count({
- userId: user.id,
- reason: 'word'
- })
- };
-});
diff --git a/src/server/api/endpoints/i/import-blocking.ts b/src/server/api/endpoints/i/import-blocking.ts
deleted file mode 100644
index d44d0b6077..0000000000
--- a/src/server/api/endpoints/i/import-blocking.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { createImportBlockingJob } from '@/queue/index';
-import * as ms from 'ms';
-import { ApiError } from '../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
-
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-
- params: {
- fileId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e'
- },
-
- unexpectedFileType: {
- message: 'We need csv file.',
- code: 'UNEXPECTED_FILE_TYPE',
- id: 'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe'
- },
-
- tooBigFile: {
- message: 'That file is too big.',
- code: 'TOO_BIG_FILE',
- id: 'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf'
- },
-
- emptyFile: {
- message: 'That file is empty.',
- code: 'EMPTY_FILE',
- id: '6f3a4dcc-f060-a707-4950-806fbdbe60d6'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) throw new ApiError(meta.errors.noSuchFile);
- //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
- if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
- if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
-
- createImportBlockingJob(user, file.id);
-});
diff --git a/src/server/api/endpoints/i/import-following.ts b/src/server/api/endpoints/i/import-following.ts
deleted file mode 100644
index b3de397661..0000000000
--- a/src/server/api/endpoints/i/import-following.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { createImportFollowingJob } from '@/queue/index';
-import * as ms from 'ms';
-import { ApiError } from '../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-
- params: {
- fileId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'b98644cf-a5ac-4277-a502-0b8054a709a3'
- },
-
- unexpectedFileType: {
- message: 'We need csv file.',
- code: 'UNEXPECTED_FILE_TYPE',
- id: '660f3599-bce0-4f95-9dde-311fd841c183'
- },
-
- tooBigFile: {
- message: 'That file is too big.',
- code: 'TOO_BIG_FILE',
- id: 'dee9d4ed-ad07-43ed-8b34-b2856398bc60'
- },
-
- emptyFile: {
- message: 'That file is empty.',
- code: 'EMPTY_FILE',
- id: '31a1b42c-06f7-42ae-8a38-a661c5c9f691'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) throw new ApiError(meta.errors.noSuchFile);
- //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
- if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
- if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
-
- createImportFollowingJob(user, file.id);
-});
diff --git a/src/server/api/endpoints/i/import-muting.ts b/src/server/api/endpoints/i/import-muting.ts
deleted file mode 100644
index c17434c587..0000000000
--- a/src/server/api/endpoints/i/import-muting.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { createImportMutingJob } from '@/queue/index';
-import * as ms from 'ms';
-import { ApiError } from '../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
-
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-
- params: {
- fileId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'e674141e-bd2a-ba85-e616-aefb187c9c2a'
- },
-
- unexpectedFileType: {
- message: 'We need csv file.',
- code: 'UNEXPECTED_FILE_TYPE',
- id: '568c6e42-c86c-ba09-c004-517f83f9f1a8'
- },
-
- tooBigFile: {
- message: 'That file is too big.',
- code: 'TOO_BIG_FILE',
- id: '9b4ada6d-d7f7-0472-0713-4f558bd1ec9c'
- },
-
- emptyFile: {
- message: 'That file is empty.',
- code: 'EMPTY_FILE',
- id: 'd2f12af1-e7b4-feac-86a3-519548f2728e'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) throw new ApiError(meta.errors.noSuchFile);
- //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
- if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
- if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
-
- createImportMutingJob(user, file.id);
-});
diff --git a/src/server/api/endpoints/i/import-user-lists.ts b/src/server/api/endpoints/i/import-user-lists.ts
deleted file mode 100644
index 9069a019a9..0000000000
--- a/src/server/api/endpoints/i/import-user-lists.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { createImportUserListsJob } from '@/queue/index';
-import * as ms from 'ms';
-import { ApiError } from '../../error';
-import { DriveFiles } from '@/models/index';
-
-export const meta = {
- secure: true,
- requireCredential: true as const,
- limit: {
- duration: ms('1hour'),
- max: 1,
- },
-
- params: {
- fileId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'ea9cc34f-c415-4bc6-a6fe-28ac40357049'
- },
-
- unexpectedFileType: {
- message: 'We need csv file.',
- code: 'UNEXPECTED_FILE_TYPE',
- id: 'a3c9edda-dd9b-4596-be6a-150ef813745c'
- },
-
- tooBigFile: {
- message: 'That file is too big.',
- code: 'TOO_BIG_FILE',
- id: 'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9'
- },
-
- emptyFile: {
- message: 'That file is empty.',
- code: 'EMPTY_FILE',
- id: '99efe367-ce6e-4d44-93f8-5fae7b040356'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const file = await DriveFiles.findOne(ps.fileId);
-
- if (file == null) throw new ApiError(meta.errors.noSuchFile);
- //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
- if (file.size > 30000) throw new ApiError(meta.errors.tooBigFile);
- if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
-
- createImportUserListsJob(user, file.id);
-});
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
deleted file mode 100644
index 56668d03b7..0000000000
--- a/src/server/api/endpoints/i/notifications.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { readNotification } from '../../common/read-notification';
-import define from '../../define';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Notifications, Followings, Mutings, Users } from '@/models/index';
-import { notificationTypes } from '@/types';
-import read from '@/services/note/read';
-import { Brackets } from 'typeorm';
-
-export const meta = {
- tags: ['account', 'notifications'],
-
- requireCredential: true as const,
-
- kind: 'read:notifications',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- following: {
- validator: $.optional.bool,
- default: false
- },
-
- unreadOnly: {
- validator: $.optional.bool,
- default: false
- },
-
- markAsRead: {
- validator: $.optional.bool,
- default: true
- },
-
- includeTypes: {
- validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])),
- },
-
- excludeTypes: {
- validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])),
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Notification',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- // includeTypes が空の場合はクエリしない
- if (ps.includeTypes && ps.includeTypes.length === 0) {
- return [];
- }
- // excludeTypes に全指定されている場合はクエリしない
- if (notificationTypes.every(type => ps.excludeTypes?.includes(type))) {
- return [];
- }
- const followingQuery = Followings.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: user.id });
-
- const mutingQuery = Mutings.createQueryBuilder('muting')
- .select('muting.muteeId')
- .where('muting.muterId = :muterId', { muterId: user.id });
-
- const suspendedQuery = Users.createQueryBuilder('users')
- .select('users.id')
- .where('users.isSuspended = TRUE');
-
- const query = makePaginationQuery(Notifications.createQueryBuilder('notification'), ps.sinceId, ps.untilId)
- .andWhere(`notification.notifieeId = :meId`, { meId: user.id })
- .leftJoinAndSelect('notification.notifier', 'notifier')
- .leftJoinAndSelect('notification.note', 'note')
- .leftJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- query.andWhere(new Brackets(qb => { qb
- .where(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`)
- .orWhere('notification.notifierId IS NULL');
- }));
- query.setParameters(mutingQuery.getParameters());
-
- query.andWhere(new Brackets(qb => { qb
- .where(`notification.notifierId NOT IN (${ suspendedQuery.getQuery() })`)
- .orWhere('notification.notifierId IS NULL');
- }));
-
- if (ps.following) {
- query.andWhere(`((notification.notifierId IN (${ followingQuery.getQuery() })) OR (notification.notifierId = :meId))`, { meId: user.id });
- query.setParameters(followingQuery.getParameters());
- }
-
- if (ps.includeTypes && ps.includeTypes.length > 0) {
- query.andWhere(`notification.type IN (:...includeTypes)`, { includeTypes: ps.includeTypes });
- } else if (ps.excludeTypes && ps.excludeTypes.length > 0) {
- query.andWhere(`notification.type NOT IN (:...excludeTypes)`, { excludeTypes: ps.excludeTypes });
- }
-
- if (ps.unreadOnly) {
- query.andWhere(`notification.isRead = false`);
- }
-
- const notifications = await query.take(ps.limit!).getMany();
-
- // Mark all as read
- if (notifications.length > 0 && ps.markAsRead) {
- readNotification(user.id, notifications.map(x => x.id));
- }
-
- const notes = notifications.filter(notification => ['mention', 'reply', 'quote'].includes(notification.type)).map(notification => notification.note!);
-
- if (notes.length > 0) {
- read(user.id, notes);
- }
-
- return await Notifications.packMany(notifications, user.id);
-});
diff --git a/src/server/api/endpoints/i/page-likes.ts b/src/server/api/endpoints/i/page-likes.ts
deleted file mode 100644
index fa2bc31730..0000000000
--- a/src/server/api/endpoints/i/page-likes.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { PageLikes } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account', 'pages'],
-
- requireCredential: true as const,
-
- kind: 'read:page-likes',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- page: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Page'
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(PageLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId)
- .andWhere(`like.userId = :meId`, { meId: user.id })
- .leftJoinAndSelect('like.page', 'page');
-
- const likes = await query
- .take(ps.limit!)
- .getMany();
-
- return await PageLikes.packMany(likes, user);
-});
diff --git a/src/server/api/endpoints/i/pages.ts b/src/server/api/endpoints/i/pages.ts
deleted file mode 100644
index ee87fffa2d..0000000000
--- a/src/server/api/endpoints/i/pages.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Pages } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account', 'pages'],
-
- requireCredential: true as const,
-
- kind: 'read:pages',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Page'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
- .andWhere(`page.userId = :meId`, { meId: user.id });
-
- const pages = await query
- .take(ps.limit!)
- .getMany();
-
- return await Pages.packMany(pages);
-});
diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts
deleted file mode 100644
index de94220ba9..0000000000
--- a/src/server/api/endpoints/i/pin.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { addPinned } from '@/services/i/pin';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['account', 'notes'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '56734f8b-3928-431e-bf80-6ff87df40cb3'
- },
-
- pinLimitExceeded: {
- message: 'You can not pin notes any more.',
- code: 'PIN_LIMIT_EXCEEDED',
- id: '72dab508-c64d-498f-8740-a8eec1ba385a'
- },
-
- alreadyPinned: {
- message: 'That note has already been pinned.',
- code: 'ALREADY_PINNED',
- id: '8b18c2b7-68fe-4edb-9892-c0cbaeb6c913'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, user) => {
- await addPinned(user, ps.noteId).catch(e => {
- if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError(meta.errors.noSuchNote);
- if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError(meta.errors.pinLimitExceeded);
- if (e.id === '23f0cf4e-59a3-4276-a91d-61a5891c1514') throw new ApiError(meta.errors.alreadyPinned);
- throw e;
- });
-
- return await Users.pack(user.id, user, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/i/read-all-messaging-messages.ts b/src/server/api/endpoints/i/read-all-messaging-messages.ts
deleted file mode 100644
index 9aca7611c9..0000000000
--- a/src/server/api/endpoints/i/read-all-messaging-messages.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { publishMainStream } from '@/services/stream';
-import define from '../../define';
-import { MessagingMessages, UserGroupJoinings } from '@/models/index';
-
-export const meta = {
- tags: ['account', 'messaging'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Update documents
- await MessagingMessages.update({
- recipientId: user.id,
- isRead: false
- }, {
- isRead: true
- });
-
- const joinings = await UserGroupJoinings.find({ userId: user.id });
-
- await Promise.all(joinings.map(j => MessagingMessages.createQueryBuilder().update()
- .set({
- reads: (() => `array_append("reads", '${user.id}')`) as any
- })
- .where(`groupId = :groupId`, { groupId: j.userGroupId })
- .andWhere('userId != :userId', { userId: user.id })
- .andWhere('NOT (:userId = ANY(reads))', { userId: user.id })
- .execute()));
-
- publishMainStream(user.id, 'readAllMessagingMessages');
-});
diff --git a/src/server/api/endpoints/i/read-all-unread-notes.ts b/src/server/api/endpoints/i/read-all-unread-notes.ts
deleted file mode 100644
index 2a7102a590..0000000000
--- a/src/server/api/endpoints/i/read-all-unread-notes.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { publishMainStream } from '@/services/stream';
-import define from '../../define';
-import { NoteUnreads } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Remove documents
- await NoteUnreads.delete({
- userId: user.id
- });
-
- // 全て既読になったイベントを発行
- publishMainStream(user.id, 'readAllUnreadMentions');
- publishMainStream(user.id, 'readAllUnreadSpecifiedNotes');
-});
diff --git a/src/server/api/endpoints/i/read-announcement.ts b/src/server/api/endpoints/i/read-announcement.ts
deleted file mode 100644
index 2f5036f953..0000000000
--- a/src/server/api/endpoints/i/read-announcement.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { genId } from '@/misc/gen-id';
-import { AnnouncementReads, Announcements, Users } from '@/models/index';
-import { publishMainStream } from '@/services/stream';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- announcementId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchAnnouncement: {
- message: 'No such announcement.',
- code: 'NO_SUCH_ANNOUNCEMENT',
- id: '184663db-df88-4bc2-8b52-fb85f0681939'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Check if announcement exists
- const announcement = await Announcements.findOne(ps.announcementId);
-
- if (announcement == null) {
- throw new ApiError(meta.errors.noSuchAnnouncement);
- }
-
- // Check if already read
- const read = await AnnouncementReads.findOne({
- announcementId: ps.announcementId,
- userId: user.id
- });
-
- if (read != null) {
- return;
- }
-
- // Create read
- await AnnouncementReads.insert({
- id: genId(),
- createdAt: new Date(),
- announcementId: ps.announcementId,
- userId: user.id,
- });
-
- if (!await Users.getHasUnreadAnnouncement(user.id)) {
- publishMainStream(user.id, 'readAllAnnouncements');
- }
-});
diff --git a/src/server/api/endpoints/i/regenerate-token.ts b/src/server/api/endpoints/i/regenerate-token.ts
deleted file mode 100644
index 1cce2d37be..0000000000
--- a/src/server/api/endpoints/i/regenerate-token.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import { publishMainStream, publishUserEvent } from '@/services/stream';
-import generateUserToken from '../../common/generate-native-user-token';
-import define from '../../define';
-import { Users, UserProfiles } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- // Generate secret
- const secret = generateUserToken();
-
- await Users.update(user.id, {
- token: secret
- });
-
- // Publish event
- publishMainStream(user.id, 'myTokenRegenerated');
-
- // Terminate streaming
- setTimeout(() => {
- publishUserEvent(user.id, 'terminate', {});
- }, 5000);
-});
diff --git a/src/server/api/endpoints/i/registry/get-all.ts b/src/server/api/endpoints/i/registry/get-all.ts
deleted file mode 100644
index c8eaf83a25..0000000000
--- a/src/server/api/endpoints/i/registry/get-all.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const items = await query.getMany();
-
- const res = {} as Record<string, any>;
-
- for (const item of items) {
- res[item.key] = item.value;
- }
-
- return res;
-});
diff --git a/src/server/api/endpoints/i/registry/get-detail.ts b/src/server/api/endpoints/i/registry/get-detail.ts
deleted file mode 100644
index 992800c44c..0000000000
--- a/src/server/api/endpoints/i/registry/get-detail.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- key: {
- validator: $.str
- },
-
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- },
-
- errors: {
- noSuchKey: {
- message: 'No such key.',
- code: 'NO_SUCH_KEY',
- id: '97a1e8e7-c0f7-47d2-957a-92e61256e01a'
- },
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.key = :key', { key: ps.key })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const item = await query.getOne();
-
- if (item == null) {
- throw new ApiError(meta.errors.noSuchKey);
- }
-
- return {
- updatedAt: item.updatedAt,
- value: item.value,
- };
-});
diff --git a/src/server/api/endpoints/i/registry/get.ts b/src/server/api/endpoints/i/registry/get.ts
deleted file mode 100644
index 569c3a9280..0000000000
--- a/src/server/api/endpoints/i/registry/get.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- key: {
- validator: $.str
- },
-
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- },
-
- errors: {
- noSuchKey: {
- message: 'No such key.',
- code: 'NO_SUCH_KEY',
- id: 'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a'
- },
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.key = :key', { key: ps.key })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const item = await query.getOne();
-
- if (item == null) {
- throw new ApiError(meta.errors.noSuchKey);
- }
-
- return item.value;
-});
diff --git a/src/server/api/endpoints/i/registry/keys-with-type.ts b/src/server/api/endpoints/i/registry/keys-with-type.ts
deleted file mode 100644
index 16a4fee374..0000000000
--- a/src/server/api/endpoints/i/registry/keys-with-type.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const items = await query.getMany();
-
- const res = {} as Record<string, string>;
-
- for (const item of items) {
- const type = typeof item.value;
- res[item.key] =
- item.value === null ? 'null' :
- Array.isArray(item.value) ? 'array' :
- type === 'number' ? 'number' :
- type === 'string' ? 'string' :
- type === 'boolean' ? 'boolean' :
- type === 'object' ? 'object' :
- null as never;
- }
-
- return res;
-});
diff --git a/src/server/api/endpoints/i/registry/keys.ts b/src/server/api/endpoints/i/registry/keys.ts
deleted file mode 100644
index 3a8aeaa195..0000000000
--- a/src/server/api/endpoints/i/registry/keys.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .select('item.key')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const items = await query.getMany();
-
- return items.map(x => x.key);
-});
diff --git a/src/server/api/endpoints/i/registry/remove.ts b/src/server/api/endpoints/i/registry/remove.ts
deleted file mode 100644
index 07bc23d4a6..0000000000
--- a/src/server/api/endpoints/i/registry/remove.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-import { ApiError } from '../../../error';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- key: {
- validator: $.str
- },
-
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- },
-
- errors: {
- noSuchKey: {
- message: 'No such key.',
- code: 'NO_SUCH_KEY',
- id: '1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019'
- },
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.key = :key', { key: ps.key })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const item = await query.getOne();
-
- if (item == null) {
- throw new ApiError(meta.errors.noSuchKey);
- }
-
- await RegistryItems.remove(item);
-});
diff --git a/src/server/api/endpoints/i/registry/scopes.ts b/src/server/api/endpoints/i/registry/scopes.ts
deleted file mode 100644
index ecbdb05a8e..0000000000
--- a/src/server/api/endpoints/i/registry/scopes.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .select('item.scope')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id });
-
- const items = await query.getMany();
-
- const res = [] as string[][];
-
- for (const item of items) {
- if (res.some(scope => scope.join('.') === item.scope.join('.'))) continue;
- res.push(item.scope);
- }
-
- return res;
-});
diff --git a/src/server/api/endpoints/i/registry/set.ts b/src/server/api/endpoints/i/registry/set.ts
deleted file mode 100644
index f129ee1b70..0000000000
--- a/src/server/api/endpoints/i/registry/set.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import $ from 'cafy';
-import { publishMainStream } from '@/services/stream';
-import define from '../../../define';
-import { RegistryItems } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- key: {
- validator: $.str.min(1)
- },
-
- value: {
- validator: $.nullable.any
- },
-
- scope: {
- validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
- default: [],
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = RegistryItems.createQueryBuilder('item')
- .where('item.domain IS NULL')
- .andWhere('item.userId = :userId', { userId: user.id })
- .andWhere('item.key = :key', { key: ps.key })
- .andWhere('item.scope = :scope', { scope: ps.scope });
-
- const existingItem = await query.getOne();
-
- if (existingItem) {
- await RegistryItems.update(existingItem.id, {
- updatedAt: new Date(),
- value: ps.value
- });
- } else {
- await RegistryItems.insert({
- id: genId(),
- createdAt: new Date(),
- updatedAt: new Date(),
- userId: user.id,
- domain: null,
- scope: ps.scope,
- key: ps.key,
- value: ps.value
- });
- }
-
- // TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
- publishMainStream(user.id, 'registryUpdated', {
- scope: ps.scope,
- key: ps.key,
- value: ps.value
- });
-});
diff --git a/src/server/api/endpoints/i/revoke-token.ts b/src/server/api/endpoints/i/revoke-token.ts
deleted file mode 100644
index bed868def4..0000000000
--- a/src/server/api/endpoints/i/revoke-token.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { AccessTokens } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-import { publishUserEvent } from '@/services/stream';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- tokenId: {
- validator: $.type(ID)
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const token = await AccessTokens.findOne(ps.tokenId);
-
- if (token) {
- await AccessTokens.delete({
- id: ps.tokenId,
- userId: user.id,
- });
-
- // Terminate streaming
- publishUserEvent(user.id, 'terminate');
- }
-});
diff --git a/src/server/api/endpoints/i/signin-history.ts b/src/server/api/endpoints/i/signin-history.ts
deleted file mode 100644
index a2c10148c6..0000000000
--- a/src/server/api/endpoints/i/signin-history.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Signins } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Signins.createQueryBuilder('signin'), ps.sinceId, ps.untilId)
- .andWhere(`signin.userId = :meId`, { meId: user.id });
-
- const history = await query.take(ps.limit!).getMany();
-
- return await Promise.all(history.map(record => Signins.pack(record)));
-});
diff --git a/src/server/api/endpoints/i/unpin.ts b/src/server/api/endpoints/i/unpin.ts
deleted file mode 100644
index dc79e255ab..0000000000
--- a/src/server/api/endpoints/i/unpin.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { removePinned } from '@/services/i/pin';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['account', 'notes'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '454170ce-9d63-4a43-9da1-ea10afe81e21'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, user) => {
- await removePinned(user, ps.noteId).catch(e => {
- if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- return await Users.pack(user.id, user, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/i/update-email.ts b/src/server/api/endpoints/i/update-email.ts
deleted file mode 100644
index 9b6fb9c410..0000000000
--- a/src/server/api/endpoints/i/update-email.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import $ from 'cafy';
-import { publishMainStream } from '@/services/stream';
-import define from '../../define';
-import rndstr from 'rndstr';
-import config from '@/config/index';
-import * as ms from 'ms';
-import * as bcrypt from 'bcryptjs';
-import { Users, UserProfiles } from '@/models/index';
-import { sendEmail } from '@/services/send-email';
-import { ApiError } from '../../error';
-import { validateEmailForAccount } from '@/services/validate-email-for-account';
-
-export const meta = {
- requireCredential: true as const,
-
- secure: true,
-
- limit: {
- duration: ms('1hour'),
- max: 3
- },
-
- params: {
- password: {
- validator: $.str
- },
-
- email: {
- validator: $.optional.nullable.str
- },
- },
-
- errors: {
- incorrectPassword: {
- message: 'Incorrect password.',
- code: 'INCORRECT_PASSWORD',
- id: 'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3'
- },
-
- unavailable: {
- message: 'Unavailable email address.',
- code: 'UNAVAILABLE',
- id: 'a2defefb-f220-8849-0af6-17f816099323'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new ApiError(meta.errors.incorrectPassword);
- }
-
- if (ps.email != null) {
- const available = await validateEmailForAccount(ps.email);
- if (!available) {
- throw new ApiError(meta.errors.unavailable);
- }
- }
-
- await UserProfiles.update(user.id, {
- email: ps.email,
- emailVerified: false,
- emailVerifyCode: null
- });
-
- const iObj = await Users.pack(user.id, user, {
- detail: true,
- includeSecrets: true
- });
-
- // Publish meUpdated event
- publishMainStream(user.id, 'meUpdated', iObj);
-
- if (ps.email != null) {
- const code = rndstr('a-z0-9', 16);
-
- await UserProfiles.update(user.id, {
- emailVerifyCode: code
- });
-
- const link = `${config.url}/verify-email/${code}`;
-
- sendEmail(ps.email, 'Email verification',
- `To verify email, please click this link:<br><a href="${link}">${link}</a>`,
- `To verify email, please click this link: ${link}`);
- }
-
- return iObj;
-});
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
deleted file mode 100644
index d0f201ab60..0000000000
--- a/src/server/api/endpoints/i/update.ts
+++ /dev/null
@@ -1,294 +0,0 @@
-import $ from 'cafy';
-import * as mfm from 'mfm-js';
-import { ID } from '@/misc/cafy-id';
-import { publishMainStream, publishUserEvent } from '@/services/stream';
-import acceptAllFollowRequests from '@/services/following/requests/accept-all';
-import { publishToFollowers } from '@/services/i/update';
-import define from '../../define';
-import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm';
-import { extractHashtags } from '@/misc/extract-hashtags';
-import * as langmap from 'langmap';
-import { updateUsertags } from '@/services/update-hashtag';
-import { ApiError } from '../../error';
-import { Users, DriveFiles, UserProfiles, Pages } from '@/models/index';
-import { User } from '@/models/entities/user';
-import { UserProfile } from '@/models/entities/user-profile';
-import { notificationTypes } from '@/types';
-import { normalizeForSearch } from '@/misc/normalize-for-search';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- name: {
- validator: $.optional.nullable.use(Users.validateName),
- },
-
- description: {
- validator: $.optional.nullable.use(Users.validateDescription),
- },
-
- lang: {
- validator: $.optional.nullable.str.or(Object.keys(langmap)),
- },
-
- location: {
- validator: $.optional.nullable.use(Users.validateLocation),
- },
-
- birthday: {
- validator: $.optional.nullable.use(Users.validateBirthday),
- },
-
- avatarId: {
- validator: $.optional.nullable.type(ID),
- },
-
- bannerId: {
- validator: $.optional.nullable.type(ID),
- },
-
- fields: {
- validator: $.optional.arr($.object()).range(1, 4),
- },
-
- isLocked: {
- validator: $.optional.bool,
- },
-
- isExplorable: {
- validator: $.optional.bool,
- },
-
- hideOnlineStatus: {
- validator: $.optional.bool,
- },
-
- publicReactions: {
- validator: $.optional.bool,
- },
-
- ffVisibility: {
- validator: $.optional.str,
- },
-
- carefulBot: {
- validator: $.optional.bool,
- },
-
- autoAcceptFollowed: {
- validator: $.optional.bool,
- },
-
- noCrawle: {
- validator: $.optional.bool,
- },
-
- isBot: {
- validator: $.optional.bool,
- },
-
- isCat: {
- validator: $.optional.bool,
- },
-
- injectFeaturedNote: {
- validator: $.optional.bool,
- },
-
- receiveAnnouncementEmail: {
- validator: $.optional.bool,
- },
-
- alwaysMarkNsfw: {
- validator: $.optional.bool,
- },
-
- pinnedPageId: {
- validator: $.optional.nullable.type(ID),
- },
-
- mutedWords: {
- validator: $.optional.arr($.arr($.str))
- },
-
- mutingNotificationTypes: {
- validator: $.optional.arr($.str.or(notificationTypes as unknown as string[]))
- },
-
- emailNotificationTypes: {
- validator: $.optional.arr($.str)
- },
- },
-
- errors: {
- noSuchAvatar: {
- message: 'No such avatar file.',
- code: 'NO_SUCH_AVATAR',
- id: '539f3a45-f215-4f81-a9a8-31293640207f'
- },
-
- noSuchBanner: {
- message: 'No such banner file.',
- code: 'NO_SUCH_BANNER',
- id: '0d8f5629-f210-41c2-9433-735831a58595'
- },
-
- avatarNotAnImage: {
- message: 'The file specified as an avatar is not an image.',
- code: 'AVATAR_NOT_AN_IMAGE',
- id: 'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191'
- },
-
- bannerNotAnImage: {
- message: 'The file specified as a banner is not an image.',
- code: 'BANNER_NOT_AN_IMAGE',
- id: '75aedb19-2afd-4e6d-87fc-67941256fa60'
- },
-
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: '8e01b590-7eb9-431b-a239-860e086c408e'
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User'
- }
-};
-
-export default define(meta, async (ps, _user, token) => {
- const user = await Users.findOneOrFail(_user.id);
- const isSecure = token == null;
-
- const updates = {} as Partial<User>;
- const profileUpdates = {} as Partial<UserProfile>;
-
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- if (ps.name !== undefined) updates.name = ps.name;
- if (ps.description !== undefined) profileUpdates.description = ps.description;
- if (ps.lang !== undefined) profileUpdates.lang = ps.lang;
- if (ps.location !== undefined) profileUpdates.location = ps.location;
- if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday;
- if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility;
- if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
- if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
- if (ps.mutedWords !== undefined) {
- profileUpdates.mutedWords = ps.mutedWords;
- profileUpdates.enableWordMute = ps.mutedWords.length > 0;
- }
- if (ps.mutingNotificationTypes !== undefined) profileUpdates.mutingNotificationTypes = ps.mutingNotificationTypes as typeof notificationTypes[number][];
- if (typeof ps.isLocked === 'boolean') updates.isLocked = ps.isLocked;
- if (typeof ps.isExplorable === 'boolean') updates.isExplorable = ps.isExplorable;
- if (typeof ps.hideOnlineStatus === 'boolean') updates.hideOnlineStatus = ps.hideOnlineStatus;
- if (typeof ps.publicReactions === 'boolean') profileUpdates.publicReactions = ps.publicReactions;
- if (typeof ps.isBot === 'boolean') updates.isBot = ps.isBot;
- if (typeof ps.carefulBot === 'boolean') profileUpdates.carefulBot = ps.carefulBot;
- if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
- if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
- if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
- if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
- if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
- if (typeof ps.alwaysMarkNsfw === 'boolean') profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
- if (ps.emailNotificationTypes !== undefined) profileUpdates.emailNotificationTypes = ps.emailNotificationTypes;
-
- if (ps.avatarId) {
- const avatar = await DriveFiles.findOne(ps.avatarId);
-
- if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar);
- if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage);
-
- updates.avatarUrl = DriveFiles.getPublicUrl(avatar, true);
-
- if (avatar.blurhash) {
- updates.avatarBlurhash = avatar.blurhash;
- }
- }
-
- if (ps.bannerId) {
- const banner = await DriveFiles.findOne(ps.bannerId);
-
- if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner);
- if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage);
-
- updates.bannerUrl = DriveFiles.getPublicUrl(banner, false);
-
- if (banner.blurhash) {
- updates.bannerBlurhash = banner.blurhash;
- }
- }
-
- if (ps.pinnedPageId) {
- const page = await Pages.findOne(ps.pinnedPageId);
-
- if (page == null || page.userId !== user.id) throw new ApiError(meta.errors.noSuchPage);
-
- profileUpdates.pinnedPageId = page.id;
- } else if (ps.pinnedPageId === null) {
- profileUpdates.pinnedPageId = null;
- }
-
- if (ps.fields) {
- profileUpdates.fields = ps.fields
- .filter(x => typeof x.name === 'string' && x.name !== '' && typeof x.value === 'string' && x.value !== '')
- .map(x => {
- return { name: x.name, value: x.value };
- });
- }
-
- //#region emojis/tags
-
- let emojis = [] as string[];
- let tags = [] as string[];
-
- const newName = updates.name === undefined ? user.name : updates.name;
- const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description;
-
- if (newName != null) {
- const tokens = mfm.parsePlain(newName);
- emojis = emojis.concat(extractCustomEmojisFromMfm(tokens!));
- }
-
- if (newDescription != null) {
- const tokens = mfm.parse(newDescription);
- emojis = emojis.concat(extractCustomEmojisFromMfm(tokens!));
- tags = extractHashtags(tokens!).map(tag => normalizeForSearch(tag)).splice(0, 32);
- }
-
- updates.emojis = emojis;
- updates.tags = tags;
-
- // ハッシュタグ更新
- updateUsertags(user, tags);
- //#endregion
-
- if (Object.keys(updates).length > 0) await Users.update(user.id, updates);
- if (Object.keys(profileUpdates).length > 0) await UserProfiles.update(user.id, profileUpdates);
-
- const iObj = await Users.pack(user.id, user, {
- detail: true,
- includeSecrets: isSecure
- });
-
- // Publish meUpdated event
- publishMainStream(user.id, 'meUpdated', iObj);
- publishUserEvent(user.id, 'updateUserProfile', await UserProfiles.findOne(user.id));
-
- // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認
- if (user.isLocked && ps.isLocked === false) {
- acceptAllFollowRequests(user);
- }
-
- // フォロワーにUpdateを配信
- publishToFollowers(user.id);
-
- return iObj;
-});
diff --git a/src/server/api/endpoints/i/user-group-invites.ts b/src/server/api/endpoints/i/user-group-invites.ts
deleted file mode 100644
index 1ebde243ca..0000000000
--- a/src/server/api/endpoints/i/user-group-invites.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { UserGroupInvitations } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['account', 'groups'],
-
- requireCredential: true as const,
-
- kind: 'read:user-groups',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- group: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup'
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(UserGroupInvitations.createQueryBuilder('invitation'), ps.sinceId, ps.untilId)
- .andWhere(`invitation.userId = :meId`, { meId: user.id })
- .leftJoinAndSelect('invitation.userGroup', 'user_group');
-
- const invitations = await query
- .take(ps.limit!)
- .getMany();
-
- return await UserGroupInvitations.packMany(invitations);
-});
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
deleted file mode 100644
index e447703546..0000000000
--- a/src/server/api/endpoints/messaging/history.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { MessagingMessage } from '@/models/entities/messaging-message';
-import { MessagingMessages, Mutings, UserGroupJoinings } from '@/models/index';
-import { Brackets } from 'typeorm';
-
-export const meta = {
- tags: ['messaging'],
-
- requireCredential: true as const,
-
- kind: 'read:messaging',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- group: {
- validator: $.optional.bool,
- default: false
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'MessagingMessage',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const mute = await Mutings.find({
- muterId: user.id,
- });
-
- const groups = ps.group ? await UserGroupJoinings.find({
- userId: user.id,
- }).then(xs => xs.map(x => x.userGroupId)) : [];
-
- if (ps.group && groups.length === 0) {
- return [];
- }
-
- const history: MessagingMessage[] = [];
-
- for (let i = 0; i < ps.limit!; i++) {
- const found = ps.group
- ? history.map(m => m.groupId!)
- : history.map(m => (m.userId === user.id) ? m.recipientId! : m.userId!);
-
- const query = MessagingMessages.createQueryBuilder('message')
- .orderBy('message.createdAt', 'DESC');
-
- if (ps.group) {
- query.where(`message.groupId IN (:...groups)`, { groups: groups });
-
- if (found.length > 0) {
- query.andWhere(`message.groupId NOT IN (:...found)`, { found: found });
- }
- } else {
- query.where(new Brackets(qb => { qb
- .where(`message.userId = :userId`, { userId: user.id })
- .orWhere(`message.recipientId = :userId`, { userId: user.id });
- }));
- query.andWhere(`message.groupId IS NULL`);
-
- if (found.length > 0) {
- query.andWhere(`message.userId NOT IN (:...found)`, { found: found });
- query.andWhere(`message.recipientId NOT IN (:...found)`, { found: found });
- }
-
- if (mute.length > 0) {
- query.andWhere(`message.userId NOT IN (:...mute)`, { mute: mute.map(m => m.muteeId) });
- query.andWhere(`message.recipientId NOT IN (:...mute)`, { mute: mute.map(m => m.muteeId) });
- }
- }
-
- const message = await query.getOne();
-
- if (message) {
- history.push(message);
- } else {
- break;
- }
- }
-
- return await Promise.all(history.map(h => MessagingMessages.pack(h.id, user)));
-});
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
deleted file mode 100644
index 6baa24609e..0000000000
--- a/src/server/api/endpoints/messaging/messages.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { MessagingMessages, UserGroups, UserGroupJoinings, Users } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Brackets } from 'typeorm';
-import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivity } from '../../common/read-messaging-message';
-
-export const meta = {
- tags: ['messaging'],
-
- requireCredential: true as const,
-
- kind: 'read:messaging',
-
- params: {
- userId: {
- validator: $.optional.type(ID),
- },
-
- groupId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- markAsRead: {
- validator: $.optional.bool,
- default: true
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'MessagingMessage',
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '11795c64-40ea-4198-b06e-3c873ed9039d'
- },
-
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: 'c4d9f88c-9270-4632-b032-6ed8cee36f7f'
- },
-
- groupAccessDenied: {
- message: 'You can not read messages of groups that you have not joined.',
- code: 'GROUP_ACCESS_DENIED',
- id: 'a053a8dd-a491-4718-8f87-50775aad9284'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- if (ps.userId != null) {
- // Fetch recipient (user)
- const recipient = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId)
- .andWhere(new Brackets(qb => { qb
- .where(new Brackets(qb => { qb
- .where('message.userId = :meId')
- .andWhere('message.recipientId = :recipientId');
- }))
- .orWhere(new Brackets(qb => { qb
- .where('message.userId = :recipientId')
- .andWhere('message.recipientId = :meId');
- }));
- }))
- .setParameter('meId', user.id)
- .setParameter('recipientId', recipient.id);
-
- const messages = await query.take(ps.limit!).getMany();
-
- // Mark all as read
- if (ps.markAsRead) {
- readUserMessagingMessage(user.id, recipient.id, messages.filter(m => m.recipientId === user.id).map(x => x.id));
-
- // リモートユーザーとのメッセージだったら既読配信
- if (Users.isLocalUser(user) && Users.isRemoteUser(recipient)) {
- deliverReadActivity(user, recipient, messages);
- }
- }
-
- return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, {
- populateRecipient: false
- })));
- } else if (ps.groupId != null) {
- // Fetch recipient (group)
- const recipientGroup = await UserGroups.findOne(ps.groupId);
-
- if (recipientGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- // check joined
- const joining = await UserGroupJoinings.findOne({
- userId: user.id,
- userGroupId: recipientGroup.id
- });
-
- if (joining == null) {
- throw new ApiError(meta.errors.groupAccessDenied);
- }
-
- const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId)
- .andWhere(`message.groupId = :groupId`, { groupId: recipientGroup.id });
-
- const messages = await query.take(ps.limit!).getMany();
-
- // Mark all as read
- if (ps.markAsRead) {
- readGroupMessagingMessage(user.id, recipientGroup.id, messages.map(x => x.id));
- }
-
- return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, {
- populateGroup: false
- })));
- } else {
- throw new Error();
- }
-});
diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts
deleted file mode 100644
index df0b455cbe..0000000000
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { MessagingMessages, DriveFiles, UserGroups, UserGroupJoinings, Blockings } from '@/models/index';
-import { User } from '@/models/entities/user';
-import { UserGroup } from '@/models/entities/user-group';
-import { createMessage } from '@/services/messages/create';
-
-export const meta = {
- tags: ['messaging'],
-
- requireCredential: true as const,
-
- kind: 'write:messaging',
-
- params: {
- userId: {
- validator: $.optional.type(ID),
- },
-
- groupId: {
- validator: $.optional.type(ID),
- },
-
- text: {
- validator: $.optional.str.pipe(MessagingMessages.validateText)
- },
-
- fileId: {
- validator: $.optional.type(ID),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'MessagingMessage',
- },
-
- errors: {
- recipientIsYourself: {
- message: 'You can not send a message to yourself.',
- code: 'RECIPIENT_IS_YOURSELF',
- id: '17e2ba79-e22a-4cbc-bf91-d327643f4a7e'
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '11795c64-40ea-4198-b06e-3c873ed9039d'
- },
-
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: 'c94e2a5d-06aa-4914-8fa6-6a42e73d6537'
- },
-
- groupAccessDenied: {
- message: 'You can not send messages to groups that you have not joined.',
- code: 'GROUP_ACCESS_DENIED',
- id: 'd96b3cca-5ad1-438b-ad8b-02f931308fbd'
- },
-
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: '4372b8e2-185d-4146-8749-2f68864a3e5f'
- },
-
- contentRequired: {
- message: 'Content required. You need to set text or fileId.',
- code: 'CONTENT_REQUIRED',
- id: '25587321-b0e6-449c-9239-f8925092942c'
- },
-
- youHaveBeenBlocked: {
- message: 'You cannot send a message because you have been blocked by this user.',
- code: 'YOU_HAVE_BEEN_BLOCKED',
- id: 'c15a5199-7422-4968-941a-2a462c478f7d'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- let recipientUser: User | undefined;
- let recipientGroup: UserGroup | undefined;
-
- if (ps.userId != null) {
- // Myself
- if (ps.userId === user.id) {
- throw new ApiError(meta.errors.recipientIsYourself);
- }
-
- // Fetch recipient (user)
- recipientUser = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check blocking
- const block = await Blockings.findOne({
- blockerId: recipientUser.id,
- blockeeId: user.id,
- });
- if (block) {
- throw new ApiError(meta.errors.youHaveBeenBlocked);
- }
- } else if (ps.groupId != null) {
- // Fetch recipient (group)
- recipientGroup = await UserGroups.findOne(ps.groupId);
-
- if (recipientGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- // check joined
- const joining = await UserGroupJoinings.findOne({
- userId: user.id,
- userGroupId: recipientGroup.id
- });
-
- if (joining == null) {
- throw new ApiError(meta.errors.groupAccessDenied);
- }
- }
-
- let file = null;
- if (ps.fileId != null) {
- file = await DriveFiles.findOne({
- id: ps.fileId,
- userId: user.id
- });
-
- if (file == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- }
-
- // テキストが無いかつ添付ファイルも無かったらエラー
- if (ps.text == null && file == null) {
- throw new ApiError(meta.errors.contentRequired);
- }
-
- return await createMessage(user, recipientUser, recipientGroup, ps.text, file);
-});
diff --git a/src/server/api/endpoints/messaging/messages/delete.ts b/src/server/api/endpoints/messaging/messages/delete.ts
deleted file mode 100644
index bd4890fc8a..0000000000
--- a/src/server/api/endpoints/messaging/messages/delete.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import * as ms from 'ms';
-import { ApiError } from '../../../error';
-import { MessagingMessages } from '@/models/index';
-import { deleteMessage } from '@/services/messages/delete';
-
-export const meta = {
- tags: ['messaging'],
-
- requireCredential: true as const,
-
- kind: 'write:messaging',
-
- limit: {
- duration: ms('1hour'),
- max: 300,
- minInterval: ms('1sec')
- },
-
- params: {
- messageId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchMessage: {
- message: 'No such message.',
- code: 'NO_SUCH_MESSAGE',
- id: '54b5b326-7925-42cf-8019-130fda8b56af'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const message = await MessagingMessages.findOne({
- id: ps.messageId,
- userId: user.id
- });
-
- if (message == null) {
- throw new ApiError(meta.errors.noSuchMessage);
- }
-
- await deleteMessage(message);
-});
diff --git a/src/server/api/endpoints/messaging/messages/read.ts b/src/server/api/endpoints/messaging/messages/read.ts
deleted file mode 100644
index a1747310d3..0000000000
--- a/src/server/api/endpoints/messaging/messages/read.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { MessagingMessages } from '@/models/index';
-import { readUserMessagingMessage, readGroupMessagingMessage } from '../../../common/read-messaging-message';
-
-export const meta = {
- tags: ['messaging'],
-
- requireCredential: true as const,
-
- kind: 'write:messaging',
-
- params: {
- messageId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchMessage: {
- message: 'No such message.',
- code: 'NO_SUCH_MESSAGE',
- id: '86d56a2f-a9c3-4afb-b13c-3e9bfef9aa14'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const message = await MessagingMessages.findOne(ps.messageId);
-
- if (message == null) {
- throw new ApiError(meta.errors.noSuchMessage);
- }
-
- if (message.recipientId) {
- await readUserMessagingMessage(user.id, message.userId, [message.id]).catch(e => {
- if (e.id === 'e140a4bf-49ce-4fb6-b67c-b78dadf6b52f') throw new ApiError(meta.errors.noSuchMessage);
- throw e;
- });
- } else if (message.groupId) {
- await readGroupMessagingMessage(user.id, message.groupId, [message.id]).catch(e => {
- if (e.id === '930a270c-714a-46b2-b776-ad27276dc569') throw new ApiError(meta.errors.noSuchMessage);
- throw e;
- });
- }
-});
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
deleted file mode 100644
index ce21556243..0000000000
--- a/src/server/api/endpoints/meta.ts
+++ /dev/null
@@ -1,598 +0,0 @@
-import $ from 'cafy';
-import config from '@/config/index';
-import define from '../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { Ads, Emojis, Users } from '@/models/index';
-import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits';
-import { MoreThan } from 'typeorm';
-
-export const meta = {
- tags: ['meta'],
-
- requireCredential: false as const,
-
- params: {
- detail: {
- validator: $.optional.bool,
- default: true
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- maintainerName: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- maintainerEmail: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- version: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- example: config.version
- },
- name: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- },
- uri: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url',
- example: 'https://misskey.example.com'
- },
- description: {
- type: 'string' as const,
- optional: false as const, nullable: true as const,
- },
- langs: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- tosUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- repositoryUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- default: 'https://github.com/misskey-dev/misskey'
- },
- feedbackUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- default: 'https://github.com/misskey-dev/misskey/issues/new'
- },
- secure: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- default: false
- },
- disableRegistration: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- disableLocalTimeline: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- disableGlobalTimeline: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- },
- driveCapacityPerLocalUserMb: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- driveCapacityPerRemoteUserMb: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- cacheRemoteFiles: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- proxyRemoteFiles: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- emailRequiredForSignup: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- enableHcaptcha: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- hcaptchaSiteKey: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- enableRecaptcha: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- recaptchaSiteKey: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- swPublickey: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- mascotImageUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- default: '/assets/ai.png'
- },
- bannerUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- errorImageUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- default: 'https://xn--931a.moe/aiart/yubitun.png'
- },
- iconUrl: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- maxNoteTextLength: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- default: 500
- },
- emojis: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- aliases: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- category: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- host: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- url: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url'
- }
- }
- }
- },
- ads: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- place: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- url: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url'
- },
- imageUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'url'
- },
- }
- }
- },
- requireSetup: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- example: false
- },
- enableEmail: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- enableTwitterIntegration: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- enableGithubIntegration: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- enableDiscordIntegration: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- enableServiceWorker: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- translatorAvailable: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- proxyAccountName: {
- type: 'string' as const,
- optional: false as const, nullable: true as const
- },
- features: {
- type: 'object' as const,
- optional: true as const, nullable: false as const,
- properties: {
- registration: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- localTimeLine: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- globalTimeLine: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- elasticsearch: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- hcaptcha: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- recaptcha: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- objectStorage: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- twitter: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- github: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- discord: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- serviceWorker: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- miauth: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const,
- default: true
- },
- }
- },
- userStarForReactionFallback: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const,
- },
- pinnedUsers: {
- type: 'array' as const,
- optional: true as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- hiddenTags: {
- type: 'array' as const,
- optional: true as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- blockedHosts: {
- type: 'array' as const,
- optional: true as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- hcaptchaSecretKey: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- recaptchaSecretKey: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- proxyAccountId: {
- type: 'string' as const,
- optional: true as const, nullable: true as const,
- format: 'id'
- },
- twitterConsumerKey: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- twitterConsumerSecret: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- githubClientId: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- githubClientSecret: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- discordClientId: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- discordClientSecret: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- summaryProxy: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- email: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- smtpSecure: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const
- },
- smtpHost: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- smtpPort: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- smtpUser: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- smtpPass: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- swPrivateKey: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- useObjectStorage: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const
- },
- objectStorageBaseUrl: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStorageBucket: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStoragePrefix: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStorageEndpoint: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStorageRegion: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStoragePort: {
- type: 'number' as const,
- optional: true as const, nullable: true as const
- },
- objectStorageAccessKey: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStorageSecretKey: {
- type: 'string' as const,
- optional: true as const, nullable: true as const
- },
- objectStorageUseSSL: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const
- },
- objectStorageUseProxy: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const
- },
- objectStorageSetPublicRead: {
- type: 'boolean' as const,
- optional: true as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const instance = await fetchMeta(true);
-
- const emojis = await Emojis.find({
- where: {
- host: null
- },
- order: {
- category: 'ASC',
- name: 'ASC'
- },
- cache: {
- id: 'meta_emojis',
- milliseconds: 3600000 // 1 hour
- }
- });
-
- const ads = await Ads.find({
- where: {
- expiresAt: MoreThan(new Date())
- },
- });
-
- const response: any = {
- maintainerName: instance.maintainerName,
- maintainerEmail: instance.maintainerEmail,
-
- version: config.version,
-
- name: instance.name,
- uri: config.url,
- description: instance.description,
- langs: instance.langs,
- tosUrl: instance.ToSUrl,
- repositoryUrl: instance.repositoryUrl,
- feedbackUrl: instance.feedbackUrl,
-
- secure: config.https != null,
-
- disableRegistration: instance.disableRegistration,
- disableLocalTimeline: instance.disableLocalTimeline,
- disableGlobalTimeline: instance.disableGlobalTimeline,
- driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
- driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
- emailRequiredForSignup: instance.emailRequiredForSignup,
- enableHcaptcha: instance.enableHcaptcha,
- hcaptchaSiteKey: instance.hcaptchaSiteKey,
- enableRecaptcha: instance.enableRecaptcha,
- recaptchaSiteKey: instance.recaptchaSiteKey,
- swPublickey: instance.swPublicKey,
- mascotImageUrl: instance.mascotImageUrl,
- bannerUrl: instance.bannerUrl,
- errorImageUrl: instance.errorImageUrl,
- iconUrl: instance.iconUrl,
- backgroundImageUrl: instance.backgroundImageUrl,
- logoImageUrl: instance.logoImageUrl,
- maxNoteTextLength: Math.min(instance.maxNoteTextLength, DB_MAX_NOTE_TEXT_LENGTH),
- emojis: await Emojis.packMany(emojis),
- ads: ads.map(ad => ({
- id: ad.id,
- url: ad.url,
- place: ad.place,
- ratio: ad.ratio,
- imageUrl: ad.imageUrl,
- })),
- enableEmail: instance.enableEmail,
-
- enableTwitterIntegration: instance.enableTwitterIntegration,
- enableGithubIntegration: instance.enableGithubIntegration,
- enableDiscordIntegration: instance.enableDiscordIntegration,
-
- enableServiceWorker: instance.enableServiceWorker,
-
- translatorAvailable: instance.deeplAuthKey != null,
-
- ...(ps.detail ? {
- pinnedPages: instance.pinnedPages,
- pinnedClipId: instance.pinnedClipId,
- cacheRemoteFiles: instance.cacheRemoteFiles,
- proxyRemoteFiles: instance.proxyRemoteFiles,
- requireSetup: (await Users.count({
- host: null,
- })) === 0,
- } : {})
- };
-
- if (ps.detail) {
- const proxyAccount = instance.proxyAccountId ? await Users.pack(instance.proxyAccountId).catch(() => null) : null;
-
- response.proxyAccountName = proxyAccount ? proxyAccount.username : null;
- response.features = {
- registration: !instance.disableRegistration,
- localTimeLine: !instance.disableLocalTimeline,
- globalTimeLine: !instance.disableGlobalTimeline,
- emailRequiredForSignup: instance.emailRequiredForSignup,
- elasticsearch: config.elasticsearch ? true : false,
- hcaptcha: instance.enableHcaptcha,
- recaptcha: instance.enableRecaptcha,
- objectStorage: instance.useObjectStorage,
- twitter: instance.enableTwitterIntegration,
- github: instance.enableGithubIntegration,
- discord: instance.enableDiscordIntegration,
- serviceWorker: instance.enableServiceWorker,
- miauth: true,
- };
-
- if (me && me.isAdmin) {
- response.useStarForReactionFallback = instance.useStarForReactionFallback;
- response.pinnedUsers = instance.pinnedUsers;
- response.hiddenTags = instance.hiddenTags;
- response.blockedHosts = instance.blockedHosts;
- response.hcaptchaSecretKey = instance.hcaptchaSecretKey;
- response.recaptchaSecretKey = instance.recaptchaSecretKey;
- response.proxyAccountId = instance.proxyAccountId;
- response.twitterConsumerKey = instance.twitterConsumerKey;
- response.twitterConsumerSecret = instance.twitterConsumerSecret;
- response.githubClientId = instance.githubClientId;
- response.githubClientSecret = instance.githubClientSecret;
- response.discordClientId = instance.discordClientId;
- response.discordClientSecret = instance.discordClientSecret;
- response.summalyProxy = instance.summalyProxy;
- response.email = instance.email;
- response.smtpSecure = instance.smtpSecure;
- response.smtpHost = instance.smtpHost;
- response.smtpPort = instance.smtpPort;
- response.smtpUser = instance.smtpUser;
- response.smtpPass = instance.smtpPass;
- response.swPrivateKey = instance.swPrivateKey;
- response.useObjectStorage = instance.useObjectStorage;
- response.objectStorageBaseUrl = instance.objectStorageBaseUrl;
- response.objectStorageBucket = instance.objectStorageBucket;
- response.objectStoragePrefix = instance.objectStoragePrefix;
- response.objectStorageEndpoint = instance.objectStorageEndpoint;
- response.objectStorageRegion = instance.objectStorageRegion;
- response.objectStoragePort = instance.objectStoragePort;
- response.objectStorageAccessKey = instance.objectStorageAccessKey;
- response.objectStorageSecretKey = instance.objectStorageSecretKey;
- response.objectStorageUseSSL = instance.objectStorageUseSSL;
- response.objectStorageUseProxy = instance.objectStorageUseProxy;
- response.objectStorageSetPublicRead = instance.objectStorageSetPublicRead;
- response.objectStorageS3ForcePathStyle = instance.objectStorageS3ForcePathStyle;
- response.deeplAuthKey = instance.deeplAuthKey;
- response.deeplIsPro = instance.deeplIsPro;
- }
- }
-
- return response;
-});
diff --git a/src/server/api/endpoints/miauth/gen-token.ts b/src/server/api/endpoints/miauth/gen-token.ts
deleted file mode 100644
index 321fa42fc9..0000000000
--- a/src/server/api/endpoints/miauth/gen-token.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { AccessTokens } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { secureRndstr } from '@/misc/secure-rndstr';
-
-export const meta = {
- tags: ['auth'],
-
- requireCredential: true as const,
-
- secure: true,
-
- params: {
- session: {
- validator: $.nullable.str
- },
-
- name: {
- validator: $.nullable.optional.str
- },
-
- description: {
- validator: $.nullable.optional.str,
- },
-
- iconUrl: {
- validator: $.nullable.optional.str,
- },
-
- permission: {
- validator: $.arr($.str).unique(),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- token: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Generate access token
- const accessToken = secureRndstr(32, true);
-
- const now = new Date();
-
- // Insert access token doc
- await AccessTokens.insert({
- id: genId(),
- createdAt: now,
- lastUsedAt: now,
- session: ps.session,
- userId: user.id,
- token: accessToken,
- hash: accessToken,
- name: ps.name,
- description: ps.description,
- iconUrl: ps.iconUrl,
- permission: ps.permission,
- });
-
- return {
- token: accessToken
- };
-});
diff --git a/src/server/api/endpoints/mute/create.ts b/src/server/api/endpoints/mute/create.ts
deleted file mode 100644
index 3fc64d3eba..0000000000
--- a/src/server/api/endpoints/mute/create.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { genId } from '@/misc/gen-id';
-import { Mutings, NoteWatchings } from '@/models/index';
-import { Muting } from '@/models/entities/muting';
-import { publishUserEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'write:mutes',
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '6fef56f3-e765-4957-88e5-c6f65329b8a5'
- },
-
- muteeIsYourself: {
- message: 'Mutee is yourself.',
- code: 'MUTEE_IS_YOURSELF',
- id: 'a4619cb2-5f23-484b-9301-94c903074e10'
- },
-
- alreadyMuting: {
- message: 'You are already muting that user.',
- code: 'ALREADY_MUTING',
- id: '7e7359cb-160c-4956-b08f-4d1c653cd007'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const muter = user;
-
- // 自分自身
- if (user.id === ps.userId) {
- throw new ApiError(meta.errors.muteeIsYourself);
- }
-
- // Get mutee
- const mutee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check if already muting
- const exist = await Mutings.findOne({
- muterId: muter.id,
- muteeId: mutee.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyMuting);
- }
-
- // Create mute
- await Mutings.insert({
- id: genId(),
- createdAt: new Date(),
- muterId: muter.id,
- muteeId: mutee.id,
- } as Muting);
-
- publishUserEvent(user.id, 'mute', mutee);
-
- NoteWatchings.delete({
- userId: muter.id,
- noteUserId: mutee.id
- });
-});
diff --git a/src/server/api/endpoints/mute/delete.ts b/src/server/api/endpoints/mute/delete.ts
deleted file mode 100644
index 3ffd1f4562..0000000000
--- a/src/server/api/endpoints/mute/delete.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { Mutings } from '@/models/index';
-import { publishUserEvent } from '@/services/stream';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'write:mutes',
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: 'b851d00b-8ab1-4a56-8b1b-e24187cb48ef'
- },
-
- muteeIsYourself: {
- message: 'Mutee is yourself.',
- code: 'MUTEE_IS_YOURSELF',
- id: 'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9'
- },
-
- notMuting: {
- message: 'You are not muting that user.',
- code: 'NOT_MUTING',
- id: '5467d020-daa9-4553-81e1-135c0c35a96d'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const muter = user;
-
- // Check if the mutee is yourself
- if (user.id === ps.userId) {
- throw new ApiError(meta.errors.muteeIsYourself);
- }
-
- // Get mutee
- const mutee = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check not muting
- const exist = await Mutings.findOne({
- muterId: muter.id,
- muteeId: mutee.id
- });
-
- if (exist == null) {
- throw new ApiError(meta.errors.notMuting);
- }
-
- // Delete mute
- await Mutings.delete({
- id: exist.id
- });
-
- publishUserEvent(user.id, 'unmute', mutee);
-});
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
deleted file mode 100644
index ae4c3a719d..0000000000
--- a/src/server/api/endpoints/mute/list.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Mutings } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- kind: 'read:mutes',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 30
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Muting',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Mutings.createQueryBuilder('muting'), ps.sinceId, ps.untilId)
- .andWhere(`muting.muterId = :meId`, { meId: me.id });
-
- const mutings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Mutings.packMany(mutings, me);
-});
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
deleted file mode 100644
index d91562b62f..0000000000
--- a/src/server/api/endpoints/my/apps.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Apps } from '@/models/index';
-
-export const meta = {
- tags: ['account', 'app'],
-
- requireCredential: true as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- name: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- callbackUrl: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- permission: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- },
- secret: {
- type: 'string' as const,
- optional: true as const, nullable: false as const
- },
- isAuthorized: {
- type: 'object' as const,
- optional: true as const, nullable: false as const,
- properties: {
- appId: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- userId: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = {
- userId: user.id
- };
-
- const apps = await Apps.find({
- where: query,
- take: ps.limit!,
- skip: ps.offset,
- });
-
- return await Promise.all(apps.map(app => Apps.pack(app, user, {
- detail: true
- })));
-});
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
deleted file mode 100644
index a3f6e187f2..0000000000
--- a/src/server/api/endpoints/notes.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../define';
-import { makePaginationQuery } from '../common/make-pagination-query';
-import { Notes } from '@/models/index';
-
-export const meta = {
- tags: ['notes'],
-
- params: {
- local: {
- validator: $.optional.bool,
- },
-
- reply: {
- validator: $.optional.bool,
- },
-
- renote: {
- validator: $.optional.bool,
- },
-
- withFiles: {
- validator: $.optional.bool,
- },
-
- poll: {
- validator: $.optional.bool,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps) => {
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.visibility = 'public'`)
- .andWhere(`note.localOnly = FALSE`)
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- if (ps.local) {
- query.andWhere('note.userHost IS NULL');
- }
-
- if (ps.reply != undefined) {
- query.andWhere(ps.reply ? 'note.replyId IS NOT NULL' : 'note.replyId IS NULL');
- }
-
- if (ps.renote != undefined) {
- query.andWhere(ps.renote ? 'note.renoteId IS NOT NULL' : 'note.renoteId IS NULL');
- }
-
- if (ps.withFiles != undefined) {
- query.andWhere(ps.withFiles ? `note.fileIds != '{}'` : `note.fileIds = '{}'`);
- }
-
- if (ps.poll != undefined) {
- query.andWhere(ps.poll ? 'note.hasPoll = TRUE' : 'note.hasPoll = FALSE');
- }
-
- // TODO
- //if (bot != undefined) {
- // query.isBot = bot;
- //}
-
- const notes = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(notes);
-});
diff --git a/src/server/api/endpoints/notes/children.ts b/src/server/api/endpoints/notes/children.ts
deleted file mode 100644
index 68881fda9e..0000000000
--- a/src/server/api/endpoints/notes/children.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { Brackets } from 'typeorm';
-import { Notes } from '@/models/index';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(new Brackets(qb => { qb
- .where(`note.replyId = :noteId`, { noteId: ps.noteId })
- .orWhere(new Brackets(qb => { qb
- .where(`note.renoteId = :noteId`, { noteId: ps.noteId })
- .andWhere(new Brackets(qb => { qb
- .where(`note.text IS NOT NULL`)
- .orWhere(`note.fileIds != '{}'`)
- .orWhere(`note.hasPoll = TRUE`);
- }));
- }));
- }))
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, user);
- if (user) generateMutedUserQuery(query, user);
- if (user) generateBlockedUserQuery(query, user);
-
- const notes = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(notes, user);
-});
diff --git a/src/server/api/endpoints/notes/clips.ts b/src/server/api/endpoints/notes/clips.ts
deleted file mode 100644
index 6b303d87ec..0000000000
--- a/src/server/api/endpoints/notes/clips.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ClipNotes, Clips } from '@/models/index';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import { In } from 'typeorm';
-
-export const meta = {
- tags: ['clips', 'notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '47db1a1c-b0af-458d-8fb4-986e4efafe1e'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const clipNotes = await ClipNotes.find({
- noteId: note.id,
- });
-
- const clips = await Clips.find({
- id: In(clipNotes.map(x => x.clipId)),
- isPublic: true
- });
-
- return await Promise.all(clips.map(x => Clips.pack(x)));
-});
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
deleted file mode 100644
index 0fe323ea00..0000000000
--- a/src/server/api/endpoints/notes/conversation.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getNote } from '../../common/getters';
-import { Note } from '@/models/entities/note';
-import { Notes } from '@/models/index';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'e1035875-9551-45ec-afa8-1ded1fcb53c8'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const conversation: Note[] = [];
- let i = 0;
-
- async function get(id: any) {
- i++;
- const p = await Notes.findOne(id);
- if (p == null) return;
-
- if (i > ps.offset!) {
- conversation.push(p);
- }
-
- if (conversation.length == ps.limit!) {
- return;
- }
-
- if (p.replyId) {
- await get(p.replyId);
- }
- }
-
- if (note.replyId) {
- await get(note.replyId);
- }
-
- return await Notes.packMany(conversation, user);
-});
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
deleted file mode 100644
index 751673f955..0000000000
--- a/src/server/api/endpoints/notes/create.ts
+++ /dev/null
@@ -1,299 +0,0 @@
-import $ from 'cafy';
-import * as ms from 'ms';
-import { length } from 'stringz';
-import create from '@/services/note/create';
-import define from '../../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { ApiError } from '../../error';
-import { ID } from '@/misc/cafy-id';
-import { User } from '@/models/entities/user';
-import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index';
-import { DriveFile } from '@/models/entities/drive-file';
-import { Note } from '@/models/entities/note';
-import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits';
-import { noteVisibilities } from '../../../../types';
-import { Channel } from '@/models/entities/channel';
-
-let maxNoteTextLength = 500;
-
-setInterval(() => {
- fetchMeta().then(m => {
- maxNoteTextLength = m.maxNoteTextLength;
- });
-}, 3000);
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- limit: {
- duration: ms('1hour'),
- max: 300
- },
-
- kind: 'write:notes',
-
- params: {
- visibility: {
- validator: $.optional.str.or(noteVisibilities as unknown as string[]),
- default: 'public',
- },
-
- visibleUserIds: {
- validator: $.optional.arr($.type(ID)).unique().min(0),
- },
-
- text: {
- validator: $.optional.nullable.str.pipe(text =>
- text.trim() != ''
- && length(text.trim()) <= maxNoteTextLength
- && Array.from(text.trim()).length <= DB_MAX_NOTE_TEXT_LENGTH // DB limit
- ),
- default: null,
- },
-
- cw: {
- validator: $.optional.nullable.str.pipe(Notes.validateCw),
- },
-
- viaMobile: {
- validator: $.optional.bool,
- default: false,
- },
-
- localOnly: {
- validator: $.optional.bool,
- default: false,
- },
-
- noExtractMentions: {
- validator: $.optional.bool,
- default: false,
- },
-
- noExtractHashtags: {
- validator: $.optional.bool,
- default: false,
- },
-
- noExtractEmojis: {
- validator: $.optional.bool,
- default: false,
- },
-
- fileIds: {
- validator: $.optional.arr($.type(ID)).unique().range(1, 4),
- },
-
- mediaIds: {
- validator: $.optional.arr($.type(ID)).unique().range(1, 4),
- deprecated: true,
- },
-
- replyId: {
- validator: $.optional.nullable.type(ID),
- },
-
- renoteId: {
- validator: $.optional.nullable.type(ID),
- },
-
- channelId: {
- validator: $.optional.nullable.type(ID),
- },
-
- poll: {
- validator: $.optional.nullable.obj({
- choices: $.arr($.str)
- .unique()
- .range(2, 10)
- .each(c => c.length > 0 && c.length < 50),
- multiple: $.optional.bool,
- expiresAt: $.optional.nullable.num.int(),
- expiredAfter: $.optional.nullable.num.int().min(1)
- }).strict(),
- ref: 'poll'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- createdNote: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- }
- },
-
- errors: {
- noSuchRenoteTarget: {
- message: 'No such renote target.',
- code: 'NO_SUCH_RENOTE_TARGET',
- id: 'b5c90186-4ab0-49c8-9bba-a1f76c282ba4'
- },
-
- cannotReRenote: {
- message: 'You can not Renote a pure Renote.',
- code: 'CANNOT_RENOTE_TO_A_PURE_RENOTE',
- id: 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a'
- },
-
- noSuchReplyTarget: {
- message: 'No such reply target.',
- code: 'NO_SUCH_REPLY_TARGET',
- id: '749ee0f6-d3da-459a-bf02-282e2da4292c'
- },
-
- cannotReplyToPureRenote: {
- message: 'You can not reply to a pure Renote.',
- code: 'CANNOT_REPLY_TO_A_PURE_RENOTE',
- id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15'
- },
-
- contentRequired: {
- message: 'Content required. You need to set text, fileIds, renoteId or poll.',
- code: 'CONTENT_REQUIRED',
- id: '6f57e42b-c348-439b-bc45-993995cc515a'
- },
-
- cannotCreateAlreadyExpiredPoll: {
- message: 'Poll is already expired.',
- code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL',
- id: '04da457d-b083-4055-9082-955525eda5a5'
- },
-
- noSuchChannel: {
- message: 'No such channel.',
- code: 'NO_SUCH_CHANNEL',
- id: 'b1653923-5453-4edc-b786-7c4f39bb0bbb'
- },
-
- youHaveBeenBlocked: {
- message: 'You have been blocked by this user.',
- code: 'YOU_HAVE_BEEN_BLOCKED',
- id: 'b390d7e1-8a5e-46ed-b625-06271cafd3d3'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- let visibleUsers: User[] = [];
- if (ps.visibleUserIds) {
- visibleUsers = (await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id))))
- .filter(x => x != null) as User[];
- }
-
- let files: DriveFile[] = [];
- const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null;
- if (fileIds != null) {
- files = (await Promise.all(fileIds.map(fileId =>
- DriveFiles.findOne({
- id: fileId,
- userId: user.id
- })
- ))).filter(file => file != null) as DriveFile[];
- }
-
- let renote: Note | undefined;
- if (ps.renoteId != null) {
- // Fetch renote to note
- renote = await Notes.findOne(ps.renoteId);
-
- if (renote == null) {
- throw new ApiError(meta.errors.noSuchRenoteTarget);
- } else if (renote.renoteId && !renote.text && !renote.fileIds) {
- throw new ApiError(meta.errors.cannotReRenote);
- }
-
- // Check blocking
- if (renote.userId !== user.id) {
- const block = await Blockings.findOne({
- blockerId: renote.userId,
- blockeeId: user.id,
- });
- if (block) {
- throw new ApiError(meta.errors.youHaveBeenBlocked);
- }
- }
- }
-
- let reply: Note | undefined;
- if (ps.replyId != null) {
- // Fetch reply
- reply = await Notes.findOne(ps.replyId);
-
- if (reply == null) {
- throw new ApiError(meta.errors.noSuchReplyTarget);
- }
-
- // 返信対象が引用でないRenoteだったらエラー
- if (reply.renoteId && !reply.text && !reply.fileIds) {
- throw new ApiError(meta.errors.cannotReplyToPureRenote);
- }
-
- // Check blocking
- if (reply.userId !== user.id) {
- const block = await Blockings.findOne({
- blockerId: reply.userId,
- blockeeId: user.id,
- });
- if (block) {
- throw new ApiError(meta.errors.youHaveBeenBlocked);
- }
- }
- }
-
- if (ps.poll) {
- if (typeof ps.poll.expiresAt === 'number') {
- if (ps.poll.expiresAt < Date.now())
- throw new ApiError(meta.errors.cannotCreateAlreadyExpiredPoll);
- } else if (typeof ps.poll.expiredAfter === 'number') {
- ps.poll.expiresAt = Date.now() + ps.poll.expiredAfter;
- }
- }
-
- // テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
- if (!(ps.text || files.length || renote || ps.poll)) {
- throw new ApiError(meta.errors.contentRequired);
- }
-
- let channel: Channel | undefined;
- if (ps.channelId != null) {
- channel = await Channels.findOne(ps.channelId);
-
- if (channel == null) {
- throw new ApiError(meta.errors.noSuchChannel);
- }
- }
-
- // 投稿を作成
- const note = await create(user, {
- createdAt: new Date(),
- files: files,
- poll: ps.poll ? {
- choices: ps.poll.choices,
- multiple: ps.poll.multiple || false,
- expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null
- } : undefined,
- text: ps.text || undefined,
- reply,
- renote,
- cw: ps.cw,
- viaMobile: ps.viaMobile,
- localOnly: ps.localOnly,
- visibility: ps.visibility,
- visibleUsers,
- channel,
- apMentions: ps.noExtractMentions ? [] : undefined,
- apHashtags: ps.noExtractHashtags ? [] : undefined,
- apEmojis: ps.noExtractEmojis ? [] : undefined,
- });
-
- return {
- createdNote: await Notes.pack(note, user)
- };
-});
diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts
deleted file mode 100644
index 7163a2b9d2..0000000000
--- a/src/server/api/endpoints/notes/delete.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import deleteNote from '@/services/note/delete';
-import define from '../../define';
-import * as ms from 'ms';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:notes',
-
- limit: {
- duration: ms('1hour'),
- max: 300,
- minInterval: ms('1sec')
- },
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '490be23f-8c1f-4796-819f-94cb4f9d1630'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: 'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- if (!user.isAdmin && !user.isModerator && (note.userId !== user.id)) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- // この操作を行うのが投稿者とは限らない(例えばモデレーター)ため
- await deleteNote(await Users.findOneOrFail(note.userId), note);
-});
diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts
deleted file mode 100644
index 1bb25edd7f..0000000000
--- a/src/server/api/endpoints/notes/favorites/create.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getNote } from '../../../common/getters';
-import { NoteFavorites } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['notes', 'favorites'],
-
- requireCredential: true as const,
-
- kind: 'write:favorites',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '6dd26674-e060-4816-909a-45ba3f4da458'
- },
-
- alreadyFavorited: {
- message: 'The note has already been marked as a favorite.',
- code: 'ALREADY_FAVORITED',
- id: 'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Get favoritee
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- // if already favorited
- const exist = await NoteFavorites.findOne({
- noteId: note.id,
- userId: user.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyFavorited);
- }
-
- // Create favorite
- await NoteFavorites.insert({
- id: genId(),
- createdAt: new Date(),
- noteId: note.id,
- userId: user.id
- });
-});
diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts
deleted file mode 100644
index 75eb9a359a..0000000000
--- a/src/server/api/endpoints/notes/favorites/delete.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getNote } from '../../../common/getters';
-import { NoteFavorites } from '@/models/index';
-
-export const meta = {
- tags: ['notes', 'favorites'],
-
- requireCredential: true as const,
-
- kind: 'write:favorites',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '80848a2c-398f-4343-baa9-df1d57696c56'
- },
-
- notFavorited: {
- message: 'You have not marked that note a favorite.',
- code: 'NOT_FAVORITED',
- id: 'b625fc69-635e-45e9-86f4-dbefbef35af5'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Get favoritee
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- // if already favorited
- const exist = await NoteFavorites.findOne({
- noteId: note.id,
- userId: user.id
- });
-
- if (exist == null) {
- throw new ApiError(meta.errors.notFavorited);
- }
-
- // Delete favorite
- await NoteFavorites.delete(exist.id);
-});
diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts
deleted file mode 100644
index 8d33c0e73d..0000000000
--- a/src/server/api/endpoints/notes/featured.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { Notes } from '@/models/index';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const max = 30;
- const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
-
- const query = Notes.createQueryBuilder('note')
- .addSelect('note.score')
- .where('note.userHost IS NULL')
- .andWhere(`note.score > 0`)
- .andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) })
- .andWhere(`note.visibility = 'public'`)
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- if (user) generateMutedUserQuery(query, user);
- if (user) generateBlockedUserQuery(query, user);
-
- let notes = await query
- .orderBy('note.score', 'DESC')
- .take(max)
- .getMany();
-
- notes.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
-
- notes = notes.slice(ps.offset, ps.offset + ps.limit);
-
- return await Notes.packMany(notes, user);
-});
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
deleted file mode 100644
index 5902c0415c..0000000000
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { ApiError } from '../../error';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Notes } from '@/models/index';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { activeUsersChart } from '@/services/chart/index';
-import { generateRepliesQuery } from '../../common/generate-replies-query';
-import { generateMutedNoteQuery } from '../../common/generate-muted-note-query';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- params: {
- withFiles: {
- validator: $.optional.bool,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num
- },
-
- untilDate: {
- validator: $.optional.num
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- gtlDisabled: {
- message: 'Global timeline has been disabled.',
- code: 'GTL_DISABLED',
- id: '0332fc13-6ab2-4427-ae80-a9fadffd1a6b'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const m = await fetchMeta();
- if (m.disableGlobalTimeline) {
- if (user == null || (!user.isAdmin && !user.isModerator)) {
- throw new ApiError(meta.errors.gtlDisabled);
- }
- }
-
- //#region Construct query
- const query = makePaginationQuery(Notes.createQueryBuilder('note'),
- ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere('note.visibility = \'public\'')
- .andWhere('note.channelId IS NULL')
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateRepliesQuery(query, user);
- if (user) generateMutedUserQuery(query, user);
- if (user) generateMutedNoteQuery(query, user);
- if (user) generateBlockedUserQuery(query, user);
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- process.nextTick(() => {
- if (user) {
- activeUsersChart.update(user);
- }
- });
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts
deleted file mode 100644
index 47f08f208b..0000000000
--- a/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { ApiError } from '../../error';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Followings, Notes } from '@/models/index';
-import { Brackets } from 'typeorm';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { activeUsersChart } from '@/services/chart/index';
-import { generateRepliesQuery } from '../../common/generate-replies-query';
-import { generateMutedNoteQuery } from '../../common/generate-muted-note-query';
-import { generateChannelQuery } from '../../common/generate-channel-query';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
-
- includeMyRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- includeRenotedMyNotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- includeLocalRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- withFiles: {
- validator: $.optional.bool,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- stlDisabled: {
- message: 'Hybrid timeline has been disabled.',
- code: 'STL_DISABLED',
- id: '620763f4-f621-4533-ab33-0577a1a3c342'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const m = await fetchMeta();
- if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) {
- throw new ApiError(meta.errors.stlDisabled);
- }
-
- //#region Construct query
- const followingQuery = Followings.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: user.id });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'),
- ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere(new Brackets(qb => {
- qb.where(`((note.userId IN (${ followingQuery.getQuery() })) OR (note.userId = :meId))`, { meId: user.id })
- .orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
- }))
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .setParameters(followingQuery.getParameters());
-
- generateChannelQuery(query, user);
- generateRepliesQuery(query, user);
- generateVisibilityQuery(query, user);
- generateMutedUserQuery(query, user);
- generateMutedNoteQuery(query, user);
- generateBlockedUserQuery(query, user);
-
- if (ps.includeMyRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.userId != :meId', { meId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.includeRenotedMyNotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.renoteUserId != :meId', { meId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.includeLocalRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.renoteUserHost IS NOT NULL');
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- process.nextTick(() => {
- if (user) {
- activeUsersChart.update(user);
- }
- });
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
deleted file mode 100644
index f670d478bf..0000000000
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { ApiError } from '../../error';
-import { Notes } from '@/models/index';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { activeUsersChart } from '@/services/chart/index';
-import { Brackets } from 'typeorm';
-import { generateRepliesQuery } from '../../common/generate-replies-query';
-import { generateMutedNoteQuery } from '../../common/generate-muted-note-query';
-import { generateChannelQuery } from '../../common/generate-channel-query';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- params: {
- withFiles: {
- validator: $.optional.bool,
- },
-
- fileType: {
- validator: $.optional.arr($.str),
- },
-
- excludeNsfw: {
- validator: $.optional.bool,
- default: false,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- ltlDisabled: {
- message: 'Local timeline has been disabled.',
- code: 'LTL_DISABLED',
- id: '45a6eb02-7695-4393-b023-dd3be9aaaefd'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const m = await fetchMeta();
- if (m.disableLocalTimeline) {
- if (user == null || (!user.isAdmin && !user.isModerator)) {
- throw new ApiError(meta.errors.ltlDisabled);
- }
- }
-
- //#region Construct query
- const query = makePaginationQuery(Notes.createQueryBuilder('note'),
- ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)')
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateChannelQuery(query, user);
- generateRepliesQuery(query, user);
- generateVisibilityQuery(query, user);
- if (user) generateMutedUserQuery(query, user);
- if (user) generateMutedNoteQuery(query, user);
- if (user) generateBlockedUserQuery(query, user);
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
-
- if (ps.fileType != null) {
- query.andWhere('note.fileIds != \'{}\'');
- 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 });
- }
- }));
-
- if (ps.excludeNsfw) {
- query.andWhere('note.cw IS NULL');
- query.andWhere('0 = (SELECT COUNT(*) FROM drive_file df WHERE df.id = ANY(note."fileIds") AND df."isSensitive" = TRUE)');
- }
- }
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- process.nextTick(() => {
- if (user) {
- activeUsersChart.update(user);
- }
- });
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
deleted file mode 100644
index ffaebd6c95..0000000000
--- a/src/server/api/endpoints/notes/mentions.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import read from '@/services/note/read';
-import { Notes, Followings } from '@/models/index';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Brackets } from 'typeorm';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-import { generateMutedNoteThreadQuery } from '../../common/generate-muted-note-thread-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- params: {
- following: {
- validator: $.optional.bool,
- default: false
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- visibility: {
- validator: $.optional.str,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const followingQuery = Followings.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: user.id });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(new Brackets(qb => { qb
- .where(`'{"${user.id}"}' <@ note.mentions`)
- .orWhere(`'{"${user.id}"}' <@ note.visibleUserIds`);
- }))
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, user);
- generateMutedUserQuery(query, user);
- generateMutedNoteThreadQuery(query, user);
- generateBlockedUserQuery(query, user);
-
- if (ps.visibility) {
- query.andWhere('note.visibility = :visibility', { visibility: ps.visibility });
- }
-
- if (ps.following) {
- query.andWhere(`((note.userId IN (${ followingQuery.getQuery() })) OR (note.userId = :meId))`, { meId: user.id });
- query.setParameters(followingQuery.getParameters());
- }
-
- const mentions = await query.take(ps.limit!).getMany();
-
- read(user.id, mentions);
-
- return await Notes.packMany(mentions, user);
-});
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
deleted file mode 100644
index 0763f0c8fd..0000000000
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { Polls, Mutings, Notes, PollVotes } from '@/models/index';
-import { Brackets, In } from 'typeorm';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = Polls.createQueryBuilder('poll')
- .where('poll.userHost IS NULL')
- .andWhere(`poll.userId != :meId`, { meId: user.id })
- .andWhere(`poll.noteVisibility = 'public'`)
- .andWhere(new Brackets(qb => { qb
- .where('poll.expiresAt IS NULL')
- .orWhere('poll.expiresAt > :now', { now: new Date() });
- }));
-
- //#region exclude arleady voted polls
- const votedQuery = PollVotes.createQueryBuilder('vote')
- .select('vote.noteId')
- .where('vote.userId = :meId', { meId: user.id });
-
- query
- .andWhere(`poll.noteId NOT IN (${ votedQuery.getQuery() })`);
-
- query.setParameters(votedQuery.getParameters());
- //#endregion
-
- //#region mute
- const mutingQuery = Mutings.createQueryBuilder('muting')
- .select('muting.muteeId')
- .where('muting.muterId = :muterId', { muterId: user.id });
-
- query
- .andWhere(`poll.userId NOT IN (${ mutingQuery.getQuery() })`);
-
- query.setParameters(mutingQuery.getParameters());
- //#endregion
-
- const polls = await query.take(ps.limit!).skip(ps.offset).getMany();
-
- if (polls.length === 0) return [];
-
- const notes = await Notes.find({
- id: In(polls.map(poll => poll.noteId))
- });
-
- return await Notes.packMany(notes, user, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts
deleted file mode 100644
index f670501385..0000000000
--- a/src/server/api/endpoints/notes/polls/vote.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishNoteStream } from '@/services/stream';
-import { createNotification } from '@/services/create-notification';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getNote } from '../../../common/getters';
-import { deliver } from '@/queue/index';
-import { renderActivity } from '@/remote/activitypub/renderer/index';
-import renderVote from '@/remote/activitypub/renderer/vote';
-import { deliverQuestionUpdate } from '@/services/note/polls/update';
-import { PollVotes, NoteWatchings, Users, Polls, Blockings } from '@/models/index';
-import { Not } from 'typeorm';
-import { IRemoteUser } from '@/models/entities/user';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:votes',
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- choice: {
- validator: $.num
- },
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'ecafbd2e-c283-4d6d-aecb-1a0a33b75396'
- },
-
- noPoll: {
- message: 'The note does not attach a poll.',
- code: 'NO_POLL',
- id: '5f979967-52d9-4314-a911-1c673727f92f'
- },
-
- invalidChoice: {
- message: 'Choice ID is invalid.',
- code: 'INVALID_CHOICE',
- id: 'e0cc9a04-f2e8-41e4-a5f1-4127293260cc'
- },
-
- alreadyVoted: {
- message: 'You have already voted.',
- code: 'ALREADY_VOTED',
- id: '0963fc77-efac-419b-9424-b391608dc6d8'
- },
-
- alreadyExpired: {
- message: 'The poll is already expired.',
- code: 'ALREADY_EXPIRED',
- id: '1022a357-b085-4054-9083-8f8de358337e'
- },
-
- youHaveBeenBlocked: {
- message: 'You cannot vote this poll because you have been blocked by this user.',
- code: 'YOU_HAVE_BEEN_BLOCKED',
- id: '85a5377e-b1e9-4617-b0b9-5bea73331e49'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const createdAt = new Date();
-
- // Get votee
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- if (!note.hasPoll) {
- throw new ApiError(meta.errors.noPoll);
- }
-
- // Check blocking
- if (note.userId !== user.id) {
- const block = await Blockings.findOne({
- blockerId: note.userId,
- blockeeId: user.id,
- });
- if (block) {
- throw new ApiError(meta.errors.youHaveBeenBlocked);
- }
- }
-
- const poll = await Polls.findOneOrFail({ noteId: note.id });
-
- if (poll.expiresAt && poll.expiresAt < createdAt) {
- throw new ApiError(meta.errors.alreadyExpired);
- }
-
- if (poll.choices[ps.choice] == null) {
- throw new ApiError(meta.errors.invalidChoice);
- }
-
- // if already voted
- const exist = await PollVotes.find({
- noteId: note.id,
- userId: user.id
- });
-
- if (exist.length) {
- if (poll.multiple) {
- if (exist.some(x => x.choice == ps.choice))
- throw new ApiError(meta.errors.alreadyVoted);
- } else {
- throw new ApiError(meta.errors.alreadyVoted);
- }
- }
-
- // Create vote
- const vote = await PollVotes.insert({
- id: genId(),
- createdAt,
- noteId: note.id,
- userId: user.id,
- choice: ps.choice
- }).then(x => PollVotes.findOneOrFail(x.identifiers[0]));
-
- // Increment votes count
- const index = ps.choice + 1; // In SQL, array index is 1 based
- await Polls.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE "noteId" = '${poll.noteId}'`);
-
- publishNoteStream(note.id, 'pollVoted', {
- choice: ps.choice,
- userId: user.id
- });
-
- // Notify
- createNotification(note.userId, 'pollVote', {
- notifierId: user.id,
- noteId: note.id,
- choice: ps.choice
- });
-
- // Fetch watchers
- NoteWatchings.find({
- noteId: note.id,
- userId: Not(user.id),
- }).then(watchers => {
- for (const watcher of watchers) {
- createNotification(watcher.userId, 'pollVote', {
- notifierId: user.id,
- noteId: note.id,
- choice: ps.choice
- });
- }
- });
-
- // リモート投票の場合リプライ送信
- if (note.userHost != null) {
- const pollOwner = await Users.findOneOrFail(note.userId) as IRemoteUser;
-
- deliver(user, renderActivity(await renderVote(user, vote, note, poll, pollOwner)), pollOwner.inbox);
- }
-
- // リモートフォロワーにUpdate配信
- deliverQuestionUpdate(note.id);
-});
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
deleted file mode 100644
index 09dd6b600b..0000000000
--- a/src/server/api/endpoints/notes/reactions.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import { NoteReactions } from '@/models/index';
-import { DeepPartial } from 'typeorm';
-import { NoteReaction } from '@/models/entities/note-reaction';
-
-export const meta = {
- tags: ['notes', 'reactions'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- type: {
- validator: $.optional.nullable.str,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num,
- default: 0
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'NoteReaction',
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '263fff3d-d0e1-4af4-bea7-8408059b451a'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const query = {
- noteId: note.id
- } as DeepPartial<NoteReaction>;
-
- if (ps.type) {
- // ローカルリアクションはホスト名が . とされているが
- // DB 上ではそうではないので、必要に応じて変換
- const suffix = '@.:';
- const type = ps.type.endsWith(suffix) ? ps.type.slice(0, ps.type.length - suffix.length) + ':' : ps.type;
- query.reaction = type;
- }
-
- const reactions = await NoteReactions.find({
- where: query,
- take: ps.limit!,
- skip: ps.offset,
- order: {
- id: -1
- }
- });
-
- return await Promise.all(reactions.map(reaction => NoteReactions.pack(reaction, user)));
-});
diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts
deleted file mode 100644
index 24a73a8d4f..0000000000
--- a/src/server/api/endpoints/notes/reactions/create.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import createReaction from '@/services/note/reaction/create';
-import define from '../../../define';
-import { getNote } from '../../../common/getters';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['reactions', 'notes'],
-
- requireCredential: true as const,
-
- kind: 'write:reactions',
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- reaction: {
- validator: $.str,
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '033d0620-5bfe-4027-965d-980b0c85a3ea'
- },
-
- alreadyReacted: {
- message: 'You are already reacting to that note.',
- code: 'ALREADY_REACTED',
- id: '71efcf98-86d6-4e2b-b2ad-9d032369366b'
- },
-
- youHaveBeenBlocked: {
- message: 'You cannot react this note because you have been blocked by this user.',
- code: 'YOU_HAVE_BEEN_BLOCKED',
- id: '20ef5475-9f38-4e4c-bd33-de6d979498ec'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
- await createReaction(user, note, ps.reaction).catch(e => {
- if (e.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError(meta.errors.alreadyReacted);
- if (e.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError(meta.errors.youHaveBeenBlocked);
- throw e;
- });
- return;
-});
diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts
deleted file mode 100644
index 69550f96de..0000000000
--- a/src/server/api/endpoints/notes/reactions/delete.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import * as ms from 'ms';
-import deleteReaction from '@/services/note/reaction/delete';
-import { getNote } from '../../../common/getters';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['reactions', 'notes'],
-
- requireCredential: true as const,
-
- kind: 'write:reactions',
-
- limit: {
- duration: ms('1hour'),
- max: 60,
- minInterval: ms('3sec')
- },
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37'
- },
-
- notReacted: {
- message: 'You are not reacting to that note.',
- code: 'NOT_REACTED',
- id: '92f4426d-4196-4125-aa5b-02943e2ec8fc'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
- await deleteReaction(user, note).catch(e => {
- if (e.id === '60527ec9-b4cb-4a88-a6bd-32d3ad26817d') throw new ApiError(meta.errors.notReacted);
- throw e;
- });
-});
diff --git a/src/server/api/endpoints/notes/renotes.ts b/src/server/api/endpoints/notes/renotes.ts
deleted file mode 100644
index 26bfc1657d..0000000000
--- a/src/server/api/endpoints/notes/renotes.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Notes } from '@/models/index';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '12908022-2e21-46cd-ba6a-3edaf6093f46'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.renoteId = :renoteId`, { renoteId: note.id })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, user);
- if (user) generateMutedUserQuery(query, user);
- if (user) generateBlockedUserQuery(query, user);
-
- const renotes = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(renotes, user);
-});
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
deleted file mode 100644
index 0bb62413ae..0000000000
--- a/src/server/api/endpoints/notes/replies.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Notes } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere('note.replyId = :replyId', { replyId: ps.noteId })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, user);
- if (user) generateMutedUserQuery(query, user);
- if (user) generateBlockedUserQuery(query, user);
-
- const timeline = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts
deleted file mode 100644
index 40e1499736..0000000000
--- a/src/server/api/endpoints/notes/search-by-tag.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Notes } from '@/models/index';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { Brackets } from 'typeorm';
-import { safeForSql } from '@/misc/safe-for-sql';
-import { normalizeForSearch } from '@/misc/normalize-for-search';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes', 'hashtags'],
-
- params: {
- tag: {
- validator: $.optional.str,
- },
-
- query: {
- validator: $.optional.arr($.arr($.str)),
- },
-
- reply: {
- validator: $.optional.nullable.bool,
- default: null,
- },
-
- renote: {
- validator: $.optional.nullable.bool,
- default: null,
- },
-
- withFiles: {
- validator: $.optional.bool,
- },
-
- poll: {
- validator: $.optional.nullable.bool,
- default: null,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, me);
- if (me) generateMutedUserQuery(query, me);
- if (me) generateBlockedUserQuery(query, me);
-
- try {
- if (ps.tag) {
- if (!safeForSql(ps.tag)) throw 'Injection';
- query.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`);
- } else {
- query.andWhere(new Brackets(qb => {
- for (const tags of ps.query!) {
- qb.orWhere(new Brackets(qb => {
- for (const tag of tags) {
- if (!safeForSql(tag)) throw 'Injection';
- qb.andWhere(`'{"${normalizeForSearch(tag)}"}' <@ note.tags`);
- }
- }));
- }
- }));
- }
- } catch (e) {
- if (e === 'Injection') return [];
- throw e;
- }
-
- if (ps.reply != null) {
- if (ps.reply) {
- query.andWhere('note.replyId IS NOT NULL');
- } else {
- query.andWhere('note.replyId IS NULL');
- }
- }
-
- if (ps.renote != null) {
- if (ps.renote) {
- query.andWhere('note.renoteId IS NOT NULL');
- } else {
- query.andWhere('note.renoteId IS NULL');
- }
- }
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
-
- if (ps.poll != null) {
- if (ps.poll) {
- query.andWhere('note.hasPoll = TRUE');
- } else {
- query.andWhere('note.hasPoll = FALSE');
- }
- }
-
- // Search notes
- const notes = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(notes, me);
-});
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
deleted file mode 100644
index eb832a6b31..0000000000
--- a/src/server/api/endpoints/notes/search.ts
+++ /dev/null
@@ -1,152 +0,0 @@
-import $ from 'cafy';
-import es from '../../../../db/elasticsearch';
-import define from '../../define';
-import { Notes } from '@/models/index';
-import { In } from 'typeorm';
-import { ID } from '@/misc/cafy-id';
-import config from '@/config/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- query: {
- validator: $.str
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- host: {
- validator: $.optional.nullable.str,
- default: undefined
- },
-
- userId: {
- validator: $.optional.nullable.type(ID),
- default: null
- },
-
- channelId: {
- validator: $.optional.nullable.type(ID),
- default: null
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- }
-};
-
-export default define(meta, async (ps, me) => {
- if (es == null) {
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId);
-
- if (ps.userId) {
- query.andWhere('note.userId = :userId', { userId: ps.userId });
- } else if (ps.channelId) {
- query.andWhere('note.channelId = :channelId', { channelId: ps.channelId });
- }
-
- query
- .andWhere('note.text ILIKE :q', { q: `%${ps.query}%` })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, me);
- if (me) generateMutedUserQuery(query, me);
- if (me) generateBlockedUserQuery(query, me);
-
- const notes = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(notes, me);
- } else {
- const userQuery = ps.userId != null ? [{
- term: {
- userId: ps.userId
- }
- }] : [];
-
- const hostQuery = ps.userId == null ?
- ps.host === null ? [{
- bool: {
- must_not: {
- exists: {
- field: 'userHost'
- }
- }
- }
- }] : ps.host !== undefined ? [{
- term: {
- userHost: ps.host
- }
- }] : []
- : [];
-
- const result = await es.search({
- index: config.elasticsearch.index || 'misskey_note',
- body: {
- size: ps.limit!,
- from: ps.offset,
- query: {
- bool: {
- must: [{
- simple_query_string: {
- fields: ['text'],
- query: ps.query.toLowerCase(),
- default_operator: 'and'
- },
- }, ...hostQuery, ...userQuery]
- }
- },
- sort: [{
- _doc: 'desc'
- }]
- }
- });
-
- const hits = result.body.hits.hits.map((hit: any) => hit._id);
-
- if (hits.length === 0) return [];
-
- // Fetch found notes
- const notes = await Notes.find({
- where: {
- id: In(hits)
- },
- order: {
- id: -1
- }
- });
-
- return await Notes.packMany(notes, me);
- }
-});
diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts
deleted file mode 100644
index fad63d6483..0000000000
--- a/src/server/api/endpoints/notes/show.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import { Notes } from '@/models/index';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '24fcbfc6-2e37-42b6-8388-c29b3861a08d'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- return await Notes.pack(note, user, {
- detail: true
- });
-});
diff --git a/src/server/api/endpoints/notes/state.ts b/src/server/api/endpoints/notes/state.ts
deleted file mode 100644
index b3913a5e79..0000000000
--- a/src/server/api/endpoints/notes/state.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { NoteFavorites, Notes, NoteThreadMutings, NoteWatchings } from '@/models/index';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- isFavorited: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isWatching: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isMutedThread: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await Notes.findOneOrFail(ps.noteId);
-
- const [favorite, watching, threadMuting] = await Promise.all([
- NoteFavorites.count({
- where: {
- userId: user.id,
- noteId: note.id,
- },
- take: 1
- }),
- NoteWatchings.count({
- where: {
- userId: user.id,
- noteId: note.id,
- },
- take: 1
- }),
- NoteThreadMutings.count({
- where: {
- userId: user.id,
- threadId: note.threadId || note.id,
- },
- take: 1
- }),
- ]);
-
- return {
- isFavorited: favorite !== 0,
- isWatching: watching !== 0,
- isMutedThread: threadMuting !== 0,
- };
-});
diff --git a/src/server/api/endpoints/notes/thread-muting/create.ts b/src/server/api/endpoints/notes/thread-muting/create.ts
deleted file mode 100644
index 2010d54331..0000000000
--- a/src/server/api/endpoints/notes/thread-muting/create.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { getNote } from '../../../common/getters';
-import { ApiError } from '../../../error';
-import { Notes, NoteThreadMutings } from '@/models';
-import { genId } from '@/misc/gen-id';
-import readNote from '@/services/note/read';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '5ff67ada-ed3b-2e71-8e87-a1a421e177d2'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const mutedNotes = await Notes.find({
- where: [{
- id: note.threadId || note.id,
- }, {
- threadId: note.threadId || note.id,
- }],
- });
-
- await readNote(user.id, mutedNotes);
-
- await NoteThreadMutings.insert({
- id: genId(),
- createdAt: new Date(),
- threadId: note.threadId || note.id,
- userId: user.id,
- });
-});
diff --git a/src/server/api/endpoints/notes/thread-muting/delete.ts b/src/server/api/endpoints/notes/thread-muting/delete.ts
deleted file mode 100644
index 05d5691870..0000000000
--- a/src/server/api/endpoints/notes/thread-muting/delete.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { getNote } from '../../../common/getters';
-import { ApiError } from '../../../error';
-import { NoteThreadMutings } from '@/models';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'bddd57ac-ceb3-b29d-4334-86ea5fae481a'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- await NoteThreadMutings.delete({
- threadId: note.threadId || note.id,
- userId: user.id,
- });
-});
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
deleted file mode 100644
index 1bd0e57d34..0000000000
--- a/src/server/api/endpoints/notes/timeline.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { Notes, Followings } from '@/models/index';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { activeUsersChart } from '@/services/chart/index';
-import { Brackets } from 'typeorm';
-import { generateRepliesQuery } from '../../common/generate-replies-query';
-import { generateMutedNoteQuery } from '../../common/generate-muted-note-query';
-import { generateChannelQuery } from '../../common/generate-channel-query';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
-
- includeMyRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- includeRenotedMyNotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- includeLocalRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- withFiles: {
- validator: $.optional.bool,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-};
-
-export default define(meta, async (ps, user) => {
- const hasFollowing = (await Followings.count({
- where: {
- followerId: user.id,
- },
- take: 1
- })) !== 0;
-
- //#region Construct query
- const followingQuery = Followings.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: user.id });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'),
- ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere(new Brackets(qb => { qb
- .where('note.userId = :meId', { meId: user.id });
- if (hasFollowing) qb.orWhere(`note.userId IN (${ followingQuery.getQuery() })`);
- }))
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .setParameters(followingQuery.getParameters());
-
- generateChannelQuery(query, user);
- generateRepliesQuery(query, user);
- generateVisibilityQuery(query, user);
- generateMutedUserQuery(query, user);
- generateMutedNoteQuery(query, user);
- generateBlockedUserQuery(query, user);
-
- if (ps.includeMyRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.userId != :meId', { meId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.includeRenotedMyNotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.renoteUserId != :meId', { meId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.includeLocalRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.renoteUserHost IS NOT NULL');
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- process.nextTick(() => {
- if (user) {
- activeUsersChart.update(user);
- }
- });
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/notes/translate.ts b/src/server/api/endpoints/notes/translate.ts
deleted file mode 100644
index b56b1debdd..0000000000
--- a/src/server/api/endpoints/notes/translate.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import fetch from 'node-fetch';
-import config from '@/config/index';
-import { getAgentByUrl } from '@/misc/fetch';
-import { URLSearchParams } from 'url';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { Notes } from '@/models';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: false as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- },
- targetLang: {
- validator: $.str,
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'bea9b03f-36e0-49c5-a4db-627a029f8971'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- if (!(await Notes.isVisibleForMe(note, user ? user.id : null))) {
- return 204; // TODO: 良い感じのエラー返す
- }
-
- if (note.text == null) {
- return 204;
- }
-
- const instance = await fetchMeta();
-
- if (instance.deeplAuthKey == null) {
- return 204; // TODO: 良い感じのエラー返す
- }
-
- let targetLang = ps.targetLang;
- if (targetLang.includes('-')) targetLang = targetLang.split('-')[0];
-
- const params = new URLSearchParams();
- params.append('auth_key', instance.deeplAuthKey);
- params.append('text', note.text);
- params.append('target_lang', targetLang);
-
- const endpoint = instance.deeplIsPro ? 'https://api.deepl.com/v2/translate' : 'https://api-free.deepl.com/v2/translate';
-
- const res = await fetch(endpoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'User-Agent': config.userAgent,
- Accept: 'application/json, */*'
- },
- body: params,
- timeout: 10000,
- agent: getAgentByUrl,
- });
-
- const json = await res.json();
-
- return {
- sourceLang: json.translations[0].detected_source_language,
- text: json.translations[0].text
- };
-});
diff --git a/src/server/api/endpoints/notes/unrenote.ts b/src/server/api/endpoints/notes/unrenote.ts
deleted file mode 100644
index dce43d9d9c..0000000000
--- a/src/server/api/endpoints/notes/unrenote.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import deleteNote from '@/services/note/delete';
-import define from '../../define';
-import * as ms from 'ms';
-import { getNote } from '../../common/getters';
-import { ApiError } from '../../error';
-import { Notes, Users } from '@/models/index';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:notes',
-
- limit: {
- duration: ms('1hour'),
- max: 300,
- minInterval: ms('1sec')
- },
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'efd4a259-2442-496b-8dd7-b255aa1a160f'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const renotes = await Notes.find({
- userId: user.id,
- renoteId: note.id
- });
-
- for (const note of renotes) {
- deleteNote(await Users.findOneOrFail(user.id), note);
- }
-});
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
deleted file mode 100644
index 32c370004c..0000000000
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ /dev/null
@@ -1,147 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { UserLists, UserListJoinings, Notes } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { activeUsersChart } from '@/services/chart/index';
-import { Brackets } from 'typeorm';
-
-export const meta = {
- tags: ['notes', 'lists'],
-
- requireCredential: true as const,
-
- params: {
- listId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
-
- includeMyRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- includeRenotedMyNotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- includeLocalRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- withFiles: {
- validator: $.optional.bool,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchList: {
- message: 'No such list.',
- code: 'NO_SUCH_LIST',
- id: '8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const list = await UserLists.findOne({
- id: ps.listId,
- userId: user.id
- });
-
- if (list == null) {
- throw new ApiError(meta.errors.noSuchList);
- }
-
- //#region Construct query
- const listQuery = UserListJoinings.createQueryBuilder('joining')
- .select('joining.userId')
- .where('joining.userListId = :userListId', { userListId: list.id });
-
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.userId IN (${ listQuery.getQuery() })`)
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .setParameters(listQuery.getParameters());
-
- generateVisibilityQuery(query, user);
-
- if (ps.includeMyRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.userId != :meId', { meId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.includeRenotedMyNotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.renoteUserId != :meId', { meId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.includeLocalRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.renoteUserHost IS NOT NULL');
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- activeUsersChart.update(user);
-
- return await Notes.packMany(timeline, user);
-});
diff --git a/src/server/api/endpoints/notes/watching/create.ts b/src/server/api/endpoints/notes/watching/create.ts
deleted file mode 100644
index 4d182d3715..0000000000
--- a/src/server/api/endpoints/notes/watching/create.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import watch from '@/services/note/watch';
-import { getNote } from '../../../common/getters';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'ea0e37a6-90a3-4f58-ba6b-c328ca206fc7'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- await watch(user.id, note);
-});
diff --git a/src/server/api/endpoints/notes/watching/delete.ts b/src/server/api/endpoints/notes/watching/delete.ts
deleted file mode 100644
index dd58c52b57..0000000000
--- a/src/server/api/endpoints/notes/watching/delete.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import unwatch from '@/services/note/unwatch';
-import { getNote } from '../../../common/getters';
-import { ApiError } from '../../../error';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: '09b3695c-f72c-4731-a428-7cff825fc82e'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- await unwatch(user.id, note);
-});
diff --git a/src/server/api/endpoints/notifications/create.ts b/src/server/api/endpoints/notifications/create.ts
deleted file mode 100644
index 8003c497ee..0000000000
--- a/src/server/api/endpoints/notifications/create.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { createNotification } from '@/services/create-notification';
-
-export const meta = {
- tags: ['notifications'],
-
- requireCredential: true as const,
-
- kind: 'write:notifications',
-
- params: {
- body: {
- validator: $.str
- },
-
- header: {
- validator: $.optional.nullable.str
- },
-
- icon: {
- validator: $.optional.nullable.str
- },
- },
-
- errors: {
- }
-};
-
-export default define(meta, async (ps, user, token) => {
- createNotification(user.id, 'app', {
- appAccessTokenId: token ? token.id : null,
- customBody: ps.body,
- customHeader: ps.header,
- customIcon: ps.icon,
- });
-});
diff --git a/src/server/api/endpoints/notifications/mark-all-as-read.ts b/src/server/api/endpoints/notifications/mark-all-as-read.ts
deleted file mode 100644
index 8d4e512750..0000000000
--- a/src/server/api/endpoints/notifications/mark-all-as-read.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { publishMainStream } from '@/services/stream';
-import define from '../../define';
-import { Notifications } from '@/models/index';
-
-export const meta = {
- tags: ['notifications', 'account'],
-
- requireCredential: true as const,
-
- kind: 'write:notifications'
-};
-
-export default define(meta, async (ps, user) => {
- // Update documents
- await Notifications.update({
- notifieeId: user.id,
- isRead: false,
- }, {
- isRead: true
- });
-
- // 全ての通知を読みましたよというイベントを発行
- publishMainStream(user.id, 'readAllNotifications');
-});
diff --git a/src/server/api/endpoints/notifications/read.ts b/src/server/api/endpoints/notifications/read.ts
deleted file mode 100644
index 66bbc4efd7..0000000000
--- a/src/server/api/endpoints/notifications/read.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishMainStream } from '@/services/stream';
-import define from '../../define';
-import { Notifications } from '@/models/index';
-import { readNotification } from '../../common/read-notification';
-import { ApiError } from '../../error';
-
-export const meta = {
- tags: ['notifications', 'account'],
-
- requireCredential: true as const,
-
- kind: 'write:notifications',
-
- params: {
- notificationId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchNotification: {
- message: 'No such notification.',
- code: 'NO_SUCH_NOTIFICATION',
- id: 'efa929d5-05b5-47d1-beec-e6a4dbed011e'
- },
- },
-};
-
-export default define(meta, async (ps, user) => {
- const notification = await Notifications.findOne({
- notifieeId: user.id,
- id: ps.notificationId,
- });
-
- if (notification == null) {
- throw new ApiError(meta.errors.noSuchNotification);
- }
-
- readNotification(user.id, [notification.id]);
-});
diff --git a/src/server/api/endpoints/page-push.ts b/src/server/api/endpoints/page-push.ts
deleted file mode 100644
index a0412e89f1..0000000000
--- a/src/server/api/endpoints/page-push.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import $ from 'cafy';
-import define from '../define';
-import { ID } from '@/misc/cafy-id';
-import { publishMainStream } from '@/services/stream';
-import { Users, Pages } from '@/models/index';
-import { ApiError } from '../error';
-
-export const meta = {
- requireCredential: true as const,
- secure: true,
-
- params: {
- pageId: {
- validator: $.type(ID)
- },
-
- event: {
- validator: $.str
- },
-
- var: {
- validator: $.optional.nullable.any
- }
- },
-
- errors: {
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: '4a13ad31-6729-46b4-b9af-e86b265c2e74'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const page = await Pages.findOne(ps.pageId);
- if (page == null) {
- throw new ApiError(meta.errors.noSuchPage);
- }
-
- publishMainStream(page.userId, 'pageEvent', {
- pageId: ps.pageId,
- event: ps.event,
- var: ps.var,
- userId: user.id,
- user: await Users.pack(user.id, { id: page.userId }, {
- detail: true
- })
- });
-});
diff --git a/src/server/api/endpoints/pages/create.ts b/src/server/api/endpoints/pages/create.ts
deleted file mode 100644
index c23978f093..0000000000
--- a/src/server/api/endpoints/pages/create.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import $ from 'cafy';
-import * as ms from 'ms';
-import define from '../../define';
-import { ID } from '@/misc/cafy-id';
-import { Pages, DriveFiles } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { Page } from '@/models/entities/page';
-import { ApiError } from '../../error';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: true as const,
-
- kind: 'write:pages',
-
- limit: {
- duration: ms('1hour'),
- max: 300
- },
-
- params: {
- title: {
- validator: $.str,
- },
-
- name: {
- validator: $.str.min(1),
- },
-
- summary: {
- validator: $.optional.nullable.str,
- },
-
- content: {
- validator: $.arr($.obj())
- },
-
- variables: {
- validator: $.arr($.obj())
- },
-
- script: {
- validator: $.str,
- },
-
- eyeCatchingImageId: {
- validator: $.optional.nullable.type(ID),
- },
-
- font: {
- validator: $.optional.str.or(['serif', 'sans-serif']),
- default: 'sans-serif'
- },
-
- alignCenter: {
- validator: $.optional.bool,
- default: false
- },
-
- hideTitleWhenPinned: {
- validator: $.optional.bool,
- default: false
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Page',
- },
-
- errors: {
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'b7b97489-0f66-4b12-a5ff-b21bd63f6e1c'
- },
- nameAlreadyExists: {
- message: 'Specified name already exists.',
- code: 'NAME_ALREADY_EXISTS',
- id: '4650348e-301c-499a-83c9-6aa988c66bc1'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- let eyeCatchingImage = null;
- if (ps.eyeCatchingImageId != null) {
- eyeCatchingImage = await DriveFiles.findOne({
- id: ps.eyeCatchingImageId,
- userId: user.id
- });
-
- if (eyeCatchingImage == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- }
-
- await Pages.find({
- userId: user.id,
- name: ps.name
- }).then(result => {
- if (result.length > 0) {
- throw new ApiError(meta.errors.nameAlreadyExists);
- }
- });
-
- const page = await Pages.save(new Page({
- id: genId(),
- createdAt: new Date(),
- updatedAt: new Date(),
- title: ps.title,
- name: ps.name,
- summary: ps.summary,
- content: ps.content,
- variables: ps.variables,
- script: ps.script,
- eyeCatchingImageId: eyeCatchingImage ? eyeCatchingImage.id : null,
- userId: user.id,
- visibility: 'public',
- alignCenter: ps.alignCenter,
- hideTitleWhenPinned: ps.hideTitleWhenPinned,
- font: ps.font
- }));
-
- return await Pages.pack(page);
-});
diff --git a/src/server/api/endpoints/pages/delete.ts b/src/server/api/endpoints/pages/delete.ts
deleted file mode 100644
index b1f8c8a709..0000000000
--- a/src/server/api/endpoints/pages/delete.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Pages } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: true as const,
-
- kind: 'write:pages',
-
- params: {
- pageId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: 'eb0c6e1d-d519-4764-9486-52a7e1c6392a'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: '8b741b3e-2c22-44b3-a15f-29949aa1601e'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const page = await Pages.findOne(ps.pageId);
- if (page == null) {
- throw new ApiError(meta.errors.noSuchPage);
- }
- if (page.userId !== user.id) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- await Pages.delete(page.id);
-});
diff --git a/src/server/api/endpoints/pages/featured.ts b/src/server/api/endpoints/pages/featured.ts
deleted file mode 100644
index f891c45f05..0000000000
--- a/src/server/api/endpoints/pages/featured.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import define from '../../define';
-import { Pages } from '@/models/index';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: false as const,
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Page',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = Pages.createQueryBuilder('page')
- .where('page.visibility = \'public\'')
- .andWhere('page.likedCount > 0')
- .orderBy('page.likedCount', 'DESC');
-
- const pages = await query.take(10).getMany();
-
- return await Pages.packMany(pages, me);
-});
diff --git a/src/server/api/endpoints/pages/like.ts b/src/server/api/endpoints/pages/like.ts
deleted file mode 100644
index a95a377802..0000000000
--- a/src/server/api/endpoints/pages/like.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Pages, PageLikes } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: true as const,
-
- kind: 'write:page-likes',
-
- params: {
- pageId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: 'cc98a8a2-0dc3-4123-b198-62c71df18ed3'
- },
-
- yourPage: {
- message: 'You cannot like your page.',
- code: 'YOUR_PAGE',
- id: '28800466-e6db-40f2-8fae-bf9e82aa92b8'
- },
-
- alreadyLiked: {
- message: 'The page has already been liked.',
- code: 'ALREADY_LIKED',
- id: 'cc98a8a2-0dc3-4123-b198-62c71df18ed3'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const page = await Pages.findOne(ps.pageId);
- if (page == null) {
- throw new ApiError(meta.errors.noSuchPage);
- }
-
- if (page.userId === user.id) {
- throw new ApiError(meta.errors.yourPage);
- }
-
- // if already liked
- const exist = await PageLikes.findOne({
- pageId: page.id,
- userId: user.id
- });
-
- if (exist != null) {
- throw new ApiError(meta.errors.alreadyLiked);
- }
-
- // Create like
- await PageLikes.insert({
- id: genId(),
- createdAt: new Date(),
- pageId: page.id,
- userId: user.id
- });
-
- Pages.increment({ id: page.id }, 'likedCount', 1);
-});
diff --git a/src/server/api/endpoints/pages/show.ts b/src/server/api/endpoints/pages/show.ts
deleted file mode 100644
index 7c55d4a9e6..0000000000
--- a/src/server/api/endpoints/pages/show.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Pages, Users } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-import { Page } from '@/models/entities/page';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: false as const,
-
- params: {
- pageId: {
- validator: $.optional.type(ID),
- },
-
- name: {
- validator: $.optional.str,
- },
-
- username: {
- validator: $.optional.str,
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Page',
- },
-
- errors: {
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: '222120c0-3ead-4528-811b-b96f233388d7'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- let page: Page | undefined;
-
- if (ps.pageId) {
- page = await Pages.findOne(ps.pageId);
- } else if (ps.name && ps.username) {
- const author = await Users.findOne({
- host: null,
- usernameLower: ps.username.toLowerCase()
- });
- if (author) {
- page = await Pages.findOne({
- name: ps.name,
- userId: author.id
- });
- }
- }
-
- if (page == null) {
- throw new ApiError(meta.errors.noSuchPage);
- }
-
- return await Pages.pack(page, user);
-});
diff --git a/src/server/api/endpoints/pages/unlike.ts b/src/server/api/endpoints/pages/unlike.ts
deleted file mode 100644
index facf2d6d5f..0000000000
--- a/src/server/api/endpoints/pages/unlike.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Pages, PageLikes } from '@/models/index';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: true as const,
-
- kind: 'write:page-likes',
-
- params: {
- pageId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: 'a0d41e20-1993-40bd-890e-f6e560ae648e'
- },
-
- notLiked: {
- message: 'You have not liked that page.',
- code: 'NOT_LIKED',
- id: 'f5e586b0-ce93-4050-b0e3-7f31af5259ee'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const page = await Pages.findOne(ps.pageId);
- if (page == null) {
- throw new ApiError(meta.errors.noSuchPage);
- }
-
- const exist = await PageLikes.findOne({
- pageId: page.id,
- userId: user.id
- });
-
- if (exist == null) {
- throw new ApiError(meta.errors.notLiked);
- }
-
- // Delete like
- await PageLikes.delete(exist.id);
-
- Pages.decrement({ id: page.id }, 'likedCount', 1);
-});
diff --git a/src/server/api/endpoints/pages/update.ts b/src/server/api/endpoints/pages/update.ts
deleted file mode 100644
index b3a7f26963..0000000000
--- a/src/server/api/endpoints/pages/update.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import $ from 'cafy';
-import * as ms from 'ms';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Pages, DriveFiles } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-import { Not } from 'typeorm';
-
-export const meta = {
- tags: ['pages'],
-
- requireCredential: true as const,
-
- kind: 'write:pages',
-
- limit: {
- duration: ms('1hour'),
- max: 300
- },
-
- params: {
- pageId: {
- validator: $.type(ID),
- },
-
- title: {
- validator: $.str,
- },
-
- name: {
- validator: $.str.min(1),
- },
-
- summary: {
- validator: $.optional.nullable.str,
- },
-
- content: {
- validator: $.arr($.obj())
- },
-
- variables: {
- validator: $.arr($.obj())
- },
-
- script: {
- validator: $.str,
- },
-
- eyeCatchingImageId: {
- validator: $.optional.nullable.type(ID),
- },
-
- font: {
- validator: $.optional.str.or(['serif', 'sans-serif']),
- },
-
- alignCenter: {
- validator: $.optional.bool,
- },
-
- hideTitleWhenPinned: {
- validator: $.optional.bool,
- },
- },
-
- errors: {
- noSuchPage: {
- message: 'No such page.',
- code: 'NO_SUCH_PAGE',
- id: '21149b9e-3616-4778-9592-c4ce89f5a864'
- },
-
- accessDenied: {
- message: 'Access denied.',
- code: 'ACCESS_DENIED',
- id: '3c15cd52-3b4b-4274-967d-6456fc4f792b'
- },
-
- noSuchFile: {
- message: 'No such file.',
- code: 'NO_SUCH_FILE',
- id: 'cfc23c7c-3887-490e-af30-0ed576703c82'
- },
- nameAlreadyExists: {
- message: 'Specified name already exists.',
- code: 'NAME_ALREADY_EXISTS',
- id: '2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const page = await Pages.findOne(ps.pageId);
- if (page == null) {
- throw new ApiError(meta.errors.noSuchPage);
- }
- if (page.userId !== user.id) {
- throw new ApiError(meta.errors.accessDenied);
- }
-
- let eyeCatchingImage = null;
- if (ps.eyeCatchingImageId != null) {
- eyeCatchingImage = await DriveFiles.findOne({
- id: ps.eyeCatchingImageId,
- userId: user.id
- });
-
- if (eyeCatchingImage == null) {
- throw new ApiError(meta.errors.noSuchFile);
- }
- }
-
- await Pages.find({
- id: Not(ps.pageId),
- userId: user.id,
- name: ps.name
- }).then(result => {
- if (result.length > 0) {
- throw new ApiError(meta.errors.nameAlreadyExists);
- }
- });
-
- await Pages.update(page.id, {
- updatedAt: new Date(),
- title: ps.title,
- name: ps.name === undefined ? page.name : ps.name,
- summary: ps.name === undefined ? page.summary : ps.summary,
- content: ps.content,
- variables: ps.variables,
- script: ps.script,
- alignCenter: ps.alignCenter === undefined ? page.alignCenter : ps.alignCenter,
- hideTitleWhenPinned: ps.hideTitleWhenPinned === undefined ? page.hideTitleWhenPinned : ps.hideTitleWhenPinned,
- font: ps.font === undefined ? page.font : ps.font,
- eyeCatchingImageId: ps.eyeCatchingImageId === null
- ? null
- : ps.eyeCatchingImageId === undefined
- ? page.eyeCatchingImageId
- : eyeCatchingImage!.id,
- });
-});
diff --git a/src/server/api/endpoints/ping.ts b/src/server/api/endpoints/ping.ts
deleted file mode 100644
index 0b1bb6e164..0000000000
--- a/src/server/api/endpoints/ping.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import define from '../define';
-
-export const meta = {
- requireCredential: false as const,
-
- tags: ['meta'],
-
- params: {
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- pong: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- }
- }
-};
-
-export default define(meta, async () => {
- return {
- pong: Date.now(),
- };
-});
diff --git a/src/server/api/endpoints/pinned-users.ts b/src/server/api/endpoints/pinned-users.ts
deleted file mode 100644
index e88dfbd535..0000000000
--- a/src/server/api/endpoints/pinned-users.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import define from '../define';
-import { Users } from '@/models/index';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { parseAcct } from '@/misc/acct';
-import { User } from '@/models/entities/user';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const meta = await fetchMeta();
-
- const users = await Promise.all(meta.pinnedUsers.map(acct => Users.findOne(parseAcct(acct))));
-
- return await Users.packMany(users.filter(x => x !== undefined) as User[], me, { detail: true });
-});
diff --git a/src/server/api/endpoints/promo/read.ts b/src/server/api/endpoints/promo/read.ts
deleted file mode 100644
index ae57bf9cf1..0000000000
--- a/src/server/api/endpoints/promo/read.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getNote } from '../../common/getters';
-import { PromoReads } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['notes'],
-
- requireCredential: true as const,
-
- params: {
- noteId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchNote: {
- message: 'No such note.',
- code: 'NO_SUCH_NOTE',
- id: 'd785b897-fcd3-4fe9-8fc3-b85c26e6c932'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const note = await getNote(ps.noteId).catch(e => {
- if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
- throw e;
- });
-
- const exist = await PromoReads.findOne({
- noteId: note.id,
- userId: user.id
- });
-
- if (exist != null) {
- return;
- }
-
- await PromoReads.insert({
- id: genId(),
- createdAt: new Date(),
- noteId: note.id,
- userId: user.id
- });
-});
diff --git a/src/server/api/endpoints/request-reset-password.ts b/src/server/api/endpoints/request-reset-password.ts
deleted file mode 100644
index f9928c2ee6..0000000000
--- a/src/server/api/endpoints/request-reset-password.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import $ from 'cafy';
-import { publishMainStream } from '@/services/stream';
-import define from '../define';
-import rndstr from 'rndstr';
-import config from '@/config/index';
-import * as ms from 'ms';
-import { Users, UserProfiles, PasswordResetRequests } from '@/models/index';
-import { sendEmail } from '@/services/send-email';
-import { ApiError } from '../error';
-import { genId } from '@/misc/gen-id';
-import { IsNull } from 'typeorm';
-
-export const meta = {
- requireCredential: false as const,
-
- limit: {
- duration: ms('1hour'),
- max: 3
- },
-
- params: {
- username: {
- validator: $.str
- },
-
- email: {
- validator: $.str
- },
- },
-
- errors: {
-
- }
-};
-
-export default define(meta, async (ps) => {
- const user = await Users.findOne({
- usernameLower: ps.username.toLowerCase(),
- host: IsNull()
- });
-
- // 合致するユーザーが登録されていなかったら無視
- if (user == null) {
- return;
- }
-
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- // 合致するメアドが登録されていなかったら無視
- if (profile.email !== ps.email) {
- return;
- }
-
- // メアドが認証されていなかったら無視
- if (!profile.emailVerified) {
- return;
- }
-
- const token = rndstr('a-z0-9', 64);
-
- await PasswordResetRequests.insert({
- id: genId(),
- createdAt: new Date(),
- userId: profile.userId,
- token
- });
-
- const link = `${config.url}/reset-password/${token}`;
-
- sendEmail(ps.email, 'Password reset requested',
- `To reset password, please click this link:<br><a href="${link}">${link}</a>`,
- `To reset password, please click this link: ${link}`);
-});
diff --git a/src/server/api/endpoints/reset-db.ts b/src/server/api/endpoints/reset-db.ts
deleted file mode 100644
index f0a9dae4ff..0000000000
--- a/src/server/api/endpoints/reset-db.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import $ from 'cafy';
-import define from '../define';
-import { ApiError } from '../error';
-import { resetDb } from '@/db/postgre';
-
-export const meta = {
- requireCredential: false as const,
-
- params: {
- },
-
- errors: {
-
- }
-};
-
-export default define(meta, async (ps, user) => {
- if (process.env.NODE_ENV !== 'test') throw 'NODE_ENV is not a test';
-
- await resetDb();
-
- await new Promise(resolve => setTimeout(resolve, 1000));
-});
diff --git a/src/server/api/endpoints/reset-password.ts b/src/server/api/endpoints/reset-password.ts
deleted file mode 100644
index 53b0bfde0b..0000000000
--- a/src/server/api/endpoints/reset-password.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import { publishMainStream } from '@/services/stream';
-import define from '../define';
-import { Users, UserProfiles, PasswordResetRequests } from '@/models/index';
-import { ApiError } from '../error';
-
-export const meta = {
- requireCredential: false as const,
-
- params: {
- token: {
- validator: $.str
- },
-
- password: {
- validator: $.str
- }
- },
-
- errors: {
-
- }
-};
-
-export default define(meta, async (ps, user) => {
- const req = await PasswordResetRequests.findOneOrFail({
- token: ps.token,
- });
-
- // 発行してから30分以上経過していたら無効
- if (Date.now() - req.createdAt.getTime() > 1000 * 60 * 30) {
- throw new Error(); // TODO
- }
-
- // Generate hash of password
- const salt = await bcrypt.genSalt(8);
- const hash = await bcrypt.hash(ps.password, salt);
-
- await UserProfiles.update(req.userId, {
- password: hash
- });
-
- PasswordResetRequests.delete(req.id);
-});
diff --git a/src/server/api/endpoints/room/show.ts b/src/server/api/endpoints/room/show.ts
deleted file mode 100644
index a6461d4a6e..0000000000
--- a/src/server/api/endpoints/room/show.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Users, UserProfiles } from '@/models/index';
-import { ID } from '@/misc/cafy-id';
-import { toPunyNullable } from '@/misc/convert-host';
-
-export const meta = {
- tags: ['room'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.optional.type(ID),
- },
-
- username: {
- validator: $.optional.str
- },
-
- host: {
- validator: $.optional.nullable.str
- },
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '7ad3fa3e-5e12-42f0-b23a-f3d13f10ee4b'
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- roomType: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- enum: ['default', 'washitsu']
- },
- furnitures: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- type: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- },
- props: {
- type: 'object' as const,
- optional: true as const, nullable: false as const,
- },
- position: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- x: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- y: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- z: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- }
- }
- },
- rotation: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- x: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- y: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- z: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
- }
- }
- },
- carpetColor: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'hex',
- example: '#85CAF0'
- }
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId != null
- ? { id: ps.userId }
- : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) });
-
- if (user == null) {
- throw new ApiError(meta.errors.noSuchUser);
- }
-
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- if (profile.room.furnitures == null) {
- await UserProfiles.update(user.id, {
- room: {
- furnitures: [],
- ...profile.room
- }
- });
-
- profile.room.furnitures = [];
- }
-
- if (profile.room.roomType == null) {
- const initialType = 'default';
- await UserProfiles.update(user.id, {
- room: {
- roomType: initialType as any,
- ...profile.room
- }
- });
-
- profile.room.roomType = initialType;
- }
-
- if (profile.room.carpetColor == null) {
- const initialColor = '#85CAF0';
- await UserProfiles.update(user.id, {
- room: {
- carpetColor: initialColor as any,
- ...profile.room
- }
- });
-
- profile.room.carpetColor = initialColor;
- }
-
- return profile.room;
-});
diff --git a/src/server/api/endpoints/room/update.ts b/src/server/api/endpoints/room/update.ts
deleted file mode 100644
index 8c4cfbdea6..0000000000
--- a/src/server/api/endpoints/room/update.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import $ from 'cafy';
-import { publishMainStream } from '@/services/stream';
-import define from '../../define';
-import { Users, UserProfiles } from '@/models/index';
-
-export const meta = {
- tags: ['room'],
-
- requireCredential: true as const,
-
- params: {
- room: {
- validator: $.obj({
- furnitures: $.arr($.obj({
- id: $.str,
- type: $.str,
- position: $.obj({
- x: $.num,
- y: $.num,
- z: $.num,
- }),
- rotation: $.obj({
- x: $.num,
- y: $.num,
- z: $.num,
- }),
- props: $.optional.nullable.obj(),
- })),
- roomType: $.str,
- carpetColor: $.str
- })
- },
- },
-};
-
-export default define(meta, async (ps, user) => {
- await UserProfiles.update(user.id, {
- room: ps.room as any
- });
-
- const iObj = await Users.pack(user.id, user, {
- detail: true,
- includeSecrets: true
- });
-
- // Publish meUpdated event
- publishMainStream(user.id, 'meUpdated', iObj);
-
- // TODO: レスポンスがおかしいと思う by YuzuRyo61
- return iObj;
-});
diff --git a/src/server/api/endpoints/server-info.ts b/src/server/api/endpoints/server-info.ts
deleted file mode 100644
index 4e636d331c..0000000000
--- a/src/server/api/endpoints/server-info.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import * as os from 'os';
-import * as si from 'systeminformation';
-import define from '../define';
-
-export const meta = {
- requireCredential: false as const,
-
- desc: {
- },
-
- tags: ['meta'],
-
- params: {
- },
-};
-
-export default define(meta, async () => {
- const memStats = await si.mem();
- const fsStats = await si.fsSize();
-
- return {
- machine: os.hostname(),
- cpu: {
- model: os.cpus()[0].model,
- cores: os.cpus().length
- },
- mem: {
- total: memStats.total
- },
- fs: {
- total: fsStats[0].size,
- used: fsStats[0].used,
- },
- };
-});
diff --git a/src/server/api/endpoints/stats.ts b/src/server/api/endpoints/stats.ts
deleted file mode 100644
index 15c8001742..0000000000
--- a/src/server/api/endpoints/stats.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import define from '../define';
-import { NoteReactions, Notes, Users } from '@/models/index';
-import { federationChart, driveChart } from '@/services/chart/index';
-
-export const meta = {
- requireCredential: false as const,
-
- tags: ['meta'],
-
- params: {
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- notesCount: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- originalNotesCount: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- usersCount: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- originalUsersCount: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- instances: {
- type: 'number' as const,
- optional: false as const, nullable: false as const,
- },
- driveUsageLocal: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- },
- driveUsageRemote: {
- type: 'number' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async () => {
- const [
- notesCount,
- originalNotesCount,
- usersCount,
- originalUsersCount,
- reactionsCount,
- //originalReactionsCount,
- instances,
- driveUsageLocal,
- driveUsageRemote
- ] = await Promise.all([
- Notes.count({ cache: 3600000 }), // 1 hour
- Notes.count({ where: { userHost: null }, cache: 3600000 }),
- Users.count({ cache: 3600000 }),
- Users.count({ where: { host: null }, cache: 3600000 }),
- NoteReactions.count({ cache: 3600000 }), // 1 hour
- //NoteReactions.count({ where: { userHost: null }, cache: 3600000 }),
- federationChart.getChart('hour', 1, null).then(chart => chart.instance.total[0]),
- driveChart.getChart('hour', 1, null).then(chart => chart.local.totalSize[0]),
- driveChart.getChart('hour', 1, null).then(chart => chart.remote.totalSize[0]),
- ]);
-
- return {
- notesCount,
- originalNotesCount,
- usersCount,
- originalUsersCount,
- reactionsCount,
- //originalReactionsCount,
- instances,
- driveUsageLocal,
- driveUsageRemote
- };
-});
diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts
deleted file mode 100644
index 6e14ba2669..0000000000
--- a/src/server/api/endpoints/sw/register.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { fetchMeta } from '@/misc/fetch-meta';
-import { genId } from '@/misc/gen-id';
-import { SwSubscriptions } from '@/models/index';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- params: {
- endpoint: {
- validator: $.str
- },
-
- auth: {
- validator: $.str
- },
-
- publickey: {
- validator: $.str
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- state: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- enum: ['already-subscribed', 'subscribed']
- },
- key: {
- type: 'string' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- // if already subscribed
- const exist = await SwSubscriptions.findOne({
- userId: user.id,
- endpoint: ps.endpoint,
- auth: ps.auth,
- publickey: ps.publickey,
- });
-
- const instance = await fetchMeta(true);
-
- if (exist != null) {
- return {
- state: 'already-subscribed',
- key: instance.swPublicKey
- };
- }
-
- await SwSubscriptions.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- endpoint: ps.endpoint,
- auth: ps.auth,
- publickey: ps.publickey
- });
-
- return {
- state: 'subscribed',
- key: instance.swPublicKey
- };
-});
diff --git a/src/server/api/endpoints/sw/unregister.ts b/src/server/api/endpoints/sw/unregister.ts
deleted file mode 100644
index 817ad1f517..0000000000
--- a/src/server/api/endpoints/sw/unregister.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { SwSubscriptions } from '../../../../models';
-
-export const meta = {
- tags: ['account'],
-
- requireCredential: true as const,
-
- params: {
- endpoint: {
- validator: $.str
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- await SwSubscriptions.delete({
- userId: user.id,
- endpoint: ps.endpoint,
- });
-});
diff --git a/src/server/api/endpoints/username/available.ts b/src/server/api/endpoints/username/available.ts
deleted file mode 100644
index 1ae75448ea..0000000000
--- a/src/server/api/endpoints/username/available.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Users, UsedUsernames } from '@/models/index';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- username: {
- validator: $.use(Users.validateLocalUsername)
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- available: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const,
- }
- }
- }
-};
-
-export default define(meta, async (ps) => {
- // Get exist
- const exist = await Users.count({
- host: null,
- usernameLower: ps.username.toLowerCase()
- });
-
- const exist2 = await UsedUsernames.count({ username: ps.username.toLowerCase() });
-
- return {
- available: exist === 0 && exist2 === 0
- };
-});
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
deleted file mode 100644
index 930dcc7616..0000000000
--- a/src/server/api/endpoints/users.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import $ from 'cafy';
-import define from '../define';
-import { Users } from '@/models/index';
-import { generateMutedUserQueryForUsers } from '../common/generate-muted-user-query';
-import { generateBlockQueryForUsers } from '../common/generate-block-query';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- },
-
- sort: {
- validator: $.optional.str.or([
- '+follower',
- '-follower',
- '+createdAt',
- '-createdAt',
- '+updatedAt',
- '-updatedAt',
- ]),
- },
-
- state: {
- validator: $.optional.str.or([
- 'all',
- 'admin',
- 'moderator',
- 'adminOrModerator',
- 'alive'
- ]),
- default: 'all'
- },
-
- origin: {
- validator: $.optional.str.or([
- 'combined',
- 'local',
- 'remote',
- ]),
- default: 'local'
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = Users.createQueryBuilder('user');
- query.where('user.isExplorable = TRUE');
-
- switch (ps.state) {
- case 'admin': query.andWhere('user.isAdmin = TRUE'); break;
- case 'moderator': query.andWhere('user.isModerator = TRUE'); break;
- case 'adminOrModerator': query.andWhere('user.isAdmin = TRUE OR user.isModerator = TRUE'); break;
- case 'alive': query.andWhere('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break;
- }
-
- switch (ps.origin) {
- case 'local': query.andWhere('user.host IS NULL'); break;
- case 'remote': query.andWhere('user.host IS NOT NULL'); break;
- }
-
- switch (ps.sort) {
- case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
- case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
- case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
- case '+updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'DESC'); break;
- case '-updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'ASC'); break;
- default: query.orderBy('user.id', 'ASC'); break;
- }
-
- if (me) generateMutedUserQueryForUsers(query, me);
- if (me) generateBlockQueryForUsers(query, me);
-
- query.take(ps.limit!);
- query.skip(ps.offset);
-
- const users = await query.getMany();
-
- return await Users.packMany(users, me, { detail: true });
-});
diff --git a/src/server/api/endpoints/users/clips.ts b/src/server/api/endpoints/users/clips.ts
deleted file mode 100644
index 8feca9422a..0000000000
--- a/src/server/api/endpoints/users/clips.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Clips } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['users', 'clips'],
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Clips.createQueryBuilder('clip'), ps.sinceId, ps.untilId)
- .andWhere(`clip.userId = :userId`, { userId: ps.userId })
- .andWhere('clip.isPublic = true');
-
- const clips = await query
- .take(ps.limit!)
- .getMany();
-
- return await Clips.packMany(clips);
-});
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
deleted file mode 100644
index 6d042a2861..0000000000
--- a/src/server/api/endpoints/users/followers.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Users, Followings, UserProfiles } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { toPunyNullable } from '@/misc/convert-host';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.optional.type(ID),
- },
-
- username: {
- validator: $.optional.str
- },
-
- host: {
- validator: $.optional.nullable.str
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Following',
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '27fa5435-88ab-43de-9360-387de88727cd'
- },
-
- forbidden: {
- message: 'Forbidden.',
- code: 'FORBIDDEN',
- id: '3c6a84db-d619-26af-ca14-06232a21df8a'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId != null
- ? { id: ps.userId }
- : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) });
-
- if (user == null) {
- throw new ApiError(meta.errors.noSuchUser);
- }
-
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- if (profile.ffVisibility === 'private') {
- if (me == null || (me.id !== user.id)) {
- throw new ApiError(meta.errors.forbidden);
- }
- } else if (profile.ffVisibility === 'followers') {
- if (me == null) {
- throw new ApiError(meta.errors.forbidden);
- } else if (me.id !== user.id) {
- const following = await Followings.findOne({
- followeeId: user.id,
- followerId: me.id,
- });
- if (following == null) {
- throw new ApiError(meta.errors.forbidden);
- }
- }
- }
-
- const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId)
- .andWhere(`following.followeeId = :userId`, { userId: user.id })
- .innerJoinAndSelect('following.follower', 'follower');
-
- const followings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Followings.packMany(followings, me, { populateFollower: true });
-});
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
deleted file mode 100644
index 1033117ef8..0000000000
--- a/src/server/api/endpoints/users/following.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { Users, Followings, UserProfiles } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { toPunyNullable } from '@/misc/convert-host';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.optional.type(ID),
- },
-
- username: {
- validator: $.optional.str
- },
-
- host: {
- validator: $.optional.nullable.str
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Following',
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '63e4aba4-4156-4e53-be25-c9559e42d71b'
- },
-
- forbidden: {
- message: 'Forbidden.',
- code: 'FORBIDDEN',
- id: 'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId != null
- ? { id: ps.userId }
- : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) });
-
- if (user == null) {
- throw new ApiError(meta.errors.noSuchUser);
- }
-
- const profile = await UserProfiles.findOneOrFail(user.id);
-
- if (profile.ffVisibility === 'private') {
- if (me == null || (me.id !== user.id)) {
- throw new ApiError(meta.errors.forbidden);
- }
- } else if (profile.ffVisibility === 'followers') {
- if (me == null) {
- throw new ApiError(meta.errors.forbidden);
- } else if (me.id !== user.id) {
- const following = await Followings.findOne({
- followeeId: user.id,
- followerId: me.id,
- });
- if (following == null) {
- throw new ApiError(meta.errors.forbidden);
- }
- }
- }
-
- const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId)
- .andWhere(`following.followerId = :userId`, { userId: user.id })
- .innerJoinAndSelect('following.followee', 'followee');
-
- const followings = await query
- .take(ps.limit!)
- .getMany();
-
- return await Followings.packMany(followings, me, { populateFollowee: true });
-});
diff --git a/src/server/api/endpoints/users/gallery/posts.ts b/src/server/api/endpoints/users/gallery/posts.ts
deleted file mode 100644
index 845de1089c..0000000000
--- a/src/server/api/endpoints/users/gallery/posts.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { GalleryPosts } from '@/models/index';
-import { makePaginationQuery } from '../../../common/make-pagination-query';
-
-export const meta = {
- tags: ['users', 'gallery'],
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
- .andWhere(`post.userId = :userId`, { userId: ps.userId });
-
- const posts = await query
- .take(ps.limit!)
- .getMany();
-
- return await GalleryPosts.packMany(posts, user);
-});
diff --git a/src/server/api/endpoints/users/get-frequently-replied-users.ts b/src/server/api/endpoints/users/get-frequently-replied-users.ts
deleted file mode 100644
index 32ebfd683a..0000000000
--- a/src/server/api/endpoints/users/get-frequently-replied-users.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { maximum } from '@/prelude/array';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { Not, In, IsNull } from 'typeorm';
-import { Notes, Users } from '@/models/index';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: 'e6965129-7b2a-40a4-bae2-cd84cd434822'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Lookup user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Fetch recent notes
- const recentNotes = await Notes.find({
- where: {
- userId: user.id,
- replyId: Not(IsNull())
- },
- order: {
- id: -1
- },
- take: 1000,
- select: ['replyId']
- });
-
- // 投稿が少なかったら中断
- if (recentNotes.length === 0) {
- return [];
- }
-
- // TODO ミュートを考慮
- const replyTargetNotes = await Notes.find({
- where: {
- id: In(recentNotes.map(p => p.replyId)),
- },
- select: ['userId']
- });
-
- const repliedUsers: any = {};
-
- // Extract replies from recent notes
- for (const userId of replyTargetNotes.map(x => x.userId.toString())) {
- if (repliedUsers[userId]) {
- repliedUsers[userId]++;
- } else {
- repliedUsers[userId] = 1;
- }
- }
-
- // Calc peak
- const peak = maximum(Object.values(repliedUsers));
-
- // Sort replies by frequency
- const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
-
- // Extract top replied users
- const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit!);
-
- // Make replies object (includes weights)
- const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({
- user: await Users.pack(user, me, { detail: true }),
- weight: repliedUsers[user] / peak
- })));
-
- return repliesObj;
-});
diff --git a/src/server/api/endpoints/users/groups/create.ts b/src/server/api/endpoints/users/groups/create.ts
deleted file mode 100644
index dc1ee3879e..0000000000
--- a/src/server/api/endpoints/users/groups/create.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { UserGroups, UserGroupJoinings } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { UserGroup } from '@/models/entities/user-group';
-import { UserGroupJoining } from '@/models/entities/user-group-joining';
-
-export const meta = {
- tags: ['groups'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- name: {
- validator: $.str.range(1, 100)
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup',
- },
-};
-
-export default define(meta, async (ps, user) => {
- const userGroup = await UserGroups.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- name: ps.name,
- } as UserGroup).then(x => UserGroups.findOneOrFail(x.identifiers[0]));
-
- // Push the owner
- await UserGroupJoinings.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- userGroupId: userGroup.id
- } as UserGroupJoining);
-
- return await UserGroups.pack(userGroup);
-});
diff --git a/src/server/api/endpoints/users/groups/delete.ts b/src/server/api/endpoints/users/groups/delete.ts
deleted file mode 100644
index 7da1b4a273..0000000000
--- a/src/server/api/endpoints/users/groups/delete.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserGroups } from '@/models/index';
-
-export const meta = {
- tags: ['groups'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: '63dbd64c-cd77-413f-8e08-61781e210b38'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- userId: user.id
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- await UserGroups.delete(userGroup.id);
-});
diff --git a/src/server/api/endpoints/users/groups/invitations/accept.ts b/src/server/api/endpoints/users/groups/invitations/accept.ts
deleted file mode 100644
index 09e6ae2647..0000000000
--- a/src/server/api/endpoints/users/groups/invitations/accept.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../../define';
-import { ApiError } from '../../../../error';
-import { UserGroupJoinings, UserGroupInvitations } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { UserGroupJoining } from '@/models/entities/user-group-joining';
-
-export const meta = {
- tags: ['groups', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- invitationId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchInvitation: {
- message: 'No such invitation.',
- code: 'NO_SUCH_INVITATION',
- id: '98c11eca-c890-4f42-9806-c8c8303ebb5e'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch the invitation
- const invitation = await UserGroupInvitations.findOne({
- id: ps.invitationId,
- });
-
- if (invitation == null) {
- throw new ApiError(meta.errors.noSuchInvitation);
- }
-
- if (invitation.userId !== user.id) {
- throw new ApiError(meta.errors.noSuchInvitation);
- }
-
- // Push the user
- await UserGroupJoinings.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- userGroupId: invitation.userGroupId
- } as UserGroupJoining);
-
- UserGroupInvitations.delete(invitation.id);
-});
diff --git a/src/server/api/endpoints/users/groups/invitations/reject.ts b/src/server/api/endpoints/users/groups/invitations/reject.ts
deleted file mode 100644
index 741fcefb35..0000000000
--- a/src/server/api/endpoints/users/groups/invitations/reject.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../../define';
-import { ApiError } from '../../../../error';
-import { UserGroupInvitations } from '@/models/index';
-
-export const meta = {
- tags: ['groups', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- invitationId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchInvitation: {
- message: 'No such invitation.',
- code: 'NO_SUCH_INVITATION',
- id: 'ad7471d4-2cd9-44b4-ac68-e7136b4ce656'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch the invitation
- const invitation = await UserGroupInvitations.findOne({
- id: ps.invitationId,
- });
-
- if (invitation == null) {
- throw new ApiError(meta.errors.noSuchInvitation);
- }
-
- if (invitation.userId !== user.id) {
- throw new ApiError(meta.errors.noSuchInvitation);
- }
-
- await UserGroupInvitations.delete(invitation.id);
-});
diff --git a/src/server/api/endpoints/users/groups/invite.ts b/src/server/api/endpoints/users/groups/invite.ts
deleted file mode 100644
index f1ee8bf8b7..0000000000
--- a/src/server/api/endpoints/users/groups/invite.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { UserGroups, UserGroupJoinings, UserGroupInvitations } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { UserGroupInvitation } from '@/models/entities/user-group-invitation';
-import { createNotification } from '@/services/create-notification';
-
-export const meta = {
- tags: ['groups', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- },
-
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: '583f8bc0-8eee-4b78-9299-1e14fc91e409'
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: 'da52de61-002c-475b-90e1-ba64f9cf13a8'
- },
-
- alreadyAdded: {
- message: 'That user has already been added to that group.',
- code: 'ALREADY_ADDED',
- id: '7e35c6a0-39b2-4488-aea6-6ee20bd5da2c'
- },
-
- alreadyInvited: {
- message: 'That user has already been invited to that group.',
- code: 'ALREADY_INVITED',
- id: 'ee0f58b4-b529-4d13-b761-b9a3e69f97e6'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the group
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- userId: me.id,
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- // Fetch the user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- const joining = await UserGroupJoinings.findOne({
- userGroupId: userGroup.id,
- userId: user.id
- });
-
- if (joining) {
- throw new ApiError(meta.errors.alreadyAdded);
- }
-
- const existInvitation = await UserGroupInvitations.findOne({
- userGroupId: userGroup.id,
- userId: user.id
- });
-
- if (existInvitation) {
- throw new ApiError(meta.errors.alreadyInvited);
- }
-
- const invitation = await UserGroupInvitations.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- userGroupId: userGroup.id
- } as UserGroupInvitation).then(x => UserGroupInvitations.findOneOrFail(x.identifiers[0]));
-
- // 通知を作成
- createNotification(user.id, 'groupInvited', {
- notifierId: me.id,
- userGroupInvitationId: invitation.id
- });
-});
diff --git a/src/server/api/endpoints/users/groups/joined.ts b/src/server/api/endpoints/users/groups/joined.ts
deleted file mode 100644
index d5e8fe4032..0000000000
--- a/src/server/api/endpoints/users/groups/joined.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import define from '../../../define';
-import { UserGroups, UserGroupJoinings } from '@/models/index';
-import { Not, In } from 'typeorm';
-
-export const meta = {
- tags: ['groups', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:user-groups',
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const ownedGroups = await UserGroups.find({
- userId: me.id,
- });
-
- const joinings = await UserGroupJoinings.find({
- userId: me.id,
- ...(ownedGroups.length > 0 ? {
- userGroupId: Not(In(ownedGroups.map(x => x.id)))
- } : {})
- });
-
- return await Promise.all(joinings.map(x => UserGroups.pack(x.userGroupId)));
-});
diff --git a/src/server/api/endpoints/users/groups/leave.ts b/src/server/api/endpoints/users/groups/leave.ts
deleted file mode 100644
index 0e52f2abdf..0000000000
--- a/src/server/api/endpoints/users/groups/leave.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserGroups, UserGroupJoinings } from '@/models/index';
-
-export const meta = {
- tags: ['groups', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: '62780270-1f67-5dc0-daca-3eb510612e31'
- },
-
- youAreOwner: {
- message: 'Your are the owner.',
- code: 'YOU_ARE_OWNER',
- id: 'b6d6e0c2-ef8a-9bb8-653d-79f4a3107c69'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the group
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- if (me.id === userGroup.userId) {
- throw new ApiError(meta.errors.youAreOwner);
- }
-
- await UserGroupJoinings.delete({ userGroupId: userGroup.id, userId: me.id });
-});
diff --git a/src/server/api/endpoints/users/groups/owned.ts b/src/server/api/endpoints/users/groups/owned.ts
deleted file mode 100644
index 17de370dbc..0000000000
--- a/src/server/api/endpoints/users/groups/owned.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import define from '../../../define';
-import { UserGroups } from '@/models/index';
-
-export const meta = {
- tags: ['groups', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:user-groups',
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const userGroups = await UserGroups.find({
- userId: me.id,
- });
-
- return await Promise.all(userGroups.map(x => UserGroups.pack(x)));
-});
diff --git a/src/server/api/endpoints/users/groups/pull.ts b/src/server/api/endpoints/users/groups/pull.ts
deleted file mode 100644
index ce4d2e2881..0000000000
--- a/src/server/api/endpoints/users/groups/pull.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { UserGroups, UserGroupJoinings } from '@/models/index';
-
-export const meta = {
- tags: ['groups', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- },
-
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: '4662487c-05b1-4b78-86e5-fd46998aba74'
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '0b5cc374-3681-41da-861e-8bc1146f7a55'
- },
-
- isOwner: {
- message: 'The user is the owner.',
- code: 'IS_OWNER',
- id: '1546eed5-4414-4dea-81c1-b0aec4f6d2af'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the group
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- userId: me.id,
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- // Fetch the user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- if (user.id === userGroup.userId) {
- throw new ApiError(meta.errors.isOwner);
- }
-
- // Pull the user
- await UserGroupJoinings.delete({ userGroupId: userGroup.id, userId: user.id });
-});
diff --git a/src/server/api/endpoints/users/groups/show.ts b/src/server/api/endpoints/users/groups/show.ts
deleted file mode 100644
index 3c030bf3a5..0000000000
--- a/src/server/api/endpoints/users/groups/show.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserGroups, UserGroupJoinings } from '@/models/index';
-
-export const meta = {
- tags: ['groups', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup',
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: 'ea04751e-9b7e-487b-a509-330fb6bd6b9b'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the group
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- const joining = await UserGroupJoinings.findOne({
- userId: me.id,
- userGroupId: userGroup.id
- });
-
- if (joining == null && userGroup.userId !== me.id) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- return await UserGroups.pack(userGroup);
-});
diff --git a/src/server/api/endpoints/users/groups/transfer.ts b/src/server/api/endpoints/users/groups/transfer.ts
deleted file mode 100644
index 17c42e1127..0000000000
--- a/src/server/api/endpoints/users/groups/transfer.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { UserGroups, UserGroupJoinings } from '@/models/index';
-
-export const meta = {
- tags: ['groups', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- },
-
- userId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup',
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: '8e31d36b-2f88-4ccd-a438-e2d78a9162db'
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '711f7ebb-bbb9-4dfa-b540-b27809fed5e9'
- },
-
- noSuchGroupMember: {
- message: 'No such group member.',
- code: 'NO_SUCH_GROUP_MEMBER',
- id: 'd31bebee-196d-42c2-9a3e-9474d4be6cc4'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the group
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- userId: me.id,
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- // Fetch the user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- const joining = await UserGroupJoinings.findOne({
- userGroupId: userGroup.id,
- userId: user.id
- });
-
- if (joining == null) {
- throw new ApiError(meta.errors.noSuchGroupMember);
- }
-
- await UserGroups.update(userGroup.id, {
- userId: ps.userId
- });
-
- return await UserGroups.pack(userGroup.id);
-});
diff --git a/src/server/api/endpoints/users/groups/update.ts b/src/server/api/endpoints/users/groups/update.ts
deleted file mode 100644
index 127bbc47a1..0000000000
--- a/src/server/api/endpoints/users/groups/update.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserGroups } from '@/models/index';
-
-export const meta = {
- tags: ['groups'],
-
- requireCredential: true as const,
-
- kind: 'write:user-groups',
-
- params: {
- groupId: {
- validator: $.type(ID),
- },
-
- name: {
- validator: $.str.range(1, 100),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserGroup',
- },
-
- errors: {
- noSuchGroup: {
- message: 'No such group.',
- code: 'NO_SUCH_GROUP',
- id: '9081cda3-7a9e-4fac-a6ce-908d70f282f6'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the group
- const userGroup = await UserGroups.findOne({
- id: ps.groupId,
- userId: me.id
- });
-
- if (userGroup == null) {
- throw new ApiError(meta.errors.noSuchGroup);
- }
-
- await UserGroups.update(userGroup.id, {
- name: ps.name
- });
-
- return await UserGroups.pack(userGroup.id);
-});
diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts
deleted file mode 100644
index e0bfe611fc..0000000000
--- a/src/server/api/endpoints/users/lists/create.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import $ from 'cafy';
-import define from '../../../define';
-import { UserLists } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-import { UserList } from '@/models/entities/user-list';
-
-export const meta = {
- tags: ['lists'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- name: {
- validator: $.str.range(1, 100)
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserList',
- },
-};
-
-export default define(meta, async (ps, user) => {
- const userList = await UserLists.insert({
- id: genId(),
- createdAt: new Date(),
- userId: user.id,
- name: ps.name,
- } as UserList).then(x => UserLists.findOneOrFail(x.identifiers[0]));
-
- return await UserLists.pack(userList);
-});
diff --git a/src/server/api/endpoints/users/lists/delete.ts b/src/server/api/endpoints/users/lists/delete.ts
deleted file mode 100644
index 5fe3bfb03d..0000000000
--- a/src/server/api/endpoints/users/lists/delete.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserLists } from '@/models/index';
-
-export const meta = {
- tags: ['lists'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- listId: {
- validator: $.type(ID),
- }
- },
-
- errors: {
- noSuchList: {
- message: 'No such list.',
- code: 'NO_SUCH_LIST',
- id: '78436795-db79-42f5-b1e2-55ea2cf19166'
- }
- }
-};
-
-export default define(meta, async (ps, user) => {
- const userList = await UserLists.findOne({
- id: ps.listId,
- userId: user.id
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchList);
- }
-
- await UserLists.delete(userList.id);
-});
diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts
deleted file mode 100644
index cf0c92bb84..0000000000
--- a/src/server/api/endpoints/users/lists/list.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import define from '../../../define';
-import { UserLists } from '@/models/index';
-
-export const meta = {
- tags: ['lists', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserList',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const userLists = await UserLists.find({
- userId: me.id,
- });
-
- return await Promise.all(userLists.map(x => UserLists.pack(x)));
-});
diff --git a/src/server/api/endpoints/users/lists/pull.ts b/src/server/api/endpoints/users/lists/pull.ts
deleted file mode 100644
index d4357fc5e7..0000000000
--- a/src/server/api/endpoints/users/lists/pull.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import { publishUserListStream } from '@/services/stream';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { UserLists, UserListJoinings, Users } from '@/models/index';
-
-export const meta = {
- tags: ['lists', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- listId: {
- validator: $.type(ID),
- },
-
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchList: {
- message: 'No such list.',
- code: 'NO_SUCH_LIST',
- id: '7f44670e-ab16-43b8-b4c1-ccd2ee89cc02'
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '588e7f72-c744-4a61-b180-d354e912bda2'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the list
- const userList = await UserLists.findOne({
- id: ps.listId,
- userId: me.id,
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchList);
- }
-
- // Fetch the user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Pull the user
- await UserListJoinings.delete({ userListId: userList.id, userId: user.id });
-
- publishUserListStream(userList.id, 'userRemoved', await Users.pack(user));
-});
diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts
deleted file mode 100644
index 8e21059d3d..0000000000
--- a/src/server/api/endpoints/users/lists/push.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { getUser } from '../../../common/getters';
-import { pushUserToUserList } from '@/services/user-list/push';
-import { UserLists, UserListJoinings, Blockings } from '@/models/index';
-
-export const meta = {
- tags: ['lists', 'users'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- listId: {
- validator: $.type(ID),
- },
-
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchList: {
- message: 'No such list.',
- code: 'NO_SUCH_LIST',
- id: '2214501d-ac96-4049-b717-91e42272a711'
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: 'a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a'
- },
-
- alreadyAdded: {
- message: 'That user has already been added to that list.',
- code: 'ALREADY_ADDED',
- id: '1de7c884-1595-49e9-857e-61f12f4d4fc5'
- },
-
- youHaveBeenBlocked: {
- message: 'You cannot push this user because you have been blocked by this user.',
- code: 'YOU_HAVE_BEEN_BLOCKED',
- id: '990232c5-3f9d-4d83-9f3f-ef27b6332a4b'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the list
- const userList = await UserLists.findOne({
- id: ps.listId,
- userId: me.id,
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchList);
- }
-
- // Fetch the user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- // Check blocking
- if (user.id !== me.id) {
- const block = await Blockings.findOne({
- blockerId: user.id,
- blockeeId: me.id,
- });
- if (block) {
- throw new ApiError(meta.errors.youHaveBeenBlocked);
- }
- }
-
- const exist = await UserListJoinings.findOne({
- userListId: userList.id,
- userId: user.id
- });
-
- if (exist) {
- throw new ApiError(meta.errors.alreadyAdded);
- }
-
- // Push the user
- await pushUserToUserList(user, userList);
-});
diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts
deleted file mode 100644
index f9a35cdab3..0000000000
--- a/src/server/api/endpoints/users/lists/show.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserLists } from '@/models/index';
-
-export const meta = {
- tags: ['lists', 'account'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- params: {
- listId: {
- validator: $.type(ID),
- },
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserList',
- },
-
- errors: {
- noSuchList: {
- message: 'No such list.',
- code: 'NO_SUCH_LIST',
- id: '7bc05c21-1d7a-41ae-88f1-66820f4dc686'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Fetch the list
- const userList = await UserLists.findOne({
- id: ps.listId,
- userId: me.id,
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchList);
- }
-
- return await UserLists.pack(userList);
-});
diff --git a/src/server/api/endpoints/users/lists/update.ts b/src/server/api/endpoints/users/lists/update.ts
deleted file mode 100644
index 1185af5043..0000000000
--- a/src/server/api/endpoints/users/lists/update.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../../define';
-import { ApiError } from '../../../error';
-import { UserLists } from '@/models/index';
-
-export const meta = {
- tags: ['lists'],
-
- requireCredential: true as const,
-
- kind: 'write:account',
-
- params: {
- listId: {
- validator: $.type(ID),
- },
-
- name: {
- validator: $.str.range(1, 100),
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'UserList',
- },
-
- errors: {
- noSuchList: {
- message: 'No such list.',
- code: 'NO_SUCH_LIST',
- id: '796666fe-3dff-4d39-becb-8a5932c1d5b7'
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- // Fetch the list
- const userList = await UserLists.findOne({
- id: ps.listId,
- userId: user.id
- });
-
- if (userList == null) {
- throw new ApiError(meta.errors.noSuchList);
- }
-
- await UserLists.update(userList.id, {
- name: ps.name
- });
-
- return await UserLists.pack(userList.id);
-});
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
deleted file mode 100644
index 0afbad9d04..0000000000
--- a/src/server/api/endpoints/users/notes.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { Notes } from '@/models/index';
-import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
-import { Brackets } from 'typeorm';
-import { generateBlockedUserQuery } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['users', 'notes'],
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- includeReplies: {
- validator: $.optional.bool,
- default: true,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
-
- includeMyRenotes: {
- validator: $.optional.bool,
- default: true,
- },
-
- withFiles: {
- validator: $.optional.bool,
- default: false,
- },
-
- fileType: {
- validator: $.optional.arr($.str),
- },
-
- excludeNsfw: {
- validator: $.optional.bool,
- default: false,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'Note',
- }
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '27e494ba-2ac2-48e8-893b-10d4d8c2387b'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Lookup user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- //#region Construct query
- const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere('note.userId = :userId', { userId: user.id })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser');
-
- generateVisibilityQuery(query, me);
- if (me) generateMutedUserQuery(query, me, user);
- if (me) generateBlockedUserQuery(query, me);
-
- if (ps.withFiles) {
- query.andWhere('note.fileIds != \'{}\'');
- }
-
- if (ps.fileType != null) {
- query.andWhere('note.fileIds != \'{}\'');
- 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 });
- }
- }));
-
- if (ps.excludeNsfw) {
- query.andWhere('note.cw IS NULL');
- query.andWhere('0 = (SELECT COUNT(*) FROM drive_file df WHERE df.id = ANY(note."fileIds") AND df."isSensitive" = TRUE)');
- }
- }
-
- if (!ps.includeReplies) {
- query.andWhere('note.replyId IS NULL');
- }
-
- if (ps.includeMyRenotes === false) {
- query.andWhere(new Brackets(qb => {
- qb.orWhere('note.userId != :userId', { userId: user.id });
- qb.orWhere('note.renoteId IS NULL');
- qb.orWhere('note.text IS NOT NULL');
- qb.orWhere('note.fileIds != \'{}\'');
- qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
- }));
- }
-
- //#endregion
-
- const timeline = await query.take(ps.limit!).getMany();
-
- return await Notes.packMany(timeline, me);
-});
diff --git a/src/server/api/endpoints/users/pages.ts b/src/server/api/endpoints/users/pages.ts
deleted file mode 100644
index 24e9e207fd..0000000000
--- a/src/server/api/endpoints/users/pages.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { Pages } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-
-export const meta = {
- tags: ['users', 'pages'],
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
- }
-};
-
-export default define(meta, async (ps, user) => {
- const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
- .andWhere(`page.userId = :userId`, { userId: ps.userId })
- .andWhere('page.visibility = \'public\'');
-
- const pages = await query
- .take(ps.limit!)
- .getMany();
-
- return await Pages.packMany(pages);
-});
diff --git a/src/server/api/endpoints/users/reactions.ts b/src/server/api/endpoints/users/reactions.ts
deleted file mode 100644
index fe5e4d84a9..0000000000
--- a/src/server/api/endpoints/users/reactions.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { NoteReactions, UserProfiles } from '@/models/index';
-import { makePaginationQuery } from '../../common/make-pagination-query';
-import { generateVisibilityQuery } from '../../common/generate-visibility-query';
-import { ApiError } from '../../error';
-
-export const meta = {
- tags: ['users', 'reactions'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- sinceId: {
- validator: $.optional.type(ID),
- },
-
- untilId: {
- validator: $.optional.type(ID),
- },
-
- sinceDate: {
- validator: $.optional.num,
- },
-
- untilDate: {
- validator: $.optional.num,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'NoteReaction',
- }
- },
-
- errors: {
- reactionsNotPublic: {
- message: 'Reactions of the user is not public.',
- code: 'REACTIONS_NOT_PUBLIC',
- id: '673a7dd2-6924-1093-e0c0-e68456ceae5c'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const profile = await UserProfiles.findOneOrFail(ps.userId);
-
- if (me == null || (me.id !== ps.userId && !profile.publicReactions)) {
- throw new ApiError(meta.errors.reactionsNotPublic);
- }
-
- const query = makePaginationQuery(NoteReactions.createQueryBuilder('reaction'),
- ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere(`reaction.userId = :userId`, { userId: ps.userId })
- .leftJoinAndSelect('reaction.note', 'note');
-
- generateVisibilityQuery(query, me);
-
- const reactions = await query
- .take(ps.limit!)
- .getMany();
-
- return await Promise.all(reactions.map(reaction => NoteReactions.pack(reaction, me, { withNote: true })));
-});
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
deleted file mode 100644
index dde6bb1037..0000000000
--- a/src/server/api/endpoints/users/recommendation.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import * as ms from 'ms';
-import $ from 'cafy';
-import define from '../../define';
-import { Users, Followings } from '@/models/index';
-import { generateMutedUserQueryForUsers } from '../../common/generate-muted-user-query';
-import { generateBlockedUserQuery, generateBlockQueryForUsers } from '../../common/generate-block-query';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: true as const,
-
- kind: 'read:account',
-
- params: {
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0
- }
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const query = Users.createQueryBuilder('user')
- .where('user.isLocked = FALSE')
- .andWhere('user.isExplorable = TRUE')
- .andWhere('user.host IS NULL')
- .andWhere('user.updatedAt >= :date', { date: new Date(Date.now() - ms('7days')) })
- .andWhere('user.id != :meId', { meId: me.id })
- .orderBy('user.followersCount', 'DESC');
-
- generateMutedUserQueryForUsers(query, me);
- generateBlockQueryForUsers(query, me);
- generateBlockedUserQuery(query, me);
-
- const followingQuery = Followings.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: me.id });
-
- query
- .andWhere(`user.id NOT IN (${ followingQuery.getQuery() })`);
-
- query.setParameters(followingQuery.getParameters());
-
- const users = await query.take(ps.limit!).skip(ps.offset).getMany();
-
- return await Users.packMany(users, me, { detail: true });
-});
diff --git a/src/server/api/endpoints/users/relation.ts b/src/server/api/endpoints/users/relation.ts
deleted file mode 100644
index 32d76a5322..0000000000
--- a/src/server/api/endpoints/users/relation.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ID } from '@/misc/cafy-id';
-import { Users } from '@/models/index';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: true as const,
-
- params: {
- userId: {
- validator: $.either($.type(ID), $.arr($.type(ID)).unique()),
- }
- },
-
- res: {
- oneOf: [
- {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- isFollowing: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- hasPendingFollowRequestFromYou: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- hasPendingFollowRequestToYou: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isFollowed: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isBlocking: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isBlocked: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isMuted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- }
- }
- },
- {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- properties: {
- id: {
- type: 'string' as const,
- optional: false as const, nullable: false as const,
- format: 'id'
- },
- isFollowing: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- hasPendingFollowRequestFromYou: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- hasPendingFollowRequestToYou: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isFollowed: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isBlocking: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isBlocked: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- },
- isMuted: {
- type: 'boolean' as const,
- optional: false as const, nullable: false as const
- }
- }
- }
- }
- ]
- }
-};
-
-export default define(meta, async (ps, me) => {
- const ids = Array.isArray(ps.userId) ? ps.userId : [ps.userId];
-
- const relations = await Promise.all(ids.map(id => Users.getRelation(me.id, id)));
-
- return Array.isArray(ps.userId) ? relations : relations[0];
-});
diff --git a/src/server/api/endpoints/users/report-abuse.ts b/src/server/api/endpoints/users/report-abuse.ts
deleted file mode 100644
index 2c8672cd47..0000000000
--- a/src/server/api/endpoints/users/report-abuse.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id';
-import define from '../../define';
-import { publishAdminStream } from '@/services/stream';
-import { ApiError } from '../../error';
-import { getUser } from '../../common/getters';
-import { AbuseUserReports, Users } from '@/models/index';
-import { genId } from '@/misc/gen-id';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: true as const,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
-
- comment: {
- validator: $.str.range(1, 2048),
- },
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '1acefcb5-0959-43fd-9685-b48305736cb5'
- },
-
- cannotReportYourself: {
- message: 'Cannot report yourself.',
- code: 'CANNOT_REPORT_YOURSELF',
- id: '1e13149e-b1e8-43cf-902e-c01dbfcb202f'
- },
-
- cannotReportAdmin: {
- message: 'Cannot report the admin.',
- code: 'CANNOT_REPORT_THE_ADMIN',
- id: '35e166f5-05fb-4f87-a2d5-adb42676d48f'
- }
- }
-};
-
-export default define(meta, async (ps, me) => {
- // Lookup user
- const user = await getUser(ps.userId).catch(e => {
- if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
- throw e;
- });
-
- if (user.id === me.id) {
- throw new ApiError(meta.errors.cannotReportYourself);
- }
-
- if (user.isAdmin) {
- throw new ApiError(meta.errors.cannotReportAdmin);
- }
-
- const report = await AbuseUserReports.save({
- id: genId(),
- createdAt: new Date(),
- targetUserId: user.id,
- targetUserHost: user.host,
- reporterId: me.id,
- reporterHost: null,
- comment: ps.comment,
- });
-
- // Publish event to moderators
- setTimeout(async () => {
- const moderators = await Users.find({
- where: [{
- isAdmin: true
- }, {
- isModerator: true
- }]
- });
-
- for (const moderator of moderators) {
- publishAdminStream(moderator.id, 'newAbuseUserReport', {
- id: report.id,
- targetUserId: report.targetUserId,
- reporterId: report.reporterId,
- comment: report.comment
- });
- }
- }, 1);
-});
diff --git a/src/server/api/endpoints/users/search-by-username-and-host.ts b/src/server/api/endpoints/users/search-by-username-and-host.ts
deleted file mode 100644
index 1ec5e1a743..0000000000
--- a/src/server/api/endpoints/users/search-by-username-and-host.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { Followings, Users } from '@/models/index';
-import { Brackets } from 'typeorm';
-import { USER_ACTIVE_THRESHOLD } from '@/const';
-import { User } from '@/models/entities/user';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- username: {
- validator: $.optional.nullable.str,
- },
-
- host: {
- validator: $.optional.nullable.str,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- detail: {
- validator: $.optional.bool,
- default: true,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
-
- if (ps.host) {
- const q = Users.createQueryBuilder('user')
- .where('user.isSuspended = FALSE')
- .andWhere('user.host LIKE :host', { host: ps.host.toLowerCase() + '%' });
-
- if (ps.username) {
- q.andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' });
- }
-
- q.andWhere('user.updatedAt IS NOT NULL');
- q.orderBy('user.updatedAt', 'DESC');
-
- const users = await q.take(ps.limit!).getMany();
-
- return await Users.packMany(users, me, { detail: ps.detail });
- } else if (ps.username) {
- let users: User[] = [];
-
- if (me) {
- const followingQuery = Followings.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: me.id });
-
- const query = Users.createQueryBuilder('user')
- .where(`user.id IN (${ followingQuery.getQuery() })`)
- .andWhere(`user.id != :meId`, { meId: me.id })
- .andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
- .andWhere(new Brackets(qb => { qb
- .where('user.updatedAt IS NULL')
- .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
- }));
-
- query.setParameters(followingQuery.getParameters());
-
- users = await query
- .orderBy('user.usernameLower', 'ASC')
- .take(ps.limit!)
- .getMany();
-
- if (users.length < ps.limit!) {
- const otherQuery = await Users.createQueryBuilder('user')
- .where(`user.id NOT IN (${ followingQuery.getQuery() })`)
- .andWhere(`user.id != :meId`, { meId: me.id })
- .andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
- .andWhere('user.updatedAt IS NOT NULL');
-
- otherQuery.setParameters(followingQuery.getParameters());
-
- const otherUsers = await otherQuery
- .orderBy('user.updatedAt', 'DESC')
- .take(ps.limit! - users.length)
- .getMany();
-
- users = users.concat(otherUsers);
- }
- } else {
- users = await Users.createQueryBuilder('user')
- .where('user.isSuspended = FALSE')
- .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' })
- .andWhere('user.updatedAt IS NOT NULL')
- .orderBy('user.updatedAt', 'DESC')
- .take(ps.limit! - users.length)
- .getMany();
- }
-
- return await Users.packMany(users, me, { detail: ps.detail });
- }
-});
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
deleted file mode 100644
index 9aa988d9ed..0000000000
--- a/src/server/api/endpoints/users/search.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { UserProfiles, Users } from '@/models/index';
-import { User } from '@/models/entities/user';
-import { Brackets } from 'typeorm';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- query: {
- validator: $.str,
- },
-
- offset: {
- validator: $.optional.num.min(0),
- default: 0,
- },
-
- limit: {
- validator: $.optional.num.range(1, 100),
- default: 10,
- },
-
- origin: {
- validator: $.optional.str.or(['local', 'remote', 'combined']),
- default: 'combined',
- },
-
- detail: {
- validator: $.optional.bool,
- default: true,
- },
- },
-
- res: {
- type: 'array' as const,
- optional: false as const, nullable: false as const,
- items: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- }
- },
-};
-
-export default define(meta, async (ps, me) => {
- const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
-
- const isUsername = ps.query.startsWith('@');
-
- let users: User[] = [];
-
- if (isUsername) {
- const usernameQuery = Users.createQueryBuilder('user')
- .where('user.usernameLower LIKE :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
- .andWhere(new Brackets(qb => { qb
- .where('user.updatedAt IS NULL')
- .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
- }))
- .andWhere('user.isSuspended = FALSE');
-
- if (ps.origin === 'local') {
- usernameQuery.andWhere('user.host IS NULL');
- } else if (ps.origin === 'remote') {
- usernameQuery.andWhere('user.host IS NOT NULL');
- }
-
- users = await usernameQuery
- .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
- .take(ps.limit!)
- .skip(ps.offset)
- .getMany();
- } else {
- const nameQuery = Users.createQueryBuilder('user')
- .where('user.name ILIKE :query', { query: '%' + ps.query + '%' })
- .andWhere(new Brackets(qb => { qb
- .where('user.updatedAt IS NULL')
- .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
- }))
- .andWhere('user.isSuspended = FALSE');
-
- if (ps.origin === 'local') {
- nameQuery.andWhere('user.host IS NULL');
- } else if (ps.origin === 'remote') {
- nameQuery.andWhere('user.host IS NOT NULL');
- }
-
- users = await nameQuery
- .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
- .take(ps.limit!)
- .skip(ps.offset)
- .getMany();
-
- if (users.length < ps.limit!) {
- const profQuery = UserProfiles.createQueryBuilder('prof')
- .select('prof.userId')
- .where('prof.description ILIKE :query', { query: '%' + ps.query + '%' });
-
- if (ps.origin === 'local') {
- profQuery.andWhere('prof.userHost IS NULL');
- } else if (ps.origin === 'remote') {
- profQuery.andWhere('prof.userHost IS NOT NULL');
- }
-
- const query = Users.createQueryBuilder('user')
- .where(`user.id IN (${ profQuery.getQuery() })`)
- .andWhere(new Brackets(qb => { qb
- .where('user.updatedAt IS NULL')
- .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
- }))
- .andWhere('user.isSuspended = FALSE')
- .setParameters(profQuery.getParameters());
-
- users = users.concat(await query
- .orderBy('user.updatedAt', 'DESC', 'NULLS LAST')
- .take(ps.limit!)
- .skip(ps.offset)
- .getMany()
- );
- }
- }
-
- return await Users.packMany(users, me, { detail: ps.detail });
-});
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
deleted file mode 100644
index f056983636..0000000000
--- a/src/server/api/endpoints/users/show.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import $ from 'cafy';
-import { resolveUser } from '@/remote/resolve-user';
-import define from '../../define';
-import { apiLogger } from '../../logger';
-import { ApiError } from '../../error';
-import { ID } from '@/misc/cafy-id';
-import { Users } from '@/models/index';
-import { In } from 'typeorm';
-import { User } from '@/models/entities/user';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.optional.type(ID),
- },
-
- userIds: {
- validator: $.optional.arr($.type(ID)).unique(),
- },
-
- username: {
- validator: $.optional.str
- },
-
- host: {
- validator: $.optional.nullable.str
- }
- },
-
- res: {
- type: 'object' as const,
- optional: false as const, nullable: false as const,
- ref: 'User',
- },
-
- errors: {
- failedToResolveRemoteUser: {
- message: 'Failed to resolve remote user.',
- code: 'FAILED_TO_RESOLVE_REMOTE_USER',
- id: 'ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c',
- kind: 'server' as const
- },
-
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '4362f8dc-731f-4ad8-a694-be5a88922a24'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- let user;
-
- const isAdminOrModerator = me && (me.isAdmin || me.isModerator);
-
- if (ps.userIds) {
- if (ps.userIds.length === 0) {
- return [];
- }
-
- const users = await Users.find(isAdminOrModerator ? {
- id: In(ps.userIds)
- } : {
- id: In(ps.userIds),
- isSuspended: false
- });
-
- // リクエストされた通りに並べ替え
- const _users: User[] = [];
- for (const id of ps.userIds) {
- _users.push(users.find(x => x.id === id)!);
- }
-
- return await Promise.all(_users.map(u => Users.pack(u, me, {
- detail: true
- })));
- } else {
- // Lookup user
- if (typeof ps.host === 'string' && typeof ps.username === 'string') {
- user = await resolveUser(ps.username, ps.host).catch(e => {
- apiLogger.warn(`failed to resolve remote user: ${e}`);
- throw new ApiError(meta.errors.failedToResolveRemoteUser);
- });
- } else {
- const q: any = ps.userId != null
- ? { id: ps.userId }
- : { usernameLower: ps.username!.toLowerCase(), host: null };
-
- user = await Users.findOne(q);
- }
-
- if (user == null || (!isAdminOrModerator && user.isSuspended)) {
- throw new ApiError(meta.errors.noSuchUser);
- }
-
- return await Users.pack(user, me, {
- detail: true
- });
- }
-});
diff --git a/src/server/api/endpoints/users/stats.ts b/src/server/api/endpoints/users/stats.ts
deleted file mode 100644
index ef8afd5625..0000000000
--- a/src/server/api/endpoints/users/stats.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import $ from 'cafy';
-import define from '../../define';
-import { ApiError } from '../../error';
-import { ID } from '@/misc/cafy-id';
-import { DriveFiles, Followings, NoteFavorites, NoteReactions, Notes, PageLikes, PollVotes, ReversiGames, Users } from '@/models/index';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false as const,
-
- params: {
- userId: {
- validator: $.type(ID),
- },
- },
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '9e638e45-3b25-4ef7-8f95-07e8498f1819'
- },
- }
-};
-
-export default define(meta, async (ps, me) => {
- const user = await Users.findOne(ps.userId);
- if (user == null) {
- throw new ApiError(meta.errors.noSuchUser);
- }
-
- const [
- notesCount,
- repliesCount,
- renotesCount,
- repliedCount,
- renotedCount,
- pollVotesCount,
- pollVotedCount,
- localFollowingCount,
- remoteFollowingCount,
- localFollowersCount,
- remoteFollowersCount,
- sentReactionsCount,
- receivedReactionsCount,
- noteFavoritesCount,
- pageLikesCount,
- pageLikedCount,
- driveFilesCount,
- driveUsage,
- reversiCount,
- ] = await Promise.all([
- Notes.createQueryBuilder('note')
- .where('note.userId = :userId', { userId: user.id })
- .getCount(),
- Notes.createQueryBuilder('note')
- .where('note.userId = :userId', { userId: user.id })
- .andWhere('note.replyId IS NOT NULL')
- .getCount(),
- Notes.createQueryBuilder('note')
- .where('note.userId = :userId', { userId: user.id })
- .andWhere('note.renoteId IS NOT NULL')
- .getCount(),
- Notes.createQueryBuilder('note')
- .where('note.replyUserId = :userId', { userId: user.id })
- .getCount(),
- Notes.createQueryBuilder('note')
- .where('note.renoteUserId = :userId', { userId: user.id })
- .getCount(),
- PollVotes.createQueryBuilder('vote')
- .where('vote.userId = :userId', { userId: user.id })
- .getCount(),
- PollVotes.createQueryBuilder('vote')
- .innerJoin('vote.note', 'note')
- .where('note.userId = :userId', { userId: user.id })
- .getCount(),
- Followings.createQueryBuilder('following')
- .where('following.followerId = :userId', { userId: user.id })
- .andWhere('following.followeeHost IS NULL')
- .getCount(),
- Followings.createQueryBuilder('following')
- .where('following.followerId = :userId', { userId: user.id })
- .andWhere('following.followeeHost IS NOT NULL')
- .getCount(),
- Followings.createQueryBuilder('following')
- .where('following.followeeId = :userId', { userId: user.id })
- .andWhere('following.followerHost IS NULL')
- .getCount(),
- Followings.createQueryBuilder('following')
- .where('following.followeeId = :userId', { userId: user.id })
- .andWhere('following.followerHost IS NOT NULL')
- .getCount(),
- NoteReactions.createQueryBuilder('reaction')
- .where('reaction.userId = :userId', { userId: user.id })
- .getCount(),
- NoteReactions.createQueryBuilder('reaction')
- .innerJoin('reaction.note', 'note')
- .where('note.userId = :userId', { userId: user.id })
- .getCount(),
- NoteFavorites.createQueryBuilder('favorite')
- .where('favorite.userId = :userId', { userId: user.id })
- .getCount(),
- PageLikes.createQueryBuilder('like')
- .where('like.userId = :userId', { userId: user.id })
- .getCount(),
- PageLikes.createQueryBuilder('like')
- .innerJoin('like.page', 'page')
- .where('page.userId = :userId', { userId: user.id })
- .getCount(),
- DriveFiles.createQueryBuilder('file')
- .where('file.userId = :userId', { userId: user.id })
- .getCount(),
- DriveFiles.calcDriveUsageOf(user),
- ReversiGames.createQueryBuilder('game')
- .where('game.user1Id = :userId', { userId: user.id })
- .orWhere('game.user2Id = :userId', { userId: user.id })
- .getCount(),
- ]);
-
- return {
- notesCount,
- repliesCount,
- renotesCount,
- repliedCount,
- renotedCount,
- pollVotesCount,
- pollVotedCount,
- localFollowingCount,
- remoteFollowingCount,
- localFollowersCount,
- remoteFollowersCount,
- followingCount: localFollowingCount + remoteFollowingCount,
- followersCount: localFollowersCount + remoteFollowersCount,
- sentReactionsCount,
- receivedReactionsCount,
- noteFavoritesCount,
- pageLikesCount,
- pageLikedCount,
- driveFilesCount,
- driveUsage,
- reversiCount,
- };
-});