"""
AlphaPulse Bot — Utility Functions
"""
import re
import hashlib
import logging
from datetime import datetime
from zoneinfo import ZoneInfo
from config import BASE_HASHTAGS, TOPIC_TAGS, KNOWN_TICKERS, NEWS_TYPE_SIGNALS
logger = logging.getLogger(__name__)
VANCOUVER = ZoneInfo('America/Vancouver')
def now_van() -> datetime:
"""Current Vancouver time (PST/PDT auto)."""
return datetime.now(VANCOUVER)
def stable_id(source: str, url: str) -> str:
"""MD5-based ID — stable across Python restarts."""
return hashlib.md5(f"{source}:{url}".encode()).hexdigest()
def build_hashtags(title: str = '', source: str = '') -> str:
"""Build dynamic hashtags from news title + base set.
Extracts $TICKERs and appends topic tags based on keywords.
"""
text_lower = (title + ' ' + source).lower()
tags = set(BASE_HASHTAGS.split())
# Extract known tickers mentioned in title
words = re.findall(r'\b([A-Za-z]{2,6})\b', title)
for w in words:
if w.lower() in KNOWN_TICKERS:
tags.add(f'${w.upper()}')
# Add topic-based tags
for keyword, tag in TOPIC_TAGS.items():
if keyword in text_lower:
tags.add(tag)
return ' '.join(sorted(tags, key=lambda t: (not t.startswith('#crypto'), t)))
def detect_news_format(title: str) -> str | None:
"""Auto-detect best AI format from news title keywords.
Returns format name or None (-> use weighted random).
"""
title_lower = title.lower()
for fmt, keywords in NEWS_TYPE_SIGNALS.items():
if any(kw in title_lower for kw in keywords):
return fmt
return None