티스토리 뷰

일단 Telegram-cli을 설치 안하신 분들은 앞 글을 참조하는게 좋을 것 이다. 참고로 Ubuntu 기준이다.

http://slg1119.tistory.com/33

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

댓글
댓글쓰기 폼