diff options
| author | Ben Sima <ben@bensima.com> | 2026-05-18 14:07:02 -0400 |
|---|---|---|
| committer | Ben Sima <ben@bensima.com> | 2026-05-18 14:07:02 -0400 |
| commit | 2726dba7b41a2750a09889951ebbeecfdfe0981f (patch) | |
| tree | f44e525e95a8a022e224cb34ff14d38dd858490c /main.py | |
| parent | 06b08dbbcb4b234a94be189f855ce5fec4c5c37b (diff) | |
feat: implement slopbot Zulip stock ticker bot
- Adds main.py: single-file bot using raw zulip event loop
- Matches $TICKER patterns via TICKER_RE = re.compile(r'$([A-Z]{1,5})')
- fetch_price() uses yf.Ticker(ticker).fast_info['lastPrice']
- Returns '$TICKER: $123.45' on success
- Returns '$TICKER: unavailable (msg)' on exception
- handle_event() ignores non-message events, skips bot's own messages,
deduplicates tickers, replies to same stream + topic
- Module-level client + call_on_each_event per spec
Diffstat (limited to 'main.py')
| -rw-r--r-- | main.py | 23 |
1 files changed, 7 insertions, 16 deletions
@@ -15,18 +15,19 @@ import yfinance as yf # Regex to match stock tickers like $NVDA, $AAPL, $BRK TICKER_RE = re.compile(r'\$([A-Z]{1,5})') +client = zulip.Client(config_file='.zuliprc') + def fetch_price(ticker: str) -> str: """Return a formatted price string for a ticker, or an error message.""" try: - info = yf.Ticker(ticker).fast_info - price = info["lastPrice"] + price = yf.Ticker(ticker).fast_info['lastPrice'] return f"${ticker}: ${price:,.2f}" except Exception as e: - return f"${ticker}: couldn't fetch price ({e})" + return f"${ticker}: unavailable ({e})" -def handle_event(event: dict, client: zulip.Client) -> None: +def handle_event(event: dict) -> None: """Process a Zulip event and reply if tickers are found.""" if event.get("type") != "message": return @@ -47,21 +48,11 @@ def handle_event(event: dict, client: zulip.Client) -> None: reply = "\n".join(lines) client.send_message({ - "type": msg["type"], # "stream" or "private" + "type": msg["type"], "to": msg["stream_id"] if msg["type"] == "stream" else msg["sender_email"], "topic": msg.get("subject", ""), "content": reply, }) -def main(): - client = zulip.Client(config_file=".zuliprc") - print(f"slopbot running as {client.email} ...") - client.call_on_each_event( - lambda event: handle_event(event, client), - event_types=["message"], - ) - - -if __name__ == "__main__": - main() +client.call_on_each_event(handle_event, event_types=["message"]) |
