virtual-insanity
← 리포트 목록

Telegram 공통 dedup 유틸 적용 — TOP3

2026-04-24 dedup [telegram, dedup, hermes, pipeline]

결론

Hermes 파이프라인 TOP3 위험 파일에 발송 전 24시간 텍스트 hash 기반 중복 방지 가드를 적용했다.

  • 공통 유틸: /Users/ron/.hermes/workspace/scripts/shared/dedup.py
  • 요청 경로 호환 사본: /Users/ron/.hermes/workspace/shared/dedup.py
  • 저장소: /Users/ron/.hermes/workspace/memory/telegram_send_hashes.json ({}로 최초 생성)
  • 적용 대상: channel_collector.py, bond_morning_quiz.py, blog_monitor.py

구현 내용

1. shared.dedup 신규 유틸

인터페이스:

def should_skip(text: str, chat_id: int, topic_id: int = 0, window_hours: int = 24) -> bool
def record_sent(text: str, chat_id: int, topic_id: int = 0) -> None

동작: - 메시지 본문을 SHA-256 hash로 저장 - dedup key = chat_id + topic_id + hash - 기본 24시간 내 동일 hash면 should_skip=True - fcntl 파일락 + atomic replace로 동시 쓰기 방어 - ledger는 7일 초과 항목을 자동 정리 - 테스트용으로 TELEGRAM_SEND_HASHES_FILE env override 지원

TOP3 적용 전후 요약

파일 변경 전 변경 후
channel_collector.py send_sector("ideas", ...) 직접 호출 _send_sector_dedup() 경유. 채널 리포트 및 수집 요약 발송 전 중복 체크
bond_morning_quiz.py send_dm()가 바로 telegram_send.py 실행 send_dm() 내부에서 should_skip() 후 성공 시 record_sent()
blog_monitor.py 블로그 인사이트별 send_sector("ideas", text) 직접 호출 notify_telegram()에서 _send_sector_dedup() 경유

백업: - channel_collector.py.bak-dedup-20260424 - bond_morning_quiz.py.bak-dedup-20260424 - blog_monitor.py.bak-dedup-20260424

검증 결과

dedup 유닛 테스트

명령:

TELEGRAM_SEND_HASHES_FILE=/tmp/dedup_test_260424.json \
PYTHONPATH=/Users/ron/.hermes/workspace/scripts \
/usr/bin/python3 - <<'PY'
from shared.dedup import should_skip, record_sent
print('first', should_skip('hello dedup', 123, 456))
record_sent('hello dedup', 123, 456)
print('second', should_skip('hello dedup', 123, 456))
PY

결과:

first False
second True

컴파일 검증

/usr/bin/python3 -m py_compile \
  /Users/ron/.hermes/workspace/scripts/shared/dedup.py \
  /Users/ron/.hermes/workspace/shared/dedup.py \
  /Users/ron/.hermes/workspace/scripts/pipeline/channel_collector.py \
  /Users/ron/.hermes/workspace/scripts/pipeline/bond_morning_quiz.py \
  /Users/ron/.hermes/workspace/scripts/pipeline/blog_monitor.py

결과: 통과.

import 검증

channel_collector import_ok
bond_morning_quiz import_ok
blog_monitor import_ok

남은 리스크

  • shared.telegram.py 내부 1시간 dedup과 이번 24시간 dedup이 중첩된다. 의도된 방어 중첩이며, 이번 TOP3에서는 외부 24시간 ledger가 더 강하게 동작한다.
  • 107개 전체 중 TOP3만 적용했다. 나머지 파이프라인은 후속 일괄 패치가 필요하다.

자체평가

  • 정확성: 4.5/5 — 요청 인터페이스와 TOP3 적용 완료.
  • 완성도: 4.3/5 — 경로 호환을 위해 scripts/shared와 요청 경로 양쪽에 배치.
  • 검증: 4.5/5 — 유닛 테스트, py_compile, import 검증 통과.
  • 최소 변경: 4.4/5 — send 시그니처 변경 없이 호출 직전 wrapper만 추가.

종합: 4.4/5

후속 미세수정

sector config 조회 실패 시 dedup key가 (0,0)으로 뭉치지 않도록 telegram_shared.NOTIFICATION_CENTER_ID를 fallback chat_id로 사용하게 보정했다. 이후 channel_collector.py, blog_monitor.py 재컴파일 및 import 검증 통과.