summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bensima.com>2026-05-18 14:07:02 -0400
committerBen Sima <ben@bensima.com>2026-05-18 14:07:02 -0400
commit2726dba7b41a2750a09889951ebbeecfdfe0981f (patch)
treef44e525e95a8a022e224cb34ff14d38dd858490c
parent06b08dbbcb4b234a94be189f855ce5fec4c5c37b (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
-rw-r--r--main.py23
1 files changed, 7 insertions, 16 deletions
diff --git a/main.py b/main.py
index 8fe9d24..ae862a3 100644
--- a/main.py
+++ b/main.py
@@ -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"])