diff options
-rw-r--r-- | accounts/gkleen@sif/systemd.nix | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/accounts/gkleen@sif/systemd.nix b/accounts/gkleen@sif/systemd.nix index 21c50008..bd506590 100644 --- a/accounts/gkleen@sif/systemd.nix +++ b/accounts/gkleen@sif/systemd.nix | |||
@@ -47,15 +47,69 @@ in { | |||
47 | Service = { | 47 | Service = { |
48 | Type = "oneshot"; | 48 | Type = "oneshot"; |
49 | WorkingDirectory = "~"; | 49 | WorkingDirectory = "~"; |
50 | ExecStart = toString (pkgs.writers.writePython3 "sync-keepass" {} '' | 50 | ExecStart = toString (pkgs.writers.writePython3 "sync-keepass" { |
51 | libraries = with pkgs.python3Packages; [ dateutil ]; | ||
52 | } '' | ||
51 | import json | 53 | import json |
52 | import subprocess | 54 | import subprocess |
53 | # from datetime import datetime | 55 | from os.path import (expanduser, getmtime, dirname) |
56 | from datetime import datetime | ||
57 | from dateutil.tz import tzlocal | ||
58 | from dateutil.parser import isoparse | ||
59 | from sys import stderr | ||
54 | 60 | ||
55 | res = None | 61 | |
56 | with subprocess.Popen(['rclone', 'lsjson', 'surtr:store.kdbx'], stdout=subprocess.PIPE) as proc: # noqa: E501 | 62 | remote_fs = 'surtr' |
57 | res = json.load(proc.stdout) | 63 | remote_file = f'{remote_fs}:store.kdbx' |
58 | print(res) | 64 | target_file = expanduser('~/store.kdbx') |
65 | meta_file = expanduser('~/.store.kdbx.json') | ||
66 | |||
67 | upload_time = None | ||
68 | our_last_upload_time = None | ||
69 | mod_time = None | ||
70 | |||
71 | |||
72 | def get_upload_time(): | ||
73 | upload_time = None | ||
74 | with subprocess.Popen(['rclone', 'lsjson', remote_file], stdout=subprocess.PIPE) as proc: # noqa: E501 | ||
75 | for file in json.load(proc.stdout): | ||
76 | if file['Path'] != 'store.kdbx': | ||
77 | continue | ||
78 | upload_time = isoparse(file['ModTime']) | ||
79 | return upload_time | ||
80 | |||
81 | |||
82 | def do_upload(): | ||
83 | print('Uploading', file=stderr) | ||
84 | subprocess.run(['rclone', 'copy', '-I', target_file, f'{remote_fs}:'], check=True) # noqa: E501 | ||
85 | upload_time = get_upload_time() | ||
86 | with open(meta_file, 'w') as file: | ||
87 | json.dump({'our_last_upload_time': upload_time.isoformat()}, file) | ||
88 | |||
89 | |||
90 | def do_download(): | ||
91 | print('Downloading', file=stderr) | ||
92 | subprocess.run(['rclone', 'copy', '-I', remote_file, dirname(target_file)], check=True) # noqa: E501 | ||
93 | |||
94 | |||
95 | upload_time = get_upload_time() | ||
96 | |||
97 | try: | ||
98 | with open(meta_file, 'r') as file: | ||
99 | file_content = json.load(file) | ||
100 | our_last_upload_time = isoparse(file_content['our_last_upload_time']) # noqa: E501 | ||
101 | except FileNotFoundError: | ||
102 | pass | ||
103 | |||
104 | try: | ||
105 | mod_time = datetime.fromtimestamp(getmtime(target_file)).replace(tzinfo=tzlocal()) # noqa: E501 | ||
106 | except FileNotFoundError: | ||
107 | pass | ||
108 | |||
109 | if upload_time is None or (mod_time is not None and mod_time > upload_time): # noqa: E501 | ||
110 | do_upload() | ||
111 | elif upload_time is not None and (mod_time is None or upload_time > mod_time) and (our_last_upload_time is None or upload_time > our_last_upload_time): # noqa: E501 | ||
112 | do_download() | ||
59 | ''); | 113 | ''); |
60 | Environment = [ "RCLONE_PASSWORD_COMMAND=\"${pkgs.coreutils}/bin/cat ${config.sops.secrets.gkleen-rclone.path}\"" "PATH=${pkgs.rclone}/bin" ]; | 114 | Environment = [ "RCLONE_PASSWORD_COMMAND=\"${pkgs.coreutils}/bin/cat ${config.sops.secrets.gkleen-rclone.path}\"" "PATH=${pkgs.rclone}/bin" ]; |
61 | }; | 115 | }; |