-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
179 lines (146 loc) · 6.15 KB
/
Copy pathapp.py
File metadata and controls
179 lines (146 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env python3
"""
Voice Command Application
A web application that listens to voice commands and executes keyboard actions.
"""
from flask import Flask, request, jsonify
from flask_cors import CORS
from flask_socketio import SocketIO
import os
import sys
import traceback
import threading
import time
# Import app modules
import db
from api import api_bp
from speech_recognition_handler import start_speech_recognition, stop_speech_recognition, update_openai_api_key, toggle_sentiment_mode, get_sentiment_mode_state, get_ai_timeout_state, toggle_scripts_execution, get_scripts_execution_state
from input_simulation import execute_script
# Initialize Flask application
app = Flask(__name__, static_folder='public')
CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*")
# Register the API blueprint
app.register_blueprint(api_bp)
# Store socketio as a global in the app context
app.config['socketio'] = socketio
# Flag to track if we've already initialized speech recognition
speech_recognition_initialized = False
# Flag to track if the AI timeout update thread is running
ai_timeout_update_thread_running = False
# Store socketio in the app config for use in API routes
@app.before_request
def before_request():
request.environ['socketio'] = socketio
def initialize_app():
"""Initialize the application."""
# Initialize database
db.init_db()
# Update OpenAI API key from database
api_key = db.get_openai_api_key()
if api_key:
update_openai_api_key(api_key)
# Start AI timeout update thread
start_ai_timeout_update_thread()
print("Application initialized.")
def ai_timeout_update_loop():
"""Background thread that sends regular AI timeout updates to clients."""
global ai_timeout_update_thread_running
try:
while ai_timeout_update_thread_running:
# Get current timeout state
timeout_state = get_ai_timeout_state()
# If timeout is active, send update to all clients
if timeout_state['active']:
socketio.emit('ai_timeout_update', timeout_state)
# Sleep for a short time to avoid excessive updates
time.sleep(0.5)
except Exception as e:
print(f"Error in AI timeout update thread: {str(e)}")
traceback.print_exc()
def start_ai_timeout_update_thread():
"""Start the AI timeout update thread."""
global ai_timeout_update_thread_running
# Set the flag to keep the thread running
ai_timeout_update_thread_running = True
# Start the thread
timeout_thread = threading.Thread(target=ai_timeout_update_loop)
timeout_thread.daemon = True
timeout_thread.start()
print("AI timeout update thread started")
@socketio.on('connect')
def handle_connect():
print('Client connected to WebSocket')
# If the app should be active, start speech recognition
global speech_recognition_initialized
if db.get_active_state() and not speech_recognition_initialized:
print("Starting speech recognition on socket connection...")
speech_recognition_initialized = True
start_speech_recognition(socketio)
# Send current AI timeout state to the newly connected client
socketio.emit('ai_timeout_update', get_ai_timeout_state(), room=request.sid)
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected from WebSocket')
# Add WebSocket route for testing scripts
@socketio.on('test_script')
def handle_test_script(data):
print(f'Testing script: {data["script"]}')
try:
# Execute in preview mode to get result message without actual key presses
result = execute_script(data['script'], preview_mode=True, socketio=socketio)
socketio.emit('script_result', {
'success': True,
'message': result if result else 'Script preview successful'
})
except Exception as e:
print(f'Error executing script: {str(e)}')
socketio.emit('script_result', {'success': False, 'message': f'Error: {str(e)}'})
@socketio.on('toggle_sentiment_mode')
def handle_toggle_sentiment_mode():
try:
# Pass socketio to toggle_sentiment_mode for timeout notifications
active = toggle_sentiment_mode(socketio)
print(f'Sentiment mode toggled via WebSocket: {"active" if active else "inactive"}')
socketio.emit('sentiment_mode', {'active': active})
socketio.emit('script_result', {'success': True, 'message': f'Sentiment mode {"activated" if active else "deactivated"}'})
except Exception as e:
print(f'Error toggling sentiment mode: {str(e)}')
socketio.emit('script_result', {'success': False, 'message': f'Error: {str(e)}'})
@socketio.on('toggle_scripts_execution')
def handle_toggle_scripts_execution():
try:
# Toggle script execution state
active = toggle_scripts_execution()
print(f'Script execution toggled via WebSocket: {"enabled" if active else "disabled"}')
socketio.emit('scripts_execution', {'active': active})
socketio.emit('script_result', {'success': True, 'message': f'Script execution {"enabled" if active else "disabled"}'})
except Exception as e:
print(f'Error toggling script execution: {str(e)}')
socketio.emit('script_result', {'success': False, 'message': f'Error: {str(e)}'})
# Global error handler for API routes
@app.errorhandler(Exception)
def handle_error(e):
print(f'Global API error: {str(e)}')
return jsonify({
'error': str(e),
'stack_trace': traceback.format_exc()
}), 500
# Route to serve the main application
@app.route('/')
def index():
return app.send_static_file('index.html')
# Generic route to serve static files
@app.route('/<path:path>')
def static_files(path):
return app.send_static_file(path)
# Catch-all route to redirect to the main application
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
def catch_all(path):
return app.send_static_file('index.html')
# Main entry point
if __name__ == '__main__':
# Initialize application
initialize_app()
# Start the Flask application with SocketIO
socketio.run(app, host='0.0.0.0', port=5000, debug=False)