Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Feeling tracker #2

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
156272b
Begin separating ToDo functions from __main__
Apr 3, 2018
192097f
Rearranged update handling
Apr 3, 2018
46b164a
Abstract out `get_item_list` function
Apr 3, 2018
cdfd22f
Add listener
Apr 3, 2018
58b2f10
Set up basic config prompts
Apr 3, 2018
c6a14af
Add basic schedule handler
Apr 3, 2018
7302bc4
Outlining the next sections
Apr 3, 2018
2ec8f5b
Move keyboard function back into main file
Apr 3, 2018
dbe603e
Add keyboards for config responses
Apr 4, 2018
1921124
First attempt at creating database tables for FT
Apr 4, 2018
238b588
Add basic functions for FT config settings
Apr 4, 2018
9fa08c8
Refactor away from huge function
Apr 4, 2018
8f4e63a
Build listener handler
Apr 4, 2018
5e4ae4e
Move many chat functions to separate helper
Apr 4, 2018
42db2b9
Moving build_keyboard to chat_helper as well
Apr 4, 2018
1bc6633
Create Feeling Tracker command_handler
Apr 4, 2018
8315607
Create listener_handler for feelings
Apr 4, 2018
cba87bb
Remove DEBUG statements
Apr 4, 2018
5f8c8c0
Forgot to save
Apr 4, 2018
0383982
Fix continue syntax error
Apr 4, 2018
f8a7896
Add a basic debug scheduler to see how it works
Apr 4, 2018
57e2fb7
Pull out frequency from config and use it to set schedule
Apr 4, 2018
8e60900
Add basic keyboard for user prompt
Apr 4, 2018
03fba27
Initialize schedule for user after setting preferences
Apr 4, 2018
64ebcff
Scaffolding listener for recording feelings
Apr 4, 2018
d735265
Fix reference error
Apr 4, 2018
3a33f98
Build horizontal keyboard
ThirdEyeRose Apr 6, 2018
dc89b8c
Consolidate keyboard building functions
ThirdEyeRose Apr 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions chat_helper.py
Original file line number Diff line number Diff line change
@@ -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)
44 changes: 37 additions & 7 deletions dbhelper.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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)]
62 changes: 62 additions & 0 deletions executive-function-bot.py
Original file line number Diff line number Diff line change
@@ -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)
61 changes: 61 additions & 0 deletions feeling_tracker.py
Original file line number Diff line number Diff line change
@@ -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)
33 changes: 33 additions & 0 deletions todo_list.py
Original file line number Diff line number Diff line change
@@ -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)
82 changes: 0 additions & 82 deletions todobot.py

This file was deleted.