From 9df8d3f29d4ba64ee37cb49a3690349b0b32f1d0 Mon Sep 17 00:00:00 2001 From: EpicUsername12 <39063367+EpicUsername12@users.noreply.github.com> Date: Tue, 30 May 2023 18:06:51 +0200 Subject: [PATCH] Updated POST /v1/communities/%s: - Implemented ``/v1/communities/%s`` (update user-made sub community) - Implemented ``/v1/communities/%s.delete`` (delete user-made sub community) - Implemented ``/v1/communities/%s.favorite`` - Implemented ``/v1/communities/%s.unfavorite`` --- src/models/community.ts | 22 +++ src/services/api/routes/communities.ts | 177 ++++++++++++++++++++--- src/types/mongoose/community.ts | 3 + src/types/mongoose/subcommunity-query.ts | 6 +- 4 files changed, 184 insertions(+), 24 deletions(-) diff --git a/src/models/community.ts b/src/models/community.ts index 96ae086..9cf2675 100644 --- a/src/models/community.ts +++ b/src/models/community.ts @@ -64,6 +64,10 @@ const CommunitySchema = new Schema { @@ -94,6 +98,24 @@ CommunitySchema.method('downFollower', async function downFollower(): Promise { + const userFavorites: number[] = this.get('user_favorites'); + if (!userFavorites.includes(pid)) { + userFavorites.push(pid); + } + + await this.save(); +}); + +CommunitySchema.method('delUserFavorite', async function delUserFavorite(pid: number): Promise { + const userFavorites: number[] = this.get('user_favorites'); + if (userFavorites.includes(pid)) { + userFavorites.splice(userFavorites.indexOf(pid), 1); + } + + await this.save(); +}); + CommunitySchema.method('json', function json(): Record { return { community_id: this.community_id, diff --git a/src/services/api/routes/communities.ts b/src/services/api/routes/communities.ts index c9628d3..a576aef 100644 --- a/src/services/api/routes/communities.ts +++ b/src/services/api/routes/communities.ts @@ -28,22 +28,48 @@ const createNewCommunitySchema = z.object({ const router: express.Router = express.Router(); +async function respondCommunityNotFound(response: express.Response) : Promise { + response.status(404); + response.send(xmlbuilder.create({ + result: { + has_error: 1, + version: 1, + code: 404, + error_code: 919, + message: 'COMMUNITY_NOT_FOUND' + } + }).end({ pretty: true })); +} + +async function commonGetSubCommunity(request: express.Request, response: express.Response, communityID: string | undefined) : Promise { + + const parentCommunity: HydratedCommunityDocument | null = await getCommunityByTitleID(request.paramPack.title_id); + if (!parentCommunity) { + await respondCommunityNotFound(response); + return parentCommunity; + } + + const query: SubCommunityQuery = { + parent: parentCommunity.olive_community_id, + community_id: communityID + }; + + const community: HydratedCommunityDocument | null = await Community.findOne(query); + if (!community) { + await respondCommunityNotFound(response); + return community; + } + + return community; +} + /* GET post titles. */ router.get('/', async function (request: express.Request, response: express.Response): Promise { response.type('application/xml'); const parentCommunity: HydratedCommunityDocument | null = await getCommunityByTitleID(request.paramPack.title_id); if (!parentCommunity) { - response.status(404); - response.send(xmlbuilder.create({ - result: { - has_error: 1, - version: 1, - code: 404, - error_code: 919, - message: 'COMMUNITY_NOT_FOUND' - } - }).end({ pretty: true })); + await respondCommunityNotFound(response); return; } @@ -70,7 +96,7 @@ router.get('/', async function (request: express.Request, response: express.Resp if (type === 'my') { query.owner = request.pid; } else if (type ==='favorite') { - // TODO + query.user_favorites = request.pid; } const communities: HydratedCommunityDocument[] = await Community.find(query).limit(limit); @@ -227,16 +253,7 @@ router.post('/', multer().none(), async function (request: express.Request, resp const parentCommunity: HydratedCommunityDocument | null = await getCommunityByTitleID(request.paramPack.title_id); if (!parentCommunity) { - response.status(404); - response.send(xmlbuilder.create({ - result: { - has_error: 1, - version: 1, - code: 404, - error_code: 919, - message: 'COMMUNITY_NOT_FOUND' - } - }).end({ pretty: true })); + await respondCommunityNotFound(response); return; } @@ -284,4 +301,122 @@ router.post('/', multer().none(), async function (request: express.Request, resp }).end({ pretty: true, allowEmpty: true })); }); +router.post('/:community_action', multer().none(), async function (request: express.Request, response: express.Response): Promise { + response.type('application/xml'); + + const parentCommunity: HydratedCommunityDocument | null = await getCommunityByTitleID(request.paramPack.title_id); + if (!parentCommunity) { + await respondCommunityNotFound(response); + return; + } + + const communityActions: string[] = request.params.community_action.split('.'); + const community: HydratedCommunityDocument | null = await commonGetSubCommunity(request, response, communityActions[0]); + if (!community) { + return; + } + + if (communityActions.length > 1) { + if (communityActions[1] === 'delete') { + await deleteSubCommunity(community, request, response); + } else if (communityActions[1] === 'favorite') { + await addFavoriteSubCommunity(community, request, response); + } else if (communityActions[1] === 'unfavorite') { + await delFavoriteSubCommunity(community, request, response); + } else { // '%s.search' + response.sendStatus(501); // Not Implemented + } + } else { + await updateSubCommunity(community, request, response); + } +}); + +async function updateSubCommunity(community: HydratedCommunityDocument, request: express.Request, response: express.Response): Promise { + response.type('application/xml'); + + if (community.owner != request.pid) { + response.sendStatus(403); // Forbidden + return; + } + + const bodyCheck: z.SafeParseReturnType = createNewCommunitySchema.safeParse(request.body); + if (!bodyCheck.success) { + response.send(xmlbuilder.create({ + result: { + has_error: 1, + version: 1, + code: 404, + error_code: 20, + message: 'BAD_COMMUNITY_DATA' + } + }).end({ pretty: true })); + return; + } + + community.name = request.body.name; + community.description = request.body.description; + community.icon = request.body.icon; + community.app_data = request.body.app_data; + await community.save(); + + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + request_name: 'community', + community: community.json() + } + }).end({ pretty: true, allowEmpty: true })); +} + +async function deleteSubCommunity(community: HydratedCommunityDocument, request: express.Request, response: express.Response): Promise { + response.type('application/xml'); + + if (community.owner != request.pid) { + response.sendStatus(403); // Forbidden + return; + } + + await Community.deleteOne({ _id: community._id }); + + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + request_name: 'community', + community: community.json() + } + }).end({ pretty: true, allowEmpty: true })); +} + +async function addFavoriteSubCommunity(community: HydratedCommunityDocument, request: express.Request, response: express.Response): Promise { + response.type('application/xml'); + + await community.addUserFavorite(request.pid); + + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + request_name: 'community', + community: community.json() + } + }).end({ pretty: true, allowEmpty: true })); +} + +async function delFavoriteSubCommunity(community: HydratedCommunityDocument, request: express.Request, response: express.Response): Promise { + response.type('application/xml'); + + await community.delUserFavorite(request.pid); + + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + request_name: 'community', + community: community.json() + } + }).end({ pretty: true, allowEmpty: true })); +} + export default router; diff --git a/src/types/mongoose/community.ts b/src/types/mongoose/community.ts index edf5a2a..152c3b2 100644 --- a/src/types/mongoose/community.ts +++ b/src/types/mongoose/community.ts @@ -28,6 +28,7 @@ export interface ICommunity { olive_community_id: string; is_recommended: number; app_data: string; + user_favorites: Types.Array; } export interface ICommunityMethods { @@ -35,6 +36,8 @@ export interface ICommunityMethods { downEmpathy(): Promise; upFollower(): Promise; downFollower(): Promise; + addUserFavorite(pid: number): Promise; + delUserFavorite(pid: number): Promise; json(): Record; } diff --git a/src/types/mongoose/subcommunity-query.ts b/src/types/mongoose/subcommunity-query.ts index 736b0cc..3ee3824 100644 --- a/src/types/mongoose/subcommunity-query.ts +++ b/src/types/mongoose/subcommunity-query.ts @@ -3,7 +3,7 @@ export interface SubCommunityQuery { parent: string; owner?: number; - olive_community_id?: { - $in: string[] - } + user_favorites?: number; + olive_community_id?: string; + community_id?: string; } \ No newline at end of file