일단 Telegram-cli을 설치 안하신 분들은 앞 글을 참조하는게 좋을 것 이다. 참고로 Ubuntu 기준이다.
Telegram-cli가 설치되있다는 가정 하에 시작하겠다.
1.hello.lua 뜯어보기
Telegram-cli는 기본적으로 lua란 언어를 사용한다.
일단 예제 코드인 hello.lua 코드를 보자.
function on_msg_receive (msg) if ( msg.text == 'hello' ) then send_msg(msg.from.print_name, "world", ok_cb, false) #hello란 명령어를 받으면 world를 보내라는 커맨드 return end end function ok_cb(extra, success, result) end |
위에 코드를 보면, hello란 메세지가 오면, world를 보내는 명령어다.
한마디로 유저가 hello.lua를 돌리고 서버한테 hello를 보내면 world를 유저한테 보내준다.
저 위에 코드를 hello.lua로 저장하고 실행시켜보자.
$ bin/telegram-cli -s hello.lua
그러면 한번 다르게 코드를 바꿔보자.
function on_msg_receive (msg) if ( msg.text == 'world' ) then send_msg(msg.from.print_name, "hello, My name is Sleepy", ok_cb, false) return end end function ok_cb(extra, success, result) end |
이렇게 하면 어떻게 작동할까?
유저가 world를 보내면 서버는 hello, My name is Sleepy 라고 답을 할 것이다.
2. 본격적으로 봇 만들어보기.
일단 txt를 읽어서 출력을 해주는 봇을 만들어 볼라고 한다.
코드는 엄청 단순하다.
function on_msg_receive (msg) if ( msg.text == 'hello' ) then send_text(msg.from.print_name, '/path/txtfile.txt', ok_cb, false) return end end function ok_cb(extra, success, result) end |
위 코드는 어떻게 작동을 할까?
hello라는 명령어가 오면 이 스크립트는 우리가 설정해준 경로에 있는 txt파일을 불러온다.
만약 txt파일 위치가 /home/sleepy/txtfile.txt에 있다면,
function on_msg_receive (msg) if ( msg.text == 'hello' ) then send_text(msg.from.print_name, '/home/sleepy/txtfile.txt', ok_cb, false) return end end function ok_cb(extra, success, result) end |
로 설정해주면 된다.
txtfile.txt에 World!라고 적혀있으면,
유저가 hello라고 보내면 서버에서는 World!라고 메세지를 보낼 것 이다.
한번 위에 소스를 조금 바꿔보겠다.
function on_msg_receive (msg) if ( msg.text == 'hello' ) then local t = os.execute("sh /home/sleepy/test.sh > /home/sleepy/txtfile.txt") send_text(msg.from.print_name, '/home/sleepy/txtfile.txt', ok_cb, false) return end end function ok_cb(extra, success, result) end |
그리고 밑에는 test.sh소스다.
#!/bin/sh
echo "Hello World!"
아마 리눅스를 많이 사용한 분들이라면 빠르게 눈치를 챗을 것이다.
나는 저런 방식으로 사용해봤다.
저 lua소스는 test.sh를 실행시키고 거기의 대한 결과값을 txtfile.txt로 저장하고, txt내용을 메세지로 보내는 것이다.
다시 말해서, 다른 사용자가 hello란 메세지를 보내면, 서버에서는 Hello World!라는 메세지를 보낼 것 이다.
그러면 저 소스를 조금 개조시켜서 사용자가 ping이란 메세지를 보내면, 서버에서 ping의 상태를 알려주는 lua스크립트를 만들어보자.
function on_msg_receive (msg) if ( msg.text == 'ping' ) then local t = os.execute("sh /home/sleepy/ping.sh > /home/sleepy/ping.txt") send_text(msg.from.print_name, '/home/sleepy/ping.txt', ok_cb, false) return end end function ok_cb(extra, success, result) end |
그리고 밑에는 ping.sh소스다.
#!/bin/sh
ping -c4 8.8.8.8 | grep packets
참고로 ping만 치면 계속 패킷 값이 올라오기 때문에, txt file에 계속 쌓여서 서버에서 txt를 못 보내준다.
그래서 나는 -c옵션을 줘서 8.8.8.8로 핑을 4번만 보내고 그 결과값을 출력시킨다.
예를 들자면, top나 이런 명령어도 계속 txt에 쌓이기 때문에, 사용하는 것을 비추천 한다.
다시 본론으로 돌아와서, 이제 다른 유저가 ping을 보내면, 서버에서 패킷값을 보내줄 것 이다.
위의 스크립트를 보고 많은 분들이 '꼭 불편하게 sh에 저장되어 있는 주소로 밖에 ping을 못보낼까?'라는 의문을 가질 것이다.
그러면 유저가 원하는 주소로 ping을 보내게 lua 스크립트를 만들어 보자.
ping_cmd = "sh /home/sleepy/ping.sh" function split(str) local arg_1st="" local arg_2nd="" local arg_cnt=1 for s in string.gmatch(str, "[^%s]+") do if ( arg_cnt == 1 ) then arg_1st = s else arg_2nd = arg_2nd .." ".. s end arg_cnt = arg_cnt + 1 end return arg_1st, arg_2nd end function on_msg_receive (msg) local recv_msg = "" if ( msg.text ~= nil ) then recv_msg = string.gsub(msg.text,"[;|<>]","") -- 받은 msg중에 ;, |, <, > 등의 문자는 지움 end local cmd, arg = split(recv_msg) -- exam : ping a b c d => cmd = "ping", arg = "a b c d" local file_name = "" cmd = string.lower(cmd) if ( msg.text == 'ping' ) then local t = os.execute(ping_cmd .. arg) send_text(msg.from.print_name, '/home/sleepy/ping.txt', ok_cb, false) return end function ok_cb(extra, success, result) end |
밑에는 ping.sh 소스이다.
#!/bin/sh
PING=`ping -c4 $1 | grep packets`
echo $PING > /home/sleepy/ping.txt
많이 소스가 바꼇다.
lua부터 살펴보자면, 우리가 ping 127.0.0.1이라고 서버에 메세지를 보내면, lua에서 ping을 cmd로 인식하고, 127.0.0.1을 args로 인식 할 것이다.
그럼 그 args를 ping.sh에 $1으로 들어간다고 생각을 하면된다.
다시 써보자면,
유저가 ping 127.0.0.1을 서버로 전송 -> lua 스크립트에서 ping을 cmd로 127.0.0.1을 args로 슬라이스 -> ping.sh에 $1 로 사용 -> sh에서 ping -c4 127.0.0.1의 결과물을 txt로 저장 -> 다시 lua 스크립트로 돌아와서 ping.txt의 내용을 유저한테 보냄
이런 순서로 진행이 된다.
저 위의 방식으로 재미있는 것도 만들 수 있다.
cmd_cmd = "sh /home/sleepy/cmd.sh" function split(str) local arg_1st="" local arg_2nd="" local arg_cnt=1 for s in string.gmatch(str, "[^%s]+") do if ( arg_cnt == 1 ) then arg_1st = s else arg_2nd = arg_2nd .." ".. s end arg_cnt = arg_cnt + 1 end return arg_1st, arg_2nd end function on_msg_receive (msg) local recv_msg = "" if ( msg.text ~= nil ) then recv_msg = string.gsub(msg.text,"[;|<>]","") -- 받은 msg중에 ;, |, <, > 등의 문자는 지움 end local cmd, arg = split(recv_msg) -- exam : ping a b c d => cmd = "ping", arg = "a b c d" local file_name = "" cmd = string.lower(cmd) if ( cmd == "cmd" ) then local t = os.execute(cmd_cmd .. arg) send_text(msg.from.print_name, '/home/sleepy/cmd.txt', ok_cb, false) return end end function ok_cb(extra, success, result) end |
밑에는 cmd.sh 소스이다.
#!/bin/sh CMD=`$1 $2 $3 $4 $5` echo $CMD > /home/sleepy/cmd.txt대충 짐작이 가시는 분들도 있을 것 이다.
만약 내가 cmd ping -c4 8.8.8.8 이라고 서버에 보내면, 서버에서 ping -c4 8.8.8.8의 값을 출력해준다.
진행 순서를 보자면,
cmd ping -c4 8.8.8.8이라고 서버에 보냄 -> lua에서 cmd를 cmd로 받아들이고, ping을 args1, -c4를 args2, 8.8.8.8을 args3로 인식하고 cmd.sh로 넘김 -> cmd.sh에서 ping을 $1에 대입, -c4를 $2에 대입, 8.8.8.8을 $3에 대입하고, 그 명령어를 실행하고 txt에 저장 -> 다시 lua로 돌아와서 cmd.txt에 있는 내용을 메세지로 보냄
이런 구조로 된다.
물론 위에서 말했듯이, top나 계속 출력이 나오는 커맨드는 안된다.
마지막으로, 꼭 sh만 쓸 수 있는게 아니다.
파이썬, 자바 다 가능하다.
물론 lua에서
function on_msg_receive (msg) if ( msg.text == 'python' ) then local t = os.execute("python /home/sleepy/test.py > /home/sleepy/test.txt") send_text(msg.from.print_name, '/home/sleepy/test.txt', ok_cb, false) return end end function ok_cb(extra, success, result) end |
이렇게 바꿔주면 된다.
만약 내 글을 보고 이해가 안된다면
https://github.com/slg1119/Telegram_Server_Monitoring
내 소스를 한번 보는것도 나쁘지 않다.
참고한 링크: http://truefeel.tistory.com/224
'Develop' 카테고리의 다른 글
우분투(Ubuntu)에 텔레그렘(Telegram) CLI설치 (0) | 2015.02.14 |
---|