aboutsummaryrefslogtreecommitdiffstats
path: root/alfred
diff options
context:
space:
mode:
Diffstat (limited to 'alfred')
-rw-r--r--alfred/mlmmj.py75
1 files changed, 65 insertions, 10 deletions
diff --git a/alfred/mlmmj.py b/alfred/mlmmj.py
index 5dfbfc3..b691a7c 100644
--- a/alfred/mlmmj.py
+++ b/alfred/mlmmj.py
@@ -1,18 +1,22 @@
"""
Sopel plugin: mlmmj mailing list management
- !list subscribe <email> - subscribe to list@gumx.cc
- !list unsubscribe <email> - unsubscribe
- !list members - show all subscribers
- !list send <message> - send a message to the list as owner
+ !list subscribe <email> - subscribe (forced, no confirmation email)
+ !list unsubscribe <email> - unsubscribe
+ !list members - show all subscribers
+ !list send <message> - send a message to the list as owner (bypasses moderation)
+ !list mod - show pending moderation queue
+ !list approve <id> - approve a held post
+ !list discard <id> - discard a held post
"""
-import email.utils, glob, os, subprocess, tempfile
+import email.utils, glob, mailbox, os, subprocess, tempfile
from sopel import plugin
LIST_DIR = "/var/spool/mlmmj/list"
LIST_ADDR = "list@gumx.cc"
OWNER_ADDR = "ahmed@gumx.cc"
+MOD_DIR = os.path.join(LIST_DIR, "moderation")
def _owner(bot, trigger):
@@ -26,7 +30,7 @@ def cmd_list(bot, trigger):
args = (trigger.group(2) or "").split(None, 1)
if not args:
- bot.say("usage: !list <subscribe|unsubscribe|members|send>")
+ bot.say("usage: !list <subscribe|unsubscribe|members|send|mod|approve|discard>")
return
action = args[0]
@@ -37,7 +41,7 @@ def cmd_list(bot, trigger):
return
email_addr = args[1].strip()
r = subprocess.run(
- ["mlmmj-sub", "-L", LIST_DIR, "-a", email_addr, "-s", "-f"],
+ ["/usr/bin/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
@@ -49,7 +53,7 @@ def cmd_list(bot, trigger):
return
email_addr = args[1].strip()
r = subprocess.run(
- ["mlmmj-unsub", "-L", LIST_DIR, "-a", email_addr, "-s", "-f"],
+ ["/usr/bin/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
@@ -85,7 +89,7 @@ def cmd_list(bot, trigger):
tmpname = f.name
try:
r = subprocess.run(
- ["mlmmj-send", "-L", LIST_DIR, "-l", "1", "-m", tmpname],
+ ["/usr/bin/mlmmj-send", "-L", LIST_DIR, "-l", "1", "-m", tmpname],
capture_output=True, text=True
)
bot.say("sent" if r.returncode == 0
@@ -93,5 +97,56 @@ def cmd_list(bot, trigger):
finally:
os.unlink(tmpname)
+ elif action == "mod":
+ files = sorted(os.listdir(MOD_DIR)) if os.path.isdir(MOD_DIR) else []
+ if not files:
+ bot.say("moderation queue empty")
+ return
+ for fname in files[:5]:
+ fpath = os.path.join(MOD_DIR, fname)
+ try:
+ with open(fpath, "rb") as f:
+ msg = mailbox.Message(f)
+ subj = (msg.get("Subject", "(no subject)") or "")[:50]
+ frm = (msg.get("From", "") or "")[:30]
+ except Exception:
+ subj, frm = "(unreadable)", ""
+ bot.say(f"{fname} {subj} — {frm}")
+ if len(files) > 5:
+ bot.say(f"... and {len(files) - 5} more")
+
+ elif action == "approve":
+ args2 = (trigger.group(2) or "").split(None, 2)
+ if len(args2) < 2:
+ bot.say("usage: !list approve <id>")
+ return
+ fid = args2[1].strip()
+ path = os.path.join(MOD_DIR, fid)
+ if not os.path.isfile(path):
+ bot.say(f"not found: {fid}")
+ return
+ r = subprocess.run(
+ ["/usr/bin/mlmmj-send", "-L", LIST_DIR, "-l", "1", "-m", path],
+ capture_output=True, text=True
+ )
+ if r.returncode == 0:
+ os.unlink(path)
+ bot.say(f"approved: {fid}")
+ else:
+ bot.say(f"error: {(r.stderr or r.stdout).strip()}")
+
+ elif action == "discard":
+ args2 = (trigger.group(2) or "").split(None, 2)
+ if len(args2) < 2:
+ bot.say("usage: !list discard <id>")
+ return
+ fid = args2[1].strip()
+ path = os.path.join(MOD_DIR, fid)
+ if not os.path.isfile(path):
+ bot.say(f"not found: {fid}")
+ return
+ os.unlink(path)
+ bot.say(f"discarded: {fid}")
+
else:
- bot.say("usage: !list <subscribe|unsubscribe|members|send>")
+ bot.say("usage: !list <subscribe|unsubscribe|members|send|mod|approve|discard>")