Update app.py
Browse files
app.py
CHANGED
@@ -27,7 +27,7 @@ FUN_USERNAMES = [
|
|
27 |
"MysticMoose π¦", "GlitchGnome π§", "VortexViper π", "ChronoChimp π"
|
28 |
]
|
29 |
|
30 |
-
#
|
31 |
LOG_DIR = "user_logs"
|
32 |
os.makedirs(LOG_DIR, exist_ok=True)
|
33 |
|
@@ -41,7 +41,6 @@ def get_node_name():
|
|
41 |
|
42 |
def get_log_file(username):
|
43 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
44 |
-
# Replace spaces and emojis with underscores for valid filenames
|
45 |
safe_username = username.replace(" ", "_").encode('ascii', 'ignore').decode('ascii')
|
46 |
return os.path.join(LOG_DIR, f"{safe_username}_{timestamp}.md")
|
47 |
|
@@ -49,7 +48,6 @@ def save_log_entry(username, entry):
|
|
49 |
log_file = get_log_file(username)
|
50 |
try:
|
51 |
with open(log_file, 'a') as f:
|
52 |
-
# Format as Markdown with timestamp
|
53 |
f.write(f"```log\n[{entry['timestamp']}] {entry['level']}: {entry['message']}\n```\n")
|
54 |
logger.info(f"Saved log entry to {log_file}")
|
55 |
return log_file
|
@@ -66,7 +64,6 @@ def load_latest_log(username):
|
|
66 |
try:
|
67 |
with open(os.path.join(LOG_DIR, latest_file), 'r') as f:
|
68 |
content = f.read()
|
69 |
-
# Add line numbers to the Markdown content
|
70 |
lines = content.strip().split('\n')
|
71 |
numbered_content = "\n".join(f"{i+1}. {line}" for i, line in enumerate(lines))
|
72 |
return f"# Log for {username} ({latest_file})\n\n{numbered_content}"
|
@@ -79,7 +76,7 @@ active_connections = {}
|
|
79 |
async def websocket_handler(websocket, path):
|
80 |
try:
|
81 |
client_id = str(uuid.uuid4())
|
82 |
-
room_id = "logs"
|
83 |
active_connections.setdefault(room_id, {})[client_id] = websocket
|
84 |
logger.info(f"Client {client_id} connected to logs")
|
85 |
|
@@ -128,7 +125,6 @@ class LogBroadcastHandler(logging.Handler):
|
|
128 |
}
|
129 |
log_file = save_log_entry(self.username, entry)
|
130 |
if log_file:
|
131 |
-
# Notify WebSocket clients of new log file
|
132 |
asyncio.create_task(broadcast_message({
|
133 |
"type": "log",
|
134 |
"content": f"New log entry saved to {log_file}",
|
@@ -138,29 +134,25 @@ class LogBroadcastHandler(logging.Handler):
|
|
138 |
}, "logs"))
|
139 |
|
140 |
def create_gradio_interface(username):
|
141 |
-
logger.handlers = [LogBroadcastHandler(username)]
|
142 |
-
|
143 |
-
|
144 |
-
.code-container { font-family: monospace; background: #1e1e1e; color: #d4d4d4; padding: 10px; border-radius: 5px; }
|
145 |
-
"""
|
146 |
-
interface.js = f"""
|
147 |
-
() => {{
|
148 |
-
setInterval(async () => {{
|
149 |
-
const response = await fetch('/get_log?username={username}');
|
150 |
-
const logContent = await response.text();
|
151 |
-
document.getElementById('log-display').innerText = logContent;
|
152 |
-
}}, 900); // Refresh every 0.9 seconds
|
153 |
-
}}
|
154 |
-
"""
|
155 |
|
|
|
156 |
gr.Markdown(f"# Log Viewer for {username} on Node: {NODE_NAME}")
|
157 |
-
gr.Markdown("
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
interface.
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
|
165 |
return interface
|
166 |
|
@@ -169,24 +161,14 @@ async def main():
|
|
169 |
NODE_NAME, port = get_node_name()
|
170 |
await start_websocket_server()
|
171 |
|
172 |
-
# Assign a random username
|
173 |
username = random.choice(FUN_USERNAMES)
|
174 |
logger.info(f"Assigned username: {username}")
|
175 |
|
176 |
# Create and run Gradio interface
|
177 |
interface = create_gradio_interface(username)
|
178 |
-
|
179 |
-
from starlette.routing import Route
|
180 |
-
from starlette.responses import PlainTextResponse
|
181 |
-
|
182 |
-
async def get_log_endpoint(request):
|
183 |
-
return PlainTextResponse(load_latest_log(username))
|
184 |
-
|
185 |
-
app = gr.routes.App.create_app(interface)
|
186 |
-
app.routes.append(Route("/get_log", get_log_endpoint))
|
187 |
-
|
188 |
import uvicorn
|
189 |
-
await uvicorn.Server(uvicorn.Config(
|
190 |
|
191 |
if __name__ == "__main__":
|
192 |
asyncio.run(main())
|
|
|
27 |
"MysticMoose π¦", "GlitchGnome π§", "VortexViper π", "ChronoChimp π"
|
28 |
]
|
29 |
|
30 |
+
# Directory for logs
|
31 |
LOG_DIR = "user_logs"
|
32 |
os.makedirs(LOG_DIR, exist_ok=True)
|
33 |
|
|
|
41 |
|
42 |
def get_log_file(username):
|
43 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
|
44 |
safe_username = username.replace(" ", "_").encode('ascii', 'ignore').decode('ascii')
|
45 |
return os.path.join(LOG_DIR, f"{safe_username}_{timestamp}.md")
|
46 |
|
|
|
48 |
log_file = get_log_file(username)
|
49 |
try:
|
50 |
with open(log_file, 'a') as f:
|
|
|
51 |
f.write(f"```log\n[{entry['timestamp']}] {entry['level']}: {entry['message']}\n```\n")
|
52 |
logger.info(f"Saved log entry to {log_file}")
|
53 |
return log_file
|
|
|
64 |
try:
|
65 |
with open(os.path.join(LOG_DIR, latest_file), 'r') as f:
|
66 |
content = f.read()
|
|
|
67 |
lines = content.strip().split('\n')
|
68 |
numbered_content = "\n".join(f"{i+1}. {line}" for i, line in enumerate(lines))
|
69 |
return f"# Log for {username} ({latest_file})\n\n{numbered_content}"
|
|
|
76 |
async def websocket_handler(websocket, path):
|
77 |
try:
|
78 |
client_id = str(uuid.uuid4())
|
79 |
+
room_id = "logs"
|
80 |
active_connections.setdefault(room_id, {})[client_id] = websocket
|
81 |
logger.info(f"Client {client_id} connected to logs")
|
82 |
|
|
|
125 |
}
|
126 |
log_file = save_log_entry(self.username, entry)
|
127 |
if log_file:
|
|
|
128 |
asyncio.create_task(broadcast_message({
|
129 |
"type": "log",
|
130 |
"content": f"New log entry saved to {log_file}",
|
|
|
134 |
}, "logs"))
|
135 |
|
136 |
def create_gradio_interface(username):
|
137 |
+
logger.handlers = [LogBroadcastHandler(username)]
|
138 |
+
def update_log_display(dummy_input):
|
139 |
+
return load_latest_log(username)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
+
with gr.Blocks(title=f"Log Viewer: {NODE_NAME}", css=".code-container { font-family: monospace; background: #1e1e1e; color: #d4d4d4; padding: 10px; border-radius: 5px; }") as interface:
|
142 |
gr.Markdown(f"# Log Viewer for {username} on Node: {NODE_NAME}")
|
143 |
+
gr.Markdown("Logs update live as new entries are written.")
|
144 |
+
# Dummy input to trigger live updates
|
145 |
+
dummy_input = gr.Textbox(visible=False, value="trigger", interactive=True)
|
146 |
+
log_display = gr.Code(label="Your Latest Log", language="markdown", lines=20, elem_classes=["code-container"])
|
147 |
+
|
148 |
+
# Set live=True to continuously update the log display
|
149 |
+
interface = gr.Interface(
|
150 |
+
fn=update_log_display,
|
151 |
+
inputs=[dummy_input],
|
152 |
+
outputs=[log_display],
|
153 |
+
live=True,
|
154 |
+
title=f"Log Viewer: {NODE_NAME}"
|
155 |
+
)
|
156 |
|
157 |
return interface
|
158 |
|
|
|
161 |
NODE_NAME, port = get_node_name()
|
162 |
await start_websocket_server()
|
163 |
|
164 |
+
# Assign a random username
|
165 |
username = random.choice(FUN_USERNAMES)
|
166 |
logger.info(f"Assigned username: {username}")
|
167 |
|
168 |
# Create and run Gradio interface
|
169 |
interface = create_gradio_interface(username)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
import uvicorn
|
171 |
+
await uvicorn.Server(uvicorn.Config(interface, host="0.0.0.0", port=port)).serve()
|
172 |
|
173 |
if __name__ == "__main__":
|
174 |
asyncio.run(main())
|