Compare commits
	
		
			No commits in common. "2284fb3a00c204d5e53c42c1c5cb99f5a0cdb5a8" and "8c19088640635c804bfe349b89a86ccfc63d3c2e" have entirely different histories.
		
	
	
		
			2284fb3a00
			...
			8c19088640
		
	
		
| @ -329,8 +329,7 @@ REDEEMS={ | |||||||
| ``` | ``` | ||||||
| #### File format | #### File format | ||||||
| `redeems.py` is a config file with just a `REDEEMS` key, that assigns a dictionary of redeems to it. | `redeems.py` is a config file with just a `REDEEMS` key, that assigns a dictionary of redeems to it. | ||||||
| Each dictionary entry is a redeem, and the dictionary keys are strings that decide the chat command for the redeem. | Each dictionary entry is a redeem, and the dictionary keys are strings that decides the chat command for the redeem. | ||||||
| The redeem names shouldn't have spaces in them. |  | ||||||
| The value is another dictionary that needs to have an entry for `"type"` and | The value is another dictionary that needs to have an entry for `"type"` and | ||||||
| an entry for `"price"` for non-milestones or `"goal"` for milestones. | an entry for `"price"` for non-milestones or `"goal"` for milestones. | ||||||
| Optionally, each redeem can also have `"info"` and `"category"` entries. | Optionally, each redeem can also have `"info"` and `"category"` entries. | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							| @ -2,7 +2,7 @@ from setuptools import find_packages, setup | |||||||
| 
 | 
 | ||||||
| setup( | setup( | ||||||
|     name='tlapbot', |     name='tlapbot', | ||||||
|     version='1.2.2', |     version='1.2.1', | ||||||
|     packages=find_packages(), |     packages=find_packages(), | ||||||
|     include_package_data=True, |     include_package_data=True, | ||||||
|     install_requires=[ |     install_requires=[ | ||||||
|  | |||||||
| @ -4,11 +4,11 @@ from flask import Flask | |||||||
| from apscheduler.schedulers.background import BackgroundScheduler | from apscheduler.schedulers.background import BackgroundScheduler | ||||||
| from tlapbot.db import get_db | from tlapbot.db import get_db | ||||||
| from tlapbot.owncast_requests import is_stream_live, give_points_to_chat | from tlapbot.owncast_requests import is_stream_live, give_points_to_chat | ||||||
| 
 | from tlapbot.redeems import remove_inactive_redeems  | ||||||
| 
 | 
 | ||||||
| def create_app(test_config=None): | def create_app(test_config=None): | ||||||
|     app = Flask(__name__, instance_relative_config=True) |     app = Flask(__name__, instance_relative_config=True) | ||||||
| 
 |      | ||||||
|     # ensure the instance folder exists |     # ensure the instance folder exists | ||||||
|     try: |     try: | ||||||
|         os.makedirs(app.instance_path) |         os.makedirs(app.instance_path) | ||||||
| @ -30,18 +30,12 @@ def create_app(test_config=None): | |||||||
|         gunicorn_logger = logging.getLogger('gunicorn.error') |         gunicorn_logger = logging.getLogger('gunicorn.error') | ||||||
|         app.logger.handlers = gunicorn_logger.handlers |         app.logger.handlers = gunicorn_logger.handlers | ||||||
|         app.logger.setLevel(gunicorn_logger.level) |         app.logger.setLevel(gunicorn_logger.level) | ||||||
| 
 |      | ||||||
|     # Check for wrong config that would break Tlapbot |     # Check for wrong config that would break Tlapbot | ||||||
|     if len(app.config['PREFIX']) != 1: |     if len(app.config['PREFIX']) != 1: | ||||||
|         raise RuntimeError("Prefix is >1 character. " |         raise RuntimeError("Prefix is >1 character. " | ||||||
|                            "Change your config to set 1-character prefix.") |                            "Change your config to set 1-character prefix.") | ||||||
| 
 | 
 | ||||||
|     # Check for spaces in redeems (they won't work) |  | ||||||
|     for redeem in app.config['REDEEMS']: |  | ||||||
|         if ' ' in redeem: |  | ||||||
|             app.logger.warning(f"Redeem '{redeem}' has spaces in its name.") |  | ||||||
|             app.logger.warning("Redeems with spaces are impossible to redeem.") |  | ||||||
| 
 |  | ||||||
|     # prepare webhooks and redeem dashboard blueprints |     # prepare webhooks and redeem dashboard blueprints | ||||||
|     from . import owncast_webhooks |     from . import owncast_webhooks | ||||||
|     from . import tlapbot_dashboard |     from . import tlapbot_dashboard | ||||||
| @ -57,7 +51,7 @@ def create_app(test_config=None): | |||||||
|     app.cli.add_command(db.refresh_milestones_command) |     app.cli.add_command(db.refresh_milestones_command) | ||||||
|     app.cli.add_command(db.reset_milestone_command) |     app.cli.add_command(db.reset_milestone_command) | ||||||
|     app.cli.add_command(db.hard_reset_milestone_command) |     app.cli.add_command(db.hard_reset_milestone_command) | ||||||
| 
 |      | ||||||
|     # scheduler job for giving points to users |     # scheduler job for giving points to users | ||||||
|     def proxy_job(): |     def proxy_job(): | ||||||
|         with app.app_context(): |         with app.app_context(): | ||||||
|  | |||||||
| @ -6,7 +6,6 @@ from flask.cli import with_appcontext | |||||||
| 
 | 
 | ||||||
| from tlapbot.redeems import milestone_complete | from tlapbot.redeems import milestone_complete | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| def get_db(): | def get_db(): | ||||||
|     if 'db' not in g: |     if 'db' not in g: | ||||||
|         g.db = sqlite3.connect( |         g.db = sqlite3.connect( | ||||||
| @ -128,7 +127,7 @@ def refresh_milestones(): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def reset_milestone(milestone): | def reset_milestone(milestone): | ||||||
|     if milestone not in current_app.config['REDEEMS']: |     if not milestone in current_app.config['REDEEMS']: | ||||||
|         print(f"Failed resetting milestone, {milestone} not in redeems file.") |         print(f"Failed resetting milestone, {milestone} not in redeems file.") | ||||||
|         return False |         return False | ||||||
|     try: |     try: | ||||||
| @ -148,6 +147,7 @@ def reset_milestone(milestone): | |||||||
|         return False |         return False | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @click.command('init-db') | @click.command('init-db') | ||||||
| @with_appcontext | @with_appcontext | ||||||
| def init_db_command(): | def init_db_command(): | ||||||
| @ -184,7 +184,7 @@ def refresh_and_clear_command(): | |||||||
| @click.command('refresh-milestones') | @click.command('refresh-milestones') | ||||||
| @with_appcontext | @with_appcontext | ||||||
| def refresh_milestones_command(): | def refresh_milestones_command(): | ||||||
|     """Initialize all milestones from the redeems file, |     """Initialize all milestones from the redeems file,  | ||||||
|     delete milestones not in redeem file.""" |     delete milestones not in redeem file.""" | ||||||
|     if refresh_milestones(): |     if refresh_milestones(): | ||||||
|         click.echo('Refreshed milestones.') |         click.echo('Refreshed milestones.') | ||||||
|  | |||||||
| @ -4,27 +4,20 @@ from tlapbot.owncast_requests import send_chat | |||||||
| 
 | 
 | ||||||
| def send_help(): | def send_help(): | ||||||
|     message = [] |     message = [] | ||||||
|     message.append("Tlapbot gives you points for being in chat, and then allows you to spend those points. <br>") |     message.append("Tlapbot gives you points for being in chat, and then allows you to spend those points.\n") | ||||||
|     message.append(f"People connected to chat receive {current_app.config['POINTS_AMOUNT_GIVEN']} points every {current_app.config['POINTS_CYCLE_TIME']} seconds. <br>") |     message.append(f"People connected to chat receive {current_app.config['POINTS_AMOUNT_GIVEN']} points every {current_app.config['POINTS_CYCLE_TIME']} seconds.\n") | ||||||
|     message.append("You can see your points and recent redeems in the Tlapbot dashboard. Look for a button to click under the stream window. <br>") |     message.append("You can see your points and recent redeems in the Tlapbot dashboard. Look for a button to click under the stream window.\n") | ||||||
|     message.append("""Tlapbot commands: <br> |     message.append("""Tlapbot commands: | ||||||
|         !help to see this help message. <br> |         !help to see this help message. | ||||||
|         !points to see your points. <br>""" |         !points to see your points.\n""" | ||||||
|     ) |     ) | ||||||
|     if current_app.config['LIST_REDEEMS']: |     if current_app.config['LIST_REDEEMS']: | ||||||
|         message.append("Active redeems: <br>") |         message.append("Active redeems:\n") | ||||||
|         for redeem, redeem_info in current_app.config['REDEEMS'].items(): |         for redeem, redeem_info in current_app.config['REDEEMS'].items(): | ||||||
|             if redeem_info.get('category', None): |  | ||||||
|                 if not set(redeem_info['category']).intersection(set(current_app.config['ACTIVE_CATEGORIES'])): |  | ||||||
|                     continue |  | ||||||
|             if 'type' in redeem_info and redeem_info['type'] == 'milestone': |  | ||||||
|                 message.append(f"!{redeem} milestone with goal of {redeem_info['goal']}.") |  | ||||||
|             else: |  | ||||||
|                 message.append(f"!{redeem} for {redeem_info['price']} points.") |  | ||||||
|             if 'info' in redeem_info: |             if 'info' in redeem_info: | ||||||
|                 message.append(f" {redeem_info['info']} <br>") |                 message.append(f"!{redeem} for {redeem_info['price']} points. {redeem_info['info']}\n") | ||||||
|             else: |             else: | ||||||
|                 message.append("<br>") |                 message.append(f"!{redeem} for {redeem_info['price']} points.\n") | ||||||
|     else: |     else: | ||||||
|         message.append("Check the dashboard for a list of currently active redeems.") |         message.append("Check the dashboard for a list of currently active redeems.") | ||||||
|     send_chat(''.join(message)) |     send_chat(''.join(message)) | ||||||
|  | |||||||
| @ -2,7 +2,6 @@ from flask import current_app | |||||||
| from sqlite3 import Error | from sqlite3 import Error | ||||||
| from re import sub | from re import sub | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| # # # db stuff # # # | # # # db stuff # # # | ||||||
| def read_users_points(db, user_id): | def read_users_points(db, user_id): | ||||||
|     """Errors out if user doesn't exist.""" |     """Errors out if user doesn't exist.""" | ||||||
| @ -98,7 +97,7 @@ def add_user_to_database(db, user_id, display_name): | |||||||
| 
 | 
 | ||||||
| def change_display_name(db, user_id, new_name): | def change_display_name(db, user_id, new_name): | ||||||
|     try: |     try: | ||||||
|         db.execute( |         cursor = db.execute( | ||||||
|             "UPDATE points SET name = ? WHERE id = ?", |             "UPDATE points SET name = ? WHERE id = ?", | ||||||
|             (new_name, user_id) |             (new_name, user_id) | ||||||
|         ) |         ) | ||||||
| @ -110,7 +109,7 @@ def change_display_name(db, user_id, new_name): | |||||||
| 
 | 
 | ||||||
| def remove_duplicate_usernames(db, user_id, username): | def remove_duplicate_usernames(db, user_id, username): | ||||||
|     try: |     try: | ||||||
|         db.execute( |         cursor = db.execute( | ||||||
|             """UPDATE points |             """UPDATE points | ||||||
|             SET name = NULL |             SET name = NULL | ||||||
|             WHERE name = ? AND NOT id = ?""", |             WHERE name = ? AND NOT id = ?""", | ||||||
| @ -122,7 +121,6 @@ def remove_duplicate_usernames(db, user_id, username): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # # # misc. stuff # # # | # # # misc. stuff # # # | ||||||
| # This is now unused since rawBody attribute of the webhook now returns cleaned-up emotes. |  | ||||||
| def remove_emoji(message): | def remove_emoji(message): | ||||||
|     return sub( |     return sub( | ||||||
|         r'<img class="emoji" alt="(:.*?:)" title=":.*?:" src="/img/emoji/.*?">', |         r'<img class="emoji" alt="(:.*?:)" title=":.*?:" src="/img/emoji/.*?">', | ||||||
|  | |||||||
| @ -45,3 +45,4 @@ def send_chat(message): | |||||||
|         current_app.logger.error(f"Check owncast instance url and access key.") |         current_app.logger.error(f"Check owncast instance url and access key.") | ||||||
|         return |         return | ||||||
|     return r.json() |     return r.json() | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -36,22 +36,22 @@ def owncast_webhook(): | |||||||
|             user_id = data["eventData"]["user"]["id"] |             user_id = data["eventData"]["user"]["id"] | ||||||
|             display_name = data["eventData"]["user"]["displayName"] |             display_name = data["eventData"]["user"]["displayName"] | ||||||
|             current_app.logger.debug(f'New chat message from {display_name}:') |             current_app.logger.debug(f'New chat message from {display_name}:') | ||||||
|             current_app.logger.debug(f'{data["eventData"]["rawBody"]}') |             current_app.logger.debug(f'{data["eventData"]["body"]}') | ||||||
|             if data["eventData"]["rawBody"].startswith(f"{prefix}help"): |             if data["eventData"]["body"].startswith(f"{prefix}help"): | ||||||
|                 send_help() |                 send_help() | ||||||
|             elif data["eventData"]["rawBody"].startswith(f"{prefix}points"): |             elif data["eventData"]["body"].startswith(f"{prefix}points"): | ||||||
|                 points = read_users_points(db, user_id) |                 points = read_users_points(db, user_id) | ||||||
|                 if points is None: |                 if points is None: | ||||||
|                     send_chat("Error reading points.") |                     send_chat("Error reading points.") | ||||||
|                 else: |                 else: | ||||||
|                     send_chat(f"{display_name}'s points: {points}") |                     send_chat(f"{display_name}'s points: {points}") | ||||||
|             elif data["eventData"]["rawBody"].startswith(f"{prefix}name_update"): |             elif data["eventData"]["body"].startswith(f"{prefix}name_update"): | ||||||
|                 # Forces name update in case bot didn't catch the NAME_CHANGE |                 # Forces name update in case bot didn't catch the NAME_CHANGE | ||||||
|                 # event. Also removes saved usernames from users with same name |                 # event. Also removes saved usernames from users with same name | ||||||
|                 # if user is authenticated. |                 # if user is authenticated. | ||||||
|                 change_display_name(db, user_id, display_name) |                 change_display_name(db, user_id, display_name) | ||||||
|                 if data["eventData"]["user"]["authenticated"]: |                 if data["eventData"]["user"]["authenticated"]: | ||||||
|                     remove_duplicate_usernames(db, user_id, display_name) |                     remove_duplicate_usernames(db, user_id, display_name) | ||||||
|             elif data["eventData"]["rawBody"].startswith(prefix): |             elif data["eventData"]["body"].startswith(prefix): | ||||||
|                 handle_redeem(data["eventData"]["rawBody"], user_id) |                 handle_redeem(data["eventData"]["body"], user_id) | ||||||
|     return data |     return data | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ def counter_exists(db, counter_name): | |||||||
| def add_to_counter(db, counter_name): | def add_to_counter(db, counter_name): | ||||||
|     if counter_exists(db, counter_name): |     if counter_exists(db, counter_name): | ||||||
|         try: |         try: | ||||||
|             db.execute( |             cursor = db.execute( | ||||||
|                 "UPDATE counters SET count = count + 1 WHERE name = ?", |                 "UPDATE counters SET count = count + 1 WHERE name = ?", | ||||||
|                 (counter_name,) |                 (counter_name,) | ||||||
|             ) |             ) | ||||||
| @ -37,7 +37,7 @@ def add_to_counter(db, counter_name): | |||||||
| 
 | 
 | ||||||
| def add_to_redeem_queue(db, user_id, redeem_name, note=None): | def add_to_redeem_queue(db, user_id, redeem_name, note=None): | ||||||
|     try: |     try: | ||||||
|         db.execute( |         cursor = db.execute( | ||||||
|             "INSERT INTO redeem_queue(redeem, redeemer_id, note) VALUES(?, ?, ?)", |             "INSERT INTO redeem_queue(redeem, redeemer_id, note) VALUES(?, ?, ?)", | ||||||
|             (redeem_name, user_id, note) |             (redeem_name, user_id, note) | ||||||
|             ) |             ) | ||||||
| @ -159,7 +159,7 @@ def all_active_milestones(db): | |||||||
|     return all_active_milestones |     return all_active_milestones | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def all_active_redeems(): | def all_active_redeems(db): | ||||||
|     redeems = current_app.config['REDEEMS'] |     redeems = current_app.config['REDEEMS'] | ||||||
|     all_active_redeems = {} |     all_active_redeems = {} | ||||||
|     for redeem_name, redeem_dict in redeems.items(): |     for redeem_name, redeem_dict in redeems.items(): | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| from flask import current_app | from flask import current_app | ||||||
| from tlapbot.db import get_db | from tlapbot.db import get_db | ||||||
| from tlapbot.owncast_requests import send_chat | from tlapbot.owncast_requests import send_chat | ||||||
| from tlapbot.redeems import (add_to_redeem_queue, add_to_counter, add_to_milestone, | from tlapbot.redeems import (add_to_redeem_queue, add_to_counter, add_to_milestone,  | ||||||
|         check_apply_milestone_completion, milestone_complete, is_redeem_active) |         check_apply_milestone_completion, milestone_complete, is_redeem_active) | ||||||
| from tlapbot.owncast_helpers import use_points, read_users_points | from tlapbot.owncast_helpers import use_points, read_users_points, remove_emoji | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def handle_redeem(message, user_id): | def handle_redeem(message, user_id): | ||||||
| @ -32,11 +32,9 @@ def handle_redeem(message, user_id): | |||||||
|         elif not note: |         elif not note: | ||||||
|             send_chat(f"Cannot redeem {redeem}, no amount of points specified.") |             send_chat(f"Cannot redeem {redeem}, no amount of points specified.") | ||||||
|         elif not note.isdigit(): |         elif not note.isdigit(): | ||||||
|             send_chat(f"Cannot redeem {redeem}, amount of points is not a positive integer.") |             send_chat(f"Cannot redeem {redeem}, amount of points is not an integer.") | ||||||
|         elif int(note) > points: |         elif int(note) > points: | ||||||
|             send_chat(f"Can't redeem {redeem}, you're donating more points than you have.") |             send_chat(f"Can't redeem {redeem}, you're donating more points than you have.") | ||||||
|         elif int(note) == 0: |  | ||||||
|             send_chat(f"Can't donate zero points.") |  | ||||||
|         elif add_to_milestone(db, user_id, redeem, int(note)): |         elif add_to_milestone(db, user_id, redeem, int(note)): | ||||||
|             send_chat(f"Succesfully donated to {redeem} milestone!") |             send_chat(f"Succesfully donated to {redeem} milestone!") | ||||||
|             if check_apply_milestone_completion(db, redeem): |             if check_apply_milestone_completion(db, redeem): | ||||||
| @ -44,7 +42,7 @@ def handle_redeem(message, user_id): | |||||||
|         else: |         else: | ||||||
|             send_chat(f"Redeeming milestone {redeem} failed.") |             send_chat(f"Redeeming milestone {redeem} failed.") | ||||||
|         return |         return | ||||||
| 
 |      | ||||||
|     # handle redeems with price argument |     # handle redeems with price argument | ||||||
|     price = current_app.config['REDEEMS'][redeem]["price"] |     price = current_app.config['REDEEMS'][redeem]["price"] | ||||||
|     if not points or points < price: |     if not points or points < price: | ||||||
| @ -66,7 +64,7 @@ def handle_redeem(message, user_id): | |||||||
|         if not note: |         if not note: | ||||||
|             send_chat(f"Cannot redeem {redeem}, no note included.") |             send_chat(f"Cannot redeem {redeem}, no note included.") | ||||||
|             return |             return | ||||||
|         if (add_to_redeem_queue(db, user_id, redeem, note) and |         if (add_to_redeem_queue(db, user_id, redeem, remove_emoji(note)) and | ||||||
|                 use_points(db, user_id, price)): |                 use_points(db, user_id, price)): | ||||||
|             send_chat(f"{redeem} redeemed for {price} points.") |             send_chat(f"{redeem} redeemed for {price} points.") | ||||||
|         else: |         else: | ||||||
|  | |||||||
| @ -30,14 +30,12 @@ | |||||||
|                         <th>Your points balance</th> |                         <th>Your points balance</th> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 </thead> |                 </thead> | ||||||
|                 <tbody> |  | ||||||
|                 {% for user in users %} |                 {% for user in users %} | ||||||
|                     <tr> |                 <tbody> | ||||||
|                         <td> {{ user[0] }} </td> |                     <td> {{ user[0] }} </td> | ||||||
|                         <td> {{ user[1] }} </td> |                     <td> {{ user[1] }} </td> | ||||||
|                     </tr> |  | ||||||
|                 {% endfor %} |  | ||||||
|                 </tbody> |                 </tbody> | ||||||
|  |                 {% endfor %} | ||||||
|             </table> |             </table> | ||||||
|             {% endif %} |             {% endif %} | ||||||
| 
 | 
 | ||||||
| @ -54,14 +52,12 @@ | |||||||
|                         <th>Active counters</th> |                         <th>Active counters</th> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 </thead> |                 </thead> | ||||||
|                 <tbody> |  | ||||||
|                 {% for counter in counters %} |                 {% for counter in counters %} | ||||||
|                     <tr> |                 <tbody> | ||||||
|                         <td> {{ counter[0] }} </td> |                     <td> {{ counter[0] }} </td> | ||||||
|                         <td> {{ counter[1] }} </td> |                     <td> {{ counter[1] }} </td> | ||||||
|                     </tr> |  | ||||||
|                 {% endfor %} |  | ||||||
|                 </tbody> |                 </tbody> | ||||||
|  |                 {% endfor %} | ||||||
|             </table> |             </table> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|             {% if milestones %} |             {% if milestones %} | ||||||
| @ -72,15 +68,13 @@ | |||||||
|                         <th>Progress</th> |                         <th>Progress</th> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 </thead> |                 </thead> | ||||||
|                 <tbody> |  | ||||||
|                 {% for milestone in milestones %} |                 {% for milestone in milestones %} | ||||||
|                     <tr> |                 <tbody> | ||||||
|                         <td> {{ milestone[0] }} </td> |                     <td> {{ milestone[0] }} </td> | ||||||
|                         <td> <progress id="file" max={{ milestone[2] }} value={{ milestone[1] }}></progress></td> |                     <td> <progress id="file" max={{ milestone[2] }} value={{ milestone[1] }}></progress></td> | ||||||
|                         <td> {{ milestone[1] }} / {{ milestone[2] }}</td> |                     <td> {{ milestone[1] }} / {{ milestone[2] }}</td> | ||||||
|                     </tr> |  | ||||||
|                 {% endfor %} |  | ||||||
|                 </tbody> |                 </tbody> | ||||||
|  |                 {% endfor %} | ||||||
|             </table> |             </table> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|             {% endif %} |             {% endif %} | ||||||
| @ -105,18 +99,16 @@ | |||||||
|                         <th>Note</th> |                         <th>Note</th> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 </thead> |                 </thead> | ||||||
|                 <tbody> |  | ||||||
|                 {% for row in queue %} |                 {% for row in queue %} | ||||||
|                     <tr> |                 <tbody> | ||||||
|                         <td>{{ row[0].replace(tzinfo=utc_timezone).astimezone().strftime("%H:%M") }}</td> |                     <td>{{ row[0].replace(tzinfo=utc_timezone).astimezone().strftime("%H:%M") }}</td> | ||||||
|                         <td>{{ row[1] }}</td> |                     <td>{{ row[1] }}</td> | ||||||
|                         <td>{{ row[3] }}</td> |                     <td>{{ row[3] }}</td> | ||||||
|                         {% if row[2] %} |                     {% if row[2] %} | ||||||
|                         <td>{{ row[2] }}</td> |                     <td>{{ row[2] }}</td> | ||||||
|                         {% endif %} |                     {% endif %} | ||||||
|                     </tr> |  | ||||||
|                 {% endfor %} |  | ||||||
|                 </tbody> |                 </tbody> | ||||||
|  |                 {% endfor %} | ||||||
|             </table> |             </table> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|         </body> |         </body> | ||||||
| @ -144,22 +136,20 @@ | |||||||
|                         <th>Description</th> |                         <th>Description</th> | ||||||
|                     </tr> |                     </tr> | ||||||
|                 </thead> |                 </thead> | ||||||
|                 <tbody> |  | ||||||
|                 {% for redeem, redeem_info in redeems.items() %} |                 {% for redeem, redeem_info in redeems.items() %} | ||||||
|                     <tr> |                 <tbody> | ||||||
|                         <td>{{ prefix }}{{ redeem }}</td> |                     <td>{{ prefix }}{{ redeem }}</td> | ||||||
|                         {% if redeem_info["type"] == "milestone" %} |                     {% if redeem_info["type"] == "milestone" %} | ||||||
|                         <td></td> |                     <td></td> | ||||||
|                         {% else %} |                     {% else %} | ||||||
|                         <td>{{ redeem_info["price"] }}</td> |                     <td>{{ redeem_info["price"] }}</td> | ||||||
|                         {% endif %} |                     {% endif %} | ||||||
|                         <td>{{ redeem_info["type"] }}</td> |                     <td>{{ redeem_info["type"] }}</td> | ||||||
|                         {% if redeem_info["info"] %} |                     {% if redeem_info["info"] %} | ||||||
|                         <td>{{ redeem_info["info"] }}</td> |                     <td>{{ redeem_info["info"] }}</td> | ||||||
|                         {% endif %} |                     {% endif %} | ||||||
|                     </tr> |  | ||||||
|                 {% endfor %} |  | ||||||
|                 </tbody> |                 </tbody> | ||||||
|  |                 {% endfor %} | ||||||
|             </table> |             </table> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|         </body> |         </body> | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| from flask import render_template, Blueprint, request, current_app | from flask import render_template, Blueprint, request, current_app | ||||||
| from tlapbot.db import get_db | from tlapbot.db import get_db | ||||||
| from tlapbot.redeems import all_active_counters, all_active_milestones, all_active_redeems, pretty_redeem_queue | from tlapbot.redeems import all_active_counters, all_active_milestones, all_active_redeems, pretty_redeem_queue | ||||||
| from tlapbot.owncast_helpers import read_all_users_with_username | from tlapbot.owncast_helpers import  read_all_users_with_username | ||||||
| from datetime import timezone | from datetime import datetime, timezone | ||||||
| 
 | 
 | ||||||
| bp = Blueprint('redeem_dashboard', __name__) | bp = Blueprint('redeem_dashboard', __name__) | ||||||
| 
 | 
 | ||||||
| @ -20,7 +20,7 @@ def dashboard(): | |||||||
|                            queue=pretty_redeem_queue(db), |                            queue=pretty_redeem_queue(db), | ||||||
|                            counters=all_active_counters(db), |                            counters=all_active_counters(db), | ||||||
|                            milestones=all_active_milestones(db), |                            milestones=all_active_milestones(db), | ||||||
|                            redeems=all_active_redeems(), |                            redeems=all_active_redeems(db), | ||||||
|                            prefix=current_app.config['PREFIX'], |                            prefix=current_app.config['PREFIX'], | ||||||
|                            passive=current_app.config['PASSIVE'], |                            passive=current_app.config['PASSIVE'], | ||||||
|                            username=username, |                            username=username, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user