From 6fd6420899826f231496c6c273f9cf2191c08b45 Mon Sep 17 00:00:00 2001 From: Pratyush Desai Date: Sun, 16 Jun 2024 23:47:49 +0530 Subject: [PATCH] Add the prev build in branch for ref Signed-off-by: Pratyush Desai --- .gitignore | 2 + README.md | 8 +- config.py | 13 +- plugin.py | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 342 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 0a10c5b..b256d59 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ venv/ .vscode +notes.txt + diff --git a/README.md b/README.md index cb244cf..07eb0f3 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ -Log and annotate your doses +# IRC DOSE MONITORING and MANAGEMENT UTILITY + +Built around the Limnoria Bot Framework. + +It's a tool to log and retrieve doses. + + diff --git a/config.py b/config.py index 4f3f9da..136b9b0 100644 --- a/config.py +++ b/config.py @@ -1,5 +1,5 @@ ### -# Copyright (c) 2021, Pratyush Desai +# Copyright (c) 2020, mogad0n # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,9 +29,11 @@ ### from supybot import conf, registry + try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('DoseLogs') + + _ = PluginInternationalization("Tripsit") except: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -44,12 +46,13 @@ def configure(advanced): # user or not. You should effect your configuration by manipulating the # registry as appropriate. from supybot.questions import expect, anything, something, yn - conf.registerPlugin('DoseLogs', True) + + conf.registerPlugin("Tripsit", True) -DoseLogs = conf.registerPlugin('DoseLogs') +Tripsit = conf.registerPlugin("Tripsit") # This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(DoseLogs, 'someConfigVariableName', +# conf.registerGlobalValue(Tripsit, 'someConfigVariableName', # registry.Boolean(False, _("""Help for someConfigVariableName."""))) diff --git a/plugin.py b/plugin.py index 793bfdb..0b70f4f 100644 --- a/plugin.py +++ b/plugin.py @@ -1,8 +1,8 @@ ### -# Copyright (c) 2021, Pratyush Desai +# Copyright (c) 2020, mogad0n # All rights reserved. # -# Redistribution and use in source and binary forms, with or without +# Redistribution and use in source and binary forms, with or wthout # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, @@ -28,17 +28,25 @@ ### -# My Libs - -import pickle - - -from supybot import utils, plugins, ircutils, callbacks -from supybot import conf +from humanize import ordinal +from supybot import utils, plugins, ircutils, callbacks, world, conf, log from supybot.commands import * + + +from num2words import num2words +import dateutil.parser +import json +import requests +import pickle +import sys +import datetime +import time +import pytz + try: from supybot.i18n import PluginInternationalization - _ = PluginInternationalization('DoseLogs') + + _ = PluginInternationalization("DoseLogs") except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module @@ -46,18 +54,318 @@ except ImportError: filename = conf.supybot.directories.data.dirize("DoseLogs.db") -# Routes of Administration - -ROA = { - -} class DoseLogs(callbacks.Plugin): - """Log and annotate your doses""" + """Tools for tracking and controlling substance use""" + threaded = True + def __init__(self, irc): + self.__parent = super(DoseLogs, self) + self.__parent.__init__(irc) + self.db = {} + self._loadDb() + world.flushers.append(self._flushDb) -Class = DoseLogs + def _loadDb(self): + """Loads the (flatfile) database mapping nicks to doses.""" + + try: + with open(filename, "rb") as f: + self.db = pickle.load(f) + except Exception as e: + self.log.debug("DoseLogs: Unable to load pickled database: %s", e) + + def _flushDb(self): + """Flushes the (flatfile) database mapping nicks to doses.""" + + try: + with open(filename, "wb") as f: + pickle.dump(self.db, f, 2) + except Exception as e: + self.log.warning("DoseLogs: Unable to write pickled database: %s", e) + + def die(self): + self._flushDb() + world.flushers.remove(self._flushDb) + self.__parent.die() + + def set(self, irc, msg, args, timezone): + """ + + Sets location for your current nick to + for eg. America/Chicago + """ + nick = msg.nick + try: + timezone = pytz.timezone(timezone) + if nick in self.db: + self.db[nick]["timezone"] = timezone + else: + self.db[nick] = {"timezone": timezone} + irc.replySuccess() + except pytz.UnknownTimeZoneError: + irc.error(_("Unknown timezone"), Raise=True) + + set = wrap(set, ["something"]) + + @wrap( + [getopts({"ago": "something"}), "something", "something", optional("something")] + ) + def idose(self, irc, msg, args, opts, dose, name, method): + """[--ago ] [] + + Logs a dose for your nick, Ex. @idose --ago 0100 20mg mph oral + would log that dose as if it was taken an hour ago. + [--ago] and [ROA] fields are optional + """ + opts = dict(opts) + found_method = False + onset = None + methods = [] + if method: + methods = [method.lower()] + methods = METHODS.get(methods[0], methods) + + drug_and_method = name + if method: + if not found_method: + method = method.title() + drug_and_method = "%s via %s" % (drug_and_method, method) + else: + method = "Undefined" + + nick = msg.nick + if nick in self.db: + timezone = self.db[nick].get("timezone", "UTC") + tz = pytz.timezone(str(timezone)) + time = datetime.datetime.now(tz=tz) + dose_td = 0 + if "ago" in opts and len(opts["ago"]) == 4: + ago = opts["ago"] + dose_td = datetime.timedelta(hours=int(ago[0:2]), minutes=int(ago[2:4])) + dose_td_s = dose_td.total_seconds() + time = time - dose_td + doseLog = {"time": time, "dose": dose, "drug": name, "method": method} + doses = self.db[nick].get("doses") + if doses: + doses.append(doseLog) + else: + doses = [doseLog] + self.db[nick]["doses"] = doses + else: + timezone = "UTC" + tz = pytz.timezone(timezone) + time = datetime.datetime.now(tz=tz) + dose_td = 0 + if "ago" in opts and len(opts["ago"]) == 4: + ago = opts["ago"] + dose_td = datetime.timedelta(hours=int(ago[0:2]), minutes=int(ago[2:4])) + dose_td_s = dose_td.total_seconds() + time = time - dose_td + doseLog = {"time": time, "dose": dose, "drug": name, "method": method} + doses = [doseLog] + self.db[nick] = {"timezone": timezone, "doses": doses} + + if dose_td == 0: + re = utils.str.format( + "You dosed %s of %s at %s, %s", + dose, + drug_and_method, + time.strftime("%c"), + timezone, + ) + if onset is not None: + re += utils.str.format( + ". You should start feeling effects %s from now", onset + ) + else: + re = utils.str.format( + "You dosed %s of %s at %s, %s ; %T ago", + dose, + drug_and_method, + time.strftime("%c"), + timezone, + dose_td.total_seconds(), + ) + if onset is not None: + re += utils.str.format( + ". You should have/will start feeling effects %s from/after dosing", + onset, + ) + # re=":-( This is currently not available, sorry. Exception ID T0T4LLYFCK3D." + irc.reply(re) + + @wrap([optional("positiveInt")]) + def undose(self, irc, msg, args, entry): + """ + + removes your last dose entry, if is provided then + deletes the nth last dose + """ + nick = msg.nick + if nick in self.db: + nick_dose_log = self.db[nick]["doses"] + if entry: + try: + del nick_dose_log[-int(entry)] + entry = num2words(entry, to="ordinal") + irc.replySuccess( + f"Deleted the {entry} last dose logged for {nick} " + ) + except IndexError: + irc.error("The dose entry doesn't exist") + return + else: + del nick_dose_log[-1] + irc.replySuccess(f"Deleted the last dose logged for {nick} ") + else: + irc.error(f"No doses saved for {nick}") + + def doseslogged(self, irc, msg, args): + """ + This command takes no arguments. + + Retrieves the number of doses logged for a given nick + """ + nick = msg.nick + if nick in self.db: + try: + nick_dose_log_count = len(self.db[nick]["doses"]) + nick_dose_log_since = self.db[nick]["doses"][0]["time"] + nick_dose_log_since_string = nick_dose_log_since.strftime("%c") + irc.reply( + f"{nick} has logged {nick_dose_log_count} doses since {nick_dose_log_since_string}" + ) + except IndexError: + irc.error("Can't seem to do math, check logs") + else: + irc.error(f"No doses saved for {nick}") + + doseslogged = wrap(doseslogged) + + @wrap([optional("positiveInt")]) + def lastdose(self, irc, msg, args, history): + """ + + retrieves your th last logged dose + """ + nick = msg.nick + if nick in self.db: + if history: + try: + lastdose = self.db[nick]["doses"][-int(history)] + except IndexError: + irc.error("You haven't logged that many doses") + return + else: + lastdose = self.db[nick]["doses"][-1] + dose = lastdose["dose"] + drug = lastdose["drug"] + method = lastdose["method"] + dose_time = lastdose["time"] + timezone = self.db[nick]["timezone"] + tz = pytz.timezone(str(timezone)) + time = datetime.datetime.now(tz=tz) + since_dose = time - dose_time + since_dose_seconds = since_dose.total_seconds() + if history: + history = num2words(history, to="ordinal") + re = utils.str.format( + "Your %i last dose was %s of %s via %s at %s %s, %T ago", + history, + dose, + drug, + method, + dose_time.strftime("%c"), + timezone, + since_dose_seconds, + ) + else: + re = utils.str.format( + "You last dosed %s of %s via %s at %s %s, %T ago", + dose, + drug, + method, + dose_time.strftime("%c"), + timezone, + since_dose_seconds, + ) + irc.reply(re) + else: + irc.error(f"No doses saved for {nick}") + + @wrap(["positiveInt"]) + def listdose(self, irc, msg, args, history): + """ + + retrieves your last logged doses + + """ + if history > 20: + irc.error("you can't retrieve more than 20 doses") + return + nick = msg.nick + if nick in self.db: + try: + rangecheck = self.db[nick]["doses"][-int(history)] + irc.reply(f"Your last {history} doses logged are:", private=True) + for number in range(history, 0, -1): + lastdose = self.db[nick]["doses"][-int(number)] + dose = lastdose["dose"] + drug = lastdose["drug"] + method = lastdose["method"] + dose_time = lastdose["time"] + timezone = self.db[nick]["timezone"] + tz = pytz.timezone(str(timezone)) + time = datetime.datetime.now(tz=tz) + since_dose = time - dose_time + since_dose_seconds = since_dose.total_seconds() + if number == 1: + number = "The" + else: + number = num2words(number, to="ordinal") + re = utils.str.format( + "::> %i last dose: Amount: %s of \x02%s\x0F via %s | datetime: %s %s | timedelta %T ", + number, + dose, + drug, + method, + dose_time.strftime("%c"), + timezone, + since_dose_seconds, + ) + irc.reply(re, private=True) + except IndexError: + irc.error("You haven't logged that many doses") + return + else: + irc.error(f"No doses saved for {nick}") + + @wrap(["something"]) + def amountdosed(self, irc, msg, args, drug): + """ + + shows Aggregate amount in "mg" for ever logged + """ + num = 0 + unit = "" + nick = msg.nick + if nick in self.db: + doselogs = self.db[nick]["doses"] + for doselog in doselogs: + if doselog["drug"] == drug: + for i, c in enumerate(doselog["dose"]): + if not c.isdigit(): + break + num += int(doselog["dose"][:i]) + unit = doselog["dose"][i:].lstrip() + irc.reply(f"You have dosed a total of {num}{unit} amount of {drug}") + else: + irc.error(f"No doses saved for {nick}") + + +Class = Tripsit # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: