From 9b19c12a53ba7fd24e77d3cb1ed024066881c434 Mon Sep 17 00:00:00 2001 From: Mike Lang Date: Thu, 3 Oct 2024 02:38:06 +1000 Subject: [PATCH] Add pubnub-watching zulip bot Which also records all pubnub messages for archival to a file SEGMENTS/pubnub-log.json. We ran this for most of last year, but not as part of wubloader. --- docker-compose.jsonnet | 17 ++++- zulip_bots/zulip_bots/pubbot.py | 107 ++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 zulip_bots/zulip_bots/pubbot.py diff --git a/docker-compose.jsonnet b/docker-compose.jsonnet index 98b836f..ea9406f 100644 --- a/docker-compose.jsonnet +++ b/docker-compose.jsonnet @@ -31,6 +31,7 @@ schedulebot: false, tootbot: false, twitchbot: false, + pubbot: false, bus_analyzer: false, graphs: false, }, @@ -297,6 +298,11 @@ args:: [], }, + pubbot:: { + zulip_email: "blog-bot@chat.videostrike.team", + zulip_api_key: "", + }, + // template for donation data urls donation_url_template:: "https://example.com/DB{}/DB{}.json", @@ -659,7 +665,7 @@ environment: $.env, }, - local bot_service(name, config, args, subcommand=null) = { + local bot_service(name, config, args=[], subcommand=null) = { image: $.get_image("zulip_bots"), restart: "always", entrypoint: ["python3", "-m", "zulip_bots.%s" % name] @@ -686,7 +692,14 @@ [if $.enabled.twitchbot then "twitchbot"]: bot_service("twitchbot", $.twitchbot + { zulip_url: $.zulip_url, - }, $.tootbot.args), + }), + + [if $.enabled.pubbot then "pubbot"]: + bot_service("pubbot", $.pubbot + { + zulip_url: $.zulip_url, + }, ["/mnt/pubnub-log.json"]) + { + volumes: ["%s:/mnt" % $.segments_path], + }, }, diff --git a/zulip_bots/zulip_bots/pubbot.py b/zulip_bots/zulip_bots/pubbot.py new file mode 100644 index 0000000..6a1a696 --- /dev/null +++ b/zulip_bots/zulip_bots/pubbot.py @@ -0,0 +1,107 @@ + +import json +import logging +import time + +from .config import get_config +from .zulip import Client + +import requests +session = requests.Session() + +def stream(): + tt = 0 + tr = 0 + while True: + resp = session.get("https://ps8.pndsn.com/v2/subscribe/sub-cbd7f5f5-1d3f-11e2-ac11-877a976e347c/db_total%2Cdb_vue/0", + params={ + "tt": tt, + "tr": tr, + }, + ) + resp.raise_for_status() + data = resp.json() + for msg in data.get("m", []): + yield msg + tt = data["t"]["t"] + tr = data["t"]["r"] + + +def get_prize(prize_id): + resp = session.get("https://desertbus.org/wapi/prize/{}".format(prize_id)) + resp.raise_for_status() + return resp.json()["prize"] + + +giveaway_cache = [None, None] +def get_giveaway(): + REFRESH_RISING = 30 + REFRESH_FALLING = 300 + t, g = giveaway_cache + now = time.time() + timeout = REFRESH_RISING if g is None else REFRESH_FALLING + if t is None or now - t > timeout: + resp = session.get("https://desertbus.org/wapi/currentGiveaway") + resp.raise_for_status() + g = resp.json()["giveaway"] + giveaway_cache[0] = t + giveaway_cache[1] = g + return g + + +def main(conf_file, message_log_file): + """Config: + zulip_url + zulip_email + zulip_api_key + """ + logging.basicConfig(level="INFO") + + config = get_config(conf_file) + client = Client(config["zulip_url"], config["zulip_email"], config["zulip_api_key"]) + message_log = open(message_log_file, "a") + + prizes = {} + total = None + for msg in stream(): + message_log.write(json.dumps(msg) + '\n') + + if msg["c"] == "db_total": + increase = None if total is None else msg["d"] - total + increase_str = "" if increase is None else " (+${:.2f})".format(msg["d"] - total) + giveaway = get_giveaway() + entries_str = "" + if increase is not None and giveaway is not None: + amount = giveaway["amount"] + if (increase + 0.005) % amount < 0.01: + entries = int((increase + 0.005) / amount) + entries_str = " ({} entries of ${:.2f})".format(entries, amount) + logging.info("New donation total: {}{}{}".format(msg["d"], increase_str, entries_str)) + client.send_to_stream("bot-spam", "Donation Firehose", "Donation total is now ${:.2f}{}{}".format(msg["d"], increase_str, entries_str)) + if increase is not None and increase >= 500: + client.send_to_stream("bot-spam", "Notable Donations", "Large donation of ${:.2f} (total ${:.2f}){}".format(increase, msg['d'], entries_str)) + total = msg["d"] + + elif msg["c"] == "db_vue" and msg["d"].get("channel").startswith("prize:"): + d = msg["d"] + prize_id = msg["d"]["channel"].split(":")[1] + data = d["data"] + logging.info(f"Prize update for {prize_id}: {data}") + if prize_id not in prizes: + prizes[prize_id] = get_prize(prize_id) + if "bidder" in data and "bid" in data: + client.send_to_stream("bot-spam", "Bids", "At , {bidder} bid ${bid:.2f} for [{title}](https://desertbus.org/prize/{prize_id})".format( + time = float(msg["p"]["t"]) / 10000000, + bidder = data["bidder"], + bid = data["bid"], + title = prizes[prize_id]["title"], + prize_id = prize_id, + )) + + else: + logging.warning("Unknown message: {}".format(msg)) + + +if __name__ == '__main__': + import argh + argh.dispatch_command(main)