Fix Telegram HTML: URL & escaping, card-level chunk splitting, session scope fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
I Luk Kim 5 months ago
parent 8ff94ad113
commit c4f9d5638b

@ -29,13 +29,12 @@ def build_listing_messages(postings: list["JobPosting"]) -> list[str]:
current = header
for site_id, site_postings in sorted(by_site.items()):
site_block = f"\n<b>── {site_id.upper()} ({len(site_postings)}) ──</b>\n"
site_header = f"\n<b>── {site_id.upper()} ({len(site_postings)}) ──</b>\n"
for p in site_postings:
# Title line
title = _escape_html(p.title)
line = f"• <b>{title}</b>"
# Details line
details = []
if p.company:
details.append(_escape_html(p.company))
@ -46,18 +45,24 @@ def build_listing_messages(postings: list["JobPosting"]) -> list[str]:
if details:
line += f"\n {' | '.join(details)}"
# Link
if p.job_url:
line += f'\n <a href="{p.job_url}">링크</a>'
safe_url = p.job_url.replace("&", "&amp;")
line += f'\n <a href="{safe_url}">링크</a>'
line += "\n"
site_block += line + "\n"
# Add site header before the first card of each site
prefix = site_header if site_header else ""
candidate = current + prefix + line
if len(candidate) > _TELEGRAM_MAX_LEN:
# Flush current chunk and start new one
chunks.append(current.rstrip())
current = prefix + line
else:
current = candidate
# Flush chunk if adding this site would exceed limit
if len(current) + len(site_block) > _TELEGRAM_MAX_LEN:
chunks.append(current.rstrip())
current = site_block
else:
current += site_block
site_header = "" # Only prepend once per site
if current.strip():
chunks.append(current.rstrip())

@ -319,31 +319,26 @@ class RunOrchestrator:
def _summarize_and_notify(self, summary: RunSummary, run_date: date) -> None:
try:
from gimme_job.db.engine import db_session
from gimme_job.db.repo import JobPostingRepo, SummaryRepo
from gimme_job.db.repo import JobPostingRepo
from gimme_job.runtime.notifier import NotificationDispatcher, build_listing_messages
from gimme_job.runtime.telegram import TelegramClient
with db_session() as session:
postings = JobPostingRepo().get_today_new(session, run_date)
if not postings:
return
chunks = build_listing_messages(postings)
if not postings:
return
from gimme_job.runtime.summarizer import OllamaSummarizer
summarizer = OllamaSummarizer(
base_url=self.cfg.summarization.ollama_base_url,
model=self.cfg.summarization.model,
temperature=self.cfg.summarization.temperature,
)
text = summarizer.summarize(postings)
summary.summary_text = text
with db_session() as session:
SummaryRepo().save_summary(session, run_date, text, self.cfg.summarization.model)
client = TelegramClient()
if client.is_configured():
for chunk in chunks:
client.send_message(chunk)
from gimme_job.runtime.notifier import NotificationDispatcher
dispatcher = NotificationDispatcher(
global_config=self.cfg, session_factory=self.session_factory
)
dispatcher.send(text, run_date)
full_text = "\n\n".join(chunks)
dispatcher.send_markdown_fallback(full_text, run_date)
except Exception as e:
logger.error(f"Summarize/notify failed: {e}")

Loading…
Cancel
Save