Created
November 23, 2022 08:10
-
-
Save huyz/6128fa639f0d028c1cbd414936b3786d to your computer and use it in GitHub Desktop.
Sort Thunderbird/Postbox identities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# For a given Thunderbird/Postbox account, this sorts the identities by email address. | |
# Only supports macOS (specific to macOS pgrep) right now, but could be easily tweaked for Linux. | |
# Prerequisites: pgrep, difft (difftastic) | |
from operator import itemgetter | |
from os import environ | |
from sys import platform, stderr | |
from typing import Dict | |
import re | |
import shutil | |
import subprocess | |
import tempfile | |
#### Config | |
DEBUG = False | |
PREFS_FILENAME = ( | |
environ["HOME"] | |
+ "/Library/Application Support/Thunderbird/Profiles/XXXXXX.default/prefs.js" | |
) | |
# Look at prefs.js and figure out the ID of the account whose identities you want to sort | |
ACCOUNT_ID = 4 | |
# If defined, this ID will be prioritized during the sort | |
PRIMARY_EMAIL_ADDRESS = "" | |
PGREP_COMMAND = shutil.which("pgrep") or "/usr/bin/pgrep" | |
DIFFT_COMMAND = shutil.which("difft") or "/opt/homebrew/bin/difft" | |
#### Init | |
if platform != "darwin": | |
stderr.write(f"error: Only supports macOS at this time.\n") | |
exit(1) | |
IDS_LINE_PREFIX = f'user_pref("mail.account.account{ACCOUNT_ID}.identities"' | |
#### Read | |
# Read in a line from a file | |
with open(PREFS_FILENAME) as f: | |
ids_line = [l for l in f.readlines() if l.startswith(IDS_LINE_PREFIX)][0] | |
if not ids_line: | |
stderr.write(f"Can't find matching line for ID {ACCOUNT_ID} in {PREFS_FILENAME}\n") | |
exit(1) | |
if DEBUG: | |
print(ids_line) | |
ids = set(re.sub(r'.*identities",\s*"([^"]+)"\);\s*$', r"\1", ids_line).split(",")) | |
if DEBUG: | |
print(ids) | |
with open(PREFS_FILENAME) as f: | |
emails: Dict[str, str] = dict() | |
for line in f.readlines(): | |
m = re.search( | |
r'^user_pref\("mail\.identity\.(id\d+)\.useremail",\s*"([^"]+)"\);\s*', line | |
) | |
if m and m.group(1) in ids: | |
emails[m.group(1)] = m.group(2) | |
#### Output | |
sorted_ids_line = ",".join( | |
map( | |
itemgetter(0), | |
sorted( | |
emails.items(), key=lambda x: "" if x[1] == PRIMARY_EMAIL_ADDRESS else x[1] | |
), | |
) | |
) | |
output = f'{IDS_LINE_PREFIX}, "{sorted_ids_line}");' | |
print(output) | |
#### Write | |
# Check if Postbox/ThunderBird is running | |
if "PostboxApp" in PREFS_FILENAME: | |
process_name = "Postbox.app" | |
elif "Thunderbird" in PREFS_FILENAME: | |
process_name = "Thunderbird.app" | |
else: | |
stderr.write( | |
f"error: Can't determine app name from {PREFS_FILENAME}; can't update file.\n" | |
) | |
exit(1) | |
# TODO: support linux pgrep as well. | |
process = subprocess.Popen( | |
[PGREP_COMMAND, "-f", process_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE | |
) | |
my_pid, err = process.communicate() | |
if err: | |
stderr.write(f"Error {err} while pgrep'ing {process_name}; can't update file.\n") | |
exit(1) | |
if my_pid: | |
stderr.write(f"\nWarning: {process_name} is running; can't update file.\n") | |
exit(1) | |
print(f"\nWARNING: {PREFS_FILENAME} will be updated thusly:\n") | |
with tempfile.NamedTemporaryFile("wt", delete=False) as tmp: | |
with open(PREFS_FILENAME) as f: | |
for line in f.readlines(): | |
if line.startswith(IDS_LINE_PREFIX): | |
tmp.write(f"{output}\n") | |
else: | |
tmp.write(line) | |
tmp.flush() | |
# TODO: fall back to regular diff? | |
subprocess.run([DIFFT_COMMAND, PREFS_FILENAME, tmp.name]) | |
answer = input("Perform update? [y/N] ") | |
if answer.lower() in ["y", "yes"]: | |
shutil.copyfile(tmp.name, PREFS_FILENAME) | |
print("File updated.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment