aboutsummaryrefslogtreecommitdiffstats
path: root/alfred
diff options
context:
space:
mode:
authorAhmed <git@gumx.cc>2026-06-18 14:30:18 +0300
committerAhmed <git@gumx.cc>2026-06-18 14:30:18 +0300
commite215418d64dac88d0998cf50438abddae5670f2b (patch)
tree4ad9ad80e64425166798a095b671360b068e2d2b /alfred
parentc41a6faab04bbf0cdb89e18299e88946557ddf99 (diff)
fix: mlmmj commands
Diffstat (limited to 'alfred')
-rw-r--r--alfred/helpstrings.py3
-rw-r--r--alfred/mlmmj.py104
2 files changed, 20 insertions, 87 deletions
diff --git a/alfred/helpstrings.py b/alfred/helpstrings.py
index 009a42a..2abaa5f 100644
--- a/alfred/helpstrings.py
+++ b/alfred/helpstrings.py
@@ -59,13 +59,12 @@ VPN = {
"remove": "vpn remove: remove a peer live and from wg0.conf. usage: !vpn remove name",
}
-LIST_TOPIC = "list: members subscribe unsubscribe send mod. type !help list <cmd> for details"
+LIST_TOPIC = "list: members subscribe unsubscribe send. type !help list <cmd> for details"
LIST = {
"members": "list members: show all subscribers. usage: !list members",
"subscribe": "list subscribe: subscribe an address. usage: !list subscribe email",
"unsubscribe": "list unsubscribe: unsubscribe an address. usage: !list unsubscribe email",
"send": "list send: send a message to the list. usage: !list send message",
- "mod": "list mod: list archive messages or remove one. usage: !list mod or !list mod rm N",
}
GIT_TOPIC = "git: list desc hook remove. type !help git <cmd> for details"
diff --git a/alfred/mlmmj.py b/alfred/mlmmj.py
index c618adf..88a6333 100644
--- a/alfred/mlmmj.py
+++ b/alfred/mlmmj.py
@@ -5,13 +5,9 @@ Sopel plugin: mlmmj mailing list management
!list unsubscribe <email> - unsubscribe
!list members - show all subscribers
!list send <message> - send a message to the list as owner
- !list mod - show recent archive messages
- !list mod rm <N> - remove message N from archive
"""
-import email.utils, glob, os, subprocess, tempfile
-import mailbox
-from email.header import decode_header
+import email.utils, glob, os, subprocess
from sopel import plugin
LIST_DIR = "/var/spool/mlmmj/list"
@@ -28,9 +24,9 @@ def cmd_list(bot, trigger):
if not _owner(bot, trigger):
return
- args = (trigger.group(2) or "").split(None, 2)
+ args = (trigger.group(2) or "").split()
if not args:
- bot.say("usage: !list <subscribe|unsubscribe|members|send|mod>")
+ bot.say("usage: !list <subscribe|unsubscribe|members|send>")
return
action = args[0]
@@ -41,7 +37,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
@@ -53,7 +49,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
@@ -75,83 +71,21 @@ def cmd_list(bot, trigger):
if len(args) < 2:
bot.say("usage: !list send <message>")
return
- message = args[1].strip()
+ message = " ".join(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"
+ f"From: {OWNER_ADDR}\r\n"
+ f"To: {LIST_ADDR}\r\n"
+ f"Subject: {message}\r\n"
+ f"Date: {email.utils.formatdate(localtime=True)}\r\n"
+ f"\r\n"
+ f"{message}\r\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, "-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)
-
- elif action == "mod":
- sub = args[1].strip() if len(args) > 1 else ""
- archive_dir = os.path.join(LIST_DIR, "archive")
-
- def _decode(s):
- if not s:
- return ''
- parts = decode_header(s)
- out = []
- for part, charset in parts:
- if isinstance(part, bytes):
- out.append(part.decode(charset or 'utf-8', errors='replace'))
- else:
- out.append(part)
- return ''.join(out)
-
- if not sub or sub == "list":
- items = sorted(
- f for f in os.listdir(archive_dir)
- if os.path.isfile(os.path.join(archive_dir, f)) and not f.endswith('.html')
- )
- if not items:
- bot.say("archive: empty")
- return
- bot.say(f"archive: {len(items)} message(s)")
- for fname in items[-10:]:
- fpath = os.path.join(archive_dir, fname)
- with open(fpath, 'rb') as f:
- msg = mailbox.Message(f)
- subject = _decode(msg.get('Subject', '(no subject)'))
- sender = _decode(msg.get('From', ''))
- name = sender.split('<')[0].strip().strip('"') or sender
- bot.say(f" {fname} {subject[:40]} <{name}>")
-
- elif sub == "rm":
- if len(args) < 3:
- bot.say("usage: !list mod rm <N>")
- return
- fname = args[2].strip()
- fpath = os.path.join(archive_dir, fname)
- if not os.path.isfile(fpath):
- bot.say(f"mod rm: not found: {fname}")
- return
- os.remove(fpath)
- html_path = fpath + '.html'
- if os.path.isfile(html_path):
- os.remove(html_path)
- subprocess.Popen(
- ["python3", "/home/ahmed/scripts/archive-gen.py", LIST_DIR],
- stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
- )
- bot.say(f"removed: {fname}")
-
- else:
- bot.say("usage: !list mod [list|rm <N>]")
+ r = subprocess.run(
+ ["/usr/sbin/sendmail", "-f", OWNER_ADDR, LIST_ADDR],
+ input=msg, capture_output=True, text=True
+ )
+ bot.say("queued" if r.returncode == 0
+ else f"error: {(r.stderr or r.stdout).strip()}")
else:
- bot.say("usage: !list <subscribe|unsubscribe|members|send|mod>")
+ bot.say("usage: !list <subscribe|unsubscribe|members|send>")