112 lines
4.8 KiB
Python
112 lines
4.8 KiB
Python
import socketio
|
|
import base64
|
|
import numpy as np
|
|
import threading
|
|
import sounddevice as sd
|
|
import protocol
|
|
|
|
sio = socketio.Client()
|
|
_client_instance = None
|
|
|
|
def init_network(client_instance):
|
|
"""Binds the network events to the active TUI client instance state."""
|
|
global _client_instance
|
|
_client_instance = client_instance
|
|
|
|
@sio.event
|
|
def incoming_packet(data):
|
|
if not _client_instance: return
|
|
from_uin = data["from_uin"]
|
|
payload_base64 = data["payload"]
|
|
try:
|
|
audio_bytes = base64.b64decode(payload_base64.encode('utf-8'))
|
|
audio_data = np.frombuffer(audio_bytes, dtype=np.float32)
|
|
|
|
srv_tone = protocol.detect_service_tone(audio_data)
|
|
if srv_tone:
|
|
sd.play(audio_data, protocol.SAMPLE_RATE)
|
|
if from_uin not in _client_instance.contacts:
|
|
return
|
|
if srv_tone == protocol.FREQ_QUERY:
|
|
if _client_instance.is_busy:
|
|
_client_instance.send_service_tone(from_uin, protocol.FREQ_RESP_YES)
|
|
else:
|
|
_client_instance.pending_windows.append({"type": "query", "uin": from_uin})
|
|
_client_instance.refresh_ui()
|
|
return
|
|
elif srv_tone == protocol.FREQ_ALERT:
|
|
_client_instance.pending_windows.append({"type": "alert", "uin": from_uin})
|
|
_client_instance.refresh_ui()
|
|
return
|
|
elif srv_tone == protocol.FREQ_RESP_YES:
|
|
_client_instance.add_to_history(from_uin, f"[SYSTEM]: Quick status answer -> Yes, I'm busy")
|
|
return
|
|
elif srv_tone == protocol.FREQ_RESP_NO:
|
|
_client_instance.add_to_history(from_uin, f"[SYSTEM]: Quick status answer -> No, go on")
|
|
return
|
|
|
|
fast_text = protocol.fast_decode(audio_data)
|
|
if fast_text.startswith("SYS:"):
|
|
cmd = fast_text[4:]
|
|
if cmd.startswith("ROOM_MSG:"):
|
|
parts = cmd.split(":", 3)
|
|
if len(parts) >= 4:
|
|
room_id = parts[1]
|
|
sender_uin = parts[2]
|
|
actual_msg = parts[3]
|
|
if room_id in _client_instance.groups:
|
|
_client_instance.add_to_history(room_id, f"[UIN {sender_uin}]: {actual_msg}")
|
|
return
|
|
elif cmd == "REQ_ADD":
|
|
if from_uin in _client_instance.blocklist:
|
|
_client_instance.send_sys_packet(from_uin, "RES_DEC")
|
|
elif _client_instance.is_busy:
|
|
_client_instance.send_sys_packet(from_uin, "RES_BSY")
|
|
else:
|
|
if from_uin not in _client_instance.pending_requests and from_uin not in _client_instance.contacts:
|
|
_client_instance.pending_requests.append(from_uin)
|
|
_client_instance.refresh_ui()
|
|
return
|
|
elif cmd == "RES_ACC":
|
|
if _client_instance.dialing_uin == from_uin:
|
|
_client_instance.dialing_uin = None
|
|
if from_uin not in _client_instance.contacts:
|
|
_client_instance.contacts[from_uin] = {"status": "online", "unread": 0, "attention": False}
|
|
_client_instance.history[from_uin] = ["[SYSTEM]: Handshake accepted. Contact added."]
|
|
_client_instance.save_config()
|
|
_client_instance.active_chat = from_uin
|
|
_client_instance.refresh_ui()
|
|
return
|
|
elif cmd == "RES_DEC" or cmd == "RES_BSY":
|
|
if _client_instance.dialing_uin == from_uin:
|
|
_client_instance.dialing_uin = None
|
|
return
|
|
|
|
if from_uin not in _client_instance.contacts:
|
|
return
|
|
if _client_instance.active_chat != from_uin:
|
|
_client_instance.contacts[from_uin]["unread"] += 1
|
|
|
|
threading.Thread(target=_client_instance.play_and_decode, args=(audio_bytes, from_uin), daemon=True).start()
|
|
except Exception as e:
|
|
pass
|
|
|
|
@sio.event
|
|
def online_statuses_response(data):
|
|
if not _client_instance: return
|
|
for uin, status in data.items():
|
|
if uin in _client_instance.contacts:
|
|
_client_instance.contacts[uin]["status"] = status
|
|
_client_instance.refresh_ui()
|
|
|
|
@sio.event
|
|
def error(data):
|
|
if not _client_instance: return
|
|
msg = data.get("message")
|
|
target = data.get("target_uin")
|
|
if msg == "offline" and target:
|
|
if _client_instance.dialing_uin == target:
|
|
_client_instance.dialing_uin = None
|
|
if target in _client_instance.contacts:
|
|
_client_instance.contacts[target]["status"] = "offline"
|
|
_client_instance.add_to_history(target, f"[SYSTEM]: They went offline. Outgoing stack will be preserved.") |