Ramesh-vani commited on
Commit
f05f654
·
verified ·
1 Parent(s): 44ea949

Update server.py

Browse files
Files changed (1) hide show
  1. server.py +977 -49
server.py CHANGED
@@ -1,52 +1,980 @@
1
- from http.server import HTTPServer, BaseHTTPRequestHandler
2
  import json
3
- from socketserver import ThreadingMixIn
4
- class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
5
- pass
6
- class MyHandler(BaseHTTPRequestHandler):
7
- API_KEY = "123" # Replace with your actual API key
8
-
9
- def do_GET(self):
10
- # Extract the API key from the request headers
11
- api_key = self.headers.get('API-Key')
12
-
13
- if api_key == self.API_KEY:
14
- # API key is valid, process the request
15
- if self.path == '/api/data':
16
- response_data = {'message': 'Hello, this is your API response!'}
17
- self.send_response(200)
18
- self.send_header('Content-type', 'application/json')
19
- self.end_headers()
20
- self.wfile.write(bytes(json.dumps(response_data), 'utf8'))
21
- else:
22
- # Serve HTML file for other requests
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  try:
24
- with open('templates/index.html', 'r') as f:
25
- content = f.read()
26
- self.send_response(200)
27
- self.send_header('Content-type', 'text/html')
28
- self.end_headers()
29
- self.wfile.write(bytes(content, 'utf8'))
30
- except FileNotFoundError:
31
- self.send_response(404)
32
- self.send_header('Content-type', 'text/html')
33
- self.end_headers()
34
- self.wfile.write(b'404: File not found')
35
- except Exception as e:
36
- self.send_response(500)
37
- self.send_header('Content-type', 'text/html')
38
- self.end_headers()
39
- self.wfile.write(f'500: Internal Server Error - {str(e)}'.encode('utf-8'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  else:
41
- # Invalid API key
42
- self.send_response(401)
43
- self.send_header('Content-type', 'text/html')
44
- self.end_headers()
45
- self.wfile.write(b'401: Unauthorized - Invalid API Key')
46
-
47
- # Create an HTTP server and bind it to a specific host and port
48
- # Create a threaded HTTP server
49
- httpd = ThreadedHTTPServer(('0.0.0.0', 7860), MyHandler)
50
-
51
- # Start serving indefinitely
52
- httpd.serve_forever()
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
  import json
3
+ import os
4
+ import secrets
5
+ import signal
6
+ import subprocess
7
+ import websockets
8
+ import shutil
9
+ #from connect4 import PLAYER1, PLAYER2, Connect4
10
+ #from user import User
11
+ __all__ = ["User",]
12
+
13
+ class User:
14
+ """
15
+ A Connect user .
16
+ """
17
+
18
+ def __init__(self):
19
+ pass
20
+ import requests
21
+ from watchdog.observers import Observer
22
+ from watchdog.events import FileSystemEventHandler
23
+
24
+ class FileHandler(FileSystemEventHandler):
25
+ def __init__(self, websocket,connected):
26
+ super().__init__()
27
+ self.websocket = websocket
28
+ self.connected = connected
29
+ def on_modified(self, event):
30
+ if event.is_directory:
31
+ return
32
+ with open(event.src_path, 'r', encoding='utf-8') as file:
33
+ content = file.read()
34
+ # print(f'File {event.src_path} has been modified.')
35
+ new_event = {
36
+ "type": "file-modifie",
37
+ "content": content,
38
+ "path": event.src_path,
39
+ }
40
+ websockets.broadcast(self.connected,json.dumps(new_event))
41
+ # websockets.broadcast(self.connected,f'File {event.src_path} has been modified.')
42
+
43
+ def on_created(self, event):
44
+ if event.is_directory:
45
+ new_event = {
46
+ "type": "folder-create",
47
+
48
+ "path": event.src_path,
49
+ "name": event.src_path.split('/')[-1]
50
+ }
51
+ # print(new_event)
52
+ websockets.broadcast(self.connected,json.dumps(new_event))
53
+ else:
54
+ with open(event.src_path, 'r', encoding='utf-8') as file:
55
+ content = file.read()
56
+ # print(f'File {event.src_path} has been created.')
57
+ new_event = {
58
+ "type": "file-create",
59
+ "content": content,
60
+ "path": event.src_path,
61
+ "name": event.src_path.split('/')[-1]
62
+ }
63
+ # print(new_event)
64
+ websockets.broadcast(self.connected,json.dumps(new_event))
65
+ # websockets.broadcast(self.connected,f'File {event.src_path} has been created.')
66
+
67
+ def on_deleted(self, event):
68
+ if event.is_directory:
69
+ new_event = {
70
+ "type": "delete",
71
+
72
+ "path": event.src_path,
73
+ "name": event.src_path.split('/')[-1],
74
+ }
75
+ websockets.broadcast(self.connected,json.dumps(new_event))
76
+ else:
77
+ # print(f'File {event.src_path} has been deleted.')
78
+ new_event = {
79
+ "type": "delete",
80
+ "name": event.src_path.split('/')[-1],
81
+ "path": event.src_path,
82
+ }
83
+ websockets.broadcast(self.connected,json.dumps(new_event))
84
+
85
+ def on_moved(self, event):
86
+ if event.is_directory:
87
+ new_event = {
88
+ "type": "rename",
89
+
90
+ "OldPath": event.src_path,
91
+ "oldname": event.src_path.split('/')[-1],
92
+ "NewPath": event.dest_path,
93
+ "newname": event.dest_path.split('/')[-1],
94
+ }
95
+ websockets.broadcast(self.connected,json.dumps(new_event))
96
+ else:
97
+ # print(f'File {event.src_path} has been renamed to {event.dest_path}.')
98
+ new_event = {
99
+ "type": "rename",
100
+
101
+ "OldPath": event.src_path,
102
+ "oldname": event.src_path.split('/')[-1],
103
+ "NewPath": event.dest_path,
104
+ "newname": event.dest_path.split('/')[-1],
105
+ }
106
+ websockets.broadcast(self.connected,json.dumps(new_event))
107
+
108
+ JOIN = {}
109
+
110
+ WATCH = {}
111
+
112
+ async def generate_file_structure(path, encoding='utf-8'):
113
+ file_structure = {'name': os.path.basename(path), 'type': 'folder', 'path': path, 'children': []}
114
+
115
+ try:
116
+ entries = os.listdir(path)
117
+ except FileNotFoundError:
118
+ return file_structure # Return an empty structure for non-existing directories
119
+
120
+ for entry in entries:
121
+ entry_path = os.path.join(path, entry)
122
+ if os.path.isdir(entry_path):
123
+ child_structure =await generate_file_structure(entry_path, encoding)
124
+ file_structure['children'].append(child_structure)
125
+ elif os.path.isfile(entry_path):
126
+ try:
127
+ with open(entry_path, 'r', encoding=encoding) as file:
128
+ content = file.read()
129
+ except UnicodeDecodeError:
130
+ content = 'Unable to read content'
131
+ file_structure['children'].append({'name': entry, 'type': 'file', 'path': entry_path, 'content': content})
132
+
133
+ return file_structure
134
+
135
+ async def rename_item(websocket, key,project_name, path,rpath,new_name,root, connected):
136
+
137
+ old_path = os.path.join(os.getcwd(),'projects', key,project_name, rpath)
138
+ new_name = new_name
139
+
140
+ try:
141
+ if os.path.exists(old_path):
142
+ # Determine the new path
143
+ new_path = os.path.join(os.path.dirname(old_path), new_name)
144
+
145
+ # Rename the file or folder
146
+ os.rename(old_path, new_path)
147
+
148
+ websockets.broadcast(connected,'success')
149
+ event = {
150
+ "type": "rename-success",
151
+ "data": f'{old_path}-->{new_path}',
152
+ "path": path,
153
+ "new_rpath":rpath,
154
+ "name": new_name,
155
+ "root":root,
156
+ }
157
+ websockets.broadcast(connected,json.dumps(event))
158
+ else:
159
+ event = {
160
+ "type": "rename-failed",
161
+ "data": f'{old_path}-->{new_path} failed Item not found',
162
+ "old_path": path,
163
+ "new_name": new_name,
164
+ }
165
+ websockets.broadcast(connected,json.dumps(event))
166
+ except Exception as e:
167
+ websockets.broadcast(connected,str(e))
168
+
169
+ async def delete_item(websocket, key,project_name, path,rpath,targetElementData, connected):
170
+ try:
171
+
172
+ item_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath)
173
+
174
+ if os.path.exists(item_path):
175
+ if os.path.isdir(item_path):
176
+ shutil.rmtree(item_path) # Remove the directory and its contents
177
+ elif os.path.isfile(item_path):
178
+ os.remove(item_path) # Remove the file
179
+
180
+ event = {
181
+ "type": "delete-success",
182
+ "data": path,
183
+ "path":path,
184
+ "targetElementData":targetElementData,
185
+ }
186
+ # print(event)
187
+ websockets.broadcast(connected,json.dumps(event))
188
+ # websockets.broadcast(connected,'success')
189
+ else:
190
+ event = {
191
+ "type": "delete-failed",
192
+ "data": f'{item_path} Item not found',
193
+ }
194
+ websockets.broadcast(connected,json.dumps(event))
195
+ except Exception as e:
196
+ # print(e)
197
+ websockets.broadcast(connected,str(e))
198
+
199
+ async def get_file_content(websocket, key,project_name, path,rpath,name,connected):
200
+
201
+ file_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath)
202
+
203
+ try:
204
+ with open(file_path, 'r', encoding='utf-8') as file:
205
+ content = file.read()
206
+ event = {
207
+ "type": "content",
208
+ "content": content,
209
+ 'fileName':name,
210
+ 'rfilePath':rpath,
211
+ 'filePath':path,
212
+ }
213
+ await websocket.send(json.dumps(event))
214
+ except Exception as e:
215
+ event = {
216
+ "type": "error",
217
+ "message": f"Failed to read file content: {str(e)}",
218
+ }
219
+ await websocket.send(json.dumps(event))
220
+
221
+
222
+
223
+ async def create_file(websocket, key,project_name, path,name,root,targetElementData,rpath, connected):
224
+ file_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath,name)
225
+ # Create the file
226
+ with open(file_path, 'w'):
227
+ pass
228
+ event = {
229
+ "type": "file-created",
230
+ "data": file_path,
231
+ "path": path,
232
+ "name": name,
233
+ "root":root,
234
+ "targetElementData":targetElementData,
235
+ }
236
+ websockets.broadcast(connected,json.dumps(event))
237
+
238
+
239
+ async def create_folder(websocket, key,project_name, path,name,root,targetElementData,rpath, connected):
240
+ folder_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath,name)
241
+ # Create the folder
242
+ os.makedirs(folder_path)
243
+ event = {
244
+ "type": "folder-created",
245
+ "data": folder_path,
246
+ "path": path,
247
+ "name": name,
248
+ "root":root,
249
+ "targetElementData":targetElementData,
250
+ }
251
+ # print(folder_path,'created')
252
+ websockets.broadcast(connected,json.dumps(event))
253
+
254
+
255
+ async def wirte_file(websocket, key,project_name, path, content, connected):
256
+ try:
257
+ file_path = os.path.join(os.getcwd(), 'projects', key,project_name, path)
258
+ file_content = content
259
+ with open(file_path, 'w', encoding='utf-8') as file:
260
+ file.write(file_content)
261
+
262
+ event = {
263
+ "type": "write-success",
264
+ "data": file_path,
265
+ "path": path,
266
+ "content": content,
267
+ }
268
+ # websockets.broadcast(connected,json.dumps(event))
269
+ except FileNotFoundError as e:
270
+ event = {
271
+ "type": "write-error",
272
+ "data": e,
273
+ }
274
+ websockets.broadcast(connected,json.dumps(event))
275
+
276
+ async def read_process_output(process, websocket):
277
+ async for line in process.stdout:
278
+ # print('sending line')
279
+
280
+ event = {
281
+ "type": "terminal-data",
282
+ "data": line.strip().decode('utf-8'),
283
+ }
284
+ await websocket.send(json.dumps(event))
285
+
286
+
287
+ async for line in process.stderr:
288
+ # print(f'error:{line.strip()}')
289
+ event = {
290
+ "type": "terminal-error",
291
+ "data": line.strip().decode('utf-8'),
292
+ }
293
+ await websocket.send(json.dumps(event))
294
+
295
+ async def handle_user_input(websocket,key, process, connected):
296
+ while True:
297
+ try:
298
+ await asyncio.sleep(0.1)
299
+ if process.returncode is not None:
300
+ break
301
+ # message = await websocket.recv()
302
+ async for message in websocket:
303
+ # user_input = json.loads(message)
304
+ # print(user_input)
305
+ # print(f'Received user input: {user_input["command"]["command"]}')
306
+
307
+ # process_input(user_input["command"]["command"], process)
308
+ event = json.loads(message)
309
+ assert event["type"] == "cmd"
310
+ # command = event["command"]
311
+ # print(f'Received user input: {event}')
312
  try:
313
+ if event["command"]["type"]=="shell":
314
+ await asyncio.sleep(0.1)
315
+ if process.returncode is not None:
316
+ base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"])
317
+ directory_path = base_path
318
+ event_handler = FileHandler(websocket,connected)
319
+ observer = Observer()
320
+ observer.schedule(event_handler, path=directory_path, recursive=True)
321
+ observer.start()
322
+
323
+ try:
324
+ # await execute_command(websocket, key,event["project_name"], event["command"]["command"], connected)
325
+ # base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"])
326
+ print(base_path)
327
+ mod_command = f'cd {base_path} && {event["command"]["command"]}'
328
+ print(mod_command)
329
+
330
+ try:
331
+ process = await asyncio.create_subprocess_shell(
332
+ mod_command,
333
+ # cwd=base_path,
334
+ stdin=asyncio.subprocess.PIPE,
335
+ stdout=asyncio.subprocess.PIPE,
336
+ stderr=asyncio.subprocess.PIPE,
337
+ # text=True,
338
+ )
339
+
340
+ async def send_message(message):
341
+ # print('sending msg')
342
+ # await websocket.send(f'data: {message}')
343
+ websockets.broadcast(connected,json.dumps(message) )
344
+
345
+
346
+
347
+ await asyncio.gather(
348
+ handle_user_input(websocket,key, process, connected),
349
+ read_process_output(process, websocket)
350
+ )
351
+
352
+ return_code = await process.wait()
353
+ if return_code == 0:
354
+ # await send_message('Code executed successfully')
355
+ pass
356
+ else:
357
+ # await send_message(f'error:Execution failed with return code {return_code}')
358
+ pass
359
+
360
+ except Exception as e:
361
+ await error(websocket, str(e))
362
+ except KeyboardInterrupt:
363
+ pass # Handle KeyboardInterrupt to gracefully stop the observer
364
+
365
+ observer.stop()
366
+ observer.join()
367
+ else:
368
+ process_input(event["command"]["command"], process)
369
+
370
+ elif event["command"]["type"]=="write":
371
+
372
+ await wirte_file(websocket, key,event["project_name"], event["path"], event["content"], connected)
373
+ elif event["command"]["type"]=="curl":
374
+
375
+ response = requests.get(event['url'])
376
+ event = {
377
+ "type": "web-data",
378
+
379
+ "data": response.text,
380
+
381
+ }
382
+ await websocket.send(json.dumps(event))
383
+ elif event["command"]["type"]=="create":
384
+ if event["item"]=="folder":
385
+ await create_folder(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected)
386
+ else:
387
+ await create_file(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected)
388
+
389
+
390
+ elif event["command"]["type"]=="delete":
391
+
392
+ await delete_item(websocket, key,event["project_name"], event["path"],event['rpath'],event['targetElementData'], connected)
393
+ elif event["command"]["type"]=="get_content":
394
+
395
+ await get_file_content(websocket, key,event["project_name"],event["filePath"], event["rfilePath"],event["fileName"] ,connected)
396
+ elif event["command"]["type"]=="rename":
397
+
398
+ await rename_item(websocket, key,event["project_name"], event["path"],event['rpath'], event["name"], event["root"], connected)
399
+ elif event["command"]["type"]=="join":
400
+ await join(websocket, event["join"])
401
+ elif event["command"]["type"]=="sendDir":
402
+ data=json.loads(event["file_structure"])
403
+ event = {
404
+ "type": "createDir",
405
+
406
+ "path": data,
407
+ "root":event['root'],
408
+
409
+ }
410
+ # websockets.broadcast(connected,json.dumps(event))
411
+ websockets.broadcast(connected, json.dumps(event))
412
+ elif event["command"]["type"]=="createItemUI":
413
+
414
+ event = {
415
+ "type": "createItemUI",
416
+
417
+ 'targetElementData':event['targetElementData'],
418
+ 'data':event['data']
419
+
420
+ }
421
+ # websockets.broadcast(connected,json.dumps(event))
422
+ websockets.broadcast(connected, json.dumps(event))
423
+
424
+ elif event["command"]["type"]=="renameItemInUI":
425
+
426
+ event = {
427
+ "type": "renameItemInUI",
428
+
429
+ 'path':event['path'],
430
+ 'new_path':event['new_path'],
431
+ 'name':event['name'],
432
+ 'new_rpath':event['new_rpath'],
433
+
434
+ }
435
+ # websockets.broadcast(connected,json.dumps(event))
436
+ websockets.broadcast(connected, json.dumps(event))
437
+ elif event["command"]["type"]=="createFolderUI":
438
+
439
+ event = {
440
+ "type": "createFolderUI",
441
+
442
+ 'targetElementData':event['targetElementData'],
443
+ 'data':event['data']
444
+
445
+ }
446
+ # websockets.broadcast(connected,json.dumps(event))
447
+ websockets.broadcast(connected, json.dumps(event))
448
+
449
+ elif event["command"]["type"]=="removeItemFromUI":
450
+
451
+ event = {
452
+ "type": "removeItemFromUI",
453
+
454
+ 'targetElementData':event['targetElementData'],
455
+ 'path':event['path']
456
+
457
+ }
458
+ # websockets.broadcast(connected,json.dumps(event))
459
+ websockets.broadcast(connected, json.dumps(event))
460
+
461
+ elif event["command"]["type"]=="project":
462
+ base_path = os.path.join(os.getcwd(), 'projects',key, event["project_name"])
463
+ data=json.loads(event["file_structure"])
464
+
465
+ await create_file_structure(websocket,data, base_path=base_path)
466
+ # await rename_item(websocket, key,event["project_name"], event["path"], event["name"], connected)
467
+ elif event["command"]["type"]=="collabration":
468
+
469
+ event = {
470
+ "type": "collabration",
471
+ 'name': event["name"],
472
+ 'line': event["cursorPos-line"],
473
+ 'ch': event["cursorPos-ch"],
474
+ 'file':event["file"],
475
+ 'content': event["content"],
476
+ 'color':event["color"]
477
+ }
478
+ websockets.broadcast(connected, json.dumps(event))
479
+ elif event["command"]["type"]=="cursor":
480
+
481
+ event = {
482
+ "type": "cursor",
483
+ 'offset': event["offset"],
484
+ 'userid': event["userid"],
485
+ 'userlabel': event["userlabel"],
486
+ 'usercolor': event["usercolor"],
487
+ 'fileName':event["fileName"],
488
+
489
+ }
490
+ websockets.broadcast(connected, json.dumps(event))
491
+ elif event["command"]["type"]=="select":
492
+
493
+ event = {
494
+ "type": "select",
495
+ 'id': event["id"],
496
+ 'startOffset': event["startOffset"],
497
+ 'endOffset': event["endOffset"],
498
+ 'userid': event["userid"],
499
+ 'userlabel': event["userlabel"],
500
+ 'usercolor': event["usercolor"],
501
+ 'fileName':event["fileName"],
502
+
503
+ }
504
+ websockets.broadcast(connected, json.dumps(event))
505
+ elif event["command"]["type"]=="addselection":
506
+
507
+ event = {
508
+ "type": "addselection",
509
+
510
+ 'userid': event["userid"],
511
+ 'userlabel': event["userlabel"],
512
+ 'usercolor': event["usercolor"],
513
+
514
+
515
+ }
516
+ websockets.broadcast(connected, json.dumps(event))
517
+ elif event["command"]["type"]=="insert":
518
+
519
+ event = {
520
+ "type": "insert",
521
+ 'index': event["index"],
522
+ 'text': event["text"],
523
+ 'userid': event["userid"],
524
+ 'userlabel': event["userlabel"],
525
+ 'usercolor': event["usercolor"],
526
+ 'fileName':event["fileName"],
527
+
528
+ }
529
+ websockets.broadcast(connected, json.dumps(event))
530
+ elif event["command"]["type"]=="replace":
531
+
532
+ event = {
533
+ "type": "replace",
534
+ 'index': event["index"],
535
+ 'length': event["length"],
536
+ 'text': event["text"],
537
+ 'userid': event["userid"],
538
+ 'userlabel': event["userlabel"],
539
+ 'usercolor': event["usercolor"],
540
+ 'fileName':event["fileName"],
541
+
542
+ }
543
+ websockets.broadcast(connected, json.dumps(event))
544
+ elif event["command"]["type"]=="edelelte":
545
+
546
+ event = {
547
+ "type": "edelelte",
548
+ 'index': event["index"],
549
+ 'length': event["length"],
550
+ 'userid': event["userid"],
551
+ 'userlabel': event["userlabel"],
552
+ 'usercolor': event["usercolor"],
553
+ 'fileName':event["fileName"],
554
+
555
+
556
+ }
557
+ websockets.broadcast(connected, json.dumps(event))
558
+ elif event["command"]["type"]=="keep-alive":
559
+ event = {
560
+ "type": "keep-alive",
561
+
562
+ }
563
+ websockets.broadcast(connected, json.dumps(event))
564
+ else:
565
+ # First player starts a new game.
566
+ pass
567
+ except RuntimeError as exc:
568
+ # Send an "error" event if the move was illegal.
569
+ await error(websocket, str(exc))
570
+ continue
571
+ break
572
+ except websockets.ConnectionClosed:
573
+ # print("WebSocket connection closed")
574
+ break
575
+ except Exception as e:
576
+ # print(f"Error in input thread: {str(e)}")
577
+ pass
578
+
579
+ def process_input(user_input, process):
580
+ if process:
581
+ try:
582
+ if user_input=='Ctrl+C':
583
+ print('process stoping')
584
+ process.send_signal(signal.SIGINT)
585
+ else:
586
+ process.stdin.write(user_input.encode('utf-8') + b'\n')
587
+ #process.stdin.flush()
588
+ except Exception as e:
589
+ # print(f"Error writing to process stdin: {str(e)}")
590
+ pass
591
+ else:
592
+ # print("No process available to write to.")
593
+ pass
594
+
595
+ async def create_file_structure(websocket, data, base_path='.'):
596
+ if data['type'] == 'folder':
597
+ folder_path = os.path.join(base_path, data['name'])
598
+ os.makedirs(folder_path, exist_ok=True)
599
+ for child in data['children']:
600
+ await create_file_structure(websocket,child, base_path=folder_path)
601
+ elif data['type'] == 'file':
602
+ file_path = os.path.join(base_path, data['name'])
603
+ with open(file_path, 'w', encoding='utf-8') as file:
604
+ file.write(data['content'])
605
+
606
+ event = {
607
+ "type": "msg",
608
+ "message": "project created",
609
+ }
610
+ await websocket.send(json.dumps(event))
611
+
612
+
613
+ async def error(websocket, message):
614
+ """
615
+ Send an error message.
616
+
617
+ """
618
+ event = {
619
+ "type": "error",
620
+ "message": message,
621
+ }
622
+ await websocket.send(json.dumps(event))
623
+
624
+
625
+ async def exe(websocket,connected,key):
626
+ """
627
+ Receive and process moves from a player.
628
+
629
+ """
630
+ # print('in exe')
631
+ async for message in websocket:
632
+ # Parse a "play" event from the UI.
633
+ # print(message)
634
+ event = json.loads(message)
635
+ assert event["type"] == "cmd"
636
+ # command = event["command"]
637
+ # print(event)
638
+
639
+ try:
640
+ if event["command"]["type"]=="shell":
641
+ base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"])
642
+ directory_path = base_path
643
+ event_handler = FileHandler(websocket,connected)
644
+ observer = Observer()
645
+ observer.schedule(event_handler, path=directory_path, recursive=True)
646
+ observer.start()
647
+
648
+ try:
649
+ # await execute_command(websocket, key,event["project_name"], event["command"]["command"], connected)
650
+ # base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"])
651
+ print(base_path)
652
+ mod_command = f'cd {base_path} && {event["command"]["command"]}'
653
+ print(mod_command)
654
+
655
+ try:
656
+ process = await asyncio.create_subprocess_shell(
657
+ mod_command,
658
+ # cwd=base_path,
659
+ stdin=asyncio.subprocess.PIPE,
660
+ stdout=asyncio.subprocess.PIPE,
661
+ stderr=asyncio.subprocess.PIPE,
662
+ # text=True,
663
+ )
664
+
665
+ async def send_message(message):
666
+ # print('sending msg')
667
+ # await websocket.send(f'data: {message}')
668
+ websockets.broadcast(connected,json.dumps(message) )
669
+
670
+
671
+
672
+ await asyncio.gather(
673
+ handle_user_input(websocket,key, process, connected),
674
+ read_process_output(process, websocket)
675
+ )
676
+
677
+ return_code = await process.wait()
678
+ if return_code == 0:
679
+ # await send_message('Code executed successfully')
680
+ pass
681
+ else:
682
+ # await send_message(f'error:Execution failed with return code {return_code}')
683
+ pass
684
+
685
+ except Exception as e:
686
+ await error(websocket, str(e))
687
+ except KeyboardInterrupt:
688
+ pass # Handle KeyboardInterrupt to gracefully stop the observer
689
+
690
+ observer.stop()
691
+ observer.join()
692
+
693
+ elif event["command"]["type"]=="write":
694
+
695
+ await wirte_file(websocket, key,event["project_name"], event["path"], event["content"], connected)
696
+ elif event["command"]["type"]=="curl":
697
+
698
+ response = requests.get(event['url'])
699
+ event = {
700
+ "type": "web-data",
701
+
702
+ "data": response.text,
703
+
704
+ }
705
+ await websocket.send(json.dumps(event))
706
+ elif event["command"]["type"]=="create":
707
+ if event["item"]=="folder":
708
+ await create_folder(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected)
709
+ else:
710
+ await create_file(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected)
711
+
712
+
713
+ elif event["command"]["type"]=="delete":
714
+
715
+ await delete_item(websocket, key,event["project_name"], event["path"],event['rpath'],event['targetElementData'], connected)
716
+ elif event["command"]["type"]=="get_content":
717
+
718
+ await get_file_content(websocket, key,event["project_name"],event["filePath"], event["rfilePath"],event["fileName"] ,connected)
719
+ elif event["command"]["type"]=="rename":
720
+
721
+ await rename_item(websocket, key,event["project_name"], event["path"],event['rpath'], event["name"], event["root"], connected)
722
+ elif event["command"]["type"]=="join":
723
+ await join(websocket, event["join"])
724
+ elif event["command"]["type"]=="sendDir":
725
+ data=json.loads(event["file_structure"])
726
+ event = {
727
+ "type": "createDir",
728
+
729
+ "path": data,
730
+ "root":event['root'],
731
+
732
+ }
733
+ # websockets.broadcast(connected,json.dumps(event))
734
+ websockets.broadcast(connected, json.dumps(event))
735
+ elif event["command"]["type"]=="createItemUI":
736
+
737
+ event = {
738
+ "type": "createItemUI",
739
+
740
+ 'targetElementData':event['targetElementData'],
741
+ 'data':event['data']
742
+
743
+ }
744
+ # websockets.broadcast(connected,json.dumps(event))
745
+ websockets.broadcast(connected, json.dumps(event))
746
+
747
+ elif event["command"]["type"]=="renameItemInUI":
748
+
749
+ event = {
750
+ "type": "renameItemInUI",
751
+
752
+ 'path':event['path'],
753
+ 'new_path':event['new_path'],
754
+ 'name':event['name'],
755
+ 'new_rpath':event['new_rpath'],
756
+
757
+ }
758
+ # websockets.broadcast(connected,json.dumps(event))
759
+ websockets.broadcast(connected, json.dumps(event))
760
+ elif event["command"]["type"]=="createFolderUI":
761
+
762
+ event = {
763
+ "type": "createFolderUI",
764
+
765
+ 'targetElementData':event['targetElementData'],
766
+ 'data':event['data']
767
+
768
+ }
769
+ # websockets.broadcast(connected,json.dumps(event))
770
+ websockets.broadcast(connected, json.dumps(event))
771
+
772
+ elif event["command"]["type"]=="removeItemFromUI":
773
+
774
+ event = {
775
+ "type": "removeItemFromUI",
776
+
777
+ 'targetElementData':event['targetElementData'],
778
+ 'path':event['path']
779
+
780
+ }
781
+ # websockets.broadcast(connected,json.dumps(event))
782
+ websockets.broadcast(connected, json.dumps(event))
783
+
784
+ elif event["command"]["type"]=="project":
785
+ base_path = os.path.join(os.getcwd(), 'projects',key, event["project_name"])
786
+ data=json.loads(event["file_structure"])
787
+
788
+ await create_file_structure(websocket,data, base_path=base_path)
789
+ # await rename_item(websocket, key,event["project_name"], event["path"], event["name"], connected)
790
+ elif event["command"]["type"]=="collabration":
791
+
792
+ event = {
793
+ "type": "collabration",
794
+ 'name': event["name"],
795
+ 'line': event["cursorPos-line"],
796
+ 'ch': event["cursorPos-ch"],
797
+ 'file':event["file"],
798
+ 'content': event["content"],
799
+ 'color':event["color"]
800
+ }
801
+ websockets.broadcast(connected, json.dumps(event))
802
+ elif event["command"]["type"]=="cursor":
803
+
804
+ event = {
805
+ "type": "cursor",
806
+ 'offset': event["offset"],
807
+ 'userid': event["userid"],
808
+ 'userlabel': event["userlabel"],
809
+ 'usercolor': event["usercolor"],
810
+ 'fileName':event["fileName"],
811
+
812
+ }
813
+ websockets.broadcast(connected, json.dumps(event))
814
+ elif event["command"]["type"]=="select":
815
+
816
+ event = {
817
+ "type": "select",
818
+ 'id': event["id"],
819
+ 'startOffset': event["startOffset"],
820
+ 'endOffset': event["endOffset"],
821
+ 'userid': event["userid"],
822
+ 'userlabel': event["userlabel"],
823
+ 'usercolor': event["usercolor"],
824
+ 'fileName':event["fileName"],
825
+
826
+ }
827
+ websockets.broadcast(connected, json.dumps(event))
828
+ elif event["command"]["type"]=="addselection":
829
+
830
+ event = {
831
+ "type": "addselection",
832
+
833
+ 'userid': event["userid"],
834
+ 'userlabel': event["userlabel"],
835
+ 'usercolor': event["usercolor"],
836
+
837
+
838
+ }
839
+ websockets.broadcast(connected, json.dumps(event))
840
+ elif event["command"]["type"]=="insert":
841
+
842
+ event = {
843
+ "type": "insert",
844
+ 'index': event["index"],
845
+ 'text': event["text"],
846
+ 'userid': event["userid"],
847
+ 'userlabel': event["userlabel"],
848
+ 'usercolor': event["usercolor"],
849
+ 'fileName':event["fileName"],
850
+ 'tabStatus':event['tabStatus'],
851
+
852
+ }
853
+ websockets.broadcast(connected, json.dumps(event))
854
+ elif event["command"]["type"]=="replace":
855
+
856
+ event = {
857
+ "type": "replace",
858
+ 'index': event["index"],
859
+ 'length': event["length"],
860
+ 'text': event["text"],
861
+ 'userid': event["userid"],
862
+ 'userlabel': event["userlabel"],
863
+ 'usercolor': event["usercolor"],
864
+ 'fileName':event["fileName"],
865
+ 'tabStatus':event['tabStatus'],
866
+ }
867
+ websockets.broadcast(connected, json.dumps(event))
868
+ elif event["command"]["type"]=="edelelte":
869
+
870
+ event = {
871
+ "type": "edelelte",
872
+ 'index': event["index"],
873
+ 'length': event["length"],
874
+ 'userid': event["userid"],
875
+ 'userlabel': event["userlabel"],
876
+ 'usercolor': event["usercolor"],
877
+ 'fileName':event["fileName"],
878
+
879
+
880
+ }
881
+ websockets.broadcast(connected, json.dumps(event))
882
+ elif event["command"]["type"]=="keep-alive":
883
+ event = {
884
+ "type": "keep-alive",
885
+
886
+ }
887
+
888
+ else:
889
+ # First player starts a new game.
890
+ pass
891
+ except RuntimeError as exc:
892
+ # Send an "error" event if the move was illegal.
893
+ await error(websocket, str(exc))
894
+ continue
895
+
896
+
897
+ async def start(websocket,events):
898
+
899
+ user = User()
900
+ connected = {websocket}
901
+
902
+ join_key = secrets.token_urlsafe(12)
903
+ JOIN[join_key] = user, connected
904
+
905
+
906
+ try:
907
+ # Send the secret access tokens to the browser of the first player,
908
+ # where they'll be used for building "join" and "watch" links.
909
+ event = {
910
+ "type": "init",
911
+ "join": join_key,
912
+
913
+ }
914
+ await websocket.send(json.dumps(event))
915
+
916
+ await exe(websocket,connected,join_key)
917
+ finally:
918
+ del JOIN[join_key]
919
+
920
+
921
+
922
+ async def join(websocket, key):
923
+ """
924
+ Handle a connection from the second player: join an existing game.
925
+
926
+ """
927
+ # Find the Connect Four game.
928
+ try:
929
+ user, connected = JOIN[key]
930
+ except KeyError:
931
+ await error(websocket, "collabration not found.")
932
+ return
933
+
934
+ # Register to receive moves from this game.
935
+ connected.add(websocket)
936
+ try:
937
+ event = {
938
+ "type": "sendDir",
939
+ }
940
+ websockets.broadcast(connected,json.dumps(event))
941
+ await exe(websocket,connected,key)
942
+ finally:
943
+ connected.remove(websocket)
944
+
945
+ async def handler(websocket):
946
+ """
947
+ Handle a connection and dispatch it according to who is connecting.
948
+
949
+ """
950
+ # Receive and parse the "init" event from the UI.
951
+ message = await websocket.recv()
952
+ event = json.loads(message)
953
+ # print(event)
954
+ # project_name = event["project_name"]
955
+ # assert event["type"] == "init"
956
+ if event["type"] == "init":
957
+ if "join" in event:
958
+ # Second player joins an existing game.
959
+ await join(websocket, event["join"])
960
  else:
961
+ # First player starts a new game.
962
+ await start(websocket, message)
963
+ elif event["type"] == "cmd":
964
+ # print('executing commad')
965
+ # Execute a command in the project folder.
966
+ await execute_command(websocket, event["project_name"], event["command"])
967
+
968
+ async def main():
969
+ # Set the stop condition when receiving SIGTERM.
970
+ loop = asyncio.get_running_loop()
971
+ stop = loop.create_future()
972
+ loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)
973
+
974
+ port = int(os.environ.get("PORT", "7860"))
975
+ async with websockets.serve(handler, "0.0.0.0", port):
976
+ await stop
977
+
978
+
979
+ if __name__ == "__main__":
980
+ asyncio.run(main())