ttracker/ttracker.py
2025-01-13 08:02:37 +01:00

123 lines
3.6 KiB
Python
Executable file

#!/usr/bin/env python3
import argparse
import datetime
import sys, tempfile, os
import sqlite3
from subprocess import call
EDITOR = os.environ.get('EDITOR', 'nano')
DATABASE = os.environ.get('TTRACKER_BD', 'ttracker.db')
def db_init(cur):
cur.execute("CREATE TABLE IF NOT EXISTS ttracker (start INTEGER, end INTEGER, text TEXT)")
def db_get_current_entry(cur):
res = cur.execute("SELECT * FROM ttracker ORDER BY start DESC").fetchone()
if res is not None and res[1] is None:
return res
return (None, None, None)
def show_last_entries(cur):
res = cur.execute("SELECT * FROM ttracker ORDER BY start DESC LIMIT 10").fetchall()
for e in res:
start = datetime.datetime.fromtimestamp(e[0])
if e[1] is not None:
end = datetime.datetime.fromtimestamp(e[1])
print(f'{when_are_we(start.date())}, {start.strftime("%H:%M")}-{end.strftime("%H:%M")}: {e[2]}')
else:
print(f'{when_are_we(start.date())}, {start.strftime("%H:%M")}-')
def new_entry(cur, now):
cur.execute(f'INSERT INTO ttracker VALUES (?, null, null)', (int(now.timestamp()),))
def cancel_last_entry(cur, entry):
if entry[0] != None:
cur.execute("DELETE FROM ttracker WHERE start = ?", (entry[0],))
else:
cur.execute("UPDATE ttracker SET end=null, text=null WHERE start = (SELECT start FROM ttracker ORDER BY start DESC LIMIT 1)")
def end_entry(cur, entry, now):
entry_start = datetime.datetime.fromtimestamp(entry[0])
res = cur.execute("SELECT * FROM ttracker ORDER BY start DESC LIMIT 11").fetchall()
initial_message = '\n\n' + \
f'# What did you do since {when_are_we(entry_start.date())} ({entry_start.strftime("%H:%M")})?\n' + \
"#\n"
for e in res:
if e[1] is not None:
start = datetime.datetime.fromtimestamp(e[0])
end = datetime.datetime.fromtimestamp(e[1])
initial_message += f'# {when_are_we(start.date())}, {start.strftime("%H:%M")}-{end.strftime("%H:%M")}: {e[2]}\n'
with tempfile.NamedTemporaryFile(suffix=".tmp") as tf:
tf.write(initial_message.encode('utf_8'))
tf.flush()
call([EDITOR, tf.name])
tf.seek(0)
edited_message = [l.decode('utf_8') for l in tf.readlines()]
stripped_message = [l.strip() for l in edited_message if l.strip() and l != "" and l[0] != "#"]
if len(stripped_message) == 0:
return
cur.execute('UPDATE ttracker SET end = ?, text = ? WHERE start = ?', (int(now.timestamp()), stripped_message[0], entry[0]))
print(f'Close entry ending at {now.strftime("%a %d %b")} - {now.strftime("%H:%M")}: {stripped_message[0]}')
def when_are_we(date):
delta = (datetime.date.today() - date).days
if delta == 0:
return "Today"
elif delta == 1:
return "Yesterday"
else:
return f'{delta} days ago'
def main():
parser = argparse.ArgumentParser(
prog='ttracker',
description='Simple time tracker')
subparsers = parser.add_subparsers()
parser_show = subparsers.add_parser('show')
parser_show.set_defaults(show=True)
parser_show = subparsers.add_parser('cancel')
parser_show.set_defaults(cancel=True)
args = parser.parse_args()
now = datetime.datetime.now()
con = sqlite3.connect(DATABASE)
cur = con.cursor()
db_init(cur)
if 'show' in args:
show_last_entries(cur)
return
entry = db_get_current_entry(cur)
if 'cancel' in args:
cancel_last_entry(cur, entry)
con.commit()
show_last_entries(cur)
return
if entry[0] is None:
new_entry(cur, now)
print(f'Add new entry starting at {now.strftime("%a %d %b")} ({when_are_we(now.date())}) - {now.strftime("%H:%M")}')
else:
end_entry(cur, entry, now)
con.commit()
if __name__ == "__main__":
main()