Quellcode durchsuchen

Added todo list

deadtom vor 2 Wochen
Ursprung
Commit
dbf02b73b6

+ 2 - 0
ownchatbot/__init__.py

@@ -29,6 +29,8 @@ def create_app(test_config=None):
     app.config.from_pyfile('kofi.py', silent=True)
     app.config.from_object('ownchatbot.defaults.announce')
     app.config.from_pyfile('announce.py', silent=True)
+    app.config.from_object('ownchatbot.defaults.todo')
+    app.config.from_pyfile('todo.py', silent=True)
 
     if app.config['GUNICORN']:  # Gunicorn logging integration
         gunicorn_logger = logging.getLogger('gunicorn.error')

+ 14 - 0
ownchatbot/defaults/todo.py

@@ -0,0 +1,14 @@
+LIST = [
+    {
+        "name": "This thing",
+        "crossed": "no"
+    },
+    {
+        "name": "That thing",
+        "crossed": "no"
+    },
+    {
+        "name": "That other thing",
+        "crossed": "yes"
+    },
+]

+ 13 - 5
ownchatbot/static/mgmtpanel.js

@@ -17,10 +17,6 @@ function openTab(event, tabName) {
     localStorage.setItem("activeTab", tabName);
 }
 
-function refreshPage() {
-    window.location.reload();
-}
-
 window.onload = function() {
     var activeTab = localStorage.getItem("activeTab");
     if (activeTab) {
@@ -39,4 +35,16 @@ window.onload = function() {
             defaultTabLink.click();
         }
     }
-};
+}
+
+function refreshPage() {
+    window.location.reload();
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+    const urlParams = new URLSearchParams(window.location.search);
+    const activeTab = urlParams.get('activeTab');
+    if (activeTab) {
+        openTab(event, activeTab);
+    }
+});

+ 63 - 0
ownchatbot/templates/list.html

@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta http-equiv="refresh" content="10">
+    <title>Today's to-do List</title>
+    <style>
+        body {
+            background-color: transparent;
+            color: #ffd39a;
+        }
+
+	@font-face {
+  	    font-family: Shunda; 
+	    src: url("/static/Shunda.ttf");
+	}
+
+	* {
+	    font-family: Shunda;
+	    color; #ffd39a;
+	}
+
+	h4 {
+	    font-size: 24px;
+	    text-decoration: underline;
+	    text-align: center;
+	    margin-bottom: 0;
+            padding-bottom: 0;
+	}
+
+	ul {
+	    margin-top: 0; 
+            padding-top: 0;
+	}
+
+	li {
+	    font-size: 20px;
+	}
+    </style>
+    <script>
+      function refreshPage() {
+          window.location.reload();
+      }
+
+      setTimeout(refreshPage, 30 * 1000);
+    </script>
+</head>
+<body>
+    {% if items %}
+        <h4>Today's to-do List</h4>
+        <ul>
+            {% for item in items %}
+                <li style="text-decoration: {{ 'line-through' if item.crossed == 'yes' else 'none' }};">
+                    {{ item.name }}
+                </li>
+            {% endfor %}
+        </ul>
+    {% else %}
+    	<h4>Nothing on the to-do list yet</h4>
+    {% endif %}
+</body>
+</html>

+ 37 - 25
ownchatbot/templates/mgmt.html

@@ -14,6 +14,7 @@
             <button class="tablinks" data-tab="categories" onclick="openTab(event, 'categories')">Categories</button>
             <button class="tablinks" data-tab="accounts" onclick="openTab(event, 'accounts')">Manage Accounts</button>
             <button class="tablinks" data-tab="announcements" onclick="openTab(event, 'announcements')">Announcements</button>
+            <button class="tablinks" data-tab="todolist" onclick="openTab(event, 'todolist')">To-Do List</button>
             <button class="tablinks" data-tab="settings" onclick="openTab(event, 'settings')">Settings</button>
             {% if kofi_integration %}
                 <button class="tablinks" data-tab="kofi-settings" onclick="openTab(event, 'kofi-settings')">Kofi Settings</button>
@@ -238,7 +239,7 @@
 
     <div id='settings' class="tabcontent">
         <body style="text-align: left;">
-            <form id='settings' method="POST" action="/mgmt/settings">
+            <form method="POST" action="/mgmt/settings">
                 <table>
                 <h3>OwnchatBot Settings</h3>
                     <thead>
@@ -328,30 +329,6 @@
                 
                 <br><button class="button button2" type="submit">Save Changes</button><br>
             </form>
-            
-                <h3>Celebration Image</h3>
-                <form id='upload' method="post" enctype="multipart/form-data" action="/mgmt/uploadimage">
-                    <table>
-                        <thead>
-                            <tr style="border-bottom: none;">
-                                <th style="width: 20%;"></th>
-                                <th></th>
-                                <th style="width: 50%;"></th>
-                            </tr>
-                        </thead>
-                        <tr>
-                            <td>Current Image:</td>
-                            <td><img src=""></td>
-                            <td></td>
-                        </tr>
-                        <tr>
-                            <td> <label for="c_image">Upload:</label> </td>
-                            <td>The image (can be an animated GIF) that will be displayed in chat when a goal is reached</td>
-                            <td> <input type="file" name="c_image" value="" checked> </td>
-                        </tr>
-                    </table>
-                    <br><button class="button button2" type="submit">Upload</button><br>
-                </form>
             <br><br>
         </body>
     </div>
@@ -443,6 +420,41 @@
 	    <i>Kofi subscription tier support coming soon.</i>
         </body>
     </div>
+
+    <div id='todolist' class="tabcontent">
+        <script>
+            function focusInput() {  // Function to focus on the input field
+                document.getElementById('itemInput').focus();
+            }
+        </script>
+        <body onload="focusInput()">
+        <h1>To-Do List</h1>
+        <form id="todo-form" method="POST" onsubmit="focusInput()" action="/mgmt/addtodo">
+            <input type="text" id="itemInput" name="item" placeholder="Add a new item" required>
+            <button class="button button2" type="submit">Add</button>
+        </form>
+        <ul>
+            {% if items %}
+                {% for item in items %}
+                    {% if item.crossed == 'no' %}
+                        <li style="text-decoration:none;">
+                            {{ item.name }}
+                            <a href="{{ url_for('web_panels.cross', item_id=loop.index0) }}">[Cross Off]</a>
+                        </li>
+                    {% else %}
+                        <li> <span style="text-decoration:line-through;">
+                            {{ item.name }}</span>
+                            <a href="{{ url_for('web_panels.uncross', item_id=loop.index0) }}">[Un-Cross]</a>
+                        </li>
+                    {% endif %}
+                {% endfor %}
+            {% endif %}
+        </ul>
+        <form action="/mgmt/clearlist" method="get" style="display: inline;">
+            <button class="button button2" type="submit" class="button">Clear List</button>
+        </form>
+        <br>
+    </div>
     
     
 </html>

+ 3 - 2
ownchatbot/templates/userpanel.html

@@ -11,7 +11,7 @@
         <div class="tab">
             <button class="tablinks" data-tab="ocbinfo" onclick="openTab(event, 'ocbinfo')">OwnchatBot Info</button>
             <button class="tablinks" data-tab="rewards" onclick="openTab(event, 'rewards')">Points and Rewards</button>
-            <button class="tablinks" data-tab="queue" onclick="openTab(event, 'queue')">Redeems Queue</button>
+            <button class="tablinks" data-tab="queue" onclick="openTab(event, 'queue')">Rewards Queue</button>
         </div>
         <img src="/static/img/ownchatbotwide.png">
     </div>
@@ -203,7 +203,7 @@
             {% endif %}
         </body>
         <body>
-            <h3>Active Redeems</h3>
+            <h3>Active Rewards</h3>
             {% if rewards %}
             <table>
                 <thead>
@@ -263,6 +263,7 @@
                 </thead>
                 <tbody>
                 {% for row in queue %}
+                    {{ row[2] }}
                     {% if not row[4] %}
                     <tr>
                         <td>{{ row[1].replace(tzinfo=utc_timezone).astimezone().strftime("%H:%M") }}</td>

+ 16 - 0
ownchatbot/user_handlers.py

@@ -3,6 +3,22 @@ from sqlite3 import Error
 from re import sub
 import random
 import time
+import json
+import os
+
+
+def save_todolist(list_items):  # Save todolist items
+    new_list = json.dumps(list_items, indent=4)
+    list_file = os.path.join(current_app.instance_path, 'todo.py')
+    try:
+        with open(list_file, 'w') as f:
+            f.write(f'LIST = {new_list}')
+        f.close
+        current_app.config.from_pyfile('todo.py', silent=True)  # Reread the list into the app
+        return True
+    except Exception as stdlerror:
+        current_app.logger.error(f'Couldn\'t save todo.py: {stdclerror.args[0]}')
+        return False
 
 
 def get_users_points(db, user_id):  # Look up one user's points by user id

+ 67 - 38
ownchatbot/web_panels.py

@@ -2,7 +2,7 @@ from flask import flash, render_template, Blueprint, current_app, redirect, requ
 from datetime import timezone
 from ownchatbot.db import get_db, reread_goals, reread_votes, rem_vote, reset_vote, reset_goal, clear_fulfilled_rewards, clear_reward_queue, rem_cool, rem_from_queue
 from ownchatbot.reward_handlers import all_active_votes, all_active_goals, all_active_rewards, get_queue, fulfill_reward, save_rewards, activate_category, deactivate_category, refund_reward, reread_categories, save_config
-from ownchatbot.user_handlers import get_all_users, get_all_users_by_name, refund_points, adjust_points, change_email, get_email_code, del_email_code
+from ownchatbot.user_handlers import get_all_users, get_all_users_by_name, refund_points, adjust_points, change_email, get_email_code, del_email_code, save_todolist
 from ownchatbot.bot_messages import save_announce
 from ownchatbot.owncast_com import send_private_chat
 import json
@@ -103,6 +103,8 @@ def mgmt():
     announce_enable = current_app.config['ANNOUNCE_ENABLE']
     announce_interval = current_app.config['ANNOUNCE_INTERVAL']
     announcements = current_app.config['ANNOUNCEMENTS']
+    todolist_items = current_app.config['LIST']
+    active_tab = request.args.get('activeTab')
     settings_info = [
         access_id,
         points_interval,
@@ -116,7 +118,7 @@ def mgmt():
         announce_enable,
         announce_interval
         ]
-    
+
     return render_template('mgmt.html',
                            queue=get_queue(db),
                            votes=all_active_votes(db),
@@ -132,7 +134,9 @@ def mgmt():
                            utc_timezone=utc_timezone,
                            active_categories=active_categories,
                            inactive_categories=inactive_categories,
-                           settings_info=settings_info)
+                           settings_info=settings_info,
+                           items=todolist_items,
+                           activeTab=active_tab)
 
 
 @ocb.route('/mgmt_queue', methods=['GET'])  # The streamer's management panel
@@ -231,7 +235,7 @@ def edit_account(user_id):
                     current_app.logger.info(f'Removed {name}\'s email')
                 else:
                     current_app.logger.info(f'Changed {name}\'s email to {newemail}')
-        return redirect(url_for('web_panels.mgmt'))
+        return redirect(url_for('web_panels.mgmt', activeTab='accounts'))
 
     return render_template('edit_account.html',
                            name=name,
@@ -251,7 +255,7 @@ def delete(reward_name):
             if reread_votes():
                 if reread_goals():
                     pass
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmt', activeTab='managerewards'))
 
 
 @ocb.route('/mgmt/edit/<reward_name>', methods=['GET', 'POST'])
@@ -300,7 +304,7 @@ def edit(reward_name):
             reread_goals()
         if reward_data['type'] == 'vote':
             reread_votes()
-        return redirect(url_for('web_panels.mgmt'))
+        return redirect(url_for('web_panels.mgmt', activeTab='managerewards'))
 
     return render_template('edit.html',
                            all_cats=all_cats,
@@ -312,6 +316,7 @@ def edit(reward_name):
 @ocb.route('/mgmt/settings', methods=['GET', 'POST'])  # OwnchatBot settings panel
 @requires_login
 def settings():
+    todolist_items = current_app.config['LIST']
     points_interval = int(request.form['points_interval'])
     points_award = int(request.form['points_award'])
     gunicorn_logging = 'gunicorn_logging' in request.form
@@ -335,32 +340,7 @@ def settings():
     if save_config(config_dict):  # Save new config.py
         current_app.logger.info('Saved new config.')
 
-    return redirect(url_for('web_panels.mgmt'))
-
-
-@ocb.route('/mgmt/uploadimage', methods=['POST'])
-def upload_image():
-    if 'file' not in request.files:
-        return redirect(request.url)
-    
-    file = request.files['file']
-    if file.filename == '':
-        return redirect(request.url)
-
-    allowed_extensions = {'png', 'jpg', 'jpeg', 'gif'}
-    if '.' in file.filename:  # Make sure it's an approved file type
-        extension = file.filename.rsplit('.', 1)[1].lower()
-        if extension not in allowed_extensions:
-            return redirect(request.url)
-
-    upload_folder = os.path.join(current_app.instance_path, 'uploads')
-
-    if not os.path.exists(upload_folder):  # Create uploads directory if it doesn't exist
-        os.makedirs(upload_folder)
-
-    filename = secure_filename(file.filename)
-    file.save(os.path.join(upload_folder, filename))
-    return f'Image successfully uploaded: {filename}'
+    return redirect(url_for('web_panels.mgmt', activeTab='settings'))
 
 
 @ocb.route('/mgmt/announcements', methods=['GET', 'POST'])  # OwnchatBot settings panel
@@ -378,7 +358,7 @@ def announcements():
     if save_announce(announce_dict):  # Save new announce.py
         current_app.logger.info('Saved new announcements.')
 
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmt', activeTab='announcements'))
 
 
 @ocb.route('/mgmt/ksettings', methods=['GET', 'POST'])  # OwnchatBot settings panel
@@ -401,7 +381,7 @@ def ksettings():
         if save_kofi_settings(kofi_settings_dict):
             current_app.logger.info(f'Saved Kofi settings')
 
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmt', activeTab='kofi-settings'))
 
 
 @ocb.route('/mgmt/add/<reward_type>', methods=['GET', 'POST'])
@@ -484,7 +464,7 @@ def add(reward_type):
             inactive_categories = current_app.config['INACTIVE_CAT']
             inactive_categories.append(name)  # Add it to the INACTIVE_CAT variable
             reread_categories()  # Write it to categories.py
-        return redirect(url_for('web_panels.mgmt'))
+        return redirect(url_for('web_panels.mgmt', activeTab='managerewards'))
 
     return render_template('add.html',
                            all_cats=all_cats,
@@ -516,13 +496,13 @@ def set_viewer_email():
 @ocb.route('/mgmt/activate/<category>', methods=['GET', 'POST'])
 def activate(category):
     activate_category(category)
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmt', activeTab='categories'))
 
 
 @ocb.route('/mgmt/deactivate/<category>', methods=['GET', 'POST'])
 def deactivate(category):
     deactivate_category(category)
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmt', activeTab='categories'))
 
 
 @ocb.route('/mgmt/delcat/<cat_name>/<cat_act>', methods=['GET', 'POST'])
@@ -539,7 +519,7 @@ def delcat(cat_name, cat_act):
         if cat_name in details['categories']:
             details['categories'].remove(cat_name)
     save_rewards(current_rewards)
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmt', activeTab='categories'))
 
 
 @ocb.route('/mgmt/reset/<reward_name>/<reward_type>', methods=['GET', 'POST'])  # Reset votes and goals to zero
@@ -569,6 +549,49 @@ def clear_queue():
     return redirect(url_for('web_panels.mgmtqueue'))
 
 
+@ocb.route('/mgmt/addtodo', methods=['POST'])
+def add_todo():
+    todo_item = request.form.get('todo_item')
+    if request.method == 'POST':
+        todolist_items = current_app.config['LIST']
+        item = request.form.get('item')
+        if item:
+            todolist_items.append({'name': item, 'crossed': 'no'})
+            if save_todolist(todolist_items):  # Save todo list
+                current_app.logger.info('Saved to-do list.')
+        return redirect(url_for('web_panels.mgmt', activeTab='todolist'))
+    return redirect(url_for('web_panels.mgmt', activeTab='todolist'))
+
+
+@ocb.route('/mgmt/cross/<int:item_id>')
+def cross(item_id):
+    todolist_items = current_app.config['LIST']
+    if 0 <= item_id < len(todolist_items):
+        todolist_items[item_id]['crossed'] = 'yes'
+        if save_todolist(todolist_items):  # Save todo list
+            current_app.logger.info('Saved to-do list.')
+    return redirect(url_for('web_panels.mgmt', activeTab='todolist'))
+
+
+@ocb.route('/mgmt/uncross/<int:item_id>')
+def uncross(item_id):
+    todolist_items = current_app.config['LIST']
+    if 0 <= item_id < len(todolist_items):
+        todolist_items[item_id]['crossed'] = 'no'
+        if save_todolist(todolist_items):  # Save todo list
+            current_app.logger.info('Saved to-do list.')
+    return redirect(url_for('web_panels.mgmt', activeTab='todolist'))
+
+
+@ocb.route('/mgmt/clearlist')
+def clear_list():
+    todolist_items = current_app.config['LIST']
+    todolist_items = []  # Clear the list
+    if save_todolist(todolist_items):  # Save todo list
+        current_app.logger.info('Saved to-do list.')
+    return redirect(url_for('web_panels.mgmt', activeTab='todolist'))
+
+
 @ocb.route('/goals', methods=['GET'])  # Route for goals overlay
 def goals():
     db = get_db()
@@ -582,3 +605,9 @@ def votes():
     db = get_db()
     return render_template('votes.html',
                            votes=all_active_votes(db))
+
+
+@ocb.route('/todo')
+def todo():
+    todolist_items = current_app.config['LIST']
+    return render_template('list.html', items=todolist_items)