Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

registered meme #52

Merged
merged 15 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,945 changes: 3,053 additions & 892 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,28 @@
},
"license": "MIT",
"dependencies": {
"@aws-sdk/client-s3": "^3.592.0",
"date-fns": "^3.6.0",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1",
"pino": "^9.1.0",
"pino-pretty": "^11.0.0",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1",
"ts-node": "^10.9.2",
"yamljs": "^0.3.0"
"yamljs": "^0.3.0",
"heic-convert": "^2.1.0",
"sharp": "^0.33.4"
},
"devDependencies": {
"@types/dotenv": "^8.2.0",
"@types/heic-convert": "^1.2.3",
"@types/express": "^4.17.21",
"@types/jest": "^29.5.11",
"@types/lodash": "^4.14.202",
"@types/multer": "^1.4.12",
"@types/node": "^20.12.2",
"@types/pino": "^7.0.5",
"@types/pino-pretty": "^5.0.0",
Expand Down
17 changes: 14 additions & 3 deletions src/controller/meme.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,20 @@ const getMemeWithKeywords = async (req: CustomRequest, res: Response, next: Next
}
};

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

const image = req.file;

if (_.isUndefined(image)) {
return next(new CustomError(`'file' should be provided.`, HttpCode.BAD_REQUEST));
}

if (!_.has(req.body, 'title')) {
return next(new CustomError(`'title' field should be provided`, HttpCode.BAD_REQUEST));
}

if (!_.has(req.body, 'image')) {
if (!req.file) {
Hyun-git marked this conversation as resolved.
Show resolved Hide resolved
return next(new CustomError(`'image' field should be provided`, HttpCode.BAD_REQUEST));
}

Expand All @@ -78,7 +86,10 @@ const createMeme = async (req: Request, res: Response, next: NextFunction) => {
}

const createPayload: IMemeCreatePayload = {
...req.body,
deviceId: user.deviceId,
title: req.body.title,
image: image.location,
source: req.body.source,
keywordIds: req.body.keywordIds.map((id: string) => new Types.ObjectId(id)),
};

Expand Down
13 changes: 12 additions & 1 deletion src/controller/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,18 @@ const getSavedMemeList = async (req: CustomRequest, res: Response, next: NextFun
}
};

export { getUser, createUser, getLastSeenMemeList, getSavedMemeList };
const getRegisteredMemeList = async (req: CustomRequest, res: Response, next: NextFunction) => {
const user = req.requestedUser;

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

export { getUser, createUser, getLastSeenMemeList, getSavedMemeList, getRegisteredMemeList };

function getLevel(watch: number, reaction: number, share: number): number {
let level = 1;
Expand Down
1 change: 1 addition & 0 deletions src/middleware/requestedInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface CustomRequest extends Request {
requestedKeyword?: IKeywordDocument;
requestedKeywordCategory?: IKeywordCategoryDocument;
requestedMemeInteraction?: IMemeInteraction;
file?: any;
}

export const getRequestedMemeInfo = async (
Expand Down
5 changes: 5 additions & 0 deletions src/model/meme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import mongoose, { Schema, Document, Types } from 'mongoose';
import { IKeywordGetResponse } from './keyword';

export interface IMemeCreatePayload {
deviceId: string;
title: string;
keywordIds: Types.ObjectId[];
image: string;
Expand All @@ -17,6 +18,7 @@ export interface IMemeUpdatePayload {
}

export interface IMeme {
deviceId: string;
title: string;
keywordIds: Types.ObjectId[];
image: string;
Expand All @@ -27,6 +29,7 @@ export interface IMeme {

export interface IMemeGetResponse {
_id: Types.ObjectId;
deviceId: string;
title: string;
image: string;
reaction: number;
Expand All @@ -42,6 +45,7 @@ export interface IMemeGetResponse {

export interface IMemeDocument extends Document {
_id: Types.ObjectId;
deviceId: string;
title: string;
keywordIds: Types.ObjectId[];
image: string;
Expand All @@ -55,6 +59,7 @@ export interface IMemeDocument extends Document {

const MemeSchema: Schema = new Schema(
{
deviceId: { type: String, required: true },
title: { type: String, required: true },
keywordIds: { type: [Types.ObjectId], ref: 'Keyword', required: true, default: [] },
image: { type: String, required: true },
Expand Down
121 changes: 47 additions & 74 deletions src/routes/meme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import {
getRequestedUserInfo,
getRequestedMemeSaveInfo,
} from '../middleware/requestedInfo';
import { compressAndUploadImageToS3, upload } from '../util/image';

const router = express.Router();

/**
* @swagger
* /api/meme/list:
Expand Down Expand Up @@ -611,134 +611,107 @@ router.get('/search/:name', getRequestedUserInfo, searchMemeList); // 밈 검색
* @swagger
* /api/meme:
* post:
* summary: "밈 등록"
* tags: [Meme]
* summary: 밈 생성 (백오피스)
* description: 밈을 생성한다. (백오피스)
* parameters:
* - in: header
* name: x-device-id
* required: true
* schema:
* type: string
* description: "유저의 고유한 deviceId"
* requestBody:
* required: true
* content:
* application/json:
* multipart/form-data:
* schema:
* type: object
* properties:
* title:
* type: string
* example: "무한도전 정총무"
* description: 밈 제목
* description: "밈 제목"
* image:
* type: string
* example: "https://ppac-meme.s3.ap-northeast-2.amazonaws.com/17207029441190.png"
* description: 밈 이미지 주소
* type: file
* description: "밈 이미지 파일"
* source:
* type: string
* example: "무한도전 102화"
* description: 밈 출처
* description: "밈 출처"
* keywordIds:
* type: array
* items:
* type: string
* example: "667fee6dc58681a42d57dc37"
* description: 밈의 키워드 id 목록
* description: "키워드의 ObjectId"
* example: ["667fa549239eeaf786f9aa75", "667fa3c824fc9c25eaf3b911"]
* description: "등록할 키워드의 ObjectId 배열"
* responses:
* 201:
* description: 생성된 밈 정보
* description: "Meme uploaded successfully"
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: success
* example: "success"
* code:
* type: integer
* example: 201
* message:
* type: string
* example: Create Meme
* example: "Create Meme"
* data:
* type: object
* properties:
* _id:
* deviceId:
* type: string
* example: "6686af56f7c49ec21e3ef1c1"
* description: 밈 id
* example: "deviceId"
* title:
* type: string
* example: "무한도전 정총무"
* description: 밈 제목
* image:
* type: string
* example: "https://ppac-meme.s3.ap-northeast-2.amazonaws.com/17207029441190.png"
* description: 밈 이미지 주소
* source:
* type: string
* example: "무한도전 102화"
* description: 밈 출처
* example: "폰보는 루피"
* keywordIds:
* type: array
* items:
* type: string
* example: "667fee6dc58681a42d57dc37"
* description: 밈의 키워드 id 목록
* example: "667ff3d1239eeaf78630a283"
* image:
* type: string
* example: "https://ppac-meme.s3.ap-northeast-2.amazonaws.com/1727269791268"
* reaction:
* type: integer
* example: 0
* description: ㅋㅋㅋ 리액션 수 (생성 시 기본값 0)
* source:
* type: string
* example: "google"
* isTodayMeme:
* type: boolean
* example: false
* description: 추천 밈 여부
* isDeleted:
* type: boolean
* example: false
* _id:
* type: string
* example: "66f40b9f775ec854840d0519"
* createdAt:
* type: string
* format: date-time
* example: "2024-07-04T14:19:02.918Z"
* description: 생성 시각
* example: "2024-09-25T13:09:51.472Z"
* updatedAt:
* type: string
* format: date-time
* example: "2024-07-04T14:19:02.918Z"
* description: 업데이트 시각
* example: "2024-09-25T13:09:51.472Z"
* 400:
* description: 잘못된 요청 - requestBody 형식 확인 필요
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: error
* code:
* type: integer
* example: 400
* message:
* type: string
* example: title field should be provided
* data:
* type: null
* example: null
* description: "Bad request (missing fields)"
* 500:
* description: Internal server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: error
* code:
* type: integer
* example: 500
* message:
* type: string
* example: Internal server error
* data:
* type: null
* example: null
* description: "Internal server error"
*/
router.post('/', createMeme); // meme 생성
router.post(
'/',
getRequestedUserInfo,
upload.single('image'),
compressAndUploadImageToS3,
createMeme,
);

/**
* @swagger
Expand Down
Loading