텔레그램 챗봇 이미지
이전 포스팅에서 파이썬에서 python-telegram-bot 라이브러리를 이용하여 텔레그램 챗봇을 만들어보고 채팅방에서 메시지를 주고받는 방법에 대해 소개해 드렸는데요. 이 python-telegram-bot 라이브러리가 13 버전에서 20 버전으로 업데이트되면서 사용방법이 많이 바뀌게 되었습니다.
메시지 전송뿐만 아니라 이미지나 음성 파일 같은 멀티미디어 파일 전송방법이 약간 달라졌는데요. 이번 포스팅에서는 최신 버전의 python-telegram-bot 라이브러리를 사용하면서 이미지 파일을 주고받는 방법에 대해 자세히 알아보도록 하겠습니다.
준비물
텔레그램 챗봇 생성이 필요하며, 해당 챗봇의 Token 값을 알아내야 합니다. 지난 포스팅에서 봇 생성관련하여 포스팅을 하였으니, 준비가 되지 않으신 분들은 이 링크를 통해 챗봇 생성과 Token 값을 알아내신 뒤 다음과정들을 진행하시면 되겠습니다.
코드 복사 방법
우클릭 방지가 적용되어 있어서 코드 복사가 어려우실 것 같습니다. 코드 블록 우측아이콘 중 세 번째 아이콘을 클릭하시면 새창에서 코드가 표시되는데요. 이 창에서 코드를 복사하셔서 활용하시면 되겠습니다.
[목차]
라이브러리 import 및 사용할 변수 설정
이번에도 python-telegram-bot 라이브러리를 사용할 예정입니다. 라이브러리를 import 하고 변수에 토근값을 저장합니다.
from telegram import Update from telegram.ext import filters, ApplicationBuilder, ContextTypes, MessageHandler # 토큰을 bot_token 변수에 저장 bot_token = '토큰을 여기에 입력합니다'
telegram에서 Update를, telegram.ext에서 filters, ApplicationBuilder, ContextTypes, MessageHandler를 import 해 줍니다.
이미지 전송 기능 구현하기
이번에는 이미지 전송 기능을 구현해 보겠습니다. 채팅방에서 사용자가 채팅을 하면, 저장되어 있는 이미지를 전송하는 코드입니다.
# 이미지 전송 함수 async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE): # 이미지 경로 image_path = "image.jpg" # 이미지 파일을 읽어 들여 채팅방으로 전송 with open(image_path, "rb") as image_file: await context.bot.send_photo(chat_id=update.effective_chat.id, photo=image_file, caption="서버에서 보낸 이미지 파일입니다.")
이미지 경로에 저장되어 있는 이미지를 open으로 파일을 읽어 들여 채팅방에 전송하는 방식인데요. send_photo 함수를 사용하면 이미지를 보내실 수 있습니다. caption에 문자열을 넣으시면, 어떤 이미지인지 간단하게 캡션을 적어서 보낼 수 있습니다.
메인함수 작성
메인함수는 기존에 메시지 처리 방법에서 작성했던 함수와 동일하게 작성하면 됩니다.
if __name__ == '__main__': # 챗봇 application 인스턴스 생성 application = ApplicationBuilder().token(bot_token).build() # 핸들러 생성 msg_handler = MessageHandler(filters.TEXT & (~filters.COMMAND), msg) # 핸들러 추가 application.add_handler(msg_handler) # 폴링 방식으로 실행 application.run_polling()
application 인스턴스를 생성하고 핸들러를 생성하고 추가하신 뒤 폴링 방식으로 채팅방에 사용자가 입력한 메시지를 받아들이게 작성하면 됩니다.
전체코드
아래는 텔레그램 챗봇의 채팅방에서 사용자가 아무 메시지를 입력하면 저장되어 있던 이미지 파일을 전송하는 코드입니다.
from telegram import Update from telegram.ext import filters, ApplicationBuilder, ContextTypes, MessageHandler # 토큰을 bot_token 변수에 저장 bot_token = '토큰을 여기에 입력합니다' # 이미지 전송 함수 async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE): # 이미지 경로 image_path = "image.jpg" # 이미지 파일을 읽어 들여 채팅방으로 전송 with open(image_path, "rb") as image_file: await context.bot.send_photo(chat_id=update.effective_chat.id, photo=image_file, caption="서버에서 보낸 이미지 파일입니다.") if __name__ == '__main__': # 챗봇 application 인스턴스 생성 application = ApplicationBuilder().token(bot_token).build() # 핸들러 생성 msg_handler = MessageHandler(filters.TEXT & (~filters.COMMAND), msg) # 핸들러 추가 application.add_handler(msg_handler) # 폴링 방식으로 실행 application.run_polling()
위 코드를 실행하고 채팅방에 메시지를 입력해 보았는데요. 아래 사진과 같이 의도한 대로 이미지가 잘 전송된 것을 확인할 수 있었습니다.
이미지 수신 방법
이번에는 반대로 챗봇 채팅방으로 사용자가 보낸 이미지를 저장해 보는 방법을 알아보도록 하겠습니다. 먼저, 이미지를 수신하는 기능의 함수를 하나 작성해 줍니다.
# 이미지 수신 함수 async def receive_img(update: Update, context: ContextTypes.DEFAULT_TYPE): # 채팅방의 이미지를 가져옴 file = await context.bot.get_file(update.message.photo[-1].file_id) # 가져온 이미지를 파일로 저장 await file.download_to_drive(f"image_{update.message.message_id}.jpg") # bytearray 형태로도 저장 가능 img_array = await file.download_as_bytearray()
get_file 함수를 사용하면 채팅방의 파일을 가져올 수 있는데요. update.message.photo[-1].file_id를 이용하여 채팅방에 보내진 이미지 파일의 아이디를 가져옵니다. 여기서 ‘-1’은 가장 최근 보내진 이미지를 가져온다는 의미입니다.
이미지를 파일로 저장하는 방법은 download_to_drive 함수를 이용해서 경로를 지정해 주면, 해당경로에 이미지가 저장됩니다. 추가적으로, download_as_bytearray 함수를 사용하시면 이미지를 따로 파일로 저장하지 않고 bytearray로 저장하여 활용하실 수도 있습니다.
다음은 메인함수를 조금 수정해야 하는데요. 기존에는 MessageHandler를 이용하여 텍스트를 가져오는 핸들러를 생성하여 메시지를 처리했었습니다. 이번에는 이미지 파일을 가져오는 핸들러를 하나 생성하고 추가해 주시면 됩니다.
if __name__ == '__main__': # 챗봇 application 인스턴스 생성 application = ApplicationBuilder().token(bot_token).build() # 핸들러 생성 msg_handler = MessageHandler(filters.TEXT & (~filters.COMMAND), msg) # 핸들러 추가 application.add_handler(msg_handler) # 이미지 핸들러 생성 img_handler = MessageHandler(filters.PHOTO & (~filters.COMMAND), receive_img) # 이미지 핸들러 추가 application.add_handler(img_handler) # 폴링 방식으로 실행 application.run_polling()
이렇게 기존 코드에 이미지 핸들러를 추가해 주시면 되는데요. MessageHandler의 필터를 PHOTO로 설정하시면 이미지 파일만 체크하는 핸들러를 만드실 수 있습니다.
이미지 파일이 감지되면 조금 전에 만들었던 이미지 수신 함수(receive_img)가 실행될 수 있도록 MessageHandler에 전달해 주시면 됩니다.
이미지 수신 추가 전체코드
이렇게 이미지 수신 기능을 추가하면 아래와 같이 전체코드가 작성이 되겠습니다.
from telegram import Update from telegram.ext import filters, ApplicationBuilder, ContextTypes, MessageHandler # 토큰을 bot_token 변수에 저장 bot_token = '토큰을 여기에 입력합니다' # 이미지 전송 함수 async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE): # 이미지 경로 image_path = "image.jpg" # 이미지 파일을 읽어 들여 채팅방으로 전송 with open(image_path, "rb") as image_file: await context.bot.send_photo(chat_id=update.effective_chat.id, photo=image_file, caption="서버에서 보낸 이미지 파일입니다.") # 이미지 수신 함수 async def receive_img(update: Update, context: ContextTypes.DEFAULT_TYPE): # 채팅방의 이미지를 가져옴 file = await context.bot.get_file(update.message.photo[-1].file_id) # 가져온 이미지를 파일로 저장 await file.download_to_drive(f"image_{update.message.message_id}.jpg") # bytearray 형태로도 저장 가능 img_array = await file.download_as_bytearray() if __name__ == '__main__': # 챗봇 application 인스턴스 생성 application = ApplicationBuilder().token(bot_token).build() # 핸들러 생성 msg_handler = MessageHandler(filters.TEXT & (~filters.COMMAND), msg) # 핸들러 추가 application.add_handler(msg_handler) # 이미지 핸들러 생성 img_handler = MessageHandler(filters.PHOTO & (~filters.COMMAND), receive_img) # 이미지 핸들러 추가 application.add_handler(img_handler) # 폴링 방식으로 실행 application.run_polling()
코드를 실행한 뒤에 채팅방에 사진을 전송해 보았습니다.
이미지 다운로드 경로에 들어가 보니 이미지가 지정한 경로에 잘 저장된 것을 확인할 수 있었습니다.
마무리
지금까지 python-telegram-bot 라이브러리를 활용하여 챗봇 채팅방에서 이미지를 주고받는 방법에 대해 알아보았는데요. 라이브러리 사용방법이 많이 바뀌어서 텔레그램 챗봇에서 이미지를 활용이 어려우셨던 분들께 도움이 되었으면 좋겠습니다.
이번 포스팅은 여기서 마무리하도록 하겠습니다.
감사합니다!