TIP게시판

제목 텔레그램 단방향 메세지 송출 팁.
글쓴이 방문넷 작성시각 2014/11/25 00:17:32
댓글 : 7 추천 : 0 스크랩 : 1 조회수 : 22585   RSS
운영하는 사이트를 A.com이라 칭하겠습니다

1. A.com에 한 손님이 회원가입을 한다.
2. 회원 가입 완료 동시에 A.com 운영자의 텔레그램으로 회원이 가입하였다는 메세지를 송출.

보통 검색으로 통하여 나오는 Lua 스크립트는 대화형이라 보시면되는데 일단 제가 자주 사용하는 node.js로 단방향으로 메세지 송출하는걸 만들었습니다.

코드를 테스트하기 앞서 선행 작업이 되셔야 합니다.
1. 서버에 telegram-cli 설치 => https://github.com/vysheng/tg
2. 서버에 telegram-cli 설치후 전화번호로 인증받기.

테스트해보니까 자기자신의 핸드폰 번호로 핸드폰에도 인증받고 서버에도 인증받으면 
자기 자신에게 메세지 날리면 푸시 알림이 안울리더라구요 그래서 전 번호 두개로 따로따로 인증
걸어두고 사용중입니다 이점 유의 하세요!


node.js코드
/**
 * 텔레그램 단방향 메세지 송출..
 * 만든놈 : 방문넷(lee@dongwon.me)
 * 라이센스 : 그딴거 없음. 주석 지우고 사용가능 하실께요~
 * 상업용이든 비상업용이든 알아서잘 수정하여 쓰세용~
 * A/S나 문의는 받지않습니다~~
 */

//======================================================================================
// 모듈 로드
//======================================================================================
var http = require('http');					//http 서버
var url  = require('url');					//URL
var exec = require('child_process').exec;	//서버 커멘트 처리(보안상 문제가 있을수 있음으로 주의)

//======================================================================================
// 변수 설정
//======================================================================================
var telegramCli = '/usr/bin/telegram-cli';		//텔레그램 실행파일 경로
var telegramKey = '/etc/telegram/server.pub';	//텔레그램 serverkey 경로
var telegramId = '텔레그램 연락처에 적힌 이름.';						//메세지 받을 아이디
var serverPort = 7890;							//리스닝할 서버 포트(외부 iptable은 웬만하면 열지마세요!);
var messageFlag = true;							//메세지 전송 여부.

//======================================================================================
// http 서버 오픈.	
// 외부에서 접근 불가능하게 해야 조금이나마 안심.
// 외부에서 접근을 시도할경우 거부하는 쪽이 좋음.
//======================================================================================
var webServer = http.createServer(function(req,res)
{
	_LOG_('호출 아이피 => ' + req.connection.remoteAddress);
	
	//로컬용도로 만든 거기에 로컬 아이피가 아닐경우는 튕겨내기.
	if(req.connection.remoteAddress != '127.0.0.1') 
	{
		_LOG_('로컬 호출이 아닙니다.');
		res.end();
		return;
	}

	//Url 쪼개기
	var urlParts = url.parse(req.url, true);
    
    //쿼리 스트링
    var query = urlParts.query;

    //쿼리스트링 로그 찍기.
    _LOG_(JSON.stringify(query));

    if(query.do == 'msg')
    {
    	SendMsg(query.message);
    }
    else if (query.do == 'flag')
    {
    	if(query.flag == 'true')
    	{
    		messageFlag = true;
    		_LOG_('메세지를 받습니다.');
    	}
    	else
    	{
    		messageFlag = false;
    		_LOG_('메세지를 안 받습니다.');
    	}
    }
    
    //끝!
    res.end();
}).listen(serverPort);;

//======================================================================================
// 로직 시작.
//======================================================================================
//메세지 송출.
function SendMsg(string)
{
	_LOG_('메세지 송출 시작');
	_LOG_('메세지 송출 메세지 => ' + string);
	
	if(messageFlag === false)
	{
		_LOG_('메세지를 받지 않고 있습니다.');
		_LOG_('메세지를 받으실려면 메세지 받기를 활성화 하십시오.');
		_LOG_('메세지 송출를 취소 하였습니다.');
		return;
	}

	exec(
		"echo 'msg "+telegramId+" "+string+"' | "+telegramCli+" -k "+telegramKey+" -W " ,
		function(err, stdout, stderr) { 
			if(err) { 
				_LOG_(err.message); 
				return;
			}

			_LOG_('메세지 송출 완료');
		}
	);
}

SendMsg('텔레그램 서버가 실행 되었습니다.');

//======================================================================================
// 로그용도.
//======================================================================================
function _LOG_(msg, type)
{
	if(typeof(type) == 'undefined') {
		type = 'info';
	}

	if(type == 'debug') {
		console.log('['+getTimeStampLog()+'] [디버그] ' + msg);
	}
	else if (type == 'info') {
		console.log('['+getTimeStampLog()+'] [정보] ' + msg);
	}
	else if (type == 'error') {
		console.log('['+getTimeStampLog()+'] [에러] ' + msg);
	}
}

function getTimeStampLog () {
	var d = new Date();
	var s =
		leadingZeros(d.getFullYear(), 4) + '-' +
		leadingZeros(d.getMonth() + 1, 2) + '-' +
		leadingZeros(d.getDate(), 2) + ' ' +
		leadingZeros(d.getHours(), 2) + ':' +
		leadingZeros(d.getMinutes(), 2) + ':' +
		leadingZeros(d.getSeconds(), 2);

	return s;
}

function leadingZeros(n, digits) {
	var zero = '';
	n = n.toString();

	if (n.length < digits) {
		for (i = 0; i < digits - n.length; i++) {
			zero += '0';
		}
	}

	return zero + n;
}


요로쿵 서버로 돌리고 PHP단에서 Curl로 규격에 맞게 메세지를 보내면 자연스럽게 텔레그램으로 메세지가 올것 입니다. 단방향으로 처리하는것이고. Lua스크립트로 공개된 것이 있습니다 그걸 이용하면 양방향 메세지가 가능합니다.

아래 스크린샷 나갑니다!





핸드폰으로 받은 메세지 입니다.

 다음글 CI에서 MSSQL연결하기. (4)
 이전글 csrf 설정 시 CKEditor 이미지 업로드 (2)

댓글

한대승(불의회상) / 2014/11/25 09:44:20 / 추천 0
같은 전화번호로 메시지 날리기는 안되는거군요. ^^
ㅋㅋㅋ 당연한건데.. ㅋㅋㅋㅋ 
좋은 정보 감사 합니다.
방문넷 / 2014/11/25 11:14:52 / 추천 0
불의회상 // 어느 블로거님이 공유 해주신 코드를 OSX에서 쓰다보니까 한글문제가 있는건지 제 OSX문제가있는건지 진행이 잘 안되더라구요...

그래서 조금 수정해서 쓰고있습니다.
원소스 링크 : http://coffeenix.net/board_view.php?bd_code=1760

살짝 수정한 소스.
--[[
   telegram용 서버 모니터링 스크립트
   - telegram으로 명령(ping, load, netlog, mrtg, 404)을 받으면, 결과값을 메신저로 보내줌
   2014.9.30
   2014.10.13(Mon) 명령어 문자열 필터링, 인증된 폰만 명령을 받도록. secret chat 지원
-- by truefeel(좋은진호, http://coffeenix.net/) 
]]

--현재 시간 --
now = os.time()

-- 쉘스크립트 또는 기타 스크립트 폴더 --
dir_cmd  = "/Volumes/DEV/workspaces/hello/telegram"

-- 커멘드 모음:시작 --
-- 예제 : cmd_ping = "cd ".. dir_cmd .."; sh ping.sh"
-- 커멘드 모음:끝 --

-- 허용할 핸드폰 번호:시작 --
auth_phone = {
 ["821012341234"] = true,
}
-- 허용할 핸드폰 번호끝 --


-- 메시지 수신 처리--
function on_msg_receive (msg)
 -- 메세지 보낸시각이 현재시간보다 적을때.--
 if msg.date < now then
  return
    end

 if msg.out then
  return
 end

 -- 명령어 처리 --
 local recv_msg = msg.text
 
 if ( msg.text ~= nil ) then
  recv_msg  = string.gsub(msg.text,"[;|<>]","") -- 받은 msg중에 ;, |, <, > 등의 문자는 지움
 end

 -- 커멘드 인자값 처리 새로작성.--
 local cmd = split(recv_msg, " ")
 
 print("들어온 명령어 => ", cmd[1], "\n")
 -- 메세지 보낸 사람의 정보 --
 print("보낸사람 => ", msg.from.print_name)  -- 메시지 보낸사람 real name 만약에 firstname lastname 이라면 firstname_lastname 으로 써야함.
 print("핸드폰번호 => ", msg.from.phone)   -- 메시지 보낸사람 전화번호  (8210AAAABBBB)
 print("메세지번호 => ", msg.id)    -- 메시지 번호
 print("받는사람 => ", msg.to.print_name)

 -- 일반대화, 비밀대화 구분해서 메시지 전송
 if (msg.to.id == our_id) then
  user_id = msg.from.print_name   -- 일반대화창
 else
  user_id = msg.to.print_name   -- 비밀대화창
 end

 -- auth (지정한 폰번호만 인증)
 if auth_phone[msg.from.phone] then
  print "인증 => OK "
 else
  print "인증 => 허용되지 않은 폰번호 입니다."
  return
 end
 
 mark_read(user_id, ok_cb, false)   -- 읽은 메시지로 표시

 -- 명령어 체크 --
 if ( cmd[1] == '콜' ) then
  --os.execute(cmd_ping .. arg) --
  --send_text(user_id, dir_cmd ..'/result_ping.txt', ok_cb, false)
  send_text(user_id, '어서오세요', ok_cb, false)
  return
 end
 
 -- 도움말
 if ( cmd[1] == '도와줘' ) then
  send_text(user_id, dir_cmd ..'/help.txt', ok_cb, false)
 end
end

function on_secret_chat_created (peer)
end

function on_secret_chat_update (schat, what)
end

function on_user_update (user)
end

function on_chat_update (user)
end

function on_our_id(id)
 our_id = id
 print("My user# : ", id)
end

function on_get_difference_end ()
end

function on_binlog_replay_end ()
end

function ok_cb(extra, success, result)
end

function trim(str)
 return ( str:gsub("^%s*(.-)%s*$", "%1") )
end

function file_exists(name)
 if type(name)~="string" then return false end
 return os.rename(name,name) and true or false
end

-- 기존의 소스 삭제 후 새로 추가한 부분 --
function split(str, delim, limit)
 local t = {}
 local tt = {}
 local s = str
 local dm = delim
 local limit_t = limit
 local ck = false or limit
 str = nil
 delim = nil
 limit = nil
 while true do
  if s == nil then break end
   local fn = function(t, s, delim)
   local idx = select(2, string.find(s, delim))
   if idx == nil then
    table.insert(t, string.sub(s, 0))
    return nil
   else
    table.insert(t, string.sub(s, 0, idx - 1))
    return string.sub(s, idx + 1)
   end
  end
  s = fn(t, s, dm);
 end
 if not ck then return t end
   if limit_t > table.maxn(t) then print("테이블보다 정한 길이가 큽니다.") return t
  else
  for i = 1, limit_t do
   table.insert(tt, t[i])
    end
  return tt
 end
end


소스를 보면 cmd[1] == '콜' 이부분 아래에 어서오세요 부분이 전송 안됩니다.
아래 도와줘는 전송이 되구요..
그래서 node.js에나 php에서 명령에 대한 결과물을 txt로 이쁘게 만들고 메세지를 보낸다면 
유연하게 메세지를 주고 받을수있을꺼같아요ㅎ 조금 허접하게 나마 PHP랑 node.js 서로 통신하면서 텔레그램 까지 겸비 하니까 웬지 
최첨단 관리자를 만든 기분입니다 ㅎㅎㅎㅎ;;;
 
방문넷 / 2014/11/25 11:17:50 / 추천 0
불의회상 // 아 그리고 같은 전화번호로 인증 가능하구요... 메세지도 보낼수있습니다.... 다만 알림만 안울리는거일뿐.......(저만그런지는 몰르겠네요 ㅎㅎ) 알림만 안울릴뿐 메세지 주고 받고 다 가능합니다
한대승(불의회상) / 2014/11/25 11:18:26 / 추천 0
방문넷// 소스코드를 보니 의욕이 무럭무럭 자라는군요.
시간 나는데로 연동을 시도해 봐야겠네요.
좋은 정보 감사 합니다.
변종원(웅파) / 2014/11/26 11:34:01 / 추천 0
기존 아파치 서버에선 그냥 php로 해도 되는거죠? cmd를 써야하긴 하겠지만요.
코드이그 / 2014/11/26 13:53:38 / 추천 0
좋은정보 감사드립니다 ^^
방문넷 / 2014/11/27 00:46:23 / 추천 0
웅파 // 넵 nodejs로 어차피 http 쿼리날리는거라 잘됩니당..

lua의경우는 잘 몰르겠어요;;