장준영

Merge branch 'server' into 'master'

Server - 표준화 로직 구현

## server 단어 입력에 따른 표준화 로직 구현

1) 단어 입력
2) 한글인지 아닌지 검사
   - 한글 : 자,모음 표준화 시행
   - 영어,숫자,특수문자 포함 : 해당 문자가 있는 곳이 어디인지에 따라 모음위치인지 자음위치인지 판별한뒤, 표준화 시행

See merge request !1
10새,10새기,10새리,10세리,10쉐이,10쉑,10스,10쌔, 10쌔기,10쎄,10알,10창,10탱,18것,18넘,18년,18노,18놈,18뇬,18럼,18롬,18새,18새끼,18색,18세끼,18세리,18섹,18쉑,18스,18아,ㄱㅐ,ㄲㅏ,ㄲㅑ,ㄲㅣ,ㅅㅂㄹㅁ,ㅅㅐ,ㅆㅂㄹㅁ,ㅆㅍ,ㅆㅣ,ㅆ앙,ㅍㅏ,凸, 갈보,갈보년,강아지,같은년,같은뇬,개같은,개구라,개년,개놈,개뇬,개대중,개독,개돼중,개랄,개보지,개뻥,개뿔,개새,개새기,개새끼,개새키,개색기,개색끼,개색키,개색히,개섀끼,개세,개세끼,개세이,개소리,개쑈, 개쇳기,개수작,개쉐,개쉐리,개쉐이,개쉑,개쉽,개스끼,개시키,개십새기, 개십새끼,개쐑,개씹,개아들,개자슥,개자지,개접,개좆,개좌식,개허접,걔새,걔수작,걔시끼,걔시키,걔썌,걸레,게색기,게색끼,광뇬,구녕,구라,구멍,그년,그새끼,냄비,놈현,뇬,눈깔,뉘미럴,니귀미,니기미,니미,니미랄,니미럴,니미씹,니아배,니아베,니아비,니어매,니어메,니어미,닝기리,닝기미,대가리,뎡신,도라이,돈놈,돌아이,돌은놈,되질래,뒈져,뒈져라,뒈진,뒈진다,뒈질, 뒤질래,등신,디져라,디진다,디질래,딩시,따식,때놈,또라이,똘아이,똘아이,뙈놈,뙤놈,뙨넘,뙨놈,뚜쟁,띠바,띠발,띠불,띠팔,메친넘,메친놈,미췬, 미췬,미친,미친넘,미친년,미친놈,미친새끼,미친스까이,미틴,미틴넘,미틴년, 미틴놈,바랄년,병자,뱅마,뱅신,벼엉신,병쉰,병신,부랄,부럴,불알,불할,붕가,붙어먹,뷰웅,븅,븅신,빌어먹,빙시,빙신,빠가,빠구리,빠굴,빠큐,뻐큐,뻑큐,뽁큐,상넘이,상놈을,상놈의,상놈이,새갸,새꺄,새끼,새새끼,새키,색끼,생쑈,세갸,세꺄,세끼,섹스,쇼하네,쉐,쉐기,쉐끼,쉐리,쉐에기,쉐키,쉑,쉣,쉨,쉬발,쉬밸,쉬벌,쉬뻘,쉬펄,쉽알,스패킹,스팽,시궁창,시끼,시댕,시뎅,시랄,시발,시벌,시부랄,시부럴,시부리,시불,시브랄,시팍,시팔,시펄,신발끈,심발끈,심탱,십8,십라,십새,십새끼,십세,십쉐,십쉐이,십스키,십쌔,십창,십탱,싶알,싸가지,싹아지,쌉년,쌍넘,쌍년,쌍놈,쌍뇬,쌔끼, 쌕,쌩쑈,쌴년,썅,썅년,썅놈,썡쇼,써벌,썩을년,썩을놈,쎄꺄,쎄엑, 쒸벌,쒸뻘,쒸팔,쒸펄,쓰바,쓰박,쓰발,쓰벌,쓰팔,씁새,씁얼,씌파,씨8, 씨끼,씨댕,씨뎅,씨바,씨바랄,씨박,씨발,씨방,씨방새,씨방세,씨밸,씨뱅,씨벌,씨벨,씨봉,씨봉알,씨부랄,씨부럴,씨부렁,씨부리,씨불,씨붕,씨브랄, 씨빠,씨빨,씨뽀랄,씨앙,씨파,씨팍,씨팔,씨펄,씸년,씸뇬,씸새끼,씹같,씹년,씹뇬,씹보지,씹새,씹새기,씹새끼,씹새리,씹세,씹쉐,씹스키,씹쌔,씹이,씹자지,씹질,씹창,씹탱,씹퇭,씹팔,씹할,씹헐,아가리,아갈,아갈이,아갈통,아구창,아구통,아굴,얌마,양넘,양년,양놈,엄창,엠병,여물통,염병,엿같,옘병,옘빙,오입,왜년,왜놈,욤병,육갑,은년,을년,이년,이새끼,이새키,이스끼,이스키,임마,자슥,잡것,잡넘,잡년,잡놈,저년,저새끼,접년,젖밥,조까,조까치,조낸,조또,조랭,조빠,조쟁이,조지냐,조진다,조찐, 조질래,존나,존나게,존니,존만, 존만한,좀물,좁년,좆,좁밥,좃까,좃또,좃만,좃밥,좃이,좃찐,좆같,좆까,좆나,좆또,좆만,좆밥,좆이,좆찐,좇같,좇이,좌식,주글,주글래,주데이,주뎅,주뎅이,주둥아리,주둥이,주접,주접떨,죽고잡,죽을래,죽통,쥐랄,쥐롤,쥬디,지랄,지럴,지롤,지미랄,짜식,짜아식,쪼다,쫍빱,찌랄,창녀,캐년,캐놈,캐스끼,캐스키,캐시키,탱구,팔럼,퍽큐,호로,호로놈,호로새끼,호로색,호로쉑,호로스까이,호로스키,후라들,후래자식,후레,후뢰,씨ㅋ발,ㅆ1발,씌발,띠발,띄발,뛰발,띠ㅋ발,뉘뮈
\ No newline at end of file
README.md
package.json
package-lock.json
{
"env": {
"browser": true,
"es6": true
},
"extends": ["airbnb-base", "plugin:prettier/recommended"],
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"plugins": ["prettier"],
"rules": {
"semi": "error",
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
}
#
node_modules
package-lock.json
.DS_Store
.env
\ No newline at end of file
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"endOfLine": "lf"
}
\ No newline at end of file
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
module.exports = app;
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('server:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
const db = require('../model/db');
const profanity1 = require('./profanity1.json');
const profanity2 = require('./profanity2.json');
const insertDB = async () => {
let sumOfProfanity = [...new Set([...profanity1.profanity,...profanity2.profanity])];
sumOfProfanity = sumOfProfanity.map((element) => [element]);
try {
const insertQuery = "insert into profanity (content) values ?;";
const result = await db.query(insertQuery, [sumOfProfanity]);
console.log('yes');
} catch (err) {
console.log(err);
}
}
module.exports = insertDB;
\ No newline at end of file
{
"badwords": [
"profanity": [
"10새",
"10새기",
"10새리",
......
{
"profanity": [
"10새","10새기","10새리","10세리","10쉐이","10쉑","10스","10쌔", "10쌔기","10쎄","10알",
"10창","10탱","18것","18넘","18년","18노","18놈","18뇬","18럼","18롬","18새","18새끼","18색","18세끼","18세리","18섹","18쉑","18스",
"18아","ㄱㅐ","ㄲㅏ","ㄲㅑ","ㄲㅣ","ㅅㅂㄹㅁ","ㅅㅐ","ㅆㅂㄹㅁ","ㅆㅍ","ㅆㅣ","ㅆ앙","ㅍㅏ","凸", "갈보","갈보년","강아지","같은년","같은뇬",
"개같은","개구라","개년","개놈","개뇬","개대중","개독","개돼중","개랄","개보지","개뻥","개뿔","개새","개새기","개새끼","개새키","개색기","개색끼",
"개색키","개색히","개섀끼","개세","개세끼","개세이","개소리","개쑈", "개쇳기","개수작","개쉐","개쉐리","개쉐이","개쉑","개쉽","개스끼","개시키",
"개십새기", "개십새끼","개쐑","개씹","개아들","개자슥","개자지","개접","개좆","개좌식","개허접","걔새","걔수작","걔시끼","걔시키","걔썌","걸레","게색기",
"게색끼","광뇬","구녕","구라","구멍","그년","그새끼","냄비","놈현","뇬","눈깔","뉘미럴","니귀미","니기미","니미","니미랄","니미럴","니미씹","니아배","니아베",
"니아비","니어매","니어메","니어미","닝기리","닝기미","대가리","뎡신","도라이","돈놈","돌아이","돌은놈","되질래","뒈져","뒈져라","뒈진","뒈진다","뒈질",
"뒤질래","등신","디져라","디진다","디질래","딩시","따식","때놈","또라이","똘아이","똘아이","뙈놈","뙤놈","뙨넘","뙨놈","뚜쟁","띠바","띠발","띠불","띠팔","메친넘",
"메친놈","미췬", "미췬","미친","미친넘","미친년","미친놈","미친새끼","미친스까이","미틴","미틴넘","미틴년", "미틴놈","바랄년","병자","뱅마","뱅신","벼엉신",
"병쉰","병신","부랄","부럴","불알","불할","붕가","붙어먹","뷰웅","븅","븅신","빌어먹","빙시","빙신","빠가","빠구리","빠굴","빠큐","뻐큐","뻑큐","뽁큐","상넘이",
"상놈을","상놈의","상놈이","새갸","새꺄","새끼","새새끼","새키","색끼","생쑈","세갸","세꺄","세끼","섹스","쇼하네","쉐","쉐기","쉐끼","쉐리","쉐에기","쉐키","쉑","쉣",
"쉨","쉬발","쉬밸","쉬벌","쉬뻘","쉬펄","쉽알","스패킹","스팽","시궁창","시끼","시댕","시뎅","시랄","시발","시벌","시부랄","시부럴","시부리","시불","시브랄","시팍","시팔",
"시펄","신발끈","심발끈","심탱","십8","십라","십새","십새끼","십세","십쉐","십쉐이","십스키","십쌔","십창","십탱","싶알","싸가지","싹아지","쌉년","쌍넘","쌍년","쌍놈","쌍뇬",
"쌔끼", "쌕","쌩쑈","쌴년","썅","썅년","썅놈","썡쇼","써벌","썩을년","썩을놈","쎄꺄","쎄엑", "쒸벌","쒸뻘","쒸팔","쒸펄","쓰바","쓰박","쓰발","쓰벌","쓰팔","씁새","씁얼",
"씌파","씨8", "씨끼","씨댕","씨뎅","씨바","씨바랄","씨박","씨발","씨방","씨방새","씨방세","씨밸","씨뱅","씨벌","씨벨","씨봉","씨봉알","씨부랄","씨부럴","씨부렁","씨부리",
"씨불","씨붕","씨브랄", "씨빠","씨빨","씨뽀랄","씨앙","씨파","씨팍","씨팔","씨펄","씸년","씸뇬","씸새끼","씹같","씹년","씹뇬","씹보지","씹새","씹새기","씹새끼","씹새리",
"씹세","씹쉐","씹스키","씹쌔","씹이","씹자지","씹질","씹창","씹탱","씹퇭","씹팔","씹할","씹헐","아가리","아갈","아갈이","아갈통","아구창","아구통","아굴","얌마","양넘",
"양년","양놈","엄창","엠병","여물통","염병","엿같","옘병","옘빙","오입","왜년","왜놈","욤병","육갑","은년","을년","이년","이새끼","이새키","이스끼","이스키","임마","자슥",
"잡것","잡넘","잡년","잡놈","저년","저새끼","접년","젖밥","조까","조까치","조낸","조또","조랭","조빠","조쟁이","조지냐","조진다","조찐","조질래","존나","존나게","존니",
"존만", "존만한","좀물","좁년","좆","좁밥","좃까","좃또","좃만","좃밥","좃이","좃찐","좆같","좆까","좆나","좆또","좆만","좆밥","좆이","좆찐","좇같","좇이","좌식","주글",
"주글래","주데이","주뎅","주뎅이","주둥아리","주둥이","주접","주접떨","죽고잡","죽을래","죽통","쥐랄","쥐롤","쥬디","지랄","지럴","지롤","지미랄","짜식","짜아식","쪼다",
"쫍빱","찌랄","창녀","캐년","캐놈","캐스끼","캐스키","캐시키","탱구","팔럼","퍽큐","호로","호로놈","호로새끼","호로색","호로쉑","호로스까이","호로스키","후라들","후래자식",
"후레","후뢰","씨ㅋ발","ㅆ1발","씌발","띠발","띄발","뛰발","띠ㅋ발","뉘뮈"
]
}
\ No newline at end of file
const mysql = require('mysql2/promise');
const dotenv = require('dotenv');
const path = require('path');
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,
});
module.exports = db;
{
"name": "server",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"dotenv": "^8.2.0",
"express": "~4.16.1",
"hangul-js": "^0.2.6",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"morgan": "~1.9.1",
"mysql2": "^2.2.5"
},
"devDependencies": {
"eslint": "^7.15.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^7.0.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-prettier": "^3.2.0",
"prettier": "^2.2.1"
}
}
const express = require('express');
const router = express.Router();
/* GET home page. */
router.post('/checkProfanity', (req, res) => {
res.send('hello');
});
module.exports = router;
/* eslint-disable no-use-before-define */
/* eslint-disable no-restricted-syntax */
const Hangul = require('hangul-js');
const standardize = (word) => {
let result = '';
let newLetter = '';
const disassembledWord = Hangul.disassemble(word);
for (const [index, letter] of disassembledWord.entries()) {
if (isKorean(letter)) {
newLetter = Hangul.isConsonant(letter)
? standardizeConsonent(letter)
: standardizeVowel(letter);
} else {
const preLetter = index === 1 ? '' : disassembledWord[index - 1];
const nextLetter = index === disassembledWord.length - 1 ? '' : disassembledWord[index + 1];
newLetter = isVowelSpecial(preLetter, letter, nextLetter)
? standardizeSpecialVowel(letter)
: standardizeSpecialConsonent(letter);
}
result += newLetter;
}
return result;
};
const isKorean = (word) => {
const numCheck = /[0-9]/; // 숫자
const engCheck = /[a-zA-Z]/; // 문자
const specialCheck = /[~!@#$%^&*()_+|<>?:{}]/; // 특수문자
if (!numCheck.test(word) && !engCheck.test(word) && !specialCheck.test(word)) {
return true;
}
return false;
};
const standardizeConsonent = (letter) => {
switch (letter) {
case ('ㄱ', 'ㄲ', 'ㅋ'):
return 'ㄱ';
case ('ㄷ', 'ㄸ', 'ㅌ'):
return 'ㄷ';
case ('ㅂ', 'ㅃ', 'ㅍ'):
return 'ㅂ';
case ('ㅅ', 'ㅆ'):
return 'ㅅ';
case ('ㅈ', 'ㅉ', 'ㅊ'):
return 'ㅈ';
default:
return letter;
}
};
const standardizeVowel = (letter) => {
switch (letter) {
case ('ㅏ', 'ㅑ'):
return 'ㅏ';
case ('ㅗ', 'ㅛ'):
return 'ㅗ';
case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'):
return 'ㅐ';
case ('ㅜ', 'ㅠ'):
return 'ㅜ';
case ('ㅓ', 'ㅕ'):
return 'ㅓ';
case ('ㅟ', 'ㅢ', 'ㅣ'):
return 'ㅣ';
default:
return letter;
}
};
const isVowelSpecial = (preLetter, letter, nextLetter) => {
if (preLetter !== '') {
if (nextLetter === '') {
if (isKorean(preLetter)) {
if (Hangul.isConsonant(preLetter)) {
return true;
}
}
} else if (isKorean(preLetter) && isKorean(nextLetter)) {
if (Hangul.isConsonant(preLetter) && Hangul.isConsonant(nextLetter)) {
return true;
}
}
}
return false;
};
const standardizeSpecialConsonent = (letter) => {
switch (letter) {
case ('g', 'ㅑ'):
return 'ㅏ';
case ('ㅗ', 'ㅛ'):
return 'ㅗ';
case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'):
return 'ㅐ';
case ('ㅜ', 'ㅠ'):
return 'ㅜ';
case ('ㅓ', 'ㅕ'):
return 'ㅓ';
case ('ㅟ', 'ㅢ', 'ㅣ'):
return 'ㅣ';
default:
return letter;
}
};
const standardizeSpecialVowel = (letter) => {
switch (letter) {
case ('g', 'ㅑ'):
return 'ㅏ';
case ('ㅗ', 'ㅛ'):
return 'ㅗ';
case ('ㅐ', 'ㅒ', 'ㅔ', 'ㅖ', 'ㅙ', 'ㅚ', 'ㅝ', 'ㅞ'):
return 'ㅐ';
case ('ㅜ', 'ㅠ'):
return 'ㅜ';
case ('ㅓ', 'ㅕ'):
return 'ㅓ';
case ('ㅟ', 'ㅢ', 'ㅣ'):
return 'ㅣ';
default:
return letter;
}
};
module.exports = { standardize };