Profile picture

[Python] 텔레그램(telegram) 봇으로 메시지 전송하기 - python-telegram-bot

JaehyoJJAng2024년 06월 20일

개요

텔레그램에서 제공하는 Bot Father를 활용하여 파이썬으로 텔레그램 메시지 보내기 실습을 진행해보자.

파이썬에서는 텔레그램 Bot API를 쉽게 사용할 수 있는python-telegra-bot 이라는 라이브러리가 존재한다


봇 생성

1. 텔레그램 앱에서 /newbot 이라고 채팅을 입력하면 봇 채팅방을 개설할 수 있는 단계가 시작된다.
image


2. 봇 채팅방 이름을 지정해주자.
image


3. 봇의 이름을 지정해주자. 중요한 점은 봇의 이름을 지정할 때는 봇 이름 마지막에 _bot 이라고 끝나야 한다.
image


4. 이후 봇 채팅방이 개설되고, 다음의 봇 토큰이 생성되었다. 해당 토큰은 이번 실습에서만 사용하고 이후 삭제된다.
image


5. 마지막으로 생성된 봇 채팅방 검색 후, start 버튼을 클릭하면 된다. (본인이 생성한 봇을 정확히 찾도록 하자.)
image

이제 생성한 봇을 가지고 파이썬으로 답변을 할 수 있는 코드를 작성하면 된다.


라이브러리 설치

해당 실습의 경우 python-telegram-bot 라이브러리의 버전이 20.1 이상이어야 한다.

20.1 이하인 라이브러리를 사용 중인 경우 정상적인 실습 진행이 불가능할 수 있다.

python-telegram-bot에 비동기 로직이 추가되면서 20.1 이하 버전에서 해당 실습 코드 사용 시 아래와 같은 에러를 만나게 될 것이다.

coroutine 'Bot.send_message' was never awaited

python-telegra-bot 라이브러리를 설치해보자.

pip install python-telegram-bot

봇을 컨트롤하기 위한 기본 코드

import os
from telegram import Update
from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler

# 텔레그램 API 토큰 가져오기
_TELEGRAM_TOKEN :str = os.getenv('TELEGRAM_TOKEN', '8015190100:AAG8nQb_Guw_2foZM8mDOOV_AndEBV9PVik')

# 텔레그램 메시지 전송을 위한 핸들러 클래스 정의
class TelegramBotHandler():
    # /help 핸들러 정의
    @classmethod
    async def help(cls, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
        message = "저는 여러분들을 돕기 위한 봇 입니다!"
        await update.message.reply_text(message)

def main() -> None:
    bot_handler = TelegramBotHandler()
    try:
        application = ApplicationBuilder().token(_TELEGRAM_TOKEN).build()
        application.add_handler(CommandHandler('help', bot_handler.help))
        application.run_polling()        
    except (KeyboardInterrupt, SystemExit):
        print(f"사용자 입력에 따라 프로그램이 종료됨.")
if __name__ == '__main__':
    main()

위 코드는 봇 채팅방에서 /help 라고 메시지를 보냈을 때, 봇이 자동으로 '저는 여러분들을 돕기 위한 봇 입니다!' 라는 답변을 하는 코드이다.

  • CommandHandler에 의해 help 명령이 TelegramBotHandler라는 클래스의 help 라는 클래스 메소드와 매핑되도록 콜백 함수를 등록하였다.
  • 이후 run_polling() 함수를 통해, 사용자로부터 /help 라는 채팅이 오는 순간 자동으로 콜백 함수가 실행된다.

위 코드를 실행하고 텔레그램 채팅방에서 /help라고 쳐보자.

python3 main.py

image


봇 명령어 등록해보기

위에서 작성했던 /help 라고하는 핸들러를 텔레그램 채팅방에서 명령어로 등록해보자.


1. 봇 채팅창 상단 제목을 클릭하여 봇 관리를 클릭하자.
image


2. 그리고 명령어 수정을 클릭하면 BotFather 채팅방으로 이동하게 된다.
image


3. BotFather 채팅방에서 추가할 명령과 명령에 대한 설명을 등록해보자.
image


4. 이제 이전에 만든 봇 채팅방으로 이동해 /help 명령을 쳐보자.
image
정상적으로 명령어가 등록 되었다.


여러 유형의 메시지를 보내는 방법

텍스트 전송하기

텍스트를 전송할 때에는 send_message 메소드를 사용하면 된다.

import telegram
import asyncio

TELEGRAM_TOKEN :str = "텔레그램 봇 토큰"
TELEGRAM_CHAT_ID :int = "텔레그램 채팅 ID"

async def main() -> None:
    bot = telegram.Bot(token=TELEGRAM_TOKEN)
    message :str = "안녕하세요!"
    await bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=message)
asyncio.run(main())

$ python3 main.py

image


이미지 전송하기

이미지를 전송할 때에는 텍스트를 전송했을 때와 비슷하게 send_photo 메소드를 사용하면 된다.

import telegram
import asyncio

TELEGRAM_TOKEN :str = "텔레그램 봇 토큰"
TELEGRAM_CHAT_ID :int = "텔레그램 채팅 ID"

async def main() -> None:
    bot = telegram.Bot(token=TELEGRAM_TOKEN)
    
    image_file_name :str = 'test.png'
    with open(image_file_name, 'rb') as fp:
        await bot.send_photo(chat_id=TELEGRAM_CHAT_ID, photo=fp)

asyncio.run(main())

$ python3 main.py

image


HTML 파일 전송하기

HTML 파일을 전송할 때에는 sendDocuemnt 메소드를 사용해보자.

import telegram
import asyncio

TELEGRAM_TOKEN :str = "텔레그램 봇 토큰"
TELEGRAM_CHAT_ID :int = "텔레그램 채팅 ID"

async def main() -> None:
    bot = telegram.Bot(token=TELEGRAM_TOKEN)
    
    html_file :str = 'test.html'
    await bot.sendDocument(chat_id=TELEGRAM_CHAT_ID, document=html_file)

asyncio.run(main())

$ python3 main.py

image


주기적으로 텍스트 전송하기

특정 메시지를 3초 간격마다 보내려면 아래와 같이 작성한다.

add_job 함수에는 seconds 말고 minutes, hours 등의 인자로도 변경할 수 있다.

from telegram.ext import ApplicationBuilder
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from telegram import Bot
import asyncio
import pytz

TELEGRAM_TOKEN :str = "텔레그램 봇 토큰"
TELEGRAM_CHAT_ID :int = "텔레그램 채팅 ID"

# 애플리케이션 빌더 생성
application = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
scheduler = AsyncIOScheduler(timezone=pytz.UTC)  # 타임존 설정

# 메시지를 보내는 함수
async def send_message(text: str) -> None:
    await application.bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=text)

# 봇 초기화 함수
async def initialize() -> None:
    await application.initialize()
    await application.start()
    await application.updater.start_polling()

# 봇 정지 함수
async def stop() -> None:
    await application.updater.stop()

# 메인 함수
async def main() -> None:
    await initialize()
    await send_message(text='안녕하세요!')

    # 스케줄러에 작업 추가 (args를 튜플로 수정)
    scheduler.add_job(send_message, trigger='interval', seconds=3, args=('안녕하세요!',))
    scheduler.start()
    
    try:
        await asyncio.Event().wait()  # 무한 대기
    except (KeyboardInterrupt, SystemExit):
        print("프로그램 종료!")
    finally:
        await application.updater.stop()

# 이벤트 루프 실행
if __name__ == '__main__':
    asyncio.run(main())

$ python main.py

실행하면 3초 간격으로 메시지가 전송된다.
image


Loading script...