Add first version of sievedit
Includes set-active and edit commands.
This commit is contained in:
commit
c1b4851c97
|
@ -0,0 +1,24 @@
|
||||||
|
[metadata]
|
||||||
|
name = sievedit
|
||||||
|
version = 0.1
|
||||||
|
description = Simple tool to
|
||||||
|
|
||||||
|
[options]
|
||||||
|
packages = find:
|
||||||
|
install_requires =
|
||||||
|
click
|
||||||
|
python-editor
|
||||||
|
clintermission
|
||||||
|
sievelib
|
||||||
|
|
||||||
|
[options.entry_points]
|
||||||
|
console_scripts =
|
||||||
|
sievedit = sievedit:main
|
||||||
|
|
||||||
|
[options.packages.find]
|
||||||
|
exclude=env
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
max-line-length = 120
|
||||||
|
exclude = .git,__pycache__,*.egg-info,*lib/python*
|
||||||
|
ignore = E241,E741,W503,W504
|
|
@ -0,0 +1,126 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import difflib
|
||||||
|
import functools
|
||||||
|
|
||||||
|
import click
|
||||||
|
from clintermission import cli_select_item
|
||||||
|
import editor
|
||||||
|
from sievelib.managesieve import Client
|
||||||
|
|
||||||
|
|
||||||
|
def default_options(f):
|
||||||
|
@click.option('--server', prompt=True, help='sieve server to connect to')
|
||||||
|
@click.option('-u', '--user', prompt=True, help='user to connect as')
|
||||||
|
@click.option('--password', prompt=True, hide_input=True,
|
||||||
|
help='Passwort to connect with. It\'s discouraged to pass passwords.'
|
||||||
|
'Use the automatic prompt instead.')
|
||||||
|
@click.option('--starttls/--no-starttls', default=True, help='Connect with starttls')
|
||||||
|
@functools.wraps(f)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
f(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def main():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@main.command()
|
||||||
|
@default_options
|
||||||
|
@click.option('--script-name',
|
||||||
|
help='script name to set as active. If not provided, choices will be presented.')
|
||||||
|
def active(server, user, password, starttls, script_name):
|
||||||
|
"""Connect to a SIEVE server and set a script as active"""
|
||||||
|
c = Client(server)
|
||||||
|
c.connect(user, password, starttls=starttls)
|
||||||
|
active, scripts = c.listscripts()
|
||||||
|
|
||||||
|
if not script_name:
|
||||||
|
if len(scripts + [active]) == 1:
|
||||||
|
click.echo('Only a single script available: {}'.format((scripts + [active])[0]))
|
||||||
|
_, script_name = cli_select_item(zip(sorted(['{} (active)'.format(active)] + scripts),
|
||||||
|
sorted([active] + scripts)))
|
||||||
|
|
||||||
|
if active == script_name:
|
||||||
|
click.echo('Script {} is already active.'.format(script_name))
|
||||||
|
return
|
||||||
|
|
||||||
|
if script_name not in scripts:
|
||||||
|
click.echo('Error: script {} cannot be found. Valid choices are: {}'
|
||||||
|
.format(script_name, ', '.join(scripts)))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
c.setactive(script_name)
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_TEMPLATE = """\
|
||||||
|
# Example script. Edit as you like
|
||||||
|
require ["fileinto"];
|
||||||
|
# rule:[amazon]
|
||||||
|
if header :contains "To" "amazon@" {
|
||||||
|
fileinto "INBOX.amazon";
|
||||||
|
stop;
|
||||||
|
}
|
||||||
|
# rule:[games]
|
||||||
|
if anyof (header :contains "To" "gw2@",
|
||||||
|
header :contains "To" "humblebundle@",
|
||||||
|
header :contains "To" "steam@",
|
||||||
|
header :contains "To" "socialclub@",
|
||||||
|
header :contains "To" "uplay@" ) {
|
||||||
|
fileinto "INBOX.games";
|
||||||
|
stop;
|
||||||
|
}
|
||||||
|
# rule:[paypal]
|
||||||
|
if header :contains "To" "paypal@" {
|
||||||
|
fileinto "INBOX.paypal";
|
||||||
|
stop;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@main.command()
|
||||||
|
@default_options
|
||||||
|
@click.option('--script-name', help='Edit this script or create it')
|
||||||
|
def edit(server, user, password, starttls, script_name):
|
||||||
|
"""Connect to a SIEVE server, download, edit and upload a script"""
|
||||||
|
c = Client(server)
|
||||||
|
c.connect(user, password, starttls=starttls)
|
||||||
|
active, scripts = c.listscripts()
|
||||||
|
|
||||||
|
if not script_name:
|
||||||
|
_, script_name = cli_select_item(zip(sorted(['{} (active)'.format(active)] + scripts),
|
||||||
|
sorted([active] + scripts)))
|
||||||
|
if script_name not in (scripts + [active]):
|
||||||
|
msg = 'Script {} does not exist. Create new script?'
|
||||||
|
click.confirm(msg.format(script_name), abort=True)
|
||||||
|
original_content = DEFAULT_TEMPLATE
|
||||||
|
newly_created = True
|
||||||
|
else:
|
||||||
|
original_content = c.getscript(script_name)
|
||||||
|
newly_created = False
|
||||||
|
|
||||||
|
new_content = editor.edit(contents=original_content).decode('utf-8')
|
||||||
|
if new_content.strip() == original_content and not newly_created:
|
||||||
|
click.echo('No changes. Aborting.')
|
||||||
|
return
|
||||||
|
|
||||||
|
while not c.checkscript(new_content):
|
||||||
|
click.confirm('Script is invalid. Try again?', abort=True)
|
||||||
|
new_content = editor.edit(contents=new_content).decode('utf-8')
|
||||||
|
if new_content == original_content and not newly_created:
|
||||||
|
click.echo('No changes. Aborting.')
|
||||||
|
return
|
||||||
|
|
||||||
|
diff = difflib.unified_diff(original_content.splitlines(), new_content.splitlines(),
|
||||||
|
fromfile='before', tofile='after')
|
||||||
|
if not newly_created:
|
||||||
|
click.echo('Following changes were made:\n{}'.format('\n'.join(diff)))
|
||||||
|
click.confirm('Upload new version?', abort=True)
|
||||||
|
|
||||||
|
c.putscript(script_name, new_content)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue