all repos — dotfiles @ ad26f7b39dc11e0239f2e116bdc4093d840e50ba

linux dotfiles

bin/scripts/pd (view raw)

 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
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
#!/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
from datetime import datetime as dt
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 os.path.exists(tmp_pd_path):
    os.remove(tmp_pd_path)


ping_cmd = "ping -c 1 8.8.8.8"
ping_args = shlex.split(ping_cmd)
p = subprocess.Popen(ping_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if p.returncode:
    print("Network Unreachable...exiting now\nWrite a better script that can "
           "cache the entry locally you lazy ass")
    exit(p.returncode)


def save_entry(entry):
    entry_filename = dt.now().strftime('%s') + ".pdentry"
    entry_file_path = env_home + "/" + entry_filename
    print("Saving the entry to {}".format(entry_file_path))
    with open(entry_file_path, 'w', encoding='utf8') as entry_file:
        entry_file.write(entry)


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 -o {} -d {}'.format(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)
            return(p.returncode)
    else:
        print("Something went wrong")
        return(1)


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 -o {} -c {}'.format( 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)
        return(p.returncode)

    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")
        return(1)



# 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()

if fetch_and_decrypt(): # if there was any error while fetching and decrypting
    save_entry(entry)
    exit(1)

with open(tmp_pd_path, 'a', encoding='utf8') as fp:
    now = dt.now()
    date_string = now.strftime('%a, %d %b %Y')
    time_string = now.strftime('%I:%M %p')
    date_and_time = '[' + date_string + ' | ' + time_string + ']'

    fp.write('\n\n\n===============================\n' + date_and_time + '\n')
    fp.write(entry)

if encrypt_and_push():
    save_entry(entry)
    exit(1)