ソースを参照

Removed superfluous INDIEAUTH variables, added new follower webhook and settings in management panel

deadtom 2 週間 前
コミット
e4622527d4

+ 5 - 4
ownchatbot/reward_handlers.py

@@ -311,6 +311,7 @@ def save_config(config_dict):  # Write settings to config.py
     settings_file = os.path.join(current_app.instance_path, 'config.py')
     secret_key = current_app.config['SECRET_KEY']
     new_settings = f"# Owncast stuff. Needed to interact with your Owncast instance\n\
+ACCESS_ID = '{config_dict['ACCESS_ID']}'\n\
 ACCESS_TOKEN = '{config_dict['ACCESS_TOKEN']}'\n\
 OWNCAST_URL = '{config_dict['OWNCAST_URL']}'\n\
 \n\
@@ -320,10 +321,10 @@ POINTS_INTERVAL = {config_dict['POINTS_INTERVAL']}  # How long, in seconds, betw
 POINTS_AWARD = {config_dict['POINTS_AWARD']}  # How many points awarded each interval?\n\
 GUNICORN = {config_dict['GUNICORN']}  # Integrate OwnchatBot logging into Gunicorn\n\
 PREFIX = '{config_dict['PREFIX']}'  # Preceeds commands, so OwnchatBot knows what is a command\n\
-MGMT_AUTH = '{config_dict['MGMT_AUTH']}'  # Needed to access the OwnchatBot management panel. See README.md for more details.\n\
 KOFI_TOKEN = '{config_dict['KOFI_TOKEN']}'  # Needed to validate Ko-fi with OCB webhook. Get from Ko-fi Settings -> More -> API -> Webhooks -> Advanced - Verification Token.\n\
-KOFI_INTEGRATION = {config_dict['KOFI_INTEGRATION']}  # Integrate OwnchatBot with Ko-fi"
-    
+KOFI_INTEGRATION = {config_dict['KOFI_INTEGRATION']}  # Integrate OwnchatBot with Ko-fi\n\
+FOLLOW_POINTS = {config_dict['FOLLOW_POINTS']}  # How many points to award viewers for following"
+
     try:
         with open(settings_file, 'w') as f:
             f.write(new_settings)
@@ -331,7 +332,7 @@ KOFI_INTEGRATION = {config_dict['KOFI_INTEGRATION']}  # Integrate OwnchatBot wit
     except Exception as scerror:
         current_app.logger.error(f'Couldn\'t save config.py: {saerror.args[0]}')
         return False
-    
+
     current_app.config.from_pyfile('config.py', silent=True)  # Reread config.py into the app
     return True
 

+ 14 - 9
ownchatbot/templates/mgmt.html

@@ -9,7 +9,7 @@
     
     <div class="navbar">
         <div class="tab">
-            <button class="tablinks" onclick="window.location.href='{{ url_for('web_panels.mgmtqueue') }}'">Rewards Queue Management</button>
+            <button class="tablinks" onclick="window.open('{{ url_for('web_panels.mgmtqueue') }}', '_blank')">Rewards Queue Management</button>
             <button class="tablinks" data-tab="managerewards" onclick="openTab(event, 'managerewards')">Rewards</button>
             <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>
@@ -248,12 +248,6 @@
                             <th style="width: 50%;"></th>
                         </tr>
                     </thead>
-                    <tr>
-                        <td> <label for="mgmt_auth">Management Auth Code:</label> </td>
-                        <td style="padding: 5px;"> <input type="text" name="mgmt_auth" value="{{ settings_info[0] }}" size="30" required> </td>
-                        <td>Pregenerated during install. Goes in your management panel URL. Keep it secret. Keep it safe.<br>
-                        http://localhost:5000/mgmt?auth={{ settings_info[0] }}</td>
-                    </tr>
                     <tr>
                         <td> <label for="points_interval">Points Interval:</label> </td>
                         <td> <input type="number" name="points_interval" value="{{ settings_info[1] }}" size="5" required> minutes</td>
@@ -264,6 +258,11 @@
                         <td> <input type="number" name="points_award" value="{{ settings_info[2] }}" size="5"  required> points</td>
                         <td>How many points do you want to award them?</td>
                     </tr>
+                    <tr>
+                        <td> <label for="follow_points">Follow Points:</label> </td>
+                        <td> <input type="number" name="follow_points" value="{{ settings_info[11] }}" size="5"  required> points</td>
+                        <td>How many points do you want to award viewers for following your stream?</td>
+                    </tr>
                     <tr>
                         <td> <label for="gunicorn_logging">Gunicorn Logging:</label> </td>
                         {% if settings_info[3] %}
@@ -289,10 +288,15 @@
                             <th style="width: 50%;"></th>
                         </tr>
                     </thead>
+                    <tr>
+                        <td> <label for="access_id">Access Token Name:</label> </td>
+                        <td style="padding: 5px;"> <input type="text" name="access_id" value="{{ settings_info[0] }}" size="40"> </td>
+                        <td>Create in Owncast Admin panel. Integrations -> Access Tokens (check all three boxes)</td>
+                    </tr>
                     <tr>
                         <td> <label for="access_token">Access Token:</label> </td>
                         <td style="padding: 5px;"> <input type="text" name="access_token" value="{{ settings_info[5] }}" size="40"> </td>
-                        <td>Create in Owncast Admin panel. Integrations -> Access Tokens (check all three boxes)</td>
+                        <td>The token you created above.</td>
                     </tr>
                     <tr>
                         <td> <label for="owncast_url">Your Owncast URL:</label> </td>
@@ -314,10 +318,11 @@
                         <td> <label for="kofi_integration">Enable:</label> </td>
                         {% if settings_info[8] %}
                         <td> <input type="checkbox" name="kofi_integration" value="{{ settings_info[8] }}" checked> </td>
+                        <td>Enable Ko-fi integration.</td>
                         {% else %}
                         <td> <input type="checkbox" name="kofi_integration" value="{{ settings_info[8] }}"> </td>
+                        <td>Enable Ko-fi integration. ("Kofi Settings" button will appear in the navigation bar when enabled.)</td>
                         {% endif %}
-                        <td>Enable Ko-fi integration.</td>
                     </tr>
                     <tr>
                         <td> <label for="kofi_token">Verification Token:</label> </td>

+ 16 - 0
ownchatbot/user_handlers.py

@@ -2,6 +2,7 @@ from flask import current_app
 from sqlite3 import Error
 from re import sub
 import random
+import time
 
 
 def get_users_points(db, user_id):  # Look up one user's points by user id
@@ -265,3 +266,18 @@ def remove_duplicates(db, user_id, username):  # Remove duplicate usernames
         db.commit()
     except Error as rderror:
         current_app.logger.error(f'Couldn\'t remove duplicate username {username} for {user_id}: {rderror.args[0]}')
+
+
+def mark_followed(db, user_id):  # Mark a user as a follower by entering the date in the followed column
+    try:
+        follow_date = time.localtime()
+        follow_date = time.strftime("%m/%d/%Y", follow_date)
+        db.execute(
+            "UPDATE points SET followed = ? WHERE id = ?",
+            (follow_date, user_id)
+        )
+        db.commit()
+        return True
+    except Error as mferror:
+        current_app.logger.error(f'Couldn\'t mark {user_id} as followed in the points database: {mferror.args[0]}')
+        return False

+ 17 - 9
ownchatbot/web_panels.py

@@ -33,7 +33,7 @@ def login():  # Verify the streamer using indieauth, to their owncast instance
     global state_value
     state_value = code_verifier
     owncast_url = current_app.config['OWNCAST_URL']
-    client_id = current_app.config['INDIEAUTH_CLIENT_ID']
+    client_id = current_app.config['ACCESS_ID']
     redirect_url = f'{owncast_url}/api/auth/provider/indieauth?client_id={client_id}&redirect_uri={url_for("web_panels.auth_response", _external=True)}&response_type=code&code_challenge_method=S256&code_challenge={code_challenge}&state={code_verifier}'
     return redirect(redirect_url)
 
@@ -46,13 +46,13 @@ def auth_response():
         current_app.logger.info(f'CSRF code is valid.')
         owncast_url = current_app.config['OWNCAST_URL']
         owncast_auth_url = f'{owncast_url}/api/auth/provider/indieauth'
-        client_id = current_app.config['INDIEAUTH_CLIENT_ID']
-        client_secret = current_app.config['INDIEAUTH_CLIENT_SECRET']
+        access_id = current_app.config['ACCESS_ID']
+        access_token = current_app.config['ACCESS_TOKEN']
         # https://owncast.online/api/latest/#tag/Auth
         # https://aaronparecki.com/2021/04/13/26/indieauth
         token_response = requests.post(owncast_auth_url, data={
-            'client_id': client_id,
-            'client_secret': client_secret,
+            'client_id': access_id,
+            'client_secret': access_token,
             'code': code,
             'redirect_uri': url_for("web_panels.auth_response", _external=True),
             'grant_type': 'authorization_code',
@@ -93,8 +93,10 @@ def mgmt():
     all_cats = current_app.config['ALL_CAT']
     points_interval = current_app.config['POINTS_INTERVAL']
     points_award = current_app.config['POINTS_AWARD']
+    follow_points = current_app.config['FOLLOW_POINTS']
     gunicorn_logging = current_app.config['GUNICORN']
     prefix = current_app.config['PREFIX']
+    access_id = current_app.config['ACCESS_ID']
     access_token = current_app.config['ACCESS_TOKEN']
     kofi_token = current_app.config['KOFI_TOKEN']
     kofi_integration = current_app.config['KOFI_INTEGRATION']
@@ -103,6 +105,7 @@ def mgmt():
     announce_interval = current_app.config['ANNOUNCE_INTERVAL']
     announcements = current_app.config['ANNOUNCEMENTS']
     settings_info = [
+        access_id,
         points_interval,
         points_award,
         gunicorn_logging,
@@ -112,7 +115,8 @@ def mgmt():
         kofi_token,
         kofi_integration,
         announce_enable,
-        announce_interval
+        announce_interval,
+        follow_points
         ]
     
     return render_template('mgmt.html',
@@ -314,19 +318,23 @@ def settings():
     points_award = int(request.form['points_award'])
     gunicorn_logging = 'gunicorn_logging' in request.form
     prefix = request.form['prefix']
+    access_id = request.form['access_id']
     access_token = request.form['access_token']
     owncast_url = request.form['owncast_url']
     kofi_integration = 'kofi_integration' in request.form
     kofi_token = request.form['kofi_token']
+    follow_points = request.form['follow_points']
     config_dict = {
         'POINTS_INTERVAL': points_interval,
         'POINTS_AWARD': points_award,
         'GUNICORN': gunicorn_logging,
         'PREFIX': prefix,
+        'ACCESS_ID': access_id,
         'ACCESS_TOKEN': access_token,
         'OWNCAST_URL': owncast_url,
         'KOFI_TOKEN': kofi_token,
-        'KOFI_INTEGRATION': kofi_integration
+        'KOFI_INTEGRATION': kofi_integration,
+        'FOLLOW_POINTS': follow_points
         }
     if save_config(config_dict):  # Save new config.py
         current_app.logger.info('Saved new config.')
@@ -531,10 +539,10 @@ def rereadv():
 @ocb.route('/mgmt/clearfulfilled', methods=['GET', 'POST'])
 def clearfulfilled():
     clear_fulfilled_rewards()
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmtqueue'))
 
 
 @ocb.route('/mgmt/clearqueue', methods=['GET', 'POST'])
 def clear_queue():
     clear_reward_queue()
-    return redirect(url_for('web_panels.mgmt'))
+    return redirect(url_for('web_panels.mgmtqueue'))

+ 18 - 8
ownchatbot/webhooks.py

@@ -1,7 +1,7 @@
 from flask import Flask, request, json, Blueprint, current_app, render_template, jsonify, request, g
 from ownchatbot.db import get_db
 from ownchatbot.owncast_com import send_chat, send_private_chat
-from ownchatbot.user_handlers import add_user_to_points, change_name, get_users_points, remove_duplicates, get_email_code, set_email_code, award_chat_points, user_in_points
+from ownchatbot.user_handlers import add_user_to_points, change_name, get_users_points, remove_duplicates, get_email_code, set_email_code, award_chat_points, user_in_points, get_all_users_with_user_id, mark_followed
 from ownchatbot.bot_messages import do_reward, help_message
 from ownchatbot.reward_handlers import all_active_goals, all_active_votes, all_active_rewards
 from ownchatbot.kofi_handlers import accept_donation, accept_sub
@@ -164,13 +164,23 @@ def votes():
 def new_follow():
     data = request.json
     db = get_db()
-    user_id = ['eventData']['id']
-    display_name_ = ['eventData']['name']
+    user_id = data['eventData']['id']
+    display_name = data['eventData']['name']
     follow_points = current_app.config['FOLLOW_POINTS']
     if user_in_points(db, user_id):  # If the user is in the database
-        award_chat_points(db, user_id, follow_points)  # Award points
-        current_app.logger.info(f'Awarded {display_name}/{user_id} {follow_points} for following.')
-        return jsonify({'status': 'success'}), 200
-    else:  # If not, don't award points. Need to find out how this is handled by Owncast
-        current_app.logger.info(f'{display_name}/{user_id} not in database. Not awarding points.')
+        user_info = get_all_users_with_user_id(db, user_id)  # Get user info
+        followed_date = user_info['followed']
+        if followed_date:  # Check if the user has already followed
+            current_app.logger.info(f'{display_name}/{user_id} already followed on {followed_date}.\
+                                    Not awarding follow points.')  # Do not award points
+            return jsonify({'status': 'success'}), 200
+        else:
+            if mark_followed(db, user_id):  # Mark as followed in the points database
+                if award_chat_points(db, user_id, follow_points):  # Award points
+                    current_app.logger.info(f'Awarded {display_name}/{user_id} {follow_points} for following.')
+                return jsonify({'status': 'success'}), 200
+    else:  # If not, don't award points.
+        # Need to find out if Owncast creates a user in the database,
+        # and if the user id matches when the user joins chat.
+        current_app.logger.info(f'{display_name}/{user_id} not in database. Not awarding follow points.')
         return jsonify({'status': 'success'}), 200