deal with config and stuff

This commit is contained in:
kaylee 2024-02-02 16:26:00 +00:00
parent 75b8451c95
commit 80fdd31ef3
2 changed files with 163 additions and 10 deletions

View File

@ -4,10 +4,11 @@ alerts u when u have unread messages by adding 📬 to your bash prompt
## USAGE:
- configure your imap server in your .muttrc (or .mutt/muttrc) file
- configure your imap server in `~/.uvgotmail/config` file. you can also use an existing `.muttrc` file.
- add `./uvgotmail.py --daemon &` to the end of your `.bashrc` file
- find the line where your PS1 is set and put `$(./uvgotmail.py --check)` at the start
## OPTIONS:
### check mode
@ -16,4 +17,6 @@ alerts u when u have unread messages by adding 📬 to your bash prompt
- `--no-count`: by default, if you have multiple messages you will get `(n) 📬` in your PS1. this option turns that off.
### daemon mode
- `--config [path]`: path to config file in `muttrc` format
- `--config [path]`: path to config file
- `--mutt`: whether to load server settings from .muttrc file

View File

@ -3,18 +3,154 @@ import argparse
import sys
import os
def parseYN(s, default = False):
if default == False:
return s.lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh', 'go for it']
else: return not s.lower() in ['false', '0', 'f', 'n', 'no', 'nah', 'nope', 'certainly not', 'nuh-huh', 'bugger that']
def getYN(b):
return "yes" if b else "no"
def parseConfig(args=None,config_path=None):
# default settings
if args:
config = { "no_count": args.no_count, "mailbox_symbol": "📬", "mutt": args.mutt, "ssl": True, "server": "", "port": 0, "user": "", "password": "" }
if not config_path:
config_path = args.config
filename = os.path.expanduser(config_path)
# if we have a config file, parse it
if os.path.exists(filename):
with open(filename) as f:
for line in f:
line = line.strip()
if len(line) == 0: continue
if line[0] == "#": continue # skip commented lines
kv = line.strip().split("=",1);
kv[0] = kv[0].replace("-","_");
if len(kv)==1:
continue
try:
# load types appropriately
if type(config[kv[0]]) == type(True):
config[kv[0]] = (kv[1] == 'True') # cast to boolean
elif type(config[kv[0]]) == type(1):
config[kv[0]] = parseInt(kv[1])
else:
config[kv[0]] = kv[1]
except:
print("uvgotmail: unknown option: "+kv[0])
# sort booleans
# otherwise, prompt the user to create one
elif(args.daemon and not args.mutt):
if parseYN(input("uvgotmail: no config file exists. create now? [Y/n] "),default=True):
createConfig(config_path, config,args)
return
else:
print("uvgotmail: failed to start.")
exit(1)
# if no port is specified, use default
if config["port"] == 0:
config["port"] = 993 if config["ssl"] else 143
# read muttrc if we should do that
if config["mutt"] == True:
try: # try both locations of dotfile
with open(os.path.expanduser("~/.muttrc")) as f:
muttrc = f.readlines();
except Exception as e:
try:
with open(os.path.expanduser("~/.mutt/muttrc")) as f:
muttrc = f.readlines();
except Exception as f:
print(e)
print(f)
print("uvgotmail: could not read your muttrc. does it exist?")
exit(1)
for line in muttrc:
line = line.strip()
if len(line) == 0:
continue
if line[0] == "#": continue # skip commented lines
if "set imap_user" in line:
config["user"]=line.split("=",1)[1].strip().replace('"','')
if "set imap_pass" in line:
# voodoo to remove "s only from the start and end of password, if present
config["password"]="".join(line.split("=",1)[1].strip().replace('"','',1).rsplit('"',1))
if "set folder" in line:
folder = line.split("=",1)[1].strip().replace('"','')
if folder.startswith("imaps"):
config["ssl"] = True
server_port = folder.split("//")[1].split(":")
config["server"] = server_port[0]
config["port"] = server_port[1]
# make sure at least a server and a username are set
if config["server"] == "" or config["user"] == "":
print("uvgotmail: failed to start. no imap server or username specified.")
print(config)
return config
def createConfig(config_path, config,args):
# helper function to deal with setting each item
def getInput(prompt, existing):
boolean = type(existing) == type(True)
existing_str = getYN(existing) if boolean else str(existing)
inp = input(prompt + " [" + existing_str + "]: ")
if inp=="":
return existing
if boolean:
inp = parseYN(inp)
return inp
import datetime
config_path = getInput("where do you want to put your config file? (directory tree will be created if necessary)",config_path)
config["mailbox_symbol"] = getInput("what symbol do you want to display when there are unread messages?",config["mailbox_symbol"])
config["no_count"] = not getInput("do you want to display the number of unread messages?",not config["no_count"])
config["mutt"] = getInput("do you want to use your muttrc for the server settings?",config["mutt"])
if not config["mutt"]:
config["server"] = getInput("what's your IMAP server?",config["server"])
config["ssl"] = getInput("are you using ssl? it's " + str(datetime.date.today().year) +" so you really should be",config["ssl"])
if(config["port"] == ""):
config["port"] = 993 if config["ssl"] else 143
config["port"] = getInput("what's the IMAP port?",config["port"])
config["user"]= getInput("what's your IMAP username?",config["user"])
config["password"] = getInput("what's your IMAP password?",config["password"])
# confirm all this is correct; if not go round again
if(not parseYN(input("is this correct? [y/N] "))):
createConfig(config_path,config)
return
else:
from pathlib import Path
while True:
path = Path(os.path.expanduser(config_path))
try:
path.parent.mkdir(parents=True, exist_ok=True,mode=0o700)
path.touch(mode=0o600,exist_ok=False)
with path.open(mode="w") as f:
for i,key in enumerate(config):
f.write(key+"="+str(config[key])+("\n" if i < len(config)-1 else ""))
print("config file created; starting daemon")
parseConfig(config_path = config_path,args=args)
break
except Exception as e:
if not parseYN(input("failed to create config file: " + str(e) +"... retry? [Y/n] ")):
exit(1)
config_path = getInput("where do you want to put your config file? (directory tree will be created if necessary)",config_path)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--daemon", help="run in daemon mode (put this at end of .bashrc)", action="store_true")
parser.add_argument("--config", help="specify config file in muttrc format")
parser.add_argument("--config", help="specify config file (default: ~/.uvgotmail/config)", default="~/.uvgotmail/config")
parser.add_argument("--mutt", help="use existing mutt configuration (experimental)", action="store_true")
parser.add_argument("--check", help="run in check mode (put this in PS1)", action="store_true")
parser.add_argument("--no-count", help="don't display how many unread messages there are", action="store_false")
parser.add_argument("--mailbox-char", help="specify a character instead of the mailbox emoji",default="📬")
parser.add_argument("--mailbox-symbol", help="specify a string instead of the mailbox emoji",default="")
args = parser.parse_args()
global mailchar, countmail;
mailchar = args.mailbox_char
countmail = args.no_count;
config_settings = parseConfig(args);
if(args.daemon == args.check):
parser.print_help()
@ -25,15 +161,29 @@ def main():
check()
def check():
filename = '/tmp/uvgotmail/'+os.getlogin()+'/unread'
filename = os.path.expanduser('~/.uvgotmail/unread')
if os.path.exists(filename):
with open(filename) as f:
unread = int(f.read());
if unread == 0:
sys.exit(0)
pre = ""
if(unread > 1 and countmail):
if(unread > 1 and countmail == True):
pre = "("+str(unread)+") "
print(pre+mailchar,end=' ')
# if there's no unread count file, just exit quietly
def daemon():
import imaplib
# handle ctrl+c gracefully
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(130)
except SystemExit:
os._exit(130)
main();