diff --git a/chat_helper.py b/chat_helper.py new file mode 100644 index 0000000..bc63ac7 --- /dev/null +++ b/chat_helper.py @@ -0,0 +1,45 @@ +import json +import requests +import urllib + +from CREDENTIALS import * + +URL = "https://api.telegram.org/bot{}/".format(TOKEN) + +def get_url(url): + response = requests.get(url) + content = response.content.decode("utf8") + return content + +def get_json_from_url(url): + content = get_url(url) + js = json.loads(content) + return js + +def get_updates(offset=None): + url = URL + "getUpdates?timeout=100" + if offset: + url += "&offset={}".format(offset) + js = get_json_from_url(url) + return js + +def get_last_update_id(updates): + update_ids = [] + for update in updates["result"]: + update_ids.append(int(update["update_id"])) + return max(update_ids) + +def build_keyboard(items, style="vert"): + if style == "vert": + keyboard = [[item] for item in items] + else: + keyboard = [[item for item in items]] + reply_markup = {"keyboard":keyboard, "one_time_keyboard": True} + return json.dumps(reply_markup) + +def send_message(text, chat_id, reply_markup=None): + text = urllib.quote_plus(text) + url = URL + "sendMessage?text={}&chat_id={}&parse_mode=Markdown".format(text, chat_id) + if reply_markup: + url += "&reply_markup={}".format(reply_markup) + get_url(url) diff --git a/dbhelper.py b/dbhelper.py index ffaf3b3..2ecbd02 100644 --- a/dbhelper.py +++ b/dbhelper.py @@ -1,17 +1,21 @@ import sqlite3 class DBHelper: - def __init__(self, dbname="todo.sqlite"): + def __init__(self, dbname="efb.sqlite"): self.dbname = dbname self.conn = sqlite3.connect(dbname) def setup(self): - tblstmt = "CREATE TABLE IF NOT EXISTS items (description text, owner text)" - itemidx = "CREATE INDEX IF NOT EXISTS itemIndex ON items (description ASC)" - ownidx = "CREATE INDEX IF NOT EXISTS ownIndex ON items (owner ASC)" - self.conn.execute(tblstmt) - self.conn.execute(itemidx) - self.conn.execute(ownidx) + create_item_table = "CREATE TABLE IF NOT EXISTS items (description text, owner text)" + create_item_index = "CREATE INDEX IF NOT EXISTS itemIndex ON items (description ASC)" + create_owner_index = "CREATE INDEX IF NOT EXISTS ownIndex ON items (owner ASC)" + create_feelings_table = "CREATE TABLE IF NOT EXISTS feelings (created_at datetime, owner text, rating integer, description text)" + create_feelings_config = "CREATE TABLE IF NOT EXISTS feelingsConfig (owner text PRIMARY KEY, frequency text, time_pref text)" + self.conn.execute(create_item_table) + self.conn.execute(create_item_index) + self.conn.execute(create_owner_index) + self.conn.execute(create_feelings_table) + self.conn.execute(create_feelings_config) self.conn.commit() def add_item(self, item_text, owner): @@ -30,3 +34,29 @@ def get_items(self, owner): stmt = "SELECT description FROM items WHERE owner = (?)" args = (owner, ) return [x[0] for x in self.conn.execute(stmt, args)] + + def add_feeling_report(self, created_at, owner, rating, description=None): + stmt = "INSERT INTO feelings (created_at, owner, rating, description) VALUES (?, ?, ?, ?)" + args = (created_at, owner, rating, description) + self.conn.execute(stmt, args) + self.conn.commit() + + def get_feeling_report(self, owner): + stmt = "SELECT rating FROM feelings WHERE owner = (?)" + + def set_feelings_config_frequency(self, owner, frequency): + stmt = "INSERT OR REPLACE INTO feelingsConfig (owner, frequency) VALUES (?, ?)" + args = (owner, frequency) + self.conn.execute(stmt, args) + self.conn.commit() + + def set_feelings_config_time_pref(self, owner, time_pref): + stmt = "UPDATE feelingsConfig SET time_pref = (?) WHERE owner = (?)" + args = (time_pref, owner) + self.conn.execute(stmt, args) + self.conn.commit() + + def get_feelings_config(self, owner): + stmt = "SELECT frequency, time_pref FROM feelingsConfig WHERE owner = (?)" + args = (owner, ) + return [x for x in self.conn.execute(stmt, args)] diff --git a/executive-function-bot.py b/executive-function-bot.py new file mode 100644 index 0000000..f1924a6 --- /dev/null +++ b/executive-function-bot.py @@ -0,0 +1,62 @@ +import time +import json +import schedule + +import chat_helper +from dbhelper import DBHelper +import todo_list as todo +import feeling_tracker as ft + +db = DBHelper() + +def command_handler(text, chat_id): + if text == "/start": + start_message = """Welcome to the Executive Function Bot. I'm here to + help you get things done. For now, I operate as a traditional To Do list. + Tell me things that you want to do and use /done to mark them complete. + """ + chat_helper.send_message(start_message, chat_id) + elif text.startswith("/todo"): + return todo.command_handler(text, chat_id) + elif text.startswith("/feelingtracker"): + return ft.command_handler(text, chat_id) + elif text == "/debug": + ft.debug(chat_id) + else: + chat_helper.send_message("I'm sorry, I don't know that command. Use /help for a list of commands.", chat_id) + +def listener_handler(listener, text, chat_id): + if listener.startswith("todo"): + chat_helper.send_message(todo.listener_handler(listener, text, chat_id), chat_id) + elif listener.startswith("feelingtracker"): + return ft.listener_handler(listener, text, chat_id) + +def handle_updates(updates, listener): + for update in updates["result"]: + text = update["message"]["text"] + chat = update["message"]["chat"]["id"] + + if text.startswith("/"): + return command_handler(text, chat) + elif listener is not None: + return listener_handler(listener, text, chat) + elif text == "end": + return None + else: + continue + +def main(): + db.setup() + last_update_id = None + listener = None + while True: + updates = chat_helper.get_updates(last_update_id) + if len(updates["result"]) > 0: + last_update_id = chat_helper.get_last_update_id(updates) + 1 + listener = handle_updates(updates, listener) + schedule.run_pending() + time.sleep(0.5) + +if __name__ == '__main__': + main() +chat_helper.send_message(text, chat) diff --git a/feeling_tracker.py b/feeling_tracker.py new file mode 100644 index 0000000..61ce3dc --- /dev/null +++ b/feeling_tracker.py @@ -0,0 +1,61 @@ +import datetime +import schedule + +import chat_helper +from dbhelper import DBHelper + +db = DBHelper() + +def set_frequency(owner, frequency): + db.set_feelings_config_frequency(owner, frequency) + +def set_time_pref(owner, time_pref): + db.set_feelings_config_time_pref(owner, time_pref) + +def prompt_user(owner): + options = ["1", "2", "3", "4","5"] + keyboard = chat_helper.build_keyboard(options, "hoz") + chat_helper.send_message("How are you feeling?", owner, keyboard) + # Set listener to record the feeling rating + +def initialize_schedule(owner): + config = db.get_feelings_config(owner) + frequency = {"Daily" : 24, "A few times a day" : 4, "Hourly" : 1 } + # config[0][0] is frequency + # config[0][1] is time pref + schedule.every(frequency[config[0][0]]).hours.do(prompt_user, owner) + +def debug(owner): + initialize_schedule(owner) + prompt_user(owner) + print schedule.jobs + +def command_handler(text, chat_id): + if text == "/feelingtrackerstart": + chat_helper.send_message("Feeling Tracking Enabled", chat_id) + options = ["Daily", "A few times a day", "Hourly"] + keyboard = chat_helper.build_keyboard(options) + chat_helper.send_message("How often would you like to talk about your feelings?", chat_id, keyboard) + return "feelingtrackerconfigfrequency" + +def listener_handler(listener, text, chat_id): + if listener == "feelingtrackerconfigfrequency": + set_frequency(chat_id, text) + options = ["Morning", "Afternoon", "Evening", "Throughout the day"] + keyboard = chat_helper.build_keyboard(options) + chat_helper.send_message("Do you have a preference of when you want to talk about your feelings?", chat_id, keyboard) + return "feelingtrackerconfigtime" + elif listener == "feelingtrackerconfigtime": + set_time_pref(chat_id, text) + initialize_schedule(chat_id) + chat_helper.send_message("Thanks for letting me know! I'll be in touch!", chat_id) + elif listener == "feelingtrackerrating": + # Add rating to database with timestamp + chat_helper.send_message("Would you like to tell me about it?", chat_id) + # Send keyboard options for "yes", "no"? + # If yes, continue to record feelings + return "feelingtrackerdescription" + # If no, say "Not a problem. Have a great day!" and quit + elif listener == "feelingtrackerdescription": + # Add description to database with timestamp + chat_helper.send_message("Thanks for talking to me about it. Is there anything else you want to say?", chat_id) diff --git a/todo_list.py b/todo_list.py new file mode 100644 index 0000000..cf979b8 --- /dev/null +++ b/todo_list.py @@ -0,0 +1,33 @@ +import chat_helper + +from dbhelper import DBHelper + +db = DBHelper() + +def get_item_list(owner): + items = db.get_items(owner) + return "\n".join(items) + +def add_item_to_list(item, owner): + db.add_item(item, owner) + +def remove_item_from_list(item, owner): + db.delete_item(item, owner) + +def command_handler(text, chat_id): + todoitems = db.get_items(chat_id) + if text == "/todoadditem": + chat_helper.send_message("What do you need to do?", chat_id) + return "todoadd" + elif text == "/todoremoveitem": + keyboard = chat_helper.build_keyboard(todoitems) + chat_helper.send_message("Select an item to mark complete", chat_id, keyboard) + return "todoremove" + +def listener_handler(listener, text, chat_id): + if listener == "todoremove": + remove_item_from_list(text, chat_id) + return get_item_list(chat_id) + elif listener == "todoadd": + add_item_to_list(text, chat_id) + return get_item_list(chat_id) diff --git a/todobot.py b/todobot.py deleted file mode 100644 index fac6461..0000000 --- a/todobot.py +++ /dev/null @@ -1,82 +0,0 @@ -import time -import json -import requests -import urllib - -from CREDENTIALS import * -from dbhelper import DBHelper - -db = DBHelper() -URL = "https://api.telegram.org/bot{}/".format(TOKEN) - -def get_url(url): - response = requests.get(url) - content = response.content.decode("utf8") - return content - -def get_json_from_url(url): - content = get_url(url) - js = json.loads(content) - return js - -def get_updates(offset=None): - url = URL + "getUpdates?timeout=100" - if offset: - url += "&offset={}".format(offset) - js = get_json_from_url(url) - return js - -def get_last_update_id(updates): - update_ids = [] - for update in updates["result"]: - update_ids.append(int(update["update_id"])) - return max(update_ids) - -def build_keyboard(items): - keyboard = [[item] for item in items] - reply_markup = {"keyboard":keyboard, "one_time_keyboard": True} - return json.dumps(reply_markup) - -def send_message(text, chat_id, reply_markup=None): - text = urllib.quote_plus(text) - url = URL + "sendMessage?text={}&chat_id={}&parse_mode=Markdown".format(text, chat_id) - if reply_markup: - url += "&reply_markup={}".format(reply_markup) - get_url(url) - -def handle_updates(updates): - for update in updates["result"]: - text = update["message"]["text"] - chat = update["message"]["chat"]["id"] - items = db.get_items(chat) - if text == "/done": - keyboard = build_keyboard(items) - send_message("Select an item to mark complete", chat, keyboard) - elif text == "/start": - send_message("Welcome to the Executive Function Bot. I'm here to help you get things done. For now, I operate as a traditional To Do list. Tell me things that you want to do and use /done to mark them complete", chat) - elif text.startswith("/"): - continue - elif text in items: - db.delete_item(text, chat) - items = db.get_items(chat) - message = "\n".join(items) - send_message(message, chat) - else: - db.add_item(text, chat) - items = db.get_items(chat) - message = "\n".join(items) - send_message(message, chat) - -def main(): - db.setup() - last_update_id = None - while True: - updates = get_updates(last_update_id) - if len(updates["result"]) > 0: - last_update_id = get_last_update_id(updates) + 1 - handle_updates(updates) - time.sleep(0.5) - -if __name__ == '__main__': - main() -send_message(text, chat)