scripts/pd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env python3 # # ------------------------------------------------------------- # Journal Keeping Script [aka Personal Diary (pd)] # Author : Prithu Goswami <prithugoswami524@gmail.com> # ------------------------------------------------------------- # Prerequisites : make sure these programs are available on the # machine: # 'rclone' # 'vim' # 'gpg' (v2.X) # # This is a very messy script and is just a quick hack and is not # a very super secure way of keeping a journal but I hope to improve on # it with time. It uses symmetric AES-128 encryption. # # This script opens a temp file in a vim buffer and after wrting # and quiting from vim, it appends the contents to the file # 'pd_path' that is in the 'pd_dir' in the $HOME dir of the machine, # with a date and timestamp. It then encrypts the file using gpg # and uploads it to the cloud storage. # # NOTE : 'rclone' should be configured # with a remote first. run 'rlone config'. # The remote should have directory with the encrypted 'pd' file # Path to remote directory should be stored in 'rclone_dir' # # I use 'rclone' to sync the journal to my dropbox # the script first fetches any changes done to the pd file, # decryptis it using 'gpg' using the passhprase-file as '$HOME/.pdkey' # and then appends the entry, encrypts it and uploads it. # # VARIABLES # # 'key_path' : passphrase for AES encrypted file # default alogrithm used by gpg v2.2 is AES-128 according # to the man page # 'pd_dir' : The directory where the pd file is stored # 'pd_path' : The path to the pd file. This is just "pd_dir+'pd'" # 'rclone_dir' ; The direrctory of the pd file on the 'remote' # in this case the 'remote' is 'drop:' # # NOTE : # Make sure there already exists a symmetrically encrypted AES file # in 'pd_path' and also in 'rclone_dir' # # To symmetrically encrypt an empty file run: # `touch empty ; gpg2 --passphrase <secret> --batch -o pd -c empty` # this should create a symmetrically encrypted AES file named 'pd' with # the passphrase <secret> # Now, save this file ('pd') in the 'pd_dir' and also upload it to the # remote dir using rclone. # This is not the most secure thing in the world I don't even intend it # to be. So anyways, the <secret> has to be saved as .pdkey in your home # directory or elsewhere ( if you're saving it elsewhere, then change # the 'key_path' variable accordingly import os import datetime import tempfile import subprocess import shlex import sys import hashlib ## VARIABLES ## # Change these accordingly env_home = os.environ['HOME'] tmp_pd_path = '/tmp/pd' key_path = env_home + '/.pdkey' pd_dir = env_home + '/Dropbox/pd' pd_path = pd_dir + '/pd' rclone_dir = 'drop:/pd' if not os.path.exists(key_path): print("Exiting..No .pdkey found in home dir") exit() if os.path.exists(tmp_pd_path): os.remove(tmp_pd_path) def fetch_and_decrypt(): """ Fetches the cloud copy first (sync) and then decrypts it to tmp_pd_path """ print("Fetching changes...") if not os.system('rclone sync {}/ {}/'.format(rclone_dir, pd_dir)): print("Done") decrypt_cmd = ('gpg --passphrase-file {} --batch -o {} -d {}' .format(key_path, tmp_pd_path, pd_path)) args = shlex.split(decrypt_cmd) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) out, err = p.communicate() if p.returncode: # if gpg exits with a non-zero return code print("Error while decrypting :\n" + err) exit() else: print("Something went wrong") def encrypt_and_push(): """ Encrypts the file at tmp_pd_path and then syncs to the cloud. i.e replace the copy in the cloud with the local one. """ if os.path.exists(pd_path): os.remove(pd_path) encrypt_cmd = ('gpg --passphrase-file {} --batch -o {} -c {}' .format(key_path, pd_path, tmp_pd_path)) args = shlex.split(encrypt_cmd) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) out, err = p.communicate() if p.returncode: print("Error while encrypting :\n" + err) exit() os.remove(tmp_pd_path) print("Pushing changes...") if not os.system('rclone sync {}/ {}/'.format(pd_dir, rclone_dir)): print("Done") else: print("Something went wrong") # PD edit argument # with the 'edit' argument passed to the script it will fetch the latest pd # version from the cloud and let you edit and then push it back if len(sys.argv) > 1: if sys.argv[1] == 'edit': if os.path.exists(tmp_pd_path): os.remove(tmp_pd_path) fetch_and_decrypt() with open(tmp_pd_path, 'r') as pdtemp: hash_before_edit = (hashlib.sha1(pdtemp.read().encode('utf-8')) .hexdigest()) os.system("vim {}".format(tmp_pd_path)) with open(tmp_pd_path, 'r') as pdtemp: hash_after_edit = (hashlib.sha1(pdtemp.read().encode('utf-8')) .hexdigest()) if hash_before_edit == hash_after_edit: print("Nothing was changed. Exiting...") exit() encrypt_and_push() exit() entry = None with tempfile.NamedTemporaryFile(suffix='.pdentry') as temp: command = "vim {}".format(temp.name) os.system(command) entry = open(temp.name, 'r').read() if len(entry.strip()) == 0: print("Nothing was entered...") exit() fetch_and_decrypt() with open(tmp_pd_path, 'a', encoding='utf8') as fp: dt = datetime.datetime.now() date_string = dt.strftime('%a, %d %b %Y') time_string = dt.strftime('%I:%M %p') date_and_time = '[' + date_string + ' | ' + time_string + ']' fp.write('\n\n\n===============================\n' + date_and_time + '\n') fp.write(entry) encrypt_and_push()