· 톺아보기

PC/모바일

이미지->PDF 변환 텔레그램 봇 만들기

Drimp · · 수정

조회 20,640 · 공감 2 · 댓글 4







LINK

<작동 예시>


Chat GPT-3의 도움으로 만들어 봤습니다.


모바일 텔레그램으로 봇이 있는 채팅방에 이미지 파일들을 보내면 PDF로 합쳐서 다시 보내줍니다.


남들이 만든게 없기도 하고(못 찾았습니다 ㅠㅜ), 보안의 이유도 있어서 직접 만들어봤습니다.

-----------------------------------

    # 합쳐진 PDF 파일 삭제

    merged_pdf.close()

    os.remove(merged_pdf_file)  <- 이 코드가 없으면 텔레그램 봇이 작업한 합쳐진 PDF파일이 작업한 컴퓨터에 남아있게 됩니다. 사용자는 알 수가 없으니 귀중한 정보를 상납하게 되는 꼴...

-----------------------------------



파이썬 설치방법이나 실행방법, 독립 실행파일로 만드는 방법 등은 이미 찾으면 많기 때문에 따로 적지는 않겠습니다.


저는 실행파일 만들어서 안쓰는 컴퓨터에 실행시켜놨어요.


쓸데없는 코드도 있는데, 귀찮아서 정리는 안했습니다.

뭐 키울 프로젝트도 아니고 해서..ㅎㅎ


파이썬은 들여쓰기가 중요하니까 뭐 건들지 마시고 요대로 복사해서 붙여넣기 후 사용하시면 될거에요.

이미지 한 10장까지는 테스트 해봤는데, 그 이상은 안해봤습니다.

애초에 가볍게 쓰기 위한 목적이에요.


써 놓고 보니 이게 팁과 강좌 카테고리가 맞나 고민이네요..?

딱히 강좌랄게 없고 코드만 나열한거라서...


일단 코드는 이렇고 

TOKEN = '123456789:sdSNDFK33jfoeRRjkEKNGORE'

위 부분은 자신의 텔레그램 봇 토큰을 넣는 자리입니다.



import os

import telebot

from fpdf import FPDF

from datetime import datetime

import threading

import time

from PIL import Image

from PyPDF2 import PdfMerger


# 텔레그램 봇 토큰 설정

TOKEN = '123456789:sdSNDFK33jfoeRRjkEKNGORE'


# 텔레그램 봇 인스턴스 생성

bot = telebot.TeleBot(TOKEN)


# 변환된 PDF 파일들을 저장할 리스트

pdf_files = []


# 이미지 처리 중인지 나타내는 플래그

processing_image = False


# PDF 파일을 합치는 동안 사용할 락

merge_lock = threading.Lock()


# 전체 이미지 개수를 저장할 변수

total_image_count = 0


@bot.message_handler(content_types=['photo'])

def handle_photos(message):

    global chatID

    global total_image_count

    chatID = message.chat.id

    # 이미지 파일을 받았을 때 처리하는 함수

    file_id = message.photo[-1].file_id

    file_info = bot.get_file(file_id)

    file_path = file_info.file_path

    total_image_count+=1

    # 이미지 처리 중인 경우 대기

    while not merge_lock.acquire(blocking=False):

        time.sleep(0.5)


    # 이미지 처리 함수 호출

    process_image(message, file_path)


    # Lock 해제

    merge_lock.release()


    # 이미지 처리가 모두 완료된 후 PDF 합치고 보내기

    if not processing_image and len(pdf_files) == total_image_count:

        send_pdf(message)






# 이미지를 받아 처리하는 동작을 수행하는 함수

def process_image(message, file_path):

    global processing_image

    global chatID

    # 이미지 파일을 받았을 때 처리하는 함수

    file_extension = os.path.splitext(file_path)[-1].lower()


    if file_extension in ['.jpg', '.jpeg', '.png']:

        # 이미지 파일을 다운로드하고 PDF로 변환

        downloaded_file = bot.download_file(file_path)


        # 이미지 파일 이름 설정 (타임스탬프 형식)

        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")

        image_file = f"image_{message.id}.jpg"

        pdf_file = f"image_{message.id}.pdf"


        with open(image_file, 'wb') as f:

            f.write(downloaded_file)


        # "처리 중" 메시지 전송

        bot.send_message(message.chat.id, "이미지 처리 중...")


        # 이미지 처리 중 플래그 설정

        processing_image = True


        image = Image.open(image_file)

        image_width, image_height = image.size

    



        pdf = FPDF()

        pdf.add_page()


        # 이미지 크기 조정

        pdf_width = 210  # A4 용지 가로 길이 (mm)

        pdf_height = 297  # A4 용지 세로 길이 (mm)


        image_ratio = image_width / image_height

        pdf_ratio = pdf_width / pdf_height

        # 이미지 크기 조정

        if image_ratio > pdf_ratio:

            # 이미지의 가로 비율이 더 클 경우

            adjusted_width = pdf_width

            adjusted_height = adjusted_width / image_ratio

            y_position = (pdf_height - adjusted_height) / 2  # 세로 가운데 정렬

            pdf.image(image_file, x=0, y=y_position, w=adjusted_width, h=adjusted_height)

        else:

            # 이미지의 세로 비율이 더 클 경우 또는 가로와 세로 비율이 같은 경우

            adjusted_height = pdf_height

            adjusted_width = adjusted_height * image_ratio

            x_position = (pdf_width - adjusted_width) / 2  # 가로 가운데 정렬

            pdf.image(image_file, x=x_position, y=0, w=adjusted_width, h=adjusted_height)


        # PDF 파일 저장

        pdf.output(pdf_file, 'F')


        # 임시 이미지 파일 삭제

        image.close()

        os.remove(image_file)


        # PDF 파일 리스트에 추가

        pdf_files.append(pdf_file)


        # 처리 완료 메시지 전송

        bot.send_message(chatID, "이미지 처리가 완료되었습니다.")


        # 이미지 처리 중 플래그 해제

        processing_image = False



def send_pdf(message):

    global chatID

    # PDF 파일들을 합쳐서 보내는 함수

    

    global total_image_count

    # 전체 PDF 파일 생성

    merged_pdf = PdfMerger()

    #print(pdf_files)

    sorted_pdf_files = sorted(pdf_files)

    #print(sorted_pdf_files)

    for pdf_file in sorted_pdf_files:

        merged_pdf.append(pdf_file)


    # 합쳐진 PDF 파일 저장

    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")

    merged_pdf_file = f'merged_pdf_{timestamp}.pdf'

    merged_pdf.write(merged_pdf_file)


    # 합쳐진 PDF 파일 전송

    with open(merged_pdf_file, 'rb') as f:

        bot.send_document(chatID, f)


    # 합쳐진 PDF 파일 삭제

    merged_pdf.close()

    os.remove(merged_pdf_file)

    cleanup_pdf_files()


    pdf_files.clear()

    

    total_image_count = 0


def cleanup_pdf_files():

    # PDF 파일들을 삭제하는 함수

    for pdf_file in pdf_files:

        os.remove(pdf_file)

    # PDF 파일 리스트 초기화


# 텔레그램 봇 시작

bot.polling()


L


댓글 4

  1. storyofthecourt ·
    귀중한 자료인데 제가 받아들이기에는 어렵군요. 찬찬히 보겠습니다. 항상 이런 프로그램 있었으면 좋겠다고 생각했는데 감사합니다.
  2. Drimp · · 공감 1
    @storyofthecourt님
    1. 파이썬 설치 방법
    2. 코드 에디터 설치 방법 (비주얼 스튜디오 코드)
    3. pip install 명령어로 모듈들 설치하는 방법
    4. 텔레그램 봇 토큰 발행방법
    등등

    필요한 배경지식들을 나열하다보니 준비해야 할게 생각보다 많네요 ㄷㄷ...
    근데 또 하나씩 찾아보다 보면 재미도 있고 금방 합니다 ㅎㅎ
    저처럼 깊이 없이 가볍게 접근하면 뒤돌아서면 잊어버리지만 그래도 이런것도 만들 수 있더라구요.
  3. lacsonluxur ·
    혹시 반대로 pdf 를 jpg 로 변경하는 봇은...ㅎ

    이런건 docker 로 만드는 어려울까요?
  4. Drimp ·
    @MochaLatte님 도커에 대해서는 들어만 보긴 했는데, 파이썬 스크립트 만들고 도커이미지로 만든 다음 실행하면 되는거 아닐까요..?

    PDF를 jpg로 변경하는 스크립트를 만드는게 우선이겠지만요.

    1. 봇한테 PDF를 보낸다
    2. 봇이 PDF의 정보를 읽는다 - 몇 장인지 파악
    3. 파이썬 모듈을 이용해서 파일명을 순차적으로 증가시키면서 PDF 장수만큼 매 페이지마다 A4 크기의 이미지로 뽑아낸다.
    4. zip으로 만들어서 다시 보내던가, 파일명 순차대로 텔레그램으로 다시 보낸다.

    정도 되려나요?

팁과강좌 최근 글

팁과강좌 목록 더 보기