#!/usr/bin/env python3
# collect_news.py (2026-07-15 전면개편) — 수집은 넓게, 필터는 alert.py가.
import feedparser, json, os, html, urllib.parse
from datetime import datetime, timezone

BASE  = os.path.expanduser("~/Claude/Projects/에이전트구축")
JSONL = os.path.join(BASE, "media_feed.jsonl")

TECH_FEEDS = [
    "https://www.eetimes.com/feed/",
    "https://semiengineering.com/feed/",
    "https://spectrum.ieee.org/rss/fulltext",
    "https://www.tomshardware.com/feeds/all",
    "https://tradingeconomics.com/rss/news.aspx",
]

def gnews(q, lang="en-US", geo="US"):
    ceid = f"{geo}:{lang.split('-')[0]}"
    return "https://news.google.com/rss/search?q=" + urllib.parse.quote(q) \
           + f"&hl={lang}&gl={geo}&ceid={ceid}"

# 축1~2 유니버스 (룰24)
FIN_EN = [
    "SK Hynix", "Samsung Electronics chip", "Micron memory", "SanDisk SNDK",
    "Nvidia stock", "Broadcom AI", "Marvell AI infrastructure",
    "Lumentum Coherent optical",
    "Corning optical fiber earnings",
    "Ciena networking earnings", "Applied Optoelectronics AAOI",
    "AXT Inc AXTI indium phosphide substrate",
    "AXTI earnings results",
    "Nebius contract deal",
    "CoreWeave contract backlog",
    "IREN AI cloud contract",
    "neocloud GPU pricing margin",
    "Meta Compute capacity resale", "Meta Platforms AI earnings",
    "semiconductor stocks", "Nasdaq chip stocks",

    # 장비 — 7/15 LRCX -5.83% 미포착이 계기. 쿼리 자체가 없었음
    "Lam Research earnings",
    "ASML Applied Materials KLA wafer fab equipment",
    "Teradyne Astera Labs earnings",
    "Aehr Test Systems burn-in",

    # 축3 수요측 — 반도체를 사는 쪽. IBM/JPM 놓친 게 계기
    "AI capex guidance hyperscaler",
    "hyperscaler capex gigawatt buildout announcement",
    "Meta Microsoft Google Amazon data center investment billion",
    "AI token cost inference spending",
    "IBM enterprise IT spending hardware",
    "ServiceNow Accenture Salesforce results",
    "JPMorgan bank AI spending",

    # 축6 기술 로드맵
    "Nvidia Rubin delay production",
    "HBM4 pricing supply",
    "HBF high bandwidth flash",
    "CXMT YMTC China DRAM NAND",
    "CoWoS interposer capacity",
    "co-packaged optics silicon photonics CPO",
    "KV cache inference memory efficiency",

    # 구글/Gemini — 7/16 Gemini 3.5 지연 미포착이 계기
    "Google Gemini model release delay",
    "Alphabet Google AI capex TPU",
    "Gemini model benchmark frontier",

    # 룰29 논지 검증
    "memory long-term agreement pricing DRAM spot price",

    # 텔레그램 우회 채널 2개 (alert.py가 1차소스만 통과시킴)
    "Iran Hormuz strait",
    "Trump tariff semiconductor export controls",
]

# 한국 매체는 메모리 논지·실적 검증용만. 정책/수급 쿼리는 2026-07-15 폐기(나스닥 집중).
FIN_KR = [
    "해외 거래소 규제 금감원",
    "가상자산 거래소 무허가 차단",
    "레버리지 ETF 규제 금융위",

    "SK하이닉스 실적 컨콜 HBM",
    "삼성전자 반도체 실적 전망",
    "HBM 가격 전망",
    "메모리 반도체 수출 단가",
]

FEEDS = list(TECH_FEEDS) + [gnews(q) for q in FIN_EN] \
        + [gnews(q, "ko-KR", "KR") for q in FIN_KR]

def domain(link):
    try: return urllib.parse.urlparse(link).netloc.replace("www.", "")
    except Exception: return ""

def fetch():
    items = []
    for url in FEEDS:
        try:
            d = feedparser.parse(url)
            for e in d.entries[:8]:
                link = e.get("link", "")
                if not link: continue
                src = e.source.title if (e.get("source") and e.source.get("title")) else domain(link)
                items.append({"url": link,
                    "text": html.unescape(e.get("title", "")).strip(),
                    "pub": e.get("published", e.get("updated", "")),
                    "source": src,
                    "ts": datetime.now(timezone.utc).isoformat()})
        except Exception as ex:
            print("feed error:", url, ex)
    return items

def load_seen():
    seen = set()
    if os.path.exists(JSONL):
        with open(JSONL, encoding="utf-8") as f:
            for line in f:
                try: seen.add(json.loads(line)["url"])
                except Exception: pass
    return seen

def save(items):
    seen = load_seen()
    new = [it for it in items if it["url"] and it["url"] not in seen]
    with open(JSONL, "a", encoding="utf-8") as f:
        for it in new:
            f.write(json.dumps(it, ensure_ascii=False) + "\n")
    return new

if __name__ == "__main__":
    os.makedirs(BASE, exist_ok=True)
    new = save(fetch())
    print(f"collected {len(new)} new items")
