Spaces:
Running
Running
import asyncio | |
import json | |
import os | |
import secrets | |
import signal | |
import subprocess | |
import websockets | |
import shutil | |
from connect4 import PLAYER1, PLAYER2, Connect4 | |
from user import User | |
import requests | |
from watchdog.observers import Observer | |
from watchdog.events import FileSystemEventHandler | |
class FileHandler(FileSystemEventHandler): | |
def __init__(self, websocket,connected): | |
super().__init__() | |
self.websocket = websocket | |
self.connected = connected | |
def on_modified(self, event): | |
if event.is_directory: | |
return | |
with open(event.src_path, 'r', encoding='utf-8') as file: | |
content = file.read() | |
# print(f'File {event.src_path} has been modified.') | |
new_event = { | |
"type": "file-modifie", | |
"content": content, | |
"path": event.src_path, | |
} | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
# websockets.broadcast(self.connected,f'File {event.src_path} has been modified.') | |
def on_created(self, event): | |
if event.is_directory: | |
new_event = { | |
"type": "folder-create", | |
"path": event.src_path, | |
"name": event.src_path.split('/')[-1] | |
} | |
# print(new_event) | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
else: | |
with open(event.src_path, 'r', encoding='utf-8') as file: | |
content = file.read() | |
# print(f'File {event.src_path} has been created.') | |
new_event = { | |
"type": "file-create", | |
"content": content, | |
"path": event.src_path, | |
"name": event.src_path.split('/')[-1] | |
} | |
# print(new_event) | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
# websockets.broadcast(self.connected,f'File {event.src_path} has been created.') | |
def on_deleted(self, event): | |
if event.is_directory: | |
new_event = { | |
"type": "delete", | |
"path": event.src_path, | |
"name": event.src_path.split('/')[-1], | |
} | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
else: | |
# print(f'File {event.src_path} has been deleted.') | |
new_event = { | |
"type": "delete", | |
"name": event.src_path.split('/')[-1], | |
"path": event.src_path, | |
} | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
def on_moved(self, event): | |
if event.is_directory: | |
new_event = { | |
"type": "rename", | |
"OldPath": event.src_path, | |
"oldname": event.src_path.split('/')[-1], | |
"NewPath": event.dest_path, | |
"newname": event.dest_path.split('/')[-1], | |
} | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
else: | |
# print(f'File {event.src_path} has been renamed to {event.dest_path}.') | |
new_event = { | |
"type": "rename", | |
"OldPath": event.src_path, | |
"oldname": event.src_path.split('/')[-1], | |
"NewPath": event.dest_path, | |
"newname": event.dest_path.split('/')[-1], | |
} | |
websockets.broadcast(self.connected,json.dumps(new_event)) | |
JOIN = {} | |
WATCH = {} | |
async def generate_file_structure(path, encoding='utf-8'): | |
file_structure = {'name': os.path.basename(path), 'type': 'folder', 'path': path, 'children': []} | |
try: | |
entries = os.listdir(path) | |
except FileNotFoundError: | |
return file_structure # Return an empty structure for non-existing directories | |
for entry in entries: | |
entry_path = os.path.join(path, entry) | |
if os.path.isdir(entry_path): | |
child_structure =await generate_file_structure(entry_path, encoding) | |
file_structure['children'].append(child_structure) | |
elif os.path.isfile(entry_path): | |
try: | |
with open(entry_path, 'r', encoding=encoding) as file: | |
content = file.read() | |
except UnicodeDecodeError: | |
content = 'Unable to read content' | |
file_structure['children'].append({'name': entry, 'type': 'file', 'path': entry_path, 'content': content}) | |
return file_structure | |
async def rename_item(websocket, key,project_name, path,rpath,new_name,root, connected): | |
old_path = os.path.join(os.getcwd(),'projects', key,project_name, rpath) | |
new_name = new_name | |
try: | |
if os.path.exists(old_path): | |
# Determine the new path | |
new_path = os.path.join(os.path.dirname(old_path), new_name) | |
# Rename the file or folder | |
os.rename(old_path, new_path) | |
websockets.broadcast(connected,'success') | |
event = { | |
"type": "rename-success", | |
"data": f'{old_path}-->{new_path}', | |
"path": path, | |
"new_rpath":rpath, | |
"name": new_name, | |
"root":root, | |
} | |
websockets.broadcast(connected,json.dumps(event)) | |
else: | |
event = { | |
"type": "rename-failed", | |
"data": f'{old_path}-->{new_path} failed Item not found', | |
"old_path": path, | |
"new_name": new_name, | |
} | |
websockets.broadcast(connected,json.dumps(event)) | |
except Exception as e: | |
websockets.broadcast(connected,str(e)) | |
async def delete_item(websocket, key,project_name, path,rpath,targetElementData, connected): | |
try: | |
item_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath) | |
if os.path.exists(item_path): | |
if os.path.isdir(item_path): | |
shutil.rmtree(item_path) # Remove the directory and its contents | |
elif os.path.isfile(item_path): | |
os.remove(item_path) # Remove the file | |
event = { | |
"type": "delete-success", | |
"data": path, | |
"path":path, | |
"targetElementData":targetElementData, | |
} | |
# print(event) | |
websockets.broadcast(connected,json.dumps(event)) | |
# websockets.broadcast(connected,'success') | |
else: | |
event = { | |
"type": "delete-failed", | |
"data": f'{item_path} Item not found', | |
} | |
websockets.broadcast(connected,json.dumps(event)) | |
except Exception as e: | |
# print(e) | |
websockets.broadcast(connected,str(e)) | |
async def get_file_content(websocket, key,project_name, path,rpath,name,connected): | |
file_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath) | |
try: | |
with open(file_path, 'r', encoding='utf-8') as file: | |
content = file.read() | |
event = { | |
"type": "content", | |
"content": content, | |
'fileName':name, | |
'rfilePath':rpath, | |
'filePath':path, | |
} | |
await websocket.send(json.dumps(event)) | |
except Exception as e: | |
event = { | |
"type": "error", | |
"message": f"Failed to read file content: {str(e)}", | |
} | |
await websocket.send(json.dumps(event)) | |
async def create_file(websocket, key,project_name, path,name,root,targetElementData,rpath, connected): | |
file_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath,name) | |
# Create the file | |
with open(file_path, 'w'): | |
pass | |
event = { | |
"type": "file-created", | |
"data": file_path, | |
"path": path, | |
"name": name, | |
"root":root, | |
"targetElementData":targetElementData, | |
} | |
websockets.broadcast(connected,json.dumps(event)) | |
async def create_folder(websocket, key,project_name, path,name,root,targetElementData,rpath, connected): | |
folder_path = os.path.join(os.getcwd(), 'projects', key,project_name, rpath,name) | |
# Create the folder | |
os.makedirs(folder_path) | |
event = { | |
"type": "folder-created", | |
"data": folder_path, | |
"path": path, | |
"name": name, | |
"root":root, | |
"targetElementData":targetElementData, | |
} | |
# print(folder_path,'created') | |
websockets.broadcast(connected,json.dumps(event)) | |
async def wirte_file(websocket, key,project_name, path, content, connected): | |
try: | |
file_path = os.path.join(os.getcwd(), 'projects', key,project_name, path) | |
file_content = content | |
with open(file_path, 'w', encoding='utf-8') as file: | |
file.write(file_content) | |
event = { | |
"type": "write-success", | |
"data": file_path, | |
"path": path, | |
"content": content, | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
except FileNotFoundError as e: | |
event = { | |
"type": "write-error", | |
"data": e, | |
} | |
websockets.broadcast(connected,json.dumps(event)) | |
async def read_process_output(process, websocket): | |
async for line in process.stdout: | |
# print('sending line') | |
event = { | |
"type": "terminal-data", | |
"data": line.strip().decode('utf-8'), | |
} | |
await websocket.send(json.dumps(event)) | |
async for line in process.stderr: | |
# print(f'error:{line.strip()}') | |
event = { | |
"type": "terminal-error", | |
"data": line.strip().decode('utf-8'), | |
} | |
await websocket.send(json.dumps(event)) | |
async def handle_user_input(websocket,key, process, connected): | |
while True: | |
try: | |
await asyncio.sleep(0.1) | |
if process.returncode is not None: | |
break | |
# message = await websocket.recv() | |
async for message in websocket: | |
# user_input = json.loads(message) | |
# print(user_input) | |
# print(f'Received user input: {user_input["command"]["command"]}') | |
# process_input(user_input["command"]["command"], process) | |
event = json.loads(message) | |
assert event["type"] == "cmd" | |
# command = event["command"] | |
# print(f'Received user input: {event}') | |
try: | |
if event["command"]["type"]=="shell": | |
await asyncio.sleep(0.1) | |
if process.returncode is not None: | |
base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"]) | |
directory_path = base_path | |
event_handler = FileHandler(websocket,connected) | |
observer = Observer() | |
observer.schedule(event_handler, path=directory_path, recursive=True) | |
observer.start() | |
try: | |
# await execute_command(websocket, key,event["project_name"], event["command"]["command"], connected) | |
# base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"]) | |
print(base_path) | |
mod_command = f'cd {base_path} && {event["command"]["command"]}' | |
print(mod_command) | |
try: | |
process = await asyncio.create_subprocess_shell( | |
mod_command, | |
# cwd=base_path, | |
stdin=asyncio.subprocess.PIPE, | |
stdout=asyncio.subprocess.PIPE, | |
stderr=asyncio.subprocess.PIPE, | |
# text=True, | |
) | |
async def send_message(message): | |
# print('sending msg') | |
# await websocket.send(f'data: {message}') | |
websockets.broadcast(connected,json.dumps(message) ) | |
await asyncio.gather( | |
handle_user_input(websocket,key, process, connected), | |
read_process_output(process, websocket) | |
) | |
return_code = await process.wait() | |
if return_code == 0: | |
# await send_message('Code executed successfully') | |
pass | |
else: | |
# await send_message(f'error:Execution failed with return code {return_code}') | |
pass | |
except Exception as e: | |
await error(websocket, str(e)) | |
except KeyboardInterrupt: | |
pass # Handle KeyboardInterrupt to gracefully stop the observer | |
observer.stop() | |
observer.join() | |
else: | |
process_input(event["command"]["command"], process) | |
elif event["command"]["type"]=="write": | |
await wirte_file(websocket, key,event["project_name"], event["path"], event["content"], connected) | |
elif event["command"]["type"]=="curl": | |
response = requests.get(event['url']) | |
event = { | |
"type": "web-data", | |
"data": response.text, | |
} | |
await websocket.send(json.dumps(event)) | |
elif event["command"]["type"]=="create": | |
if event["item"]=="folder": | |
await create_folder(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected) | |
else: | |
await create_file(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected) | |
elif event["command"]["type"]=="delete": | |
await delete_item(websocket, key,event["project_name"], event["path"],event['rpath'],event['targetElementData'], connected) | |
elif event["command"]["type"]=="get_content": | |
await get_file_content(websocket, key,event["project_name"],event["filePath"], event["rfilePath"],event["fileName"] ,connected) | |
elif event["command"]["type"]=="rename": | |
await rename_item(websocket, key,event["project_name"], event["path"],event['rpath'], event["name"], event["root"], connected) | |
elif event["command"]["type"]=="join": | |
await join(websocket, event["join"]) | |
elif event["command"]["type"]=="sendDir": | |
data=json.loads(event["file_structure"]) | |
event = { | |
"type": "createDir", | |
"path": data, | |
"root":event['root'], | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="createItemUI": | |
event = { | |
"type": "createItemUI", | |
'targetElementData':event['targetElementData'], | |
'data':event['data'] | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="renameItemInUI": | |
event = { | |
"type": "renameItemInUI", | |
'path':event['path'], | |
'new_path':event['new_path'], | |
'name':event['name'], | |
'new_rpath':event['new_rpath'], | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="createFolderUI": | |
event = { | |
"type": "createFolderUI", | |
'targetElementData':event['targetElementData'], | |
'data':event['data'] | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="removeItemFromUI": | |
event = { | |
"type": "removeItemFromUI", | |
'targetElementData':event['targetElementData'], | |
'path':event['path'] | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="project": | |
base_path = os.path.join(os.getcwd(), 'projects',key, event["project_name"]) | |
data=json.loads(event["file_structure"]) | |
await create_file_structure(websocket,data, base_path=base_path) | |
# await rename_item(websocket, key,event["project_name"], event["path"], event["name"], connected) | |
elif event["command"]["type"]=="collabration": | |
event = { | |
"type": "collabration", | |
'name': event["name"], | |
'line': event["cursorPos-line"], | |
'ch': event["cursorPos-ch"], | |
'file':event["file"], | |
'content': event["content"], | |
'color':event["color"] | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="cursor": | |
event = { | |
"type": "cursor", | |
'offset': event["offset"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="select": | |
event = { | |
"type": "select", | |
'id': event["id"], | |
'startOffset': event["startOffset"], | |
'endOffset': event["endOffset"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="addselection": | |
event = { | |
"type": "addselection", | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="insert": | |
event = { | |
"type": "insert", | |
'index': event["index"], | |
'text': event["text"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="replace": | |
event = { | |
"type": "replace", | |
'index': event["index"], | |
'length': event["length"], | |
'text': event["text"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="edelelte": | |
event = { | |
"type": "edelelte", | |
'index': event["index"], | |
'length': event["length"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="keep-alive": | |
event = { | |
"type": "keep-alive", | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
else: | |
# First player starts a new game. | |
pass | |
except RuntimeError as exc: | |
# Send an "error" event if the move was illegal. | |
await error(websocket, str(exc)) | |
continue | |
break | |
except websockets.ConnectionClosed: | |
# print("WebSocket connection closed") | |
break | |
except Exception as e: | |
# print(f"Error in input thread: {str(e)}") | |
pass | |
def process_input(user_input, process): | |
if process: | |
try: | |
if user_input=='Ctrl+C': | |
print('process stoping') | |
process.send_signal(signal.SIGINT) | |
else: | |
process.stdin.write(user_input.encode('utf-8') + b'\n') | |
#process.stdin.flush() | |
except Exception as e: | |
# print(f"Error writing to process stdin: {str(e)}") | |
pass | |
else: | |
# print("No process available to write to.") | |
pass | |
async def create_file_structure(websocket, data, base_path='.'): | |
if data['type'] == 'folder': | |
folder_path = os.path.join(base_path, data['name']) | |
os.makedirs(folder_path, exist_ok=True) | |
for child in data['children']: | |
await create_file_structure(websocket,child, base_path=folder_path) | |
elif data['type'] == 'file': | |
file_path = os.path.join(base_path, data['name']) | |
with open(file_path, 'w', encoding='utf-8') as file: | |
file.write(data['content']) | |
event = { | |
"type": "msg", | |
"message": "project created", | |
} | |
await websocket.send(json.dumps(event)) | |
async def error(websocket, message): | |
""" | |
Send an error message. | |
""" | |
event = { | |
"type": "error", | |
"message": message, | |
} | |
await websocket.send(json.dumps(event)) | |
async def exe(websocket,connected,key): | |
""" | |
Receive and process moves from a player. | |
""" | |
# print('in exe') | |
async for message in websocket: | |
# Parse a "play" event from the UI. | |
# print(message) | |
event = json.loads(message) | |
assert event["type"] == "cmd" | |
# command = event["command"] | |
# print(event) | |
try: | |
if event["command"]["type"]=="shell": | |
base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"]) | |
directory_path = base_path | |
event_handler = FileHandler(websocket,connected) | |
observer = Observer() | |
observer.schedule(event_handler, path=directory_path, recursive=True) | |
observer.start() | |
try: | |
# await execute_command(websocket, key,event["project_name"], event["command"]["command"], connected) | |
# base_path = os.path.join(os.getcwd(), 'projects', key,event["project_name"]) | |
print(base_path) | |
mod_command = f'cd {base_path} && {event["command"]["command"]}' | |
print(mod_command) | |
try: | |
process = await asyncio.create_subprocess_shell( | |
mod_command, | |
# cwd=base_path, | |
stdin=asyncio.subprocess.PIPE, | |
stdout=asyncio.subprocess.PIPE, | |
stderr=asyncio.subprocess.PIPE, | |
# text=True, | |
) | |
async def send_message(message): | |
# print('sending msg') | |
# await websocket.send(f'data: {message}') | |
websockets.broadcast(connected,json.dumps(message) ) | |
await asyncio.gather( | |
handle_user_input(websocket,key, process, connected), | |
read_process_output(process, websocket) | |
) | |
return_code = await process.wait() | |
if return_code == 0: | |
# await send_message('Code executed successfully') | |
pass | |
else: | |
# await send_message(f'error:Execution failed with return code {return_code}') | |
pass | |
except Exception as e: | |
await error(websocket, str(e)) | |
except KeyboardInterrupt: | |
pass # Handle KeyboardInterrupt to gracefully stop the observer | |
observer.stop() | |
observer.join() | |
elif event["command"]["type"]=="write": | |
await wirte_file(websocket, key,event["project_name"], event["path"], event["content"], connected) | |
elif event["command"]["type"]=="curl": | |
response = requests.get(event['url']) | |
event = { | |
"type": "web-data", | |
"data": response.text, | |
} | |
await websocket.send(json.dumps(event)) | |
elif event["command"]["type"]=="create": | |
if event["item"]=="folder": | |
await create_folder(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected) | |
else: | |
await create_file(websocket, key,event["project_name"], event["path"],event["name"],event['root'],event['targetElementData'],event["rpath"], connected) | |
elif event["command"]["type"]=="delete": | |
await delete_item(websocket, key,event["project_name"], event["path"],event['rpath'],event['targetElementData'], connected) | |
elif event["command"]["type"]=="get_content": | |
await get_file_content(websocket, key,event["project_name"],event["filePath"], event["rfilePath"],event["fileName"] ,connected) | |
elif event["command"]["type"]=="rename": | |
await rename_item(websocket, key,event["project_name"], event["path"],event['rpath'], event["name"], event["root"], connected) | |
elif event["command"]["type"]=="join": | |
await join(websocket, event["join"]) | |
elif event["command"]["type"]=="sendDir": | |
data=json.loads(event["file_structure"]) | |
event = { | |
"type": "createDir", | |
"path": data, | |
"root":event['root'], | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="createItemUI": | |
event = { | |
"type": "createItemUI", | |
'targetElementData':event['targetElementData'], | |
'data':event['data'] | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="renameItemInUI": | |
event = { | |
"type": "renameItemInUI", | |
'path':event['path'], | |
'new_path':event['new_path'], | |
'name':event['name'], | |
'new_rpath':event['new_rpath'], | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="createFolderUI": | |
event = { | |
"type": "createFolderUI", | |
'targetElementData':event['targetElementData'], | |
'data':event['data'] | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="removeItemFromUI": | |
event = { | |
"type": "removeItemFromUI", | |
'targetElementData':event['targetElementData'], | |
'path':event['path'] | |
} | |
# websockets.broadcast(connected,json.dumps(event)) | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="project": | |
base_path = os.path.join(os.getcwd(), 'projects',key, event["project_name"]) | |
data=json.loads(event["file_structure"]) | |
await create_file_structure(websocket,data, base_path=base_path) | |
# await rename_item(websocket, key,event["project_name"], event["path"], event["name"], connected) | |
elif event["command"]["type"]=="collabration": | |
event = { | |
"type": "collabration", | |
'name': event["name"], | |
'line': event["cursorPos-line"], | |
'ch': event["cursorPos-ch"], | |
'file':event["file"], | |
'content': event["content"], | |
'color':event["color"] | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="cursor": | |
event = { | |
"type": "cursor", | |
'offset': event["offset"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="select": | |
event = { | |
"type": "select", | |
'id': event["id"], | |
'startOffset': event["startOffset"], | |
'endOffset': event["endOffset"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="addselection": | |
event = { | |
"type": "addselection", | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="insert": | |
event = { | |
"type": "insert", | |
'index': event["index"], | |
'text': event["text"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
'tabStatus':event['tabStatus'], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="replace": | |
event = { | |
"type": "replace", | |
'index': event["index"], | |
'length': event["length"], | |
'text': event["text"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
'tabStatus':event['tabStatus'], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="edelelte": | |
event = { | |
"type": "edelelte", | |
'index': event["index"], | |
'length': event["length"], | |
'userid': event["userid"], | |
'userlabel': event["userlabel"], | |
'usercolor': event["usercolor"], | |
'fileName':event["fileName"], | |
} | |
websockets.broadcast(connected, json.dumps(event)) | |
elif event["command"]["type"]=="keep-alive": | |
event = { | |
"type": "keep-alive", | |
} | |
else: | |
# First player starts a new game. | |
pass | |
except RuntimeError as exc: | |
# Send an "error" event if the move was illegal. | |
await error(websocket, str(exc)) | |
continue | |
async def start(websocket,events): | |
user = User() | |
connected = {websocket} | |
join_key = secrets.token_urlsafe(12) | |
JOIN[join_key] = user, connected | |
try: | |
# Send the secret access tokens to the browser of the first player, | |
# where they'll be used for building "join" and "watch" links. | |
event = { | |
"type": "init", | |
"join": join_key, | |
} | |
await websocket.send(json.dumps(event)) | |
await exe(websocket,connected,join_key) | |
finally: | |
del JOIN[join_key] | |
async def join(websocket, key): | |
""" | |
Handle a connection from the second player: join an existing game. | |
""" | |
# Find the Connect Four game. | |
try: | |
user, connected = JOIN[key] | |
except KeyError: | |
await error(websocket, "collabration not found.") | |
return | |
# Register to receive moves from this game. | |
connected.add(websocket) | |
try: | |
event = { | |
"type": "sendDir", | |
} | |
websockets.broadcast(connected,json.dumps(event)) | |
await exe(websocket,connected,key) | |
finally: | |
connected.remove(websocket) | |
async def handler(websocket): | |
""" | |
Handle a connection and dispatch it according to who is connecting. | |
""" | |
# Receive and parse the "init" event from the UI. | |
message = await websocket.recv() | |
event = json.loads(message) | |
# print(event) | |
# project_name = event["project_name"] | |
# assert event["type"] == "init" | |
if event["type"] == "init": | |
if "join" in event: | |
# Second player joins an existing game. | |
await join(websocket, event["join"]) | |
else: | |
# First player starts a new game. | |
await start(websocket, message) | |
elif event["type"] == "cmd": | |
# print('executing commad') | |
# Execute a command in the project folder. | |
await execute_command(websocket, event["project_name"], event["command"]) | |
async def main(): | |
# Set the stop condition when receiving SIGTERM. | |
loop = asyncio.get_running_loop() | |
stop = loop.create_future() | |
loop.add_signal_handler(signal.SIGTERM, stop.set_result, None) | |
port = int(os.environ.get("PORT", "7860")) | |
async with websockets.serve(handler, "0.0.0.0", port): | |
await stop | |
if __name__ == "__main__": | |
asyncio.run(main()) |