기타

Telethon을 이용한 텔레그램 메시지 전달 프로그램 만들기 (w/ AWS)

Sila 2023. 12. 11. 01:17

친구가 암호화폐 트레이딩 관련 텔레그램 방에서 정보를 받아 읽어보는데,

 

말하는 사람이 너무 많고, 유용한 정보는 한정되어 있어 읽기가 힘들다고 했다.

 

그래서 트레이딩을 잘하는 사람(이하 타깃)이 차트 분석을 해 설명과 함께 차트를 올리면 이것만 따로 감지해서

 

다른 텔레그램 방으로 전달해주는 프로그램을 만들어줬다.

 

이걸 AWS에서 구동해 언제나 스크립트가 가동되도록 하는 것까지 해보았다.

 

1. 준비물

1. 텔레그램 계정

봇을 사용하는 건 생각보다 제약이 심하다.

 

텔레그램 계정은 인증에 핸드폰 번호를 요구하는데, 이미 텔레그램 계정이 있었지만

 

해당 작업을 위해 LG U+ 에서 회선을 하나 더 사서 월 3천원 정도를 주고 사용하고 있다.

 

범수씨, 핸드폰 번호를 바꾸실거면 그 전에 그 번호로 가입한 곳은 탈퇴좀 해주세요..

 

연락이 너무 많이 와요..

 

2. AWS 계정

처음에는 내 컴퓨터를 사용하려 했지만 항시 구동하기엔 불편한 점이 많기도 하고,

 

EC2를 오랜만에 사용해보고 싶어 AWS를 이용했다.

 

3. 타깃 메시지가 전송되는 방에 들어가 있어야 함.

 

2. Telethon

사용한 라이브러리인데 telegram + python 이라는 뜻인 것 같다.

 

지원하는 기능이 많아 이 라이브러리와 dotenv만 가지고 필요한 작업을 전부 수행할 수 있었다.

 

sudo apt-get install python3.8
sudo apt-get install python3-pip
pip3 install telethon
pip3 install python-dotenv

 

2-1. 텔레그램 api 발급

우선 텔레그램 api를 사용할 수 있도록 id를 발급 받아야 한다.

 

여기에서 전화번호를 입력하고 텔레그램 어플에서 코드를 받아 입력하면 내 api id, hash를 받을 수 있다.

 

전화 번호는 인터네셔널 포맷으로 입력하면, 문자가 아닌 텔레그램 메시지로 온다는 점에 유의한다.

 

전화번호가 010-xxxx-yyyy라면 +8210xxxxyyyy로 입력하면 된다.

 

app 이름 등은 원하는대로 입력해주면 된다.

 

2-2. 타깃이 있는 방 특정

이제 전달해야 하는 메시지를 전송하는 타깃이 있는 채팅 방을 특정해야 한다.

 

다음과 같이 스크립트를 짜줄 수 있다.

 

from telethon import TelegramClient
from dotenv import load_dotenv
import os

load_dotenv()

api_id = os.getenv("API_ID")
api_hash = os.getenv('API_HASH')
session_name = os.getenv("SESSION_NAME")

client = TelegramClient(session_name, api_id, api_hash)

async def main():
    async for dialog in client.iter_dialogs():
        print(dialog.name, 'has ID', dialog.id)

with client:
    client.loop.run_until_complete(main())

 

내 텔레그램 계정이 참여중인 모든 채팅에 대한 아이디를 알려준다.

 

SESSION_NAME은 원하는대로 정해주면 된다.

 

앞서 발급받은 api id, hash를 이용해 내 계정으로 세션을 만들 수 있고,

 

이를 통해 해당 계정에 참여 중인 채팅방들에 접근한다.

 

유의할 점은 ID의 값은 양수, 음수 전부 가능하다는 것.

 

(1:1 채팅은 대화 상대의 ID(양수), 그룹 챗은 음수가 나오는 것 같다.)

 

추후에도 음수여도 문제없이 처리할 수 있게끔 코드를 짜야한다. 

 

이 파일을 실행하면 다음과 같이 나온다.

 

xxx has ID yyy...

 

yyy가 필요한 방의 ID이다.

 

2-3. 타깃 ID 특정

이제 타깃의 ID를 특정해보자.

 

방금 방의 ID를 구했으니, 이 방의 채팅 기록을 불러오면 타깃이 말을 한 걸 찾을 수 있을 것이고,

 

거기서 타깃의 ID를 특정할 수 있다.

 

from telethon import TelegramClient, sync
import os
from dotenv import load_dotenv

load_dotenv()

api_id = os.getenv("API_ID")
api_hash = os.getenv('API_HASH')
target_room_id = int(os.getenv('TARGET_ROOMID'))
session_name = os.getenv("SESSION_NAME")

client = TelegramClient(session_name, api_id, api_hash)

async def main():
    async with client:
        history = await client.get_messages(target_room_id, limit=50)
        for message in history:
            print(message.sender.id, message.text)

client.loop.run_until_complete(main())

 

타깃 룸의 채팅 기록을 50개 가져오는 코드이다. 

 

가져올 채팅 숫자는 최근 채팅 기록을 보고 타깃의 채팅이 포함될 만큼 적당히 설정하면 된다. 

 

target_room_id는 음수를 int 타입으로 바꾸기 위한 처리를 해주었다. 

 

이 파일을 실행하면 다음과 같이 콘솔에 출력된다.

 

xxxxxx 안녕하세요

 

xxxxxx가 우리가 원하는 타깃의 ID 이다.

 

아마 유저의 ID는 양수로 나오는 것 같다.

 

2-4. 타깃의 대사 포워딩

이제 타깃이 채팅을 하면 그걸 감지해서 다른 방으로 메시지를 포워드해주는 코드를 만들어보자.

 

from telethon import TelegramClient, events
from dotenv import load_dotenv
import os
from datetime import datetime
import asyncio

load_dotenv()

api_id = os.getenv("API_ID")
api_hash = os.getenv('API_HASH')
dot_room_id = int(os.getenv('TARGET_ROOM'))
target_id = int(os.getenv('TARGET_ID'))
my_chatroom_id = int(os.getenv('MY_ROOM'))
session_name = os.getenv("SESSION_NAME")

print("Application run...")

client = TelegramClient(session_name, api_id, api_hash)

print("Instance created")

async def periodic_message():
    while True:
        await client.send_message(my_chatroom_id, 'Periodic status message')
        await asyncio.sleep(43200)

async def my_event_handler(event):
    if event.sender_id == target_id:
        now = datetime.now()
        print("Target spoke", "time:", now.date(), now.time())
        await client.forward_messages(my_chatroom_id, event.message)

async def main():
    await client.start()
    print("Client started")
    client.loop.create_task(periodic_message())
    client.add_event_handler(my_event_handler, events.NewMessage(chats=dot_room_id))
    await client.run_until_disconnected()

with client:
    client.loop.run_until_complete(main())

 

.env는 다음과 같이 작성해주면 된다.

 

API_ID=<내 텔래그램 api id>
API_HASH=<내 텔래그램 api hash>
TARGET_ROOM=<타깃이 있는 채팅방 ID>
MY_ROOM=<메시지를 포워딩할 채팅방 ID>
TARGET_ID=<타깃의 텔래그램 ID>

 

프로그램이 잘 돌아가는지를 확인하기 위해 12시간에 한 번 메시지를 보내도록 해두었고,

 

타깃 채팅방에서 채팅이 발생하면 화자의 id를 확인 후, 타깃의 id와 일치 할 때 내 방으로 포워딩되도록 해두었다.

 

3. AWS

이제 이 프로그램을 항시 동작하도록 하기 위해 AWS EC2를 사용했다.

 

python 스크립트 파일과 pm2의 리소스 사용을 보니 전자가 약 40mb를 사용하는 것으로 보아,

 

pm2로 구동하더라도 1gb 이상 메모리를 사용할 것 같지는 않아서,

 

500mb의 메모리를 제공하는 t2.nano 인스턴스를 사용했다.

 

단, 이렇게 하면 vs code로 원격 접근을 하기엔 조금 부족하다.

 

플러그인을 하나도 설치 안하면 간신히 돌릴 수는 있는데, 플러그인을 설치하고 vs code로 재접속을 하면

 

메모리가 부족해 프리징 되어버려 인스턴스를 재시작해야했다.

 

 

3-1. 인스턴스 생성

AWS에 접속해 회원가입, 로그인을 진행한다.

 

1. 위쪽 검색창에서 EC2를 검색하고, 해당 항목을 클릭한다.

 

 

지역은 서울로 선택하고 (다른 더 싼 곳이 있는데, 가격과 속도 차이를 상황에 따라 고려해 잘 선택하면 된다.)

 

2. 인스턴스 시작을 클릭한다.

 

 

3. 이름과 os 이미지를 정한다. 

 

os는 우분투로 설정하고 나머지는 굳이 건들이지 않아도 된다.

 

 

4. 아래로 내려 인스턴스 유형과 키 페어를 설정한다.

 

아마 t2.micro가 프리티어로 사용이 가능할 것이다. 그걸 사용해도 상관없다. 

 

키 페어는 클라우드에 원격 접속을 하기 위한 패스워드라고 생각하면 된다.

 

아무나 내가 돈 내고 쓰는 클라우드에 접근하면 안 되니까..

 

새 키 페어를 생성하면 이름과 유형 등을 정하라고 할텐데,

 

나 같은 경우 키페어 이름은 인스턴스 이름과 동일하게 해주었고,

 

유형은 RSA, 파일 형식은 .pem으로 해주었다. 즉, 아무것도 안 건들면 된다.

 

그러면 키 이름.pem 파일이 생성될텐데

 

이 파일은 잃어버리거나 깃허브에 올리거나, 수정하거나 하면 안된다.

 

 

5. 이제 오른쪽의 인스턴스 시작을 클릭하면 인스턴스가 생성된다.

 

다음과 같이 확인할 수 있다.

 

 

클릭하면 현재 클라우드 서비스의 퍼블릭 ip, 리소스 사용량등을 확인할 수 있다.

 

3-2. 인스턴스 원격 접속

이제 인스턴스에 원격으로 접속한다.

 

1. 우측 상단의 연결 버튼을 클릭한다.

 

2. SSH 클라이언트를 선택하고, 필요하다면 pem 키 파일의 권한을 변경하고, ssh로 원격 접속한다.

 

 

그러면 ip 주소가 바뀌면서 접속이 될 것이다. 여기에 아까 만든 python 파일과 env 파일을 두고, pm2로 구동하면 된다.

 

 

3-3. pm2로 스크립트 구동

먼저 nodejs, npm을 설치하고, pm2를 설치하면 된다.

 

nodejs, npm 설치는 여기서는 생략한다.

# 최신 버전 pm2 설치
npm install pm2@latest -g

# python3를 이용해 파일을 구동하고, 이름은 원하는 대로 정한다.
pm2 start [python 파일 이름.py] --interpreter python3 --name [프로세스 이름]

# 파이썬 스크립트가 잘 돌아가고 있는지 확인
pm2 list

# 프로세스를 중단하고 싶을 때
pm2 stop [프로세스 이름]

 

4. vs code로 원격 접속

터미널만 가지고 코드를 관리하는게 힘들다는 건 조금만 생각해도 알 수 있고,

 

MS에서는 원격으로 접속한 컴퓨터에서도 vs code를 이용해 코드를 수정할 수 있게끔 플러그인을 지원하고 있다.

 

1. 다음 플러그인들을 검색해 설치한다. 전부 MS가 배포한 것이라는 걸 확인하며 설치할 것.

 

 

2. SSH 구성 파일 생성

vs code에러 f1은 누르고 Remote-SSH: SSH 구성 파일 열기를 선택한다.

 

이제부터 윈도우 경로를 사용하는데, 보통 C:\Users\[User명]\.ssh 폴더를 사용한다.

 

이 폴더에 아까 받은 .pem 키를 복사해 넣어준다.

 

 

3. 동일 폴더에 config 파일을 생성하고 다음과 같이 작성한다.

Host [인스턴스 이름]
    HostName [인스턴스 퍼블릭 IP]
    User ubuntu
    IdentityFile ~/.ssh/telethon_key.pem

 

Host 이름은 마음대로 설정해줘도 문제 없을 것이다. 나는 헷갈리지 않게 인스턴스 이름과 동일하게 해주었다.

 

인스턴스에서 새로 유저를 생성하지 않았다면 유저 이름은 ubuntu로 해주면 된다.

 

IdentityFIle은 원격 접속에 필요한 pem키의 `윈도우`의 절대경로를 넣어주면 된다.

 

파일명은 config로 해준다. 확장자는 붙이지 않는다.

 

이렇게 파일을 작성하고 저장하고 닫는다.

 

4. f1을 다시 누르고, Remote-SSH : 호스트에 연결을 선택한다.

연결할 호스트를 선택하라고 할텐데, 위에서 Host의 이름으로 정한 값이 나올 것이다. 이를 클릭하면 접속이 된다.

 

다시 말하지만, t2.nano에서 플러그인을 설치한 vs code를 구동하는 건 힘드므로 이 구성으로 사용할 것이라면

 

vs code 플러그인을 인스턴스에 설치하는 건 지양하는 것이 좋다.

 

5. 주의 사항

다른 사람 대화를 포워딩에서 사용하는 것이 괜찮은지 사실 잘 모르겠다.

 

ID등을 전부 어렵지 않게 확인할 수 있는 것을 보면 텔레그램쪽에서도

 

적어도 오피셜하게는 별로 신경을 쓰지 않는 듯한데,

 

이렇게 사용할 것이라면 염두는 해두는 것이 좋을 것 같다.

 

또 t2.nano 인스턴스 사용료는 월 대략 5$, LG U+ 기준 회선 추가는 월 3300원이 필요하다.

'기타' 카테고리의 다른 글

docker로 ubuntu 환경 셋업  (0) 2023.04.01
google 검색에 대한 스킬  (0) 2022.12.04