From 529265ad6f334fb3cbe43a1a518242cff25bb19d Mon Sep 17 00:00:00 2001 From: Edwin Eames Date: Wed, 28 Jan 2026 21:55:22 -0500 Subject: [PATCH] major claude changes --- app/main.py | 57 ++++++++++++++++++++++++++++++++++++++++++++ app/voipms_client.py | 13 ++++++---- config.py | 13 +++++----- requirements.txt | 22 +++++++++++------ settings_local.py | 54 +++++++++++++++++++---------------------- settings_prod.py | 44 +++++++++++++++++----------------- 6 files changed, 133 insertions(+), 70 deletions(-) diff --git a/app/main.py b/app/main.py index 3ea7572..7ec6e18 100644 --- a/app/main.py +++ b/app/main.py @@ -1,3 +1,4 @@ +import logging import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) @@ -11,6 +12,31 @@ elif mode == 'LOCAL': else: from settings_dev import settings +# Configure logging +def setup_logging(): + """Configure structured logging for the application.""" + log_level = logging.DEBUG if mode != 'PRODUCTION' else logging.INFO + + formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' + ) + + root_logger = logging.getLogger() + root_logger.setLevel(log_level) + root_logger.handlers.clear() + + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setLevel(log_level) + console_handler.setFormatter(formatter) + root_logger.addHandler(console_handler) + + logging.getLogger('uvicorn.access').setLevel(logging.WARNING) + + return logging.getLogger('eamco_voipms') + +logger = setup_logging() + import requests from fastapi import FastAPI, HTTPException, status from fastapi.middleware.cors import CORSMiddleware @@ -19,6 +45,19 @@ from starlette.responses import JSONResponse from .voipms_client import update_did_routing, get_forwardings from .database import Session from .models import Call +from sqlalchemy import text + +def check_db_connection(): + """ + Test database connectivity. + """ + try: + db = Session() + db.execute(text("SELECT 1")) + db.close() + return True + except Exception: + return False # class AuthMiddleware(BaseHTTPMiddleware): # async def dispatch(self, request, call_next): @@ -177,3 +216,21 @@ def route_to_cellphone_2(): } except HTTPException as e: raise e + + +@app.on_event("startup") +async def startup_event(): + """Application startup - log configuration and test DB connection.""" + logger.info("🚀 eamco_voipms STARTING") + if mode in ['DEVELOPMENT', 'DEV']: + logger.info("🤖🤖🤖🤖🤖 Mode: Development 🤖🤖🤖🤖🤖") + elif mode in ['PRODUCTION', 'PROD']: + logger.info("💀💀💀💀💀💀💀💀💀💀 ⚠️ WARNING PRODUCTION 💀💀💀💀💀💀💀💀💀💀") + logger.info(f"DB: {settings.SQLALCHEMY_DATABASE_URI[:30]}...") + logger.info(f"CORS: {len(settings.origins)} origins configured") + + # Test database connection + if check_db_connection(): + logger.info("DB Connection: ✅ OK") + else: + logger.info("DB Connection: ❌ FAILED") diff --git a/app/voipms_client.py b/app/voipms_client.py index 853636d..17c66a9 100644 --- a/app/voipms_client.py +++ b/app/voipms_client.py @@ -1,3 +1,4 @@ +import logging import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) @@ -9,6 +10,8 @@ if mode == 'PRODUCTION': else: from settings_dev import settings +logger = logging.getLogger(__name__) + import requests from fastapi import HTTPException, status @@ -80,11 +83,11 @@ def update_did_routing(did: str, routing: str): try: response = requests.get(settings.voipms_api_url, params=params) - print(f"Request URL: {response.request.url}") # Debug - print(f"Request Params: {params}") # Debug + logger.debug(f"Request URL: {response.request.url}") # Debug + logger.debug(f"Request Params: {params}") # Debug response.raise_for_status() data = response.json() - print(f"VoIP.ms API Response: {data}") # Debug + logger.debug(f"VoIP.ms API Response: {data}") # Debug if data.get("status") != "success": raise HTTPException( @@ -124,8 +127,8 @@ def get_forwardings(phone_number: str = None): } try: response = requests.get(settings.voipms_api_url, params=params) - print(f"Get Forwardings Request URL: {response.request.url}") - print(f"Get Forwardings Response: {response.json()}") + logger.debug(f"Get Forwardings Request URL: {response.request.url}") + logger.debug(f"Get Forwardings Response: {response.json()}") response.raise_for_status() data = response.json() if data.get("status") != "success": diff --git a/config.py b/config.py index 4f22694..51c6450 100644 --- a/config.py +++ b/config.py @@ -1,21 +1,20 @@ +import logging import os +logger = logging.getLogger(__name__) + def load_config(mode=os.environ.get('MODE')): try: - print(f"mode is {mode}") if mode == 'PRODUCTION': from settings_prod import ApplicationConfig return ApplicationConfig - + elif mode == 'LOCAL': from settings_local import ApplicationConfig return ApplicationConfig - + elif mode == 'DEVELOPMENT': - print("poop") - print("poop") - print("poop") from settings_dev import ApplicationConfig return ApplicationConfig else: @@ -23,4 +22,4 @@ def load_config(mode=os.environ.get('MODE')): except ImportError: from settings_dev import ApplicationConfig - return ApplicationConfig \ No newline at end of file + return ApplicationConfig diff --git a/requirements.txt b/requirements.txt index 96ffb4f..63c5f06 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,15 @@ -fastapi -uvicorn[standard] -pydantic-settings -python-dotenv -requests -sqlalchemy -psycopg2-binary \ No newline at end of file +# eamco_voipms dependencies +# FastAPI web framework and server +fastapi==0.115.6 +uvicorn[standard]==0.34.0 +pydantic-settings==2.7.1 + +# Database +SQLAlchemy==2.0.40 +psycopg2-binary==2.9.10 + +# HTTP client +requests==2.32.3 + +# Configuration +python-dotenv==1.1.0 diff --git a/settings_local.py b/settings_local.py index c3e61ea..33e7251 100644 --- a/settings_local.py +++ b/settings_local.py @@ -1,43 +1,38 @@ - - import os -from dotenv import load_dotenv -# Load environment variables from .env file -load_dotenv() class ApplicationConfig: """ - Basic Configuration for a generic User + Local Configuration (LAN deployment) """ CURRENT_SETTINGS = 'LOCAL' - # databases info - POSTGRES_USERNAME = 'postgres' - POSTGRES_PW = 'password' - POSTGRES_SERVER = '192.168.1.204' - POSTGRES_PORT = '5432' - POSTGRES_DBNAME00 = 'auburnoil' - SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(POSTGRES_USERNAME, - POSTGRES_PW, - POSTGRES_SERVER, - POSTGRES_DBNAME00 - ) - + + # Database credentials from environment variables + POSTGRES_USERNAME = os.environ.get('POSTGRES_USERNAME', 'postgres') + POSTGRES_PW = os.environ.get('POSTGRES_PW') + POSTGRES_SERVER = os.environ.get('POSTGRES_SERVER', '192.168.1.204') + POSTGRES_PORT = os.environ.get('POSTGRES_PORT', '5432') + POSTGRES_DBNAME00 = os.environ.get('POSTGRES_DBNAME', 'auburnoil') + + SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format( + POSTGRES_USERNAME, + POSTGRES_PW, + POSTGRES_SERVER, + POSTGRES_DBNAME00 + ) SQLALCHEMY_BINDS = {'auburnoil': SQLALCHEMY_DATABASE_URI} - origins = [ - "http://192.168.1.204:9000", - "http://192.168.1.204:9613", - "http://192.168.1.204:9614", - "http://192.168.1.204:9612", - "http://192.168.1.204:9616", - "http://192.168.1.204:9611", - "http://192.168.1.204:9511", -] + "http://192.168.1.204:9000", + "http://192.168.1.204:9613", + "http://192.168.1.204:9614", + "http://192.168.1.204:9612", + "http://192.168.1.204:9616", + "http://192.168.1.204:9611", + "http://192.168.1.204:9511", + ] - - # VoIP.ms Credentials and Settings + # VoIP.ms Credentials and Settings voipms_api_username = os.environ.get('VOIPMS_API_USERNAME') voipms_api_password = os.environ.get('VOIPMS_API_PASSWORD') @@ -50,5 +45,6 @@ class ApplicationConfig: # VoIP.ms API endpoint voipms_api_url = os.environ.get('VOIPMS_API_URL', "https://voip.ms/api/v1/rest.php") + # Create a single instance of the settings to be used throughout the app settings = ApplicationConfig() diff --git a/settings_prod.py b/settings_prod.py index d7e0d95..7810efd 100644 --- a/settings_prod.py +++ b/settings_prod.py @@ -1,36 +1,35 @@ - import os -from dotenv import load_dotenv -# Load environment variables from .env file -load_dotenv() class ApplicationConfig: """ - Basic Configuration for a generic User + Production Configuration """ CURRENT_SETTINGS = 'PRODUCTION' - # databases info - POSTGRES_USERNAME = 'postgres' - POSTGRES_PW = 'password' - POSTGRES_SERVER = '192.168.1.204' - POSTGRES_PORT = '5432' - POSTGRES_DBNAME00 = 'auburnoil' - SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(POSTGRES_USERNAME, - POSTGRES_PW, - POSTGRES_SERVER, - POSTGRES_DBNAME00 - ) + + # Database credentials from environment variables + POSTGRES_USERNAME = os.environ.get('POSTGRES_USERNAME', 'postgres') + POSTGRES_PW = os.environ.get('POSTGRES_PW') + POSTGRES_SERVER = os.environ.get('POSTGRES_SERVER', '192.168.1.204') + POSTGRES_PORT = os.environ.get('POSTGRES_PORT', '5432') + POSTGRES_DBNAME00 = os.environ.get('POSTGRES_DBNAME', 'auburnoil') + + SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format( + POSTGRES_USERNAME, + POSTGRES_PW, + POSTGRES_SERVER, + POSTGRES_DBNAME00 + ) SQLALCHEMY_BINDS = {'auburnoil': SQLALCHEMY_DATABASE_URI} origins = [ - "https://oil.edwineames.com", - "https://apiphone.edwineames.com", - "https://apiauto.edwineames.com", - "https://apioil.edwineames.com", - + "https://oil.edwineames.com", + "https://apiphone.edwineames.com", + "https://apiauto.edwineames.com", + "https://apioil.edwineames.com", ] - # VoIP.ms Credentials and Settings + + # VoIP.ms Credentials and Settings voipms_api_username = os.environ.get('VOIPMS_API_USERNAME') voipms_api_password = os.environ.get('VOIPMS_API_PASSWORD') @@ -43,5 +42,6 @@ class ApplicationConfig: # VoIP.ms API endpoint voipms_api_url = os.environ.get('VOIPMS_API_URL', "https://voip.ms/api/v1/rest.php") + # Create a single instance of the settings to be used throughout the app settings = ApplicationConfig()