@@ -283,6 +283,11 @@ def setup_password(self):
283283 logger .error (f"Failed to setup password: { e } " )
284284 exit (1 )
285285# Routes and handlers
286+ @app .errorhandler (404 )
287+ def handle_not_found (e ):
288+ """Handle 404 errors."""
289+ return jsonify ({"error" : "Not found" }), 404
290+
286291@app .errorhandler (FreeGPTException )
287292def handle_freegpt_exception (e ):
288293 """Handle FreeGPT exceptions."""
@@ -292,68 +297,88 @@ def handle_freegpt_exception(e):
292297@app .errorhandler (Exception )
293298def handle_general_exception (e ):
294299 """Handle general exceptions."""
300+ from werkzeug .exceptions import NotFound
301+
302+ # Don't log 404 errors as unexpected errors
303+ if isinstance (e , NotFound ):
304+ return jsonify ({"error" : "Not found" }), 404
305+
295306 logger .error (f"Unexpected error: { e } " , exc_info = True )
296307 return jsonify ({"error" : "Internal server error" }), 500
297308
298309@app .route ("/" , methods = ["GET" , "POST" ])
299- async def index ():
310+ def index ():
300311 """Main API endpoint for chat completion."""
312+ import asyncio
313+
314+ async def _async_index ():
315+ try :
316+ # Get current settings
317+ settings = db_manager .get_settings ()
318+
319+ # Extract question from request
320+ question = None
321+ if request .method == "GET" :
322+ question = request .args .get (server_manager .args .keyword )
323+ else :
324+ # Handle file upload
325+ if 'file' in request .files :
326+ file = request .files ['file' ]
327+ is_valid , error_msg = validate_file_upload (file , config .files .allowed_extensions )
328+ if not is_valid :
329+ raise FileUploadError (error_msg )
330+
331+ question = file .read ().decode ('utf-8' )
332+
333+ if not question :
334+ return "<p id='response'>Please enter a question</p>"
335+
336+ # Sanitize input
337+ question = sanitize_input (question , 10000 ) # 10KB limit
338+
339+ # Verify token access
340+ token = request .args .get ("token" )
341+ username = auth_service .verify_token_access (
342+ token ,
343+ server_manager .args .private_mode
344+ )
345+
346+ if server_manager .args .private_mode and not username :
347+ return "<p id='response'>Invalid token</p>"
348+
349+ if not username :
350+ username = "admin"
351+
352+ # Generate AI response
353+ response_text = await ai_service .generate_response (
354+ message = question ,
355+ username = username ,
356+ use_history = server_manager .args .enable_history ,
357+ remove_sources = server_manager .args .remove_sources ,
358+ use_proxies = server_manager .args .enable_proxies ,
359+ cookie_file = server_manager .args .cookie_file
360+ )
361+
362+ logger .info (f"Generated response for user '{ username } ' ({ len (response_text )} chars)" )
363+ return response_text
364+
365+ except FreeGPTException as e :
366+ logger .error (f"API error: { e } " )
367+ return f"<p id='response'>Error: { e } </p>"
368+ except Exception as e :
369+ logger .error (f"Unexpected API error: { e } " , exc_info = True )
370+ return "<p id='response'>Internal server error</p>"
371+
372+ # Run the async function
301373 try :
302- # Get current settings
303- settings = db_manager .get_settings ()
304-
305- # Extract question from request
306- question = None
307- if request .method == "GET" :
308- question = request .args .get (server_manager .args .keyword )
309- else :
310- # Handle file upload
311- if 'file' in request .files :
312- file = request .files ['file' ]
313- is_valid , error_msg = validate_file_upload (file , config .files .allowed_extensions )
314- if not is_valid :
315- raise FileUploadError (error_msg )
316-
317- question = file .read ().decode ('utf-8' )
318-
319- if not question :
320- return "<p id='response'>Please enter a question</p>"
321-
322- # Sanitize input
323- question = sanitize_input (question , 10000 ) # 10KB limit
324-
325- # Verify token access
326- token = request .args .get ("token" )
327- username = auth_service .verify_token_access (
328- token ,
329- server_manager .args .private_mode
330- )
331-
332- if server_manager .args .private_mode and not username :
333- return "<p id='response'>Invalid token</p>"
334-
335- if not username :
336- username = "admin"
337-
338- # Generate AI response
339- response_text = await ai_service .generate_response (
340- message = question ,
341- username = username ,
342- use_history = server_manager .args .enable_history ,
343- remove_sources = server_manager .args .remove_sources ,
344- use_proxies = server_manager .args .enable_proxies ,
345- cookie_file = server_manager .args .cookie_file
346- )
347-
348- logger .info (f"Generated response for user '{ username } ' ({ len (response_text )} chars)" )
349- return response_text
350-
351- except FreeGPTException as e :
352- logger .error (f"API error: { e } " )
353- return f"<p id='response'>Error: { e } </p>"
374+ loop = asyncio .new_event_loop ()
375+ asyncio .set_event_loop (loop )
376+ return loop .run_until_complete (_async_index ())
354377 except Exception as e :
355- logger .error (f"Unexpected API error: { e } " , exc_info = True )
356- return "<p id='response'>Internal server error</p>"
378+ logger .error (f"Async execution error: { e } " , exc_info = True )
379+ return f"<p id='response'>Error: AI API call failed: { e } </p>"
380+ finally :
381+ loop .close ()
357382
358383@app .route ("/login" , methods = ["GET" , "POST" ])
359384def login ():
@@ -631,6 +656,20 @@ def generate_token():
631656 """Generate a new token."""
632657 return generate_uuid ()
633658
659+ @app .route ("/favicon.ico" )
660+ def favicon ():
661+ """Serve favicon."""
662+ try :
663+ from flask import send_from_directory
664+ return send_from_directory (
665+ str (Path (app .static_folder ) / "img" ),
666+ "favicon(Nicoladipa).png" ,
667+ mimetype = 'image/png'
668+ )
669+ except :
670+ # Return empty response if favicon not found
671+ return "" , 204
672+
634673def main ():
635674 """Main entry point."""
636675 try :
0 commit comments