| import asyncio |
| import requests |
| import io as i_o |
| import contextlib |
| import sys |
| import concurrent.futures |
| from FoxDot import * |
|
|
| |
| API_URL = "https://houseofplaying.com/hop/api.php" |
| POLL_INTERVAL = 1 |
|
|
| def change_key(amt = 3, scl="minor", duration=4, flag=True): |
| Root.default = ((Root.default+amt) % 14)-5 |
| print(f"Key changed to {Root.default}") |
| Scale.default = scl |
| if flag: |
| Clock.future(duration, change_key, args=[amt, scl, duration]) |
|
|
| def change_cycle(notes, scales, plen, flag=True): |
| if (Clock.now() % plen) == 0: |
| Scale.default = scales[(Clock.now()/plen) % len(notes)] |
| Root.default = notes[(Clock.now()/plen) % len(notes)] |
| if flag: |
| change_cycle(notes, scales, plen) |
|
|
| |
| active_tasks = {} |
|
|
| def poll_server(): |
| try: |
| response = requests.get(f"{API_URL}?action=poll") |
| if response.status_code == 200: |
| return response.json() |
| except Exception as e: |
| print(f"Error polling server: {e}") |
| return None |
|
|
| def update_server(uid, output, status): |
| try: |
| data = {'uid': uid, 'output': output, 'status': status} |
| requests.post(f"{API_URL}?action=update", json=data) |
| except Exception as e: |
| print(f"Error updating server: {e}") |
|
|
| def stop(uid): |
| """Stops the execution of the cell with the given uid.""" |
| if uid in active_tasks: |
| print(f"Stopping task {uid}...") |
| task = active_tasks[uid] |
| if task != asyncio.current_task(): |
| task.cancel() |
| return f"Stopped {uid}" |
| else: |
| return "Cannot stop itself." |
| return f"Task {uid} not found or not running." |
|
|
| def stopall(): |
| """Stops all running executions.""" |
| count = 0 |
| for uid in list(active_tasks.keys()): |
| if active_tasks[uid] != asyncio.current_task(): |
| stop(uid) |
| count += 1 |
| try: |
| |
| try: |
| oldloop = asyncio.get_running_loop() |
| print("Starting new event loop...") |
| loop = asyncio.run(main()) |
| oldloop.stop() |
| except RuntimeError: |
| loop = asyncio.run(main()) |
| oldloop.stop() |
| if oldloop and oldloop.is_running(): |
| print("Event loop already running. Scheduling main task...") |
| loop.create_task(main()) |
| else: |
| print("Starting new event loop...") |
| loop=asyncio.run(main()) |
| loop.run_forever() |
|
|
| except KeyboardInterrupt: |
| print("Stopping consumer...") |
|
|
| return f"Stopped {count} tasks, killed main loop and restarted" |
|
|
| def execute_code_sync(code, uid): |
| |
| stdout_capture = i_o.StringIO() |
| status = "completed" |
| output = "" |
| |
| |
| local_scope = locals() |
| local_scope['stop'] = stop |
| local_scope['stopall'] = stopall |
| local_scope['change_key'] = change_key |
| local_scope['change_cycle'] = change_cycle |
| |
| try: |
| with contextlib.redirect_stdout(stdout_capture): |
| |
| |
| exec(code, globals(), local_scope) |
| output = stdout_capture.getvalue() |
| except Exception as e: |
| status = "error" |
| output = f"{e}" |
| print(f"An unexpected error occurred in {uid}: {e}") |
| |
| return output, status |
|
|
| async def process_task(uid, code): |
| |
| |
| print(f"Processing {uid}...") |
| |
| try: |
| |
| |
| update_server(uid, "Execution started...", "wait") |
| |
| |
| loop = asyncio.get_running_loop() |
| |
| output, status = await loop.run_in_executor(None, execute_code_sync, code, uid) |
| |
| |
| update_server(uid, output, status) |
| |
| except asyncio.CancelledError: |
| print(f"Task {uid} cancelled.") |
| update_server(uid, "Execution cancelled.", "error") |
| except Exception as e: |
| print(f"Error in task {uid}: {e}") |
| update_server(uid, str(e), "error") |
| finally: |
| if uid in active_tasks: |
| del active_tasks[uid] |
|
|
| async def main(): |
| print(f"Starting FoxDot Consumer (Async)... Polling {API_URL}") |
|
|
| while True: |
| |
| task_data = await asyncio.to_thread(poll_server) |
|
|
| if task_data: |
| uid = task_data.get('uid') |
| code = task_data.get('code') |
| print(f"Received task {uid}") |
|
|
| |
| taskold = None |
| if uid in active_tasks: |
| taskold = active_tasks[uid] |
| task = asyncio.create_task(process_task(uid, code)) |
| active_tasks[uid] = task |
| if taskold and taskold.is_running(): |
| taskold.cancel() |
|
|
| await asyncio.sleep(POLL_INTERVAL) |
| |
| if __name__ == "__main__": |
| try: |
| |
| try: |
| loop = asyncio.get_running_loop() |
| except RuntimeError: |
| loop = None |
|
|
| if loop and loop.is_running(): |
| print("Event loop already running. Scheduling main task...") |
| loop.create_task(main()) |
| |
| |
| else: |
| print("Starting new event loop...") |
| loop = asyncio.run(main()) |
|
|
| loop.run_forever() |
| except KeyboardInterrupt: |
| print("Stopping consumer...") |
|
|