From 5a8d568931d9b23ce0df1265d05259a7012081c9 Mon Sep 17 00:00:00 2001 From: Ahmed Date: Sun, 14 Jun 2026 01:46:29 +0300 Subject: init: mostly vibed --- alfred/mlmmj.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 alfred/mlmmj.py (limited to 'alfred/mlmmj.py') diff --git a/alfred/mlmmj.py b/alfred/mlmmj.py new file mode 100644 index 0000000..5dfbfc3 --- /dev/null +++ b/alfred/mlmmj.py @@ -0,0 +1,97 @@ +""" +Sopel plugin: mlmmj mailing list management + + !list subscribe - subscribe to list@gumx.cc + !list unsubscribe - unsubscribe + !list members - show all subscribers + !list send - send a message to the list as owner +""" + +import email.utils, glob, os, subprocess, tempfile +from sopel import plugin + +LIST_DIR = "/var/spool/mlmmj/list" +LIST_ADDR = "list@gumx.cc" +OWNER_ADDR = "ahmed@gumx.cc" + + +def _owner(bot, trigger): + return trigger.nick == bot.settings.core.owner + + +@plugin.command("list") +def cmd_list(bot, trigger): + if not _owner(bot, trigger): + return + + args = (trigger.group(2) or "").split(None, 1) + if not args: + bot.say("usage: !list ") + return + + action = args[0] + + if action == "subscribe": + if len(args) < 2: + bot.say("usage: !list subscribe ") + return + email_addr = args[1].strip() + r = subprocess.run( + ["mlmmj-sub", "-L", LIST_DIR, "-a", email_addr, "-s", "-f"], + capture_output=True, text=True + ) + bot.say(f"subscribed: {email_addr}" if r.returncode == 0 + else f"error: {(r.stderr or r.stdout).strip()}") + + elif action == "unsubscribe": + if len(args) < 2: + bot.say("usage: !list unsubscribe ") + return + email_addr = args[1].strip() + r = subprocess.run( + ["mlmmj-unsub", "-L", LIST_DIR, "-a", email_addr, "-s", "-f"], + capture_output=True, text=True + ) + bot.say(f"unsubscribed: {email_addr}" if r.returncode == 0 + else f"error: {(r.stderr or r.stdout).strip()}") + + elif action == "members": + subs_dir = os.path.join(LIST_DIR, "subscribers.d") + subs = [] + if os.path.isdir(subs_dir): + for fname in sorted(glob.glob(os.path.join(subs_dir, "*"))): + with open(fname) as f: + subs.extend(line.strip() for line in f if line.strip()) + if subs: + bot.say(f"{len(subs)} subscriber(s): " + ", ".join(subs)) + else: + bot.say("no subscribers") + + elif action == "send": + if len(args) < 2: + bot.say("usage: !list send ") + return + message = args[1].strip() + msg = ( + f"From: {OWNER_ADDR}\n" + f"To: {LIST_ADDR}\n" + f"Subject: {message}\n" + f"Date: {email.utils.formatdate(localtime=True)}\n" + f"\n" + f"{message}\n" + ) + with tempfile.NamedTemporaryFile(mode="w", suffix=".eml", delete=False) as f: + f.write(msg) + tmpname = f.name + try: + r = subprocess.run( + ["mlmmj-send", "-L", LIST_DIR, "-l", "1", "-m", tmpname], + capture_output=True, text=True + ) + bot.say("sent" if r.returncode == 0 + else f"error: {(r.stderr or r.stdout).strip()}") + finally: + os.unlink(tmpname) + + else: + bot.say("usage: !list ") -- cgit v1.2.3