""" Sopel plugin: jeeves quotes Maintains a shared quote bank with automatic periodic posting. !quote - post a random quote !quote add - add a quote (op/owner) !quote del - delete quote by index (op/owner) !quote list - show total count !quotes - show auto-post state for this channel !quotes on|off - enable/disable auto-posting (op/owner) Auto-post interval is configured via: !set quotes_interval - minutes between auto-posts (default 60) """ import os as _os, sys as _sys _d = _os.path.dirname(_os.path.abspath(__file__)) if _d not in _sys.path: _sys.path.insert(0, _d) import jv_core as jv import random import time from sopel import plugin def setup(bot): jv.ensure_setup(bot) @plugin.command("quote") def cmd_quote(bot, trigger): args = (trigger.group(2) or "").strip().split(None, 1) sub = args[0].lower() if args else "" if sub == "add": if not jv.is_authorized(bot, trigger): return text = args[1].strip() if len(args) > 1 else "" if not text: bot.notice("usage: !quote add ", trigger.nick) return with bot.memory["jv_lock"]: bot.memory["jv_db"].setdefault("quotes", []).append(text) n = len(bot.memory["jv_db"]["quotes"]) jv.save(bot) bot.notice(f"quote #{n} added", trigger.nick) return if sub == "del": if not jv.is_authorized(bot, trigger): return if len(args) < 2: bot.notice("usage: !quote del ", trigger.nick) return try: idx = int(args[1]) - 1 except ValueError: bot.notice("usage: !quote del ", trigger.nick) return with bot.memory["jv_lock"]: quotes = bot.memory["jv_db"].get("quotes", []) if idx < 0 or idx >= len(quotes): bot.notice(f"no quote #{idx + 1}", trigger.nick) return quotes.pop(idx) jv.save(bot) bot.notice(f"quote #{idx + 1} deleted", trigger.nick) return if sub == "list": quotes = bot.memory.get("jv_db", {}).get("quotes", []) count = len(quotes) dest = trigger.sender if str(trigger.sender).startswith("#") else trigger.nick bot.say(f"{count} quote(s) in the bank", dest) return quotes = bot.memory.get("jv_db", {}).get("quotes", []) if not quotes: dest = trigger.sender if str(trigger.sender).startswith("#") else trigger.nick bot.say("no quotes in the bank yet", dest) return dest = trigger.sender if str(trigger.sender).startswith("#") else trigger.nick bot.say(random.choice(quotes), dest) @plugin.command("quotes") def cmd_quotes(bot, trigger): args = (trigger.group(2) or "").strip().split() arg = args[0].lower() if args else "" in_chan = str(trigger.sender).startswith("#") channel = str(trigger.sender) if in_chan else None if arg in ("on", "off"): if not jv.is_authorized(bot, trigger): return if not in_chan: bot.notice("use !quotes on|off in a channel", trigger.nick) return with bot.memory["jv_lock"]: jv.chan_db(bot, channel)["quotes"]["enabled"] = (arg == "on") jv.save(bot) bot.say(f"quote auto-post turned {arg} for {channel}", channel) return if in_chan: ch = jv.chan_db(bot, channel) enabled = ch["quotes"]["enabled"] last = ch["quotes"]["last_broadcast"] interval = jv.cfg_val(bot, "quotes_interval", channel) if last: ago = int(time.time() - last) last_str = f"{ago // 60}m ago" if ago >= 60 else f"{ago}s ago" else: last_str = "never" state = "on" if enabled else "off" count = len(bot.memory.get("jv_db", {}).get("quotes", [])) bot.say( f"quote auto-post: {state} | every {interval} min | {count} quote(s) | last: {last_str}", channel, ) else: bot.notice("usage: !quotes [on|off] (use in a channel)", trigger.nick) @plugin.interval(60) def _quotes_tick(bot): if "jv_db" not in bot.memory: return now = time.time() quotes = bot.memory["jv_db"].get("quotes", []) if not quotes: return for chan_name in list(bot.channels): channel = str(chan_name) ch = jv.chan_db(bot, channel) if not ch["quotes"]["enabled"]: continue interval_sec = jv.cfg_val(bot, "quotes_interval", channel) * 60 if now - ch["quotes"]["last_broadcast"] < interval_sec: continue quote = random.choice(quotes) with bot.memory["jv_lock"]: jv.chan_db(bot, channel)["quotes"]["last_broadcast"] = now jv.save(bot) bot.say(quote, channel)