123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- import sqlite3
- from flask import current_app, g
- from ownchatbot.reward_handlers import goal_reached, get_queue
- from flask.cli import with_appcontext
- import click
- from time import time
- def rem_from_queue(reward_name): # Remove a reward from the queue
- db = get_db()
- try:
- cursor = db.execute(
- "DELETE FROM reward_queue WHERE reward = ?", (reward_name,)
- )
- db.commit()
- except sqlite3.Error as rfqerror:
- print(f'Couldn\'t remove {reward_name} from reward queue: {rfqerror.args[0]}')
- return False
- return True
- def init_app(app):
- app.teardown_appcontext(close_db)
- app.cli.add_command(init_db_command)
-
- def get_db():
- if 'db' not in g:
- g.db = sqlite3.connect(
- current_app.config['DATABASE'],
- detect_types=sqlite3.PARSE_DECLTYPES
- )
- g.db.row_factory = sqlite3.Row
- return g.db
- def close_db(e=None):
- db = g.pop('db', None)
- if db is not None:
- db.close()
- def init_db(): # Setup the database. If it already exists, apply new schema
- db = get_db()
- with current_app.open_resource('schema.sql') as f: # Set up database
- db.executescript(f.read().decode('utf8'))
- reread_votes()
- reread_goals()
- if get_queue(db): # Make sure database is initialized
- return True
- @click.command('init-db')
- @with_appcontext
- def init_db_command(): # If there is already a database, clear it and do setup
- if init_db():
- click.echo('Database initialized.')
- def clear_reward_queue(): # Completely clear the reward queue
- db = get_db()
- try:
- cursor = db.execute(
- "DELETE FROM reward_queue"
- )
- cursor.execute(
- "UPDATE votes SET count = 0"
- )
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t clear reward queue: {serror.args[0]}')
- return False
- return True
- def clear_fulfilled_rewards(): # Clears only fulfilled rewards from the queue
- db = get_db()
- try:
- cursor = db.execute(
- "DELETE FROM reward_queue WHERE fulfilled = 1"
- )
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t clear fulfilled rewards: {serror.args[0]}')
- return False
- return True
- def rem_all_votes(): # USED TO BE "clear_votes" Clear all votes from the database
- db = get_db()
- try:
- db.execute("DELETE FROM votes")
- db.commit()
- except sqlite3.Error as cverror:
- print(f'Couldn\'t clear all votes: {cverror.args[0]}')
- return False
- if put_votes(db):
- return True
- def rem_vote(): # Remove a single vote from the database
- db = get_db(vote)
- try:
- db.execute("DELETE FROM votes WHERE name = ?", ('vote',))
- db.commit()
- except sqlite3.Error as rverror:
- print(f'Couldn\'t remove \"{vote}\" from database: {rverror.args[0]}')
- return False
- if put_votes(db):
- return True
- def is_cool(reward_name): # Check if a reward is cooling down.
- current_time = time() # In seconds
- rewards = current_app.config['REWARDS']
- this_cool_down = rewards[reward_name]['cooldown']
- if this_cool_down > 0: # If this reward has a cooldown
- try: # Get the cooldown time for it
- db = get_db()
- cursor = db.execute(
- "SELECT created FROM cool_downs WHERE reward = ?", (reward_name,)
- )
- current_cds = cursor.fetchall()
- except sqlite3.Error as icerror:
- print(f'Couldn\'t get \"{reward_name}\" from database: {icerror.args[0]}')
- if current_cds:
- last_time = current_cds[0][0]
- hot_time = current_time - last_time
- if hot_time < this_cool_down * 60: # If it is in the database and still within the cooldown time, return False
- hot_time = this_cool_down - (hot_time / 60) # Get remaining minutes in cooldown
- return False, hot_time # Return False, and the time left on the cooldown
- else: # If it is in the database and the cooldown has expired, update the cooldown time, and return True
- try:
- db.execute(
- "UPDATE cool_downs SET created = ? WHERE reward = ?",
- (current_time, reward_name)
- )
- db.commit()
- return True, 0
- except sqlite3.Error as scerror:
- print(f'Couldn\'t update \"{reward_name}\"\'s cooldown time in the database: {scerror.args[0]}')
- else: # If it is not in the database, add it and return True
- try:
- db.execute(
- "INSERT INTO cool_downs(created, reward) VALUES(?, ?)",
- (current_time, reward_name)
- )
- db.commit()
- return True, 0
- except sqlite3.Error as scerror:
- print(f'Couldn\'t add \"{reward_name}\" to database: {scerror.args[0]}')
- else: # If the redeem has no cooldown
- return True, 0
- def rem_cool(reward_name): # Remove a reward from the database
- try:
- db = get_db()
- cursor = db.execute(
- "DELETE FROM cool_downs WHERE reward = ?", (reward_name,)
- )
- current_cds = cursor.fetchall()
- except sqlite3.Error as icerror:
- print(f'Couldn\'t remove \"{reward_name}\" from database: {icerror.args[0]}')
- return False
- return True
- def put_votes(db): # Reread votes from rewards.py, and sync with database
- info = details['info']
- for reward, details in current_app.config['REWARDS'].items():
- if details['type'] == 'vote':
- try:
- db.execute(
- "INSERT INTO votes(name, count, info) VALUES(?, 0, ?)",
- (reward, info)
- )
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t insert \"{vote}\" into database: {serror.args[0]}')
- return False
- return True
- def reread_votes(): # Reread votes from rewards.py, and sync with database
- db = get_db()
- try: # Remove votes not in rewards.py
- cursor = db.execute("SELECT name FROM votes")
- votes = cursor.fetchall()
- chopping_block = []
- for vote in votes:
- vote = vote[0]
- if vote not in current_app.config['REWARDS'].keys():
- chopping_block.append(vote)
- elif current_app.config['REWARDS'][vote]['type'] != 'vote':
- chopping_block.append(vote)
- for vote in chopping_block:
- cursor.execute("DELETE FROM votes WHERE name = ?", (vote,))
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t clear deleted votes from database: {serror.args[0]}')
- return False
- try: # Add new votes found in rewards.py
- for reward, details in current_app.config['REWARDS'].items():
- if details['type'] == 'vote': # Check if the vote is already in the database
- cursor = db.execute(
- "SELECT count FROM votes WHERE name = ?",
- (reward,)
- )
- result = cursor.fetchone()
- if result is None: # If it isn't, add it
- info = details['info']
- if details['type'] == 'vote':
- db.execute(
- "INSERT INTO votes(name, count, info) VALUES(?, 0, ?)",
- (reward, details["info"])
- )
- else: # If it is, update the info
- cursor.execute(
- "UPDATE votes SET info = ? WHERE name = ?",
- (details['info'], reward)
- )
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t insert \"{vote}\" into database: {serror.args[0]}')
- return False
- return True
- def reread_goals(): # Reread goals from rewards.py, and sync with database
- db = get_db()
- try: # Remove goals not in rewards.py
- cursor = db.execute("SELECT name FROM goals")
- goals = cursor.fetchall()
- chopping_block = []
- for goal in goals:
- goal = goal[0]
- if goal not in current_app.config['REWARDS'].keys():
- chopping_block.append(goal)
- elif current_app.config['REWARDS'][goal]['type'] != 'goal':
- chopping_block.append(goal)
- for goal in chopping_block:
- cursor.execute("DELETE FROM goals WHERE name = ?", (goal,))
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t clear removed goals from database: {serror.args[0]}')
- return False
- try: # Add new goals found in rewards.py
- for reward, details in current_app.config['REWARDS'].items():
- if details['type'] == 'goal': # Check if the goal is already in the database
- cursor = db.execute(
- "SELECT target FROM goals WHERE name = ?",
- (reward,)
- )
- result = cursor.fetchone()
- if result is None: # If it isn't, add it
- cursor.execute(
- "INSERT INTO goals(name, progress, target, info, complete) VALUES(?, 0, ?, ?, FALSE)",
- (reward, details['target'], details['info'])
- )
- elif result != details['target']: # If it is, update the target
- cursor.execute(
- "UPDATE goals SET target = ?, info = ? WHERE name = ?",
- (details["target"], details["info"], reward)
- )
- db.commit()
- except sqlite3.Error as serror:
- print(f'Couldn\'t insert \"{reward}\" into database: {serror.args[0]}')
- return False
- return True
- def reset_goal(goal): # Set goal progress back to zero
- if goal not in current_app.config['REWARDS']: # If it doesn't exist in rewards.py
- print(f'Couldn\'t reset goal, {goal} not in rewards file.')
- return False
- try:
- db = get_db()
- target = current_app.config['REWARDS'][goal]['target']
- info = current_app.config['REWARDS'][goal]['info']
- cursor = db.cursor()
- cursor.execute(
- "UPDATE goals SET progress = 0, target = ?, complete = FALSE, info = ? WHERE name = ?",
- (target, info, goal)
- )
- db.commit()
- return True
- except sqlite3.Error as rgerror:
- current_app.logger.error(f'Couldn\'t reset {goal} in the goals table: {rgerror.args[0]}')
- return False
- def reset_vote(vote):
- if vote not in current_app.config['REWARDS']: # Check if it exists in rewards.py
- print(f'Couldn\'t reset vote, {vote} not in rewards file.')
- return False
- else:
- try:
- db = get_db()
- cursor = db.cursor()
- cursor.execute(
- "UPDATE votes SET count = 0, voters = '' WHERE name = ?",
- (vote,)
- )
- db.commit()
- except sqlite3.Error as rverror:
- current_app.logger.error(f'Couldn\'t reset {vote} in the votes table: {rverror.args[0]}')
- return False
- return True
|