장준영

Merge branch 'server' into 'master'

BE-API 최종구현

## BACKEND API 최종구현

- calcDistance 구현  
 ( 넘어온 word에 대해서 1. 원본/  2. 특수기호, 영어, 숫자 제거 / 3. 특수기호, 영어, 숫자 표준화  
각각의 disassenbled 된 단어들로 db 욕설들과 유사도 검사 => 최소 값 검증)

See merge request !2
const e = require('express');
const levenshtein = require('js-levenshtein');
const db = require('../model/db');
const {calcDistance} = require('../service/calcDistance');
const {getProfanity} = require('../service/query');
const {standardize, removeSpecial} = require('../service/standardization');
exports.calcDistance = async (req, res, next) => {
const { word } = req.body;
const profanityList = await getProfanity();
let specialRemoved = removeSpecial(word);
let specialNotRemoved = word;
specialRemoved = standardize(specialRemoved);
specialNotRemoved = standardize(specialNotRemoved);
const rareResult = calcDistance(word, profanityList);
const specialRemovedResult = calcDistance(specialRemoved, profanityList);
const specialNotRemovedResult = calcDistance(specialNotRemoved, profanityList);
const minResult = Math.min(rareResult, specialRemovedResult, specialNotRemovedResult);
if (minResult <= 1){
res.status(200).json({success : true, isProfanity : "YES"});
}else{
res.status(200).json({success : true, isProfanity : "NO"});
}
};
\ No newline at end of file
......@@ -2,16 +2,15 @@ const mysql = require('mysql2/promise');
const dotenv = require('dotenv');
const path = require('path');
dotenv.config({path:path.join(__dirname, "../.env")});
dotenv.config({ path: path.join(__dirname, '../.env') });
const db = mysql
.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
port: process.env.DB_PORT,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
connectionLimit: 10,
});
const db = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
port: process.env.DB_PORT,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
connectionLimit: 10,
});
module.exports = db;
......
......@@ -14,6 +14,7 @@
"hangul-js": "^0.2.6",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"js-levenshtein": "^1.1.6",
"morgan": "~1.9.1",
"mysql2": "^2.2.5"
},
......
......@@ -2,9 +2,9 @@ const express = require('express');
const router = express.Router();
const { calcDistance } = require('../controller/calcDistance');
/* GET home page. */
router.post('/checkProfanity', (req, res) => {
res.send('hello');
});
router.post('/checkProfanity', calcDistance);
module.exports = router;
......
/* eslint-disable no-restricted-syntax */
const levenshtein = require('js-levenshtein');
const Hangul = require('hangul-js');
exports.calcDistance = (word, profanityList) => {
let leastLevenshtein = 1000;
for (const profanity of profanityList[0]) {
let compareWord = Hangul.disassemble(profanity.content);
compareWord = compareWord.join('');
if (leastLevenshtein > levenshtein(word, compareWord)) {
leastLevenshtein = levenshtein(word, compareWord);
}
}
return leastLevenshtein;
};
......
const db = require('../model/db');
exports.getProfanity = async () => {
const selectResult = await db.query("SELECT DISTINCT content from profanity");
return selectResult;
};
/* eslint-disable no-use-before-define */
/* eslint-disable no-restricted-syntax */
const { config } = require('dotenv');
const Hangul = require('hangul-js');
const standardize = (word) => {
......@@ -12,7 +13,7 @@ const standardize = (word) => {
? standardizeConsonent(letter)
: standardizeVowel(letter);
} else {
const preLetter = index === 1 ? '' : disassembledWord[index - 1];
const preLetter = index === 0 ? '' : disassembledWord[index - 1];
const nextLetter = index === disassembledWord.length - 1 ? '' : disassembledWord[index + 1];
newLetter = isVowelSpecial(preLetter, letter, nextLetter)
? standardizeSpecialVowel(letter)
......@@ -92,40 +93,72 @@ const isVowelSpecial = (preLetter, letter, nextLetter) => {
const standardizeSpecialConsonent = (letter) => {
switch (letter) {
case ('g', 'ㅑ'):
return 'ㅏ';
case ('ㅗ', 'ㅛ'):
return 'ㅗ';
case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'):
return 'ㅐ';
case ('ㅜ', 'ㅠ'):
return 'ㅜ';
case ('ㅓ', 'ㅕ'):
return 'ㅓ';
case ('ㅟ', 'ㅢ', 'ㅣ'):
return 'ㅣ';
case ('g', 'k', 'G', 'K'):
return 'ㄱ';
case ('b', 'v', 'B', 'V'):
return 'ㅂ';
case ('P', 'p', 'F', 'f'):
return 'ㅍ';
case ('n', 'L', 'N'):
return 'ㄴ';
case ('s', 'A', 'S', 'C', 'c'):
return 'ㅅ';
case ('d', 't', 'E'):
return 'ㄷ';
case ('o', 'O'):
return 'ㅇ';
case ('r', 'R'):
return 'ㄹ';
case ('j', 'z', 'J', 'Z'):
return 'ㅈ';
case ('m', '口', 'M'):
return 'ㅁ';
case ('h', 'H'):
return 'ㅎ';
default:
return letter;
}
};
const standardizeSpecialVowel = (letter) => {
let result = '';
switch (letter) {
case ('g', 'ㅑ'):
return 'ㅏ';
case ('ㅗ', 'ㅛ'):
return 'ㅗ';
case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'):
return 'ㅐ';
case ('ㅜ', 'ㅠ'):
return 'ㅜ';
case ('ㅓ', 'ㅕ'):
return 'ㅓ';
case ('ㅟ', 'ㅢ', 'ㅣ'):
return 'ㅣ';
case ('a', 'A'):
result = 'ㅏ';
break;
case ('u', 'U'):
result = 'ㅓ';
break;
case ('@', 'H'):
result = 'ㅐ';
break;
case ('l', 'i', 'I', '!', 1):
result = 'ㅣ';
break;
case '1':
result = 'ㅣ';
break;
default:
return letter;
result = letter;
break;
}
return result;
};
const removeSpecial = (word) => {
const numCheck = /[0-9]/g; // 숫자
const engCheck = /[a-zA-Z]/g; // 문자
const specialCheck = /[~!@#$%^&*()_+|<>?:{}]/g; // 특수문자
let result = word.replace(numCheck, '');
result = result.replace(engCheck, '');
result = result.replace(specialCheck, '');
return result;
};
module.exports = { standardize };
module.exports = { standardize, removeSpecial };
......