옛날에 읽었던 소설책이 떠올라 최근에 다시 읽기 시작했다.
그 책 속에 천재 프로그래머가 자신에게 온 문자를 상황에 맞게 봇에게 대신 답장하도록 하는 장면이 나왔다.
그 내용을 보고나서 카카오톡 자동응답 봇을 만들어 보고 싶다고 생각했다.
이 책을 처음 읽었을 때도 같은 생각을 했었는데,
이번에는 컴공과에 재학하면서 배운 내용도 있으니 뭔가 할 수 있을 것 같다는 생각이 들었다.
또 최근 피곤해서 평소보다 일찍 잤던 적이 있었다.
그 때 내가 안잘거라고 생각한 친구가 카톡을 보냈었고, 나는 답장하지 못했었다.
만약 그럴 때 내가 자고 있다는 자동응답을 보냈다면, 그 친구는 하염없이 기다리지 않아도 되지 않았을까?
이런 계기로 나는 관련 정보를 찾기 시작했다.
구글을 통해 알아보니 능력있으신 분들이 이미 자동응답 앱을 개발한 것이 보였다.
단순히 버튼을 조작해서 자동응답을 시키는 단순한 앱도 있었던 것 같다.
그러나 내가 구현하고 싶은 기능들을 모두 구현하려면 그 앱의 기능만으로는 부족할 것 같았다.
그러던 중 "메신저 봇" 이라는 앱을 알게되었다.
그 앱은 자바스크립트를 통해 봇을 작동시킬 수 있었다.
그 앱은 내가 원하는 기능을 충족시켜줄 것 같았고, 바로 그 앱에 대한 정보를 찾아 코딩을 시작했다.
이 블로그가 그 앱을 개발하신 분의 블로그라고 한다.
올해(2020년) 수능보는 고3이라고 하신다..
능력이 있으신 분이니 꼭 좋은 대학에서 재능을 발휘하셨으면 좋겠다.
이 분의 블로그를 통해 함수 정보를 얻고, 구글링을 통해 얻은 강좌글들로 예제를 수집했다.
자바스크립트 언어는 처음이었지만, 자바, 파이썬, c언어와 문법적으로 비슷한 부분들이 있어
검색을 통해 비교적 편하게 배울 수 있었다.
앱에서 새로운 봇을 만들면 다음과 같은 기본 틀이 있다.
const scriptName = "실명봇헬퍼";
/**
* (string) room
* (string) sender
* (boolean) isGroupChat
* (void) replier.reply(message)
* (boolean) replier.reply(room, message, hideErrorToast = false) // 전송 성공시 true, 실패시 false 반환
* (string) imageDB.getProfileBase64()
* (string) packageName
*/
function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) {
}
//아래 4개의 메소드는 액티비티 화면을 수정할때 사용됩니다.
function onCreate(savedInstanceState, activity) {
var textView = new android.widget.TextView(activity);
textView.setText("Hello, World!");
textView.setTextColor(android.graphics.Color.DKGRAY);
activity.setContentView(textView);
}
function onStart(activity) {}
function onResume(activity) {}
function onPause(activity) {}
function onStop(activity) {}
이 앱이 작동하는 기본적인 원리는 개발자님 블로그에도 소개되어있다시피
카톡 알림이 오면, 알림창에서 바로 답장보내는 기능을 이용하는 것이다.
알림을 앱이 캐치를 해서, 앱에서 코딩한대로 "알림창에서 답장보내는 통로"를 통해 답장을 보낸다.
그 답장을 보내는 함수가 function response 함수이다.
room = 카톡이 온 채팅방 이름
sender = 카톡을 보내온 사람의 이름
isGroupChat = 카톡이 온 채팅방이 단톡방인지 아닌지
replier = 카톡이 온 채팅방으로 답장을 보낼 때 사용하는 객체.
여기에 카톡이 온 채팅방의 정보가 담겨있다.
이 정보를 토대로 다음과 같이 코딩을 해보았다.
const scriptName = "test";
/**
* (string) room
* (string) sender
* (boolean) isGroupChat
* (void) replier.reply(message)
* (boolean) replier.reply(room, message, hideErrorToast = false) // 전송 성공시 true, 실패시 false 반환
* (string) imageDB.getProfileBase64()
* (string) packageName
*/
//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;
//function
function set_study(day, start, end) {
if (now_day == day) {
if (start <= now_hour && now_hour < end) {
study = true;
msg_study = "실명님은 지금 수업중이에요!" + '\n' + end + "시에 수업이 끝나니 그때 연락주세요!";
} else {
study = false;
}
}
}
function set_sleep(start, end) {
if (start <= now_hour && now_hour < end) {
sleep = true;
} else {
sleep = false;
}
}
function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) {
DataBase.appendDataBase("testDB", msg + '\n');
//value set
date = new Date();
now_hour = date.getHours();
now_sec = date.getSeconds();
now_day = date.getDay();
//auto setting
set_sleep(0, 9);
set_study(1, 11, 14);
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);
//user setting
//sleep = false;
//reply
if (!isGroupChat && (sender != "친구이름"))
{
if (msg == "hello" || msg == "안녕") {
replier.reply("안녕");
}
java.lang.Thread.sleep(1500);
if (sleep)
{
replier.reply(msg_sleep);
}
else if (study)
{
replier.reply(msg_study);
}
}
}
//아래 4개의 메소드는 액티비티 화면을 수정할때 사용됩니다.
function onCreate(savedInstanceState, activity) {
var textView = new android.widget.TextView(activity);
textView.setText("Hello, World!");
textView.setTextColor(android.graphics.Color.DKGRAY);
activity.setContentView(textView);
}
function onStart(activity) {
}
function onResume(activity) {
}
function onPause(activity) {
}
function onStop(activity) {
}
글을 쓰는 시점에서는 개발이 더 진행되어있는 코드를 적절히 편집해 올린 것이라
현재 코드상에 의미 없이 선언된 듯 보이는 변수들도 있을 것 같다.
우선 이 코드는 내가 실제 일상에서 쓰는 카톡에 적용되어있는 코드이고
두가지 기능을 수행한다.
1. 취침 시간 자동 응답
밤 12시부터 오전 9시까지는 자고 있는 것으로 간주한다.
그래서 이 시간대에 온 카톡에는 지금 자고 있으니 나중에 연락을 달라는 답을 하게 된다.
아직 이 앱과 자바스크립트에 익숙하지 않아서 간단한 if문으로 코드를 짰지만,
원하는 목표는 저렇게 굳이 시간을 정하지 않고,
내가 자기전에 명령어를 딱 보냈을 때, 그 시간 이후로 오는 모든 카톡에 대해 취침 응답을 보내는 것.
그리고 일어나서 다시 명령어를 보내면, 그 시간 이후로 취침응답을 취소하는 것이다.
현재 내가 갖고 있는 지식으로는, 이 앱만으로 그걸 구현할 수는 없었다.
그래서 안쓰는 공기계와 가상전화번호를 이용해 카톡 부계정을 파서 서로 상호 연동으로 구현시킬 예정이다.
(이미 부계정은 파놓았는데, 다른 기능을 구현중이라 아직 취침시간 자유 설정은 구현하지 않았다.)
2. 수업 시간 자동 응답
학교 시간표에 맞게 요일별로 시간대를 정해, 정한 시간대에는 수업중이라는 안내메세지를 보내도록 하였다.
수업이 끝나는 시간 정보도 같이 담아 보내, 언제쯤에 다시 보내야 할지 알 수 있게 하였다.
=============================================
이 앱을 통해 코딩하면서 한가지 헷갈린 점이 있었다.
이 앱에서의 "컴파일" 의 의미가 내가 알던 컴파일의 의미와 조금 다르게 느껴졌다.
이 앱은 컴파일 완료를 "컴파일 후 실행 완료" 로 간주한다.
중요한 점은 "실행 중" 이 아니다.
"실행 완료" 라는 점이다.
따라서 함수 밖에 있는 코드는, 컴파일 후 실행을 끝낼 때까지, 단 한번만 실행된다.
다른 사람에게 카톡을 받아서 자동으로 응답하는 과정 중에는
함수 밖의 코드가 전혀 실행되지 않는다.
또한 함수 밖에 있는 코드에 무한 루프를 도는 코드가 있다면, 컴파일 자체가 안된다.
무한 루프를 도는 상황은 "컴파일 후 실행 중" 이지. "컴파일 후 실행 완료" 가 아니기 때문이다.
다만 함수 밖 변수의 값은 계속해서 읽고 쓰기가 가능하다.
그래서 함수가 실행될 때마다 변수를 초기화 하거나, 값을 수정할 수 있다.
이것과 관련한 예시로,
date = new Date();
라는 코드가 함수 안에 있음을 알 수 있다.
Date() 객체를 함수가 실행될 때마다 생성해야한다.
나는 처음에 아무렇지 않게 함수 밖에서 생성했다가 낭패를 봤다.
함수 밖에서 Date 객체를 생성하면, 현재 요일/시간 정보가 "컴파일 시점"을 기준으로 하게 되어 영원히 변하지 않는다.
그래서 만약 컴파일을 새벽에 했다면, 다음날 낮이 되어도 봇은 현재 시간을 새벽으로 인식한다.
따라서 메세지를 수신해서 reponse 함수가 실행될 때마다 Date 객체를 생성하여
메세지를 받은 순간의 요일/시간 정보를 받아야 한다.
이 정보를 알기까지 수많은 시행착오를 겪었기 때문에,
만약 나처럼 자바스크립트와 안드로이드 구동 방식에 무지한 사람은 이 글을 통해 더 적은 시행착오를 겪었으면 좋겠다..
'개인 프로젝트 > [2020] 카카오톡 봇' 카테고리의 다른 글
[카카오톡 봇 만들기] 3. 카카오링크 전송하기(1) : 테스트 & 봇 기능 수정 (3) | 2020.10.22 |
---|---|
[카카오톡 봇 만들기] 2. 명령어로 조작하기(3) : 테스트 (0) | 2020.10.18 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(2) : 알고리즘 구현(2) (2) | 2020.10.16 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(2) : 알고리즘 구현(1) (0) | 2020.10.15 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(1) : 알고리즘 설계 (0) | 2020.10.12 |