테스트 강화 및 코드 품질 개선
This commit is contained in:
@@ -4,6 +4,11 @@ import time
|
||||
import requests
|
||||
|
||||
from .common import logger
|
||||
from .constants import (
|
||||
TELEGRAM_MAX_MESSAGE_LENGTH,
|
||||
TELEGRAM_RATE_LIMIT_DELAY,
|
||||
TELEGRAM_REQUEST_TIMEOUT,
|
||||
)
|
||||
|
||||
__all__ = ["send_telegram", "send_telegram_with_retry", "report_error", "send_startup_test_message"]
|
||||
|
||||
@@ -51,10 +56,29 @@ def send_telegram_with_retry(
|
||||
return False
|
||||
|
||||
|
||||
def send_telegram(token: str, chat_id: str, text: str, add_thread_prefix: bool = True, parse_mode: str = None):
|
||||
def send_telegram(
|
||||
token: str,
|
||||
chat_id: str,
|
||||
text: str,
|
||||
add_thread_prefix: bool = True,
|
||||
parse_mode: str = None,
|
||||
max_length: int = TELEGRAM_MAX_MESSAGE_LENGTH,
|
||||
):
|
||||
"""
|
||||
텔레그램 메시지를 한 번 전송합니다. 실패 시 예외를 발생시킵니다.
|
||||
WARNING: 이 함수는 예외 처리가 없으므로, 프로덕션에서는 send_telegram_with_retry() 사용 권장
|
||||
텔레그램 메시지를 전송합니다 (자동 분할 지원).
|
||||
|
||||
Args:
|
||||
token: 텔레그램 봇 토큰
|
||||
chat_id: 채팅 ID
|
||||
text: 메시지 내용
|
||||
add_thread_prefix: 스레드 이름 prefix 추가 여부
|
||||
parse_mode: HTML/Markdown 파싱 모드
|
||||
max_length: 최대 메시지 길이 (Telegram 제한 4096자, 안전하게 4000자)
|
||||
|
||||
Note:
|
||||
- 메시지가 max_length를 초과하면 자동으로 분할하여 전송합니다.
|
||||
- 실패 시 예외를 발생시킵니다.
|
||||
- 프로덕션에서는 send_telegram_with_retry() 사용 권장
|
||||
"""
|
||||
if add_thread_prefix:
|
||||
thread_name = threading.current_thread().name
|
||||
@@ -67,23 +91,56 @@ def send_telegram(token: str, chat_id: str, text: str, add_thread_prefix: bool =
|
||||
payload_text = text
|
||||
|
||||
url = f"https://api.telegram.org/bot{token}/sendMessage"
|
||||
payload = {"chat_id": chat_id, "text": payload_text}
|
||||
if parse_mode:
|
||||
payload["parse_mode"] = parse_mode
|
||||
|
||||
try:
|
||||
# ⚠️ 타임아웃 증가 (20초): SSL handshake 느림 대비
|
||||
resp = requests.post(url, json=payload, timeout=20)
|
||||
resp.raise_for_status() # 2xx 상태 코드가 아니면 HTTPError 발생
|
||||
logger.debug("텔레그램 메시지 전송 성공: %s", text[:80])
|
||||
# ✅ 메시지 길이 확인 및 분할
|
||||
if len(payload_text) <= max_length:
|
||||
# 단일 메시지 전송
|
||||
payload = {"chat_id": chat_id, "text": payload_text}
|
||||
if parse_mode:
|
||||
payload["parse_mode"] = parse_mode
|
||||
|
||||
try:
|
||||
resp = requests.post(url, json=payload, timeout=TELEGRAM_REQUEST_TIMEOUT)
|
||||
resp.raise_for_status()
|
||||
logger.debug("텔레그램 메시지 전송 성공: %s", payload_text[:80])
|
||||
return True
|
||||
except requests.exceptions.Timeout as e:
|
||||
logger.warning("텔레그램 타임아웃: %s", e)
|
||||
raise
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
logger.warning("텔레그램 연결 오류: %s", e)
|
||||
raise
|
||||
except requests.exceptions.HTTPError as e:
|
||||
logger.warning("텔레그램 HTTP 오류: %s", e)
|
||||
raise
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.warning("텔레그램 API 요청 실패: %s", e)
|
||||
raise
|
||||
else:
|
||||
# ✅ 메시지 분할 전송
|
||||
chunks = [payload_text[i : i + max_length] for i in range(0, len(payload_text), max_length)]
|
||||
logger.info("텔레그램 메시지 길이 초과 (%d자), %d개로 분할 전송", len(payload_text), len(chunks))
|
||||
|
||||
for i, chunk in enumerate(chunks, 1):
|
||||
header = f"[메시지 {i}/{len(chunks)}]\n" if len(chunks) > 1 else ""
|
||||
payload = {"chat_id": chat_id, "text": header + chunk}
|
||||
if parse_mode:
|
||||
payload["parse_mode"] = parse_mode
|
||||
|
||||
try:
|
||||
resp = requests.post(url, json=payload, timeout=TELEGRAM_REQUEST_TIMEOUT)
|
||||
resp.raise_for_status()
|
||||
logger.debug("텔레그램 분할 메시지 전송 성공 (%d/%d)", i, len(chunks))
|
||||
|
||||
# Rate Limit 방지
|
||||
if i < len(chunks):
|
||||
time.sleep(TELEGRAM_RATE_LIMIT_DELAY)
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error("텔레그램 분할 메시지 전송 실패 (%d/%d): %s", i, len(chunks), e)
|
||||
raise
|
||||
|
||||
return True
|
||||
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
||||
# 네트워크 오류: 로깅하고 예외 발생
|
||||
logger.warning("텔레그램 네트워크 오류 (타임아웃/연결): %s", e)
|
||||
raise
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.warning("텔레그램 API 요청 실패: %s", e)
|
||||
raise # 예외를 다시 발생시켜 호출자가 처리하도록 함
|
||||
|
||||
|
||||
def report_error(bot_token: str, chat_id: str, message: str, dry_run: bool):
|
||||
|
||||
Reference in New Issue
Block a user