diff options
Diffstat (limited to 'packages/backend/src/server/api/endpoints/following')
6 files changed, 372 insertions, 0 deletions
diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts new file mode 100644 index 0000000000..92e86bf6b2 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -0,0 +1,100 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import 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/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts new file mode 100644 index 0000000000..030d30c9b5 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -0,0 +1,82 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import 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/packages/backend/src/server/api/endpoints/following/requests/accept.ts b/packages/backend/src/server/api/endpoints/following/requests/accept.ts new file mode 100644 index 0000000000..af39ea1d90 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/requests/accept.ts @@ -0,0 +1,48 @@ +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/packages/backend/src/server/api/endpoints/following/requests/cancel.ts b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts new file mode 100644 index 0000000000..b69c9d2fe1 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts @@ -0,0 +1,58 @@ +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/packages/backend/src/server/api/endpoints/following/requests/list.ts b/packages/backend/src/server/api/endpoints/following/requests/list.ts new file mode 100644 index 0000000000..84440ccac7 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/requests/list.ts @@ -0,0 +1,44 @@ +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/packages/backend/src/server/api/endpoints/following/requests/reject.ts b/packages/backend/src/server/api/endpoints/following/requests/reject.ts new file mode 100644 index 0000000000..620324361f --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/requests/reject.ts @@ -0,0 +1,40 @@ +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; +}); |