Skip to content

Commit

Permalink
Merge pull request #241 from boostcampwm2023/feat/greeneye_api
Browse files Browse the repository at this point in the history
Clova GreenEye API 요청
  • Loading branch information
msjang4 authored Dec 11, 2023
2 parents 458c752 + b59dc19 commit c064244
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 5 deletions.
2 changes: 1 addition & 1 deletion server/src/auth/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class AuthGuard implements CanActivate {
}
try {
const payload = await this.jwtService.verifyAsync(token);
request.user = payload;
request.user = { ...payload };
} catch (e) {
if (e instanceof TokenExpiredError) {
throw new TokenExpiredException();
Expand Down
6 changes: 4 additions & 2 deletions server/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export class AuthService {
}

async create(signupRequestDto: SignupRequestDto): Promise<SignupResponseDto> {
const { uuid, profileImageExtension } = signupRequestDto;
const { uuid, profileImageExtension, accessToken } = signupRequestDto;
console.log(accessToken);
await this.checkUserConflict(uuid);
if (
profileImageExtension &&
Expand Down Expand Up @@ -94,7 +95,8 @@ export class AuthService {
}

async signin(signinRequestDto: SigninRequestDto): Promise<SigninResponseDto> {
const { uuid } = signinRequestDto;
const { uuid, accessToken } = signinRequestDto;
console.log(accessToken);
const user = await this.UserModel.findOne({ uuid });
if (!user) {
throw new LoginFailException();
Expand Down
4 changes: 4 additions & 0 deletions server/src/exceptions/enum/exception.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ enum ErrorCode {
BadThumbnailFormat = 8100,
BadRequestFormat = 8200,
EncodingActionFail = 4280,
GreenEyeApiFail = 4281,
GreenEyeActionFail = 4282,
}

const ErrorMessage = {
Expand All @@ -43,6 +45,8 @@ const ErrorMessage = {
[ErrorCode.VideoUploadRequired]: '비디오를 먼저 업로드 해야합니다.',
[ErrorCode.BadRequestFormat]: '요청 형식이 잘못됨',
[ErrorCode.EncodingActionFail]: '인코딩 액션 실패',
[ErrorCode.GreenEyeApiFail]: 'greeneye api 요청 실패',
[ErrorCode.GreenEyeActionFail]: 'greeneye 액션 실패',
};

export { ErrorCode, ErrorMessage };
9 changes: 9 additions & 0 deletions server/src/exceptions/greeneye-action-fail.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { HttpStatus } from '@nestjs/common';
import { ErrorCode } from 'src/exceptions/enum/exception.enum';
import { BaseException } from './base.exception';

export class GreenEyeActionFailException extends BaseException {
constructor() {
super(ErrorCode.GreenEyeActionFail, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
9 changes: 9 additions & 0 deletions server/src/exceptions/greeneye-api-fail.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { HttpStatus } from '@nestjs/common';
import { ErrorCode } from 'src/exceptions/enum/exception.enum';
import { BaseException } from './base.exception';

export class GreenEyeApiFailException extends BaseException {
constructor() {
super(ErrorCode.GreenEyeApiFail, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
85 changes: 85 additions & 0 deletions server/src/ncpAPI/cloud-function/greeneye-action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/no-var-requires */
const ffmpeg = require('fluent-ffmpeg');
const fs = require('fs');
const axios = require('axios');

const apiUrl = '비밀';

async function main(params) {
const results = [];
const { videoUrl, object_name, greenEyeSecret, accessToken } = params;
await createScreanshots(videoUrl);
const files = Array.from(
{ length: 4 },
(_, k) => `${object_name}_${k + 1}.png`,
);
// eslint-disable-next-line no-restricted-syntax
for (const file of files) {
const data = fs.readFileSync(file);
const imageData = data.toString('base64');
// eslint-disable-next-line no-await-in-loop
const result = await greenEye(file, file, imageData, greenEyeSecret);
results.push(result);
fs.unlinkSync(file);
// eslint-disable-next-line no-await-in-loop
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});
}
console.log(results);
if (checkHarmful(results)) {
axios.delete(`http://223.130.136.106/videos/${object_name}`, {
headers: { Authorization: `Bearer ${accessToken}` },
});
}
}

const createScreanshots = async (videoUrl) => {
const timestamps = Array.from(
{ length: 4 },
() => `${Math.floor(Math.random() * 101)}%`,
);
console.log(timestamps);
return new Promise((resolve) => {
ffmpeg(videoUrl)
.screenshots({
timestamps,
filename: `%b.png`,
folder: './',
})
.on('end', () => {
resolve();
});
});
};

const greenEye = (requestId, imageName, imageData, greenEyeSecret) => {
const headers = {
'X-GREEN-EYE-SECRET': greenEyeSecret,
'Content-Type': 'application/json',
};

const data = {
version: 'V1',
requestId,
timestamp: Number(new Date()),
images: [
{
name: imageName,
data: imageData,
},
],
};

return axios
.post(apiUrl, data, {
headers,
})
.then((response) => response.data.images.pop().result);
};

const checkHarmful = (results) => {
return results.some((result) => result.normal.confidence < 0.5);
};
36 changes: 36 additions & 0 deletions server/src/ncpAPI/greenEye.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import axios from 'axios';
import { GreenEyeApiFailException } from 'src/exceptions/greeneye-api-fail.exception';

export const greenEye = (
requestId: string,
imageName: string,
imageUrl: string,
) => {
const apiUrl = process.env.GREENEYE_API_URL;

const headers = {
'X-GREEN-EYE-SECRET': process.env.GREENEYE_SECRET,
'Content-Type': 'application/json',
};

const data = {
version: 'V1',
requestId,
timestamp: Number(new Date()),
images: [
{
name: imageName,
url: imageUrl,
},
],
};

return axios
.post(apiUrl, data, {
headers,
})
.then((response) => response.data.images.pop().result)
.catch(() => {
throw new GreenEyeApiFailException();
});
};
31 changes: 29 additions & 2 deletions server/src/video/video.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { VideoUploadRequiredException } from 'src/exceptions/video-upload-requir
import { ThumbnailUploadRequiredException } from 'src/exceptions/thumbnail-upload-required-exception copy 2';
import { BadRequestFormatException } from 'src/exceptions/bad-request-format.exception';
import { EncodingActionFailException } from 'src/exceptions/encoding-action-fail.exception';
import { GreenEyeActionFailException } from 'src/exceptions/greeneye-action-fail.exception';
import { VideoDto } from './dto/video.dto';
import { Video } from './schemas/video.schema';
import { CategoryEnum } from './enum/category.enum';
Expand Down Expand Up @@ -188,7 +189,10 @@ export class VideoService {
thumbnailExtension,
videoExtension,
});
await newVideo.save();
await Promise.all([
newVideo.save(),
this.requestGreenEyeAPI(process.env.INPUT_BUCKET, videoName, videoId),
]);
return { videoId, ...videoDto };
}

Expand All @@ -215,6 +219,26 @@ export class VideoService {
}
}

async requestGreenEyeAPI(
inputBucket: string,
videoName: string,
videoId: string,
) {
const videoUrl = await createPresignedUrl(inputBucket, videoName, 'GET');
const data = {
videoUrl,
object_name: videoId,
greenEyeSecret: process.env.GREENEYE_SECRET,
accessToken: process.env.ADMIN_ACCESS_TOKEN,
};

try {
await axios.post(process.env.GREENEYE_API_URL, data);
} catch (error) {
throw new GreenEyeActionFailException();
}
}

async deleteEncodedVideo(videoId: string) {
const deleteList = await listObjects(process.env.OUTPUT_BUCKET, {
prefix: videoId,
Expand All @@ -234,7 +258,10 @@ export class VideoService {
if (!video) {
throw new VideoNotFoundException();
}
if (video.uploaderId.uuid !== uuid) {
if (
uuid !== process.env.ADMIN_UUID &&
video.uploaderId.uuid !== uuid
) {
throw new NotYourVideoException();
}
await Promise.all([
Expand Down

0 comments on commit c064244

Please sign in to comment.