aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fl.fischer@fau.de>2018-12-28 23:52:37 +0100
committerFlorian Fischer <florian.fl.fischer@fau.de>2018-12-28 23:52:37 +0100
commitfbfb3afeb757f9633cce84cb600e249780743616 (patch)
tree7ca3c07dd39661e72235fedb03f0fab8534d8d62
parent9e7bc2aedebedce864bb5a4968c1b77e8d751e2d (diff)
downloadgeldschieberbot-fbfb3afeb757f9633cce84cb600e249780743616.tar.gz
geldschieberbot-fbfb3afeb757f9633cce84cb600e249780743616.zip
add suppport for legacy data stores and scheduled exec refactoring
* monthly commands with days > 28 are executed on 28. * bug fixes in cancel * add support for python3 < 3.7 (date.fromisoformat) * add support for cmds in changes (cancel)
-rw-r--r--geldschieberbot.py127
1 files changed, 95 insertions, 32 deletions
diff --git a/geldschieberbot.py b/geldschieberbot.py
index 234ab68..99c308b 100644
--- a/geldschieberbot.py
+++ b/geldschieberbot.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
-from datetime import datetime
-from datetime import timedelta
+from datetime import date, datetime, timedelta
import json
import os
import subprocess
@@ -28,6 +27,26 @@ else:
"changes" : {},
}
+ # check if a legacy file layout is present
+ store_dir = os.path.dirname(state_file)
+ if os.path.isfile(os.path.join(store_dir, "balance.json")):
+ with open(os.path.join(store_dir, "balance.json"), "r") as f:
+ state["balance"] = json.load(f)
+
+ with open(os.path.join(store_dir, "registration.json"), "r") as f:
+ state["name2num"] = json.load(f)
+ print(state["name2num"])
+ for name in state["name2num"]:
+ state["num2name"][state["name2num"][name]] = name
+ print(state["num2name"])
+
+ with open(os.path.join(store_dir, "last_change.json"), "r") as f:
+ state["changes"] = json.load(f)
+ for num in state["changes"]:
+ name = state["num2name"][num]
+ state["changes"][name] = state["changes"[num]
+ del(state["changes"][num])
+
balance = state["balance"]
name2num = state["name2num"]
num2name = state["num2name"]
@@ -45,6 +64,9 @@ dry_run = False
"""Run without sending messages"""
quiet = False
+"""Should changes be recorded"""
+record_changes = True
+
def record(recipient, donor, amount):
"""Apply changes to the balance"""
@@ -239,7 +261,8 @@ def split(sender, args, msg):
record(recipient, p, amount_per_person)
change.append([recipient, p, amount_per_person])
- changes[recipient].append(change)
+ if record_changes and not dry_run:
+ changes[recipient].append(change)
output += "New Balance:\n"
output += create_summary(recipient)
@@ -281,7 +304,8 @@ def transaction(sender, args, msg):
if args[0] in ["!zieh", "!nimm"]:
amount *= -1
- changes[sender].append([args, [sender, recipient, amount]])
+ if record_changes and not dry_run:
+ changes[sender].append([args, [sender, recipient, amount]])
record(sender, recipient, amount)
@@ -333,6 +357,9 @@ def tanken(sender, args, msg):
else:
output += p[0] + " not known. Please take care manually\n"
+ if record_changes and not dry_run:
+ changes[sender].append(change)
+
output += "New Balance:\n"
output += create_summary(recipient)
send(output)
@@ -340,7 +367,6 @@ def tanken(sender, args, msg):
cmds["tanken"] = tanken
-#TODO
def fuck(sender, args, msg):
if not sender in num2name:
send("ERROR: you must register first")
@@ -359,13 +385,19 @@ def fuck(sender, args, msg):
output = name + ": sorry I fucked up!\nRewinding:\n"
output += ' '.join(args) + "\n"
for change in last_changes:
- output += "{} {} {} {}\n".format(change[0],
- ("->" if change[2] < 0 else "<-"),
- to_euro(abs(change[2])),
- change[1])
- record(change[1], change[0], change[2])
+ if not change[0] in cmds:
+ output += "{} {} {} {}\n".format(change[0],
+ ("->" if change[2] < 0 else "<-"),
+ to_euro(abs(change[2])),
+ change[1])
+ record(change[1], change[0], change[2])
send(output)
+
+ for change in last_changes:
+ if change[0] in cmds:
+ cmds[change[0]](sender, change, "")
+
return 0
cmds["fuck"] = fuck
@@ -376,8 +408,9 @@ def schedule(sender, args, msg):
if not sender in num2name:
send("ERROR: you must register first")
return 1
+ sender_name = num2name[sender]
- if args < 3:
+ if len(args) < 3:
send('ERROR: not in form "{} name cmd"'.format(args[0]))
return 1
@@ -401,13 +434,22 @@ def schedule(sender, args, msg):
send('ERROR: the command "{}" failed and will not be recorded')
return 1
- scheduled_cmd = {"schedule": args[0][0],
+ scheduled_cmd = {"schedule": args[0][1:],
"last_time": None,
"sender": sender,
"cmd": cmd}
scheduled_cmds[name] = scheduled_cmd
- send('Recorded the {} command "{}" as {}'.format(args[0], cmd, name))
+ send('Recorded the {} command "{}" as "{}"\n'.format(args[0][1:], ' '.join(cmd), name))
+
+ send("Running {} command {} for {} initially\n".format(scheduled_cmd["schedule"],
+ name, sender_name))
+
+ cmds[cmd[0]](sender, cmd, "")
+ changes[sender_name][0].append(["cancel", name])
+
+ now = datetime.now().date()
+ scheduled_cmd["last_time"] = now.isoformat()
cmds["weekly"] = schedule
cmds["monthly"] = schedule
@@ -420,14 +462,16 @@ def cancel(sender, args, msg):
return 1
cmd = scheduled_cmds[cmd_name]
- if not cmd.sender == sender:
+ if not cmd["sender"] == sender:
send('ERROR: only the original creator can cancel this command')
return 1
del(scheduled_cmds[cmd_name])
- send('Canceled {}'.format(cmd_name))
+ send('Cancelled the {} cmd "{}"'.format(cmd["schedule"], cmd_name))
return 0
+cmds["cancel"] = cancel
+
def main():
if len(sys.argv) > 1 and sys.argv[1] in ["-d", "--dry-run"]:
global dry_run
@@ -457,27 +501,46 @@ def main():
send('ERROR: unknown cmd. Enter !help for a list of commands.')
# Handle scheduled commands
- now = datetime.now()
- day_delta = timedelta(60 * 60 * 24)
- week_delta = day_delta * 7
- year_delta = day_delta * 365
- for name, cmd in scheduled_cmds.items():
- run = False
- last_time = datetime.fromtimestamp(cmd.last_time)
+ global record_changes
+ record_changes = False
- if cmd.schedule == "y":
- run = now - last_time > year_delta
- elif cmd.schedule == "w":
- run = now.month > last_time.month and now.day >= last_time.day
+ now = datetime.now().date()
+ week_delta = timedelta(days=7)
+ year_delta = timedelta(days=365)
+ for name, cmd in scheduled_cmds.items():
- run = run or last_time.month == 12 and now.year > last_time.year\
- and now.day >= last_time.day
+ last_time = cmd["last_time"]
+ if hasattr(date, "fromisoformat"):
+ last_time = date.fromisoformat(last_time)
else:
- run = now - last_time > week_delta
+ last_time = date(*map(int, last_time.split("-")))
+
+ d = last_time
+ while True:
+ if cmd["schedule"] == "yearly":
+ d = date(d.year+1, d.month, d.day)
+ elif cmd["schedule"] == "monthly":
+ if d.day > 28:
+ d = date(d.year, d.month, 28)
+
+ if d.month == 12:
+ d = date(d.year+1, 1, d.day)
+ else:
+ d = date(d.year, d.month+1, d.day)
+ else:
+ d = d + timedelta(7)
+
+ if d <= now:
+ send("Running {} command {} for {} triggert on {}\n".format(cmd["schedule"],
+ name,
+ num2name[cmd["sender"]],
+ d.isoformat()))
+
+ cmds[cmd["cmd"][0]](cmd["sender"], cmd["cmd"], "")
+ cmd["last_time"] = d.isoformat()
+ else:
+ break
- if run:
- cmds[cmd.cmd[0]](cmd.sender, cmd.cmd, "")
- cmd["last_time"] = now.timestamp()
with open(state_file, "w") as f:
json.dump(state, f)