-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
220 lines (194 loc) · 8.07 KB
/
app.py
File metadata and controls
220 lines (194 loc) · 8.07 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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from flask import Flask, render_template, request, jsonify
from flask_socketio import SocketIO, emit
import threading
import json
import requests
import os
import platform
import sys
# Import keyboard library based on OS
if platform.system() == "Windows":
from pynput.keyboard import Key, Controller
import ctypes
from ctypes import wintypes
else:
# For Linux servers without X11, use keyboard library instead
try:
from pynput.keyboard import Key, Controller
except ImportError:
import keyboard as kb_lib
Controller = None
Key = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'jugfhuigfyhghfyghfygfgfgff4gf545g5g5h7548ù74ù'
# Fix for PyInstaller compatibility
try:
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')
except:
socketio = SocketIO(app, cors_allowed_origins="*", logger=False, engineio_logger=False)
# Initialize keyboard controller if available
if Controller:
keyboard = Controller()
else:
keyboard = None
pressed_keys = set()
def check_version():
try:
# Try to read from file first (development mode)
if os.path.exists('version.txt'):
with open('version.txt', 'r') as f:
current_version = f.read().strip()
else:
# Fallback to embedded version (executable mode)
current_version = "beta-2026.01.07-1"
response = requests.get('https://raw.githubusercontent.com/liveweeeb13/SimControl/refs/heads/main/version.txt')
latest_version = response.text.strip()
if current_version != latest_version:
print(f"⚠️ UPDATE AVAILABLE!")
print(f"Current version: {current_version}")
print(f"Latest version: {latest_version}")
return current_version, latest_version, True
else:
print(f"✅ Updated version: {current_version}")
return current_version, latest_version, False
except:
return "beta-2026.01.07-1", "unknown", False
current_ver, latest_ver, needs_update = check_version()
def get_config_path():
# Dossier où se trouve l'exécutable
if getattr(sys, 'frozen', False):
# Si c'est un exécutable PyInstaller
app_dir = os.path.dirname(sys.executable)
else:
# Si c'est en développement
app_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(app_dir, 'config.js')
def create_default_config():
config_path = get_config_path()
if not os.path.exists(config_path):
default_config = '''const buttons = [];
const rules = {
autodisable: [],
stopmac: []
};'''
with open(config_path, 'w', encoding='utf-8') as f:
f.write(default_config)
print(f"✅ Default config.js created at {config_path}")
create_default_config()
@app.route('/')
def menu():
return render_template('menu.html', current_version=current_ver, latest_version=latest_ver, needs_update=needs_update)
@app.route('/keytest')
def keytest():
return render_template('keytest.html')
@app.route('/simcontrol')
def index():
return render_template('index.html')
@app.route('/config.js')
def serve_config():
config_path = get_config_path()
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
content = f.read()
return content, 200, {'Content-Type': 'application/javascript'}
else:
return 'const buttons = []; const rules = {autodisable: [], stopmac: []};', 200, {'Content-Type': 'application/javascript'}
@app.route('/save-config', methods=['POST'])
def save_config():
config_data = request.json
config_js = f"""const buttons = {json.dumps(config_data['buttons'], indent=4)};
const rules = {json.dumps(config_data['rules'], indent=4)};"""
config_path = get_config_path()
with open(config_path, 'w', encoding='utf-8') as f:
f.write(config_js)
return jsonify({'success': True})
@socketio.on('keydown')
def handle_keydown(data):
key = data['key']
print(f"[DEBUG] Received keydown: {key}")
if key not in pressed_keys:
pressed_keys.add(key)
try:
if not keyboard:
print(f"[WARNING] No keyboard controller available on this system")
return
if key == 'space':
print(f"[DEBUG] Pressing Key.space")
keyboard.press(Key.space)
elif key == 'NumpadEnter':
if platform.system() == "Windows":
print(f"[DEBUG] NumpadEnter avec flag étendu")
# Flag KEYEVENTF_EXTENDEDKEY = 0x0001
ctypes.windll.user32.keybd_event(0x0D, 0x1C, 0x0001, 0)
ctypes.windll.user32.keybd_event(0x0D, 0x1C, 0x0001 | 0x0002, 0)
else:
print(f"[DEBUG] NumpadEnter on Linux")
keyboard.press(Key.enter)
keyboard.release(Key.enter)
elif key == 'Enter':
print(f"[DEBUG] Pressing Key.enter (Enter)")
keyboard.press(Key.enter)
elif key.startswith('Numpad'):
# Gérer les autres touches numpad
numpad_map = {
'Numpad0': Key.insert, 'Numpad1': Key.end, 'Numpad2': Key.down,
'Numpad3': Key.page_down, 'Numpad4': Key.left, 'Numpad5': '5',
'Numpad6': Key.right, 'Numpad7': Key.home, 'Numpad8': Key.up,
'Numpad9': Key.page_up, 'NumpadAdd': '+', 'NumpadSubtract': '-',
'NumpadMultiply': '*', 'NumpadDivide': '/', 'NumpadDecimal': Key.delete
}
if key in numpad_map:
print(f"[DEBUG] Pressing numpad key: {key} -> {numpad_map[key]}")
keyboard.press(numpad_map[key])
else:
print(f"[DEBUG] Pressing unknown numpad key: {key}")
keyboard.press(key)
else:
print(f"[DEBUG] Pressing regular key: {key}")
keyboard.press(key)
print(f"✅ Touche enfoncée: {key}")
except Exception as e:
print(f"❌ Erreur keydown: {e}")
@socketio.on('keyup')
def handle_keyup(data):
key = data['key']
print(f"[DEBUG] Received keyup: {key}")
if key in pressed_keys:
pressed_keys.remove(key)
try:
if key == 'space':
print(f"[DEBUG] Releasing Key.space")
keyboard.release(Key.space)
elif key == 'NumpadEnter':
print(f"[DEBUG] NumpadEnter handled by press event")
pass # Déjà géré dans keydown
elif key == 'Enter':
print(f"[DEBUG] Releasing Key.enter (Enter)")
keyboard.release(Key.enter)
elif key.startswith('Numpad'):
# Gérer les autres touches numpad
numpad_map = {
'Numpad0': Key.insert, 'Numpad1': Key.end, 'Numpad2': Key.down,
'Numpad3': Key.page_down, 'Numpad4': Key.left, 'Numpad5': '5',
'Numpad6': Key.right, 'Numpad7': Key.home, 'Numpad8': Key.up,
'Numpad9': Key.page_up, 'NumpadAdd': '+', 'NumpadSubtract': '-',
'NumpadMultiply': '*', 'NumpadDivide': '/', 'NumpadDecimal': Key.delete
}
if key in numpad_map:
print(f"[DEBUG] Releasing numpad key: {key} -> {numpad_map[key]}")
keyboard.release(numpad_map[key])
else:
print(f"[DEBUG] Releasing unknown numpad key: {key}")
keyboard.release(key)
else:
print(f"[DEBUG] Releasing regular key: {key}")
keyboard.release(key)
print(f"✅ Touche relâchée: {key}")
except Exception as e:
print(f"❌ Erreur keyup: {e}")
if __name__ == '__main__':
try:
socketio.run(app, host='0.0.0.0', port=3001, debug=False)
except Exception as e:
print(f"Error starting server: {e}")
input("Press Enter to exit...")