diff --git a/app/app.py b/app/app.py index 93fe0b2..f81d82f 100644 --- a/app/app.py +++ b/app/app.py @@ -483,13 +483,9 @@ def create_app(config=None): return app -if __name__ == '__main__': - # Only used for development - production uses wsgi.py (Waitress) - app = create_app() - debug_mode = os.getenv('FLASK_DEBUG', 'false').lower() == 'true' - if debug_mode: - app.logger.warning( - 'Running in DEBUG mode with Flask built-in server. ' - 'This is NOT suitable for production. Use wsgi.py instead.' - ) - app.run(debug=debug_mode, host='0.0.0.0', port=10000) +# No __main__ block here on purpose. There used to be one, and with run.py +# and wsgi.py that made three ways to start the application, each with its +# own host, port and debug default — `python app/app.py` bound 0.0.0.0:10000 +# while `python run.py` bound 127.0.0.2:5000 with the debugger on. This +# module defines the factory; run.py starts it for development, wsgi.py for +# production (ARCH-007). diff --git a/app/discord_bot.py b/app/discord_bot.py index 0e227b0..dc1a80f 100644 --- a/app/discord_bot.py +++ b/app/discord_bot.py @@ -56,7 +56,6 @@ class TeamTryoutsBot(commands.Bot): intents.reactions = True intents.guilds = True - super().__init__(command_prefix='!', intents=intents) self.flask_app = flask_app self.pending_requests = {} # Maps message_id to {type, id} for reaction handling @@ -471,35 +470,6 @@ class TeamTryoutsBot(commands.Bot): except Exception as e: logger.error(f"Error handling attendance decline: {e}\n{traceback.format_exc()}") - async def notify_player_about_one_on_one(self, request, approved=True, refusal_note=None): - """Send confirmation to player about One on One response. - - This is the legacy method kept for backward compatibility with any - callers that pass a fully-loaded request object. - """ - try: - player = request.player - coach = request.coach - - if not player or not player.discord_user_id: - logger.warning(f"Player has no Discord user ID for request {request.id}") - return - - if not coach: - logger.warning(f"Coach not found for request {request.id}") - return - - await self.notify_player_about_one_on_one_direct( - player_discord_id=player.discord_user_id, - player_full_name=player.full_name, - coach_full_name=coach.full_name, - request=request, - approved=approved, - refusal_note=refusal_note - ) - except Exception as e: - logger.error(f"Error notifying player about One on One: {e}") - async def notify_player_about_one_on_one_direct(self, player_discord_id, player_full_name, coach_full_name, request, approved=True, refusal_note=None): diff --git a/app/routes/evaluations.py b/app/routes/evaluations.py index f89057b..134123f 100644 --- a/app/routes/evaluations.py +++ b/app/routes/evaluations.py @@ -92,7 +92,11 @@ def list_evaluations(): 'player': p, 'count': row.eval_count, 'avg': round(row.avg_score, 1) if row.avg_score else 0, } - elif user.can_evaluate(): + else: + # Everyone still here evaluates: players were redirected above, and + # can_evaluate() is true for the four remaining roles. The former + # `else` branch listed evaluations *received* — a player's view, + # unreachable from this point (ARCH-007). evaluations = Evaluation.query \ .outerjoin(Tryout, Evaluation.tryout_id == Tryout.id) \ .outerjoin(player_alias, Evaluation.player_id == player_alias.id) \ @@ -100,14 +104,6 @@ def list_evaluations(): .filter(Evaluation.evaluator_id == user.id) \ .order_by(sort_expr).all() player_scores = {} - else: - evaluations = Evaluation.query \ - .outerjoin(Tryout, Evaluation.tryout_id == Tryout.id) \ - .outerjoin(player_alias, Evaluation.player_id == player_alias.id) \ - .outerjoin(evaluator_alias, Evaluation.evaluator_id == evaluator_alias.id) \ - .filter(Evaluation.player_id == user.id) \ - .order_by(sort_expr).all() - player_scores = {} return render_template('pages/evaluations.html', evaluations=evaluations, player_scores=player_scores, diff --git a/run.py b/run.py index 5d3c1e3..6f178a0 100644 --- a/run.py +++ b/run.py @@ -1,10 +1,21 @@ -"""Entry point for the Team Tryouts application. +"""Development entry point for the Team Tryouts application. Usage (from the project root): python run.py -Or for production with Waitress: - python app/wsgi.py +Production uses Waitress, from the project root as well: + python wsgi.py + +These two are the only entry points. app/app.py exposes the factory and +nothing else. + +Environment variables: + FLASK_DEBUG: 'true' turns on the reloader and the interactive debugger. + Off by default — the Werkzeug debugger executes code submitted + through the browser, so a process left running with it on is a + remote shell. Opt in per session, never in a deployed .env. + DEV_HOST: interface to bind (default 127.0.0.1, loopback only). + DEV_PORT: port to listen on (default 5000). """ import os @@ -13,14 +24,19 @@ import sys # Ensure the project root is on sys.path so 'app' is importable as a package sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -from app.app import create_app +from app.app import create_app # noqa: E402 if __name__ == '__main__': app = create_app() - debug_mode = os.getenv('FLASK_DEBUG', 'true').lower() == 'true' + debug_mode = os.getenv('FLASK_DEBUG', 'false').lower() == 'true' if debug_mode: app.logger.warning( - 'Running in DEBUG mode with Flask built-in server. ' - 'This is NOT suitable for production. Use wsgi.py instead.' + 'Running in DEBUG mode with the Flask built-in server. The ' + 'interactive debugger accepts code from the browser: do not ' + 'leave this reachable from anywhere but this machine.' ) - app.run(debug=debug_mode, host='127.0.0.2', port=5000) \ No newline at end of file + app.run( + debug=debug_mode, + host=os.getenv('DEV_HOST', '127.0.0.1'), + port=int(os.getenv('DEV_PORT', 5000)), + )