Skip to content

Commit

Permalink
Merge pull request #28 from mash-up-kr/feature/add-header-update-inte…
Browse files Browse the repository at this point in the history
…raction

API별 �헤더 추가, MemeInteractionService 추가
  • Loading branch information
seohyun0120 committed Jul 14, 2024
2 parents a6cbd81 + 55a097d commit f19c8e7
Show file tree
Hide file tree
Showing 18 changed files with 481 additions and 256 deletions.
1 change: 1 addition & 0 deletions get-s3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const AWS = require('aws-sdk')
5 changes: 3 additions & 2 deletions src/controller/meme.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const getMemeWithKeywords = async (req: CustomRequest, res: Response, next: Next
}

logger.info(`Get meme with keywords - ${meme._id})`);
return res.json(createSuccessResponse(HttpCode.OK, 'Get Meme', meme));
return res.json(createSuccessResponse(HttpCode.OK, 'Get Meme', ret));
} catch (err) {
return next(new CustomError(err.message, err.status));
}
Expand Down Expand Up @@ -167,6 +167,7 @@ const getTodayMemeList = async (req: CustomRequest, res: Response, next: NextFun
};

const searchMemeListByKeyword = async (req: CustomRequest, res: Response, next: NextFunction) => {
const user = req.requestedUser;
const keyword = req.requestedKeyword;

const page = parseInt(req.query.page as string) || 1;
Expand All @@ -180,7 +181,7 @@ const searchMemeListByKeyword = async (req: CustomRequest, res: Response, next:
}

try {
const memeList = await MemeService.searchMemeByKeyword(page, size, keyword);
const memeList = await MemeService.searchMemeByKeyword(page, size, keyword, user);
const data = {
pagination: {
total: memeList.total,
Expand Down
10 changes: 5 additions & 5 deletions src/controller/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ const getUser = async (req: CustomRequest, res: Response, next: NextFunction) =>
}
};

const getLastSeenMemes = async (req: CustomRequest, res: Response, next: NextFunction) => {
const getLastSeenMemeList = async (req: CustomRequest, res: Response, next: NextFunction) => {
const user = req.requestedUser;

try {
const memeList = await UserService.getLastSeenMemes(user);
const memeList = await UserService.getLastSeenMemeList(user);
return res.json(createSuccessResponse(HttpCode.OK, 'Get Last Seen Meme', memeList));
} catch (err) {
return next(new CustomError(err.message, err.status));
}
};

const getSavedMemes = async (req: CustomRequest, res: Response, next: NextFunction) => {
const getSavedMemeList = async (req: CustomRequest, res: Response, next: NextFunction) => {
const user = req.requestedUser;

const page = parseInt(req.query.page as string) || 1;
Expand All @@ -58,7 +58,7 @@ const getSavedMemes = async (req: CustomRequest, res: Response, next: NextFuncti
}

try {
const memeList = await UserService.getSavedMemes(page, size, user);
const memeList = await UserService.getSavedMemeList(page, size, user);

const data = {
pagination: {
Expand All @@ -76,7 +76,7 @@ const getSavedMemes = async (req: CustomRequest, res: Response, next: NextFuncti
}
};

export { getUser, createUser, getLastSeenMemes, getSavedMemes };
export { getUser, createUser, getLastSeenMemeList, getSavedMemeList };

function getLevel(watch: number, reaction: number, share: number): number {
let level = 1;
Expand Down
5 changes: 2 additions & 3 deletions src/middleware/requestedInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ export const getKeywordInfoByName = async (
}

const keyword = await getKeywordByName(keywordName);

if (!keyword) {
if (_.isNull(keyword)) {
return next(
new CustomError(`Keyword with name ${keywordName} does not exist`, HttpCode.NOT_FOUND),
);
Expand Down Expand Up @@ -100,7 +99,7 @@ export const getRequestedUserInfo = async (

const user = await getUser(deviceId);

if (!user) {
if (_.isNull(user)) {
return next(new CustomError(`user(${deviceId}) does not exist`, HttpCode.NOT_FOUND));
}

Expand Down
12 changes: 2 additions & 10 deletions src/model/meme.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import mongoose, { Schema, Document, Types } from 'mongoose';

import { IKeywordGetResponse } from './keyword';

export interface IMemeCreatePayload {
Expand All @@ -24,18 +25,9 @@ export interface IMeme {
isTodayMeme: boolean;
}

export interface IMemeGetResponse {
_id: Types.ObjectId;
title: string;
export interface IMemeGetResponse extends Omit<IMemeDocument, 'keywordIds'> {
keywords: IKeywordGetResponse[];
image: string;
reaction: number;
source: string;
isTodayMeme: boolean;
isSaved: boolean; // 나의 파밈함 저장 여부
createdAt: Date;
updatedAt: Date;
isDeleted: boolean;
}

export interface IMemeDocument extends Document {
Expand Down
8 changes: 4 additions & 4 deletions src/model/memeInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ export enum InteractionType {
}

export interface IMemeInteraction {
deviceId: String;
deviceId: string;
memeId: Types.ObjectId;
interactionType: InteractionType;
}

export interface IMemeInteraction extends Document {
export interface IMemeInteractionDocument extends Document {
_id: Types.ObjectId;
deviceId: String;
deviceId: string;
memeId: Types.ObjectId;
interactionType: InteractionType;
isDeleted: boolean;
Expand All @@ -37,7 +37,7 @@ const MemeInteractionSchema: Schema = new Schema(
},
);

export const MemeInteractionModel = mongoose.model<IMemeInteraction>(
export const MemeInteractionModel = mongoose.model<IMemeInteractionDocument>(
'memeInteraction',
MemeInteractionSchema,
);
74 changes: 47 additions & 27 deletions src/routes/meme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ const router = express.Router();
* summary: 밈 전체 목록 조회 (페이지네이션 적용)
* description: 밈 전체 목록 조회
* parameters:
* - name: x-device-id
* in: header
* description: 유저의 고유한 deviceId
* required: true
* type: string
* - in: query
* name: page
* schema:
Expand Down Expand Up @@ -176,6 +181,11 @@ router.get('/list', getRequestedUserInfo, getAllMemeList); // meme 목록 전체
* summary: 추천 밈 정보 조회
* description: 추천 밈 목록을 조회한다. (현재는 주 단위, 추후 일 단위로 변경될 수 있음)
* parameters:
* - name: x-device-id
* in: header
* description: 유저의 고유한 deviceId
* required: true
* type: string
* - in: query
* name: size
* schema:
Expand Down Expand Up @@ -426,12 +436,17 @@ router.post('/', createMeme); // meme 생성
* summary: 밈 정보 조회(키워드 포함)
* description: 밈 정보를 조회한다. 밈의 키워드 정보도 함께 포함한다. 이때 키워드는 키워드명만 제공된다 (키워드의 개별 정보 X)
* parameters:
* - name: x-device-id
* in: header
* description: 유저의 고유한 deviceId
* required: true
* type: string
* - in: path
* name: memeId
* required: true
* schema:
* type: string
* description: 밈 ID
* description: 밈 ID
* responses:
* 200:
* description: The meme
Expand Down Expand Up @@ -826,7 +841,7 @@ router.delete('/:memeId', getRequestedMemeInfo, deleteMeme); // meme 삭제
* name: memeId
* schema:
* type: string
* description: 저장할 밈 id
* description: 저장할 밈 id
* responses:
* 201:
* description: Meme successfully saved
Expand Down Expand Up @@ -924,7 +939,7 @@ router.post('/:memeId/save', getRequestedUserInfo, getRequestedMemeInfo, createM
* name: memeId
* schema:
* type: string
* description: 저장할 밈 id
* description: 저장할 밈 id
* responses:
* 200:
* description: Meme successfully saved
Expand Down Expand Up @@ -1023,7 +1038,7 @@ router.delete('/:memeId/save', getRequestedUserInfo, getRequestedMemeInfo, delet
* name: memeId
* schema:
* type: string
* description: 공유할 밈 id
* description: 공유할 밈 id
* responses:
* 201:
* description: Meme successfully shared
Expand Down Expand Up @@ -1122,7 +1137,7 @@ router.post('/:memeId/share', getRequestedUserInfo, getRequestedMemeInfo, create
* required: true
* schema:
* type: string
* description: 밈 id
* description: 밈 id
* - in: path
* name: type
* required: true
Expand Down Expand Up @@ -1232,8 +1247,8 @@ router.post('/:memeId/watch/:type', getRequestedUserInfo, getRequestedMemeInfo,
* name: memeId
* schema:
* type: string
* required: true
* description: 리액션할 밈 id
* required: true
* description: 리액션할 밈 id
* responses:
* 201:
* description: Created Meme Reaction
Expand Down Expand Up @@ -1319,25 +1334,30 @@ router.post('/:memeId/reaction', getRequestedUserInfo, getRequestedMemeInfo, cre
* summary: 키워드가 포함된 밈 검색 (페이지네이션 적용)
* description: 키워드 클릭 시 해당 키워드를 포함한 밈을 조회하고 목록을 반환한다.
* parameters:
* - in: query
* name: page
* schema:
* type: number
* example: 1
* description: 현재 페이지 번호 (기본값 1)
* - in: query
* name: size
* schema:
* type: number
* example: 10
* description: 한 번에 조회할 밈 개수 (기본값 10)
* - in: path
* name: name
* schema:
* type: string
* example: "행복"
* required: true
* description: 키워드명
* - name: x-device-id
* in: header
* description: 유저의 고유한 deviceId
* required: true
* type: string
* - in: query
* name: page
* schema:
* type: number
* example: 1
* description: 현재 페이지 번호 (기본값 1)
* - in: query
* name: size
* schema:
* type: number
* example: 10
* description: 한 번에 조회할 밈 개수 (기본값 10)
* - in: path
* name: name
* schema:
* type: string
* example: "행복"
* required: true
* description: 키워드명
* responses:
* 200:
* description: 키워드를 포함한 밈 목록
Expand Down Expand Up @@ -1462,6 +1482,6 @@ router.post('/:memeId/reaction', getRequestedUserInfo, getRequestedMemeInfo, cre
* type: null
* example: null
*/
router.get('/search/:name', getKeywordInfoByName, searchMemeListByKeyword); // 키워드에 해당하는 밈 검색하기 (페이지네이션)
router.get('/search/:name', getRequestedUserInfo, getKeywordInfoByName, searchMemeListByKeyword); // 키워드에 해당하는 밈 검색하기 (페이지네이션)

export default router;
6 changes: 3 additions & 3 deletions src/routes/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ router.get('/', getRequestedUserInfo, UserController.getUser); // user 조회
* example: false
* isSaved:
* type: boolean
* example: false
* example: true
* keywords:
* type: array
* items:
Expand Down Expand Up @@ -362,7 +362,7 @@ router.get('/', getRequestedUserInfo, UserController.getUser); // user 조회
* type: null
* example: null
*/
router.get('/saved-memes', getRequestedUserInfo, UserController.getSavedMemes); // user가 저장한 meme 조회 (페이지네이션 적용)
router.get('/saved-memes', getRequestedUserInfo, UserController.getSavedMemeList); // user가 저장한 meme 조회 (페이지네이션 적용)

/**
* @swagger
Expand Down Expand Up @@ -484,6 +484,6 @@ router.get('/saved-memes', getRequestedUserInfo, UserController.getSavedMemes);
* type: null
* example: null
*/
router.get('/recent-memes', getRequestedUserInfo, UserController.getLastSeenMemes); // user가 최근에 본 밈 정보 조회 (10개 제한)
router.get('/recent-memes', getRequestedUserInfo, UserController.getLastSeenMemeList); // user가 최근에 본 밈 정보 조회 (10개 제한)

export default router;
28 changes: 20 additions & 8 deletions src/service/keyword.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function updateKeyword(
}
async function deleteKeyword(keywordId: Types.ObjectId): Promise<boolean> {
const deletedKeyword = await KeywordModel.findOneAndDelete({ _id: keywordId }).lean();
if (!deletedKeyword) {
if (_.isNull(deletedKeyword)) {
throw new CustomError(`Keyword with ID ${keywordId} not found`, HttpCode.NOT_FOUND);
}
return true;
Expand All @@ -75,7 +75,7 @@ async function increaseSearchCount(keywordId: Types.ObjectId): Promise<IKeywordD
{ $inc: { searchCount: 1 } },
{ new: true, projection: { isDeleted: 0 } },
);
if (!updatedKeyword) {
if (_.isNull(updatedKeyword)) {
throw new CustomError(`KeywordId ${keywordId} not found`, HttpCode.NOT_FOUND);
}
return updatedKeyword;
Expand All @@ -85,21 +85,29 @@ async function increaseSearchCount(keywordId: Types.ObjectId): Promise<IKeywordD
}
}

async function getKeywordByName(keywordName: string): Promise<IKeywordDocument> {
async function getKeywordByName(keywordName: string): Promise<IKeywordDocument | null> {
try {
const keyword = await KeywordModel.findOne({ name: keywordName, isDeleted: false }).lean();
return keyword;
return keyword || null;
} catch (err) {
logger.info(`Failed to get a Keyword Info By Name(${keywordName})`);
logger.error(`Failed to get a Keyword Info By Name(${keywordName})`);
throw new CustomError(
`Failed to get a Keyword Info By Name(${keywordName}) (${err.message})`,
HttpCode.INTERNAL_SERVER_ERROR,
);
}
}

async function getKeywordById(keywordId: Types.ObjectId): Promise<IKeywordDocument> {
async function getKeywordById(keywordId: Types.ObjectId): Promise<IKeywordDocument | null> {
try {
const keyword = await KeywordModel.findOne({ _id: keywordId, isDeleted: false }).lean();
return keyword;
return keyword || null;
} catch (err) {
logger.info(`Failed to get a Keyword Info By id (${keywordId})`);
throw new CustomError(
`Failed to get a Keyword Info By id(${keywordId}) (${err.message})`,
HttpCode.INTERNAL_SERVER_ERROR,
);
}
}

Expand All @@ -116,7 +124,11 @@ async function getKeywordInfoByKeywordIds(
).lean();
return keyword;
} catch (err) {
logger.info(`Failed to get a Keyword Info By id (${keywordIds})`);
logger.error(`Failed to get a Keyword Info By keywordIds(${JSON.stringify(keywordIds)})`);
throw new CustomError(
`Failed to get a Keyword Info By keywordIds(${JSON.stringify(keywordIds)})`,
HttpCode.INTERNAL_SERVER_ERROR,
);
}
}

Expand Down
Loading

0 comments on commit f19c8e7

Please sign in to comment.