Merge branch 'server' into 'master'
BE-API 최종구현 ## BACKEND API 최종구현 - calcDistance 구현 ( 넘어온 word에 대해서 1. 원본/ 2. 특수기호, 영어, 숫자 제거 / 3. 특수기호, 영어, 숫자 표준화 각각의 disassenbled 된 단어들로 db 욕설들과 유사도 검사 => 최소 값 검증) See merge request !2
Showing
7 changed files
with
129 additions
and
40 deletions
server/controller/calcDistance.js
0 → 100644
1 | + | ||
2 | +const e = require('express'); | ||
3 | +const levenshtein = require('js-levenshtein'); | ||
4 | +const db = require('../model/db'); | ||
5 | +const {calcDistance} = require('../service/calcDistance'); | ||
6 | +const {getProfanity} = require('../service/query'); | ||
7 | +const {standardize, removeSpecial} = require('../service/standardization'); | ||
8 | + | ||
9 | + | ||
10 | +exports.calcDistance = async (req, res, next) => { | ||
11 | + const { word } = req.body; | ||
12 | + | ||
13 | + const profanityList = await getProfanity(); | ||
14 | + | ||
15 | + let specialRemoved = removeSpecial(word); | ||
16 | + let specialNotRemoved = word; | ||
17 | + | ||
18 | + specialRemoved = standardize(specialRemoved); | ||
19 | + specialNotRemoved = standardize(specialNotRemoved); | ||
20 | + | ||
21 | + const rareResult = calcDistance(word, profanityList); | ||
22 | + const specialRemovedResult = calcDistance(specialRemoved, profanityList); | ||
23 | + const specialNotRemovedResult = calcDistance(specialNotRemoved, profanityList); | ||
24 | + | ||
25 | + const minResult = Math.min(rareResult, specialRemovedResult, specialNotRemovedResult); | ||
26 | + | ||
27 | + if (minResult <= 1){ | ||
28 | + res.status(200).json({success : true, isProfanity : "YES"}); | ||
29 | + }else{ | ||
30 | + res.status(200).json({success : true, isProfanity : "NO"}); | ||
31 | + } | ||
32 | + }; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -2,16 +2,15 @@ const mysql = require('mysql2/promise'); | ... | @@ -2,16 +2,15 @@ const mysql = require('mysql2/promise'); |
2 | const dotenv = require('dotenv'); | 2 | const dotenv = require('dotenv'); |
3 | const path = require('path'); | 3 | const path = require('path'); |
4 | 4 | ||
5 | -dotenv.config({path:path.join(__dirname, "../.env")}); | 5 | +dotenv.config({ path: path.join(__dirname, '../.env') }); |
6 | 6 | ||
7 | -const db = mysql | 7 | +const db = mysql.createPool({ |
8 | - .createPool({ | 8 | + host: process.env.DB_HOST, |
9 | - host: process.env.DB_HOST, | 9 | + user: process.env.DB_USER, |
10 | - user: process.env.DB_USER, | 10 | + port: process.env.DB_PORT, |
11 | - port: process.env.DB_PORT, | 11 | + password: process.env.DB_PASSWORD, |
12 | - password: process.env.DB_PASSWORD, | 12 | + database: process.env.DB_DATABASE, |
13 | - database: process.env.DB_DATABASE, | 13 | + connectionLimit: 10, |
14 | - connectionLimit: 10, | 14 | +}); |
15 | - }); | ||
16 | 15 | ||
17 | module.exports = db; | 16 | module.exports = db; | ... | ... |
... | @@ -14,6 +14,7 @@ | ... | @@ -14,6 +14,7 @@ |
14 | "hangul-js": "^0.2.6", | 14 | "hangul-js": "^0.2.6", |
15 | "http-errors": "~1.6.3", | 15 | "http-errors": "~1.6.3", |
16 | "jade": "~1.11.0", | 16 | "jade": "~1.11.0", |
17 | + "js-levenshtein": "^1.1.6", | ||
17 | "morgan": "~1.9.1", | 18 | "morgan": "~1.9.1", |
18 | "mysql2": "^2.2.5" | 19 | "mysql2": "^2.2.5" |
19 | }, | 20 | }, | ... | ... |
... | @@ -2,9 +2,9 @@ const express = require('express'); | ... | @@ -2,9 +2,9 @@ const express = require('express'); |
2 | 2 | ||
3 | const router = express.Router(); | 3 | const router = express.Router(); |
4 | 4 | ||
5 | +const { calcDistance } = require('../controller/calcDistance'); | ||
6 | + | ||
5 | /* GET home page. */ | 7 | /* GET home page. */ |
6 | -router.post('/checkProfanity', (req, res) => { | 8 | +router.post('/checkProfanity', calcDistance); |
7 | - res.send('hello'); | ||
8 | -}); | ||
9 | 9 | ||
10 | module.exports = router; | 10 | module.exports = router; | ... | ... |
1 | +/* eslint-disable no-restricted-syntax */ | ||
2 | +const levenshtein = require('js-levenshtein'); | ||
3 | +const Hangul = require('hangul-js'); | ||
4 | + | ||
5 | +exports.calcDistance = (word, profanityList) => { | ||
6 | + let leastLevenshtein = 1000; | ||
7 | + | ||
8 | + for (const profanity of profanityList[0]) { | ||
9 | + let compareWord = Hangul.disassemble(profanity.content); | ||
10 | + compareWord = compareWord.join(''); | ||
11 | + if (leastLevenshtein > levenshtein(word, compareWord)) { | ||
12 | + leastLevenshtein = levenshtein(word, compareWord); | ||
13 | + } | ||
14 | + } | ||
15 | + | ||
16 | + return leastLevenshtein; | ||
17 | +}; | ... | ... |
server/service/query.js
0 → 100644
1 | /* eslint-disable no-use-before-define */ | 1 | /* eslint-disable no-use-before-define */ |
2 | /* eslint-disable no-restricted-syntax */ | 2 | /* eslint-disable no-restricted-syntax */ |
3 | +const { config } = require('dotenv'); | ||
3 | const Hangul = require('hangul-js'); | 4 | const Hangul = require('hangul-js'); |
4 | 5 | ||
5 | const standardize = (word) => { | 6 | const standardize = (word) => { |
... | @@ -12,7 +13,7 @@ const standardize = (word) => { | ... | @@ -12,7 +13,7 @@ const standardize = (word) => { |
12 | ? standardizeConsonent(letter) | 13 | ? standardizeConsonent(letter) |
13 | : standardizeVowel(letter); | 14 | : standardizeVowel(letter); |
14 | } else { | 15 | } else { |
15 | - const preLetter = index === 1 ? '' : disassembledWord[index - 1]; | 16 | + const preLetter = index === 0 ? '' : disassembledWord[index - 1]; |
16 | const nextLetter = index === disassembledWord.length - 1 ? '' : disassembledWord[index + 1]; | 17 | const nextLetter = index === disassembledWord.length - 1 ? '' : disassembledWord[index + 1]; |
17 | newLetter = isVowelSpecial(preLetter, letter, nextLetter) | 18 | newLetter = isVowelSpecial(preLetter, letter, nextLetter) |
18 | ? standardizeSpecialVowel(letter) | 19 | ? standardizeSpecialVowel(letter) |
... | @@ -92,40 +93,72 @@ const isVowelSpecial = (preLetter, letter, nextLetter) => { | ... | @@ -92,40 +93,72 @@ const isVowelSpecial = (preLetter, letter, nextLetter) => { |
92 | 93 | ||
93 | const standardizeSpecialConsonent = (letter) => { | 94 | const standardizeSpecialConsonent = (letter) => { |
94 | switch (letter) { | 95 | switch (letter) { |
95 | - case ('g', 'ㅑ'): | 96 | + case ('g', 'k', 'G', 'K'): |
96 | - return 'ㅏ'; | 97 | + return 'ㄱ'; |
97 | - case ('ㅗ', 'ㅛ'): | 98 | + case ('b', 'v', 'B', 'V'): |
98 | - return 'ㅗ'; | 99 | + return 'ㅂ'; |
99 | - case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'): | 100 | + case ('P', 'p', 'F', 'f'): |
100 | - return 'ㅐ'; | 101 | + return 'ㅍ'; |
101 | - case ('ㅜ', 'ㅠ'): | 102 | + case ('n', 'L', 'N'): |
102 | - return 'ㅜ'; | 103 | + return 'ㄴ'; |
103 | - case ('ㅓ', 'ㅕ'): | 104 | + case ('s', 'A', 'S', 'C', 'c'): |
104 | - return 'ㅓ'; | 105 | + return 'ㅅ'; |
105 | - case ('ㅟ', 'ㅢ', 'ㅣ'): | 106 | + case ('d', 't', 'E'): |
106 | - return 'ㅣ'; | 107 | + return 'ㄷ'; |
108 | + case ('o', 'O'): | ||
109 | + return 'ㅇ'; | ||
110 | + case ('r', 'R'): | ||
111 | + return 'ㄹ'; | ||
112 | + case ('j', 'z', 'J', 'Z'): | ||
113 | + return 'ㅈ'; | ||
114 | + case ('m', '口', 'M'): | ||
115 | + return 'ㅁ'; | ||
116 | + case ('h', 'H'): | ||
117 | + return 'ㅎ'; | ||
107 | default: | 118 | default: |
108 | return letter; | 119 | return letter; |
109 | } | 120 | } |
110 | }; | 121 | }; |
111 | 122 | ||
112 | const standardizeSpecialVowel = (letter) => { | 123 | const standardizeSpecialVowel = (letter) => { |
124 | + let result = ''; | ||
125 | + | ||
113 | switch (letter) { | 126 | switch (letter) { |
114 | - case ('g', 'ㅑ'): | 127 | + case ('a', 'A'): |
115 | - return 'ㅏ'; | 128 | + result = 'ㅏ'; |
116 | - case ('ㅗ', 'ㅛ'): | 129 | + break; |
117 | - return 'ㅗ'; | 130 | + case ('u', 'U'): |
118 | - case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'): | 131 | + result = 'ㅓ'; |
119 | - return 'ㅐ'; | 132 | + break; |
120 | - case ('ㅜ', 'ㅠ'): | 133 | + case ('@', 'H'): |
121 | - return 'ㅜ'; | 134 | + result = 'ㅐ'; |
122 | - case ('ㅓ', 'ㅕ'): | 135 | + break; |
123 | - return 'ㅓ'; | 136 | + case ('l', 'i', 'I', '!', 1): |
124 | - case ('ㅟ', 'ㅢ', 'ㅣ'): | 137 | + result = 'ㅣ'; |
125 | - return 'ㅣ'; | 138 | + break; |
139 | + case '1': | ||
140 | + result = 'ㅣ'; | ||
141 | + break; | ||
126 | default: | 142 | default: |
127 | - return letter; | 143 | + result = letter; |
144 | + break; | ||
128 | } | 145 | } |
146 | + | ||
147 | + return result; | ||
148 | +}; | ||
149 | + | ||
150 | +const removeSpecial = (word) => { | ||
151 | + const numCheck = /[0-9]/g; // 숫자 | ||
152 | + | ||
153 | + const engCheck = /[a-zA-Z]/g; // 문자 | ||
154 | + | ||
155 | + const specialCheck = /[~!@#$%^&*()_+|<>?:{}]/g; // 특수문자 | ||
156 | + | ||
157 | + let result = word.replace(numCheck, ''); | ||
158 | + result = result.replace(engCheck, ''); | ||
159 | + result = result.replace(specialCheck, ''); | ||
160 | + | ||
161 | + return result; | ||
129 | }; | 162 | }; |
130 | 163 | ||
131 | -module.exports = { standardize }; | 164 | +module.exports = { standardize, removeSpecial }; | ... | ... |
-
Please register or login to post a comment