앞서 작성했던 알고리즘을 실제 코드로 구현해보았다.
우선 봇은 "마스터" / "관리(매니저)봇" / "커맨드봇" 으로 구분된다.
마스터봇은 내 원래 계정으로 들어오는 알림을 처리한다.
매니저 봇은 내가 내린 명령어를 받아들이고
커맨드봇은 매니저 봇이 받은 명령을 전달받아 나한테 전송하는 봇이다.
그럼 마스터봇이 커맨드봇에게 받은 명령대로 변수를 조작한다.
마스터봇/커맨드봇 이 두개는 듀얼메신저를 통해 하나의 휴대폰에 들어있다.
따라서 이 두 계정으로 들어온 알림은 모두 하나의 스크립트에 의해 처리된다.
const scriptName = "test";
const manager = "관리봇";
const worker1 = "커맨드봇";
const master = "실명";
//var
let date;
let msg_send;
let msg_introduce = "안녕하세요! 저는 실명님의 봇 '버듀(가명)' 입니다." + '\n' + "앞으로 실명님이 답장하실 수 없을 때는 제가 대신 답장을 하니 너무 놀라지 말아주세요 :)";
let msg_sleep = "지금은 실명님이 자고 있습니다. 아침에 다시 연락해주세요.";
let msg_study;
let now_day;
let now_hour;
let now_sec;
let sleep;
let study;
let timer_set = new Object();
let timer_time = 1000*60*30;
let send_delay = 5;
let user_meet = {};
let user_meet_data = DataBase.getDataBase("user_meet").split('\n');
for (var i = 0; i < user_meet_data.length; i++)
{user_meet[user_meet_data[i].trim()] = 1;}
let study_time = {
'0' : {},
'1' : {},
'2' : {},
'3' : {},
'4' : {},
'5' : {},
'6' : {}
};
//일정 세팅
set_study(1, 13, 16);
set_study(2, 9, 11);
set_study(2, 14, 17);
set_study(2, 19, 20);
set_study(3, 11, 18);
set_study(3, 19, 20);
set_study(4, 9, 14);
set_study(5, 11, 12);
set_study(6, 12, 13);
function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) {
//value set
date = new Date();
now_year = date.getFullYear();
now_month = date.getMonth();
now_date = date.getDate();
now_hour = date.getHours();
now_min = date.getMinutes();
now_sec = date.getSeconds();
now_day = date.getDay();
//auto setting
set_sleep(0, 9);
if (now_hour in study_time[now_day])
{
study = true;
msg_study = "실명님은 지금 수업중입니다." + '\n' + study_time[now_day][now_hour] + "시에 수업이 끝나니 그때 연락주세요.";
}
else
{study = false;}
set_reply(msg);
//reply
if (sender == manager) // 커맨드봇이 관리자봇에게 카톡을 받은 경우
{replier.reply(master, msg);}
else if (sender == worker1) //커맨드봇이 톡을 보낸 경우 => 명령어 처리
{
let msg_recv = msg.split(' ');
if (msg_recv.length >= 2 && msg_recv[0].trim() == 'timer_off')
{timer_set[msg_recv[1].trim()] = false;}
}
else if (sender == master) // 내가 커맨드봇에게 메세지 보낸 경우
{
replier.reply("확인하였습니다.");
}
else if (!isGroupChat && (sender != "친구")) //본 계정으로 톡이 온 경우 (단톡방, 친구 제외)
{
{
if (!(room in timer_set))
{ timer_set[room] = false; }
java.lang.Thread.sleep(1500);
//test
//replier.reply(now_day + ' ' + now_hour + ' ' + study );
//test
if (sleep)
{replier.reply(msg_sleep);}
else if (study)
{replier.reply(msg_study);}
else // free now
{
if (!timer_set[room])
{
timer_set[room] = true;
replier.reply(manager,"[notice] " + room + " 에서 " + sender + " 에게 카톡이 왔습니다.");
//test
//timer_time = 1000*10;
java.lang.Thread.sleep(timer_time);
if (timer_set[room])
{
replier.reply(msg_send);
timer_set[room] = false;
}
}
}
}
}
}
//function
function set_study(day, start, end) {
for (var i = start; i < end; i++)
{study_time[day][i] = end;}
}
function set_sleep(start, end) {
if (start <= now_hour && now_hour < end) {
sleep = true;
}
else {
sleep = false;
}
}
function set_reply(recv_msg)
{
if (recv_msg == "뭐해?")
{
msg_send = "저는 지금 인간의 언어를 공부하는 중이에요";
}
else
{
msg_send = "일정시간 경과 후 자동응답 테스트 중입니다. :: 메세지를 수신 후 30분 경과했습니다.";// + '\n' + recv_msg + '\n' + date.getSeconds();
}
}
1. 수업시간 체크 알고리즘 변경
수업시간 체크를 지난 코드처럼 단순히 if문으로 처리했더니 논리적 오류가 발생했다.
가령, 화요일에 14시부터 15시에 수업이 있고, 17시부터 18시에 수업이 있다고 할 때,
현재 시간이 14시 30분이라면
만약 오늘이 화요일이고 14시부터 15시 사이라면 study = true로 한다.
그렇지 않으면 study = false 로 한다.
라는 코드에서 bold 된 부분이 실행되어,
수업중인지 판별하는 변수 study 의 값이 true가 된다.
그러나
만약 오늘이 화요일이고 17시부터 18시 사이라면, 수업중으로 설정한다.
그렇지 않으면 study = false 로 한다.
라는 코드로 넘어가면
볼드체 부분이 실행되며 결과적으로 study값은 false가 된다.
if 문 대신 else if 문으로 처리하면 해결될 일이기는 하지만,
단순 if문 반복은 쓰고싶지 않아 어떻게든 함수로 빼서 처리하고 싶었다.
그렇게 고민끝에 study_time 이라는 객체를 만들었다.
이 객체 안에는 각각의 요일에 대한 7개의 객체를 담았다.
그리고 각각의 요일객체에는 수업시간에 대한 정보가 담긴다.
위의 예시대로라면
study_time 의 화요일 속성에
"14" : 15
"17" : 18
이라는 key : value 쌍이 담긴다.
key는 수업시간, value 는 수업의 종료시간으로
만약 수업이 2시간 이상 길어진다면
"14" : 16
"15" : 16
이런식으로 매 시간마다 끝나는 시간의 정보를 담아서 저장했다.
자바스크립트의 경우 == 연산은 "15" 와 15 를 같다고 판단해서
숫자를 키로 넣어도 문자열처럼 알아서 인식해 담아주고,
키에서 값을 읽어 비교할 때도 문제없이 비교가 되는 것 같다.
2. 명령어로 조작시키기
우선 내가 이번에 넣은 명령어는 "자동응답 타이머 해제" 기능이다.
30분 지나도 답장이 없을 경우 상대방에게 안내메세지(?)를 보내는 기능을 넣었다.
문제는 30분이 되기 전에 메세지를 읽었음에도, 안내메세지를 보낸다는 것.
카카오톡봇은 내가 읽었는지를 알 수 없으니 내가 읽었다면 읽었다고 알려줘야한다.
내가 궁극적으로 원하는 것은 내가 만든 봇과 대화를 하는 것이기 때문에
대화체로 명령을 주고 싶었다.
2-1. 타이머의 설정
코드를 보면 timer_set 객체가 있다.
저번 코드에서 마찬가지로 개선한 부분이다.
timer_set 객체를 통해 자동응답을 언제할 지
"채팅방별로" 관리한다.
기존에는 변수 하나로 컨트롤 하는 방식이었기 때문에,
채팅방 하나에서 자동응답이 진행되면 변수값이 false로 바뀐다.
그래서 다른 방에서 자동응답 해야할 것을 안하게 됐었다.
timer_set 객체에는
[방이름] : 자동응답 여부 true / false
정보를 담게된다.
타이머를 설정할 때는 [방이름] : true 로 설정한다.
그리고 타이머가 흘러 자동응답을 해야하는 시간이 되었을 때
여전히 [방이름] 속성값이 true 라면 자동응답을 하게된다.
2-2 타이머의 해제
타이머의 해제는 간단하다.
내가 봇에게 확인했다고 메세지를 주면
봇이 timer_set 객체의 [방이름] 속성값을 false로 바꾼다.
그러면 자동응답을 해야하는 시간이 됐을 때
[방이름] 의 속성값이 false이므로 자동응답을 하지 않게 된다.
문제는 저 밑줄친 부분을 구체적으로 어떻게 구현할 것인가인데,
그걸 구현하는 알고리즘이 지난 포스팅에 작성한 알고리즘이다.
나는 "(톡을 보낸사람이름) 확인" 형태로 관리자봇에게 메세지를 보내는 걸 기본 명령으로 삼았다.
대화체와 비슷하게 하고 싶었기 때문이다.
만약 내가 타이머 설정 이후 확인해고 답장을 보낸 친구이름이 "김이박" 이라면
"김이박 확인" 이라고 채팅을 보내게된다.
관리자봇은 받은 메세지를 무조건 띄어쓰기를 기준으로 잘라 배열로 만들고
배열의 크기가 2이상이면서 두번째 어절이 "확인" 인 경우
다음과 같은 명령어를 만들어 커맨드봇에게 보낸다.
"timer_off 김이박"
이걸 처리하는 코드는 공기계에 다음과 같이 작성하였다
const scriptName = "manager";
const worker1 = "커맨드봇";
const master = "실명";
let recv_msg;
function response(room, msg, sender, isGroupChat, replier, imageDB, packageName)
{
if (room == master)
{
recv_msg = msg.split(' ');
if (recv_msg.length >= 2 && recv_msg[1].trim() == "확인")
{
replier.reply(worker1, "timer_off " + recv_msg[0].trim());
}
else if (recv_msg[0] == "세션")
{
replier.reply("확인");
}
}
}
커맨드봇은 받은 명령어를 그대로 마스터봇에게 보낸다.
그러면 마스터봇은 관리자봇과 대화중인 상태에도 명령어 알림을 받아 명령어대로 처리하게된다.
복잡하지만
커맨드봇은 사실상 명령어 전달기 역할 밖에 안하게 되긴한다 ㅋㅋ
이렇게 복잡하게 안하고
그냥 "timer_off 김이박" 라는 명령어를 관리자봇에게 보내면
관리자봇이 그 명령어를 커맨드 봇에게 보내고
커맨드봇이 그 명령어를 다시 나(마스터봇) 한테 보내서 명령어대로 변수를 조작시킬 수도 있다.
1대1로는 알림을 읽어오질 못하니 중간에 제3자를 경유시켜서 말을 돌려듣는 과정이라고 보면된다.
'개인 프로젝트 > [2020] 카카오톡 봇' 카테고리의 다른 글
[카카오톡 봇 만들기] 3. 카카오링크 전송하기(1) : 테스트 & 봇 기능 수정 (3) | 2020.10.22 |
---|---|
[카카오톡 봇 만들기] 2. 명령어로 조작하기(3) : 테스트 (0) | 2020.10.18 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(2) : 알고리즘 구현(2) (2) | 2020.10.16 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(1) : 알고리즘 설계 (0) | 2020.10.12 |
[카카오톡 봇 만들기] 1. 수업시간 / 취침시간 자동응답 구현하기 (0) | 2020.10.10 |