email_notifications #7

Merged
jonas merged 18 commits from email_notifications into main 2025-10-16 13:20:27 +00:00
2 changed files with 33 additions and 37 deletions
Showing only changes of commit 716e5066e1 - Show all commits

View File

@@ -56,7 +56,7 @@ email:
from_name: "AlpineBits Monitor" # Sender display name from_name: "AlpineBits Monitor" # Sender display name
api_tokens: api_tokens:
- "tLTI8wXF1OVEvUX7kdZRhSW3Qr5feBCz0mHo-kbnEp0" - tLTI8wXF1OVEvUX7kdZRhSW3Qr5feBCz0mHo-kbnEp0
# Monitoring and alerting # Monitoring and alerting
monitoring: monitoring:

View File

@@ -12,16 +12,21 @@ from pathlib import Path
from typing import Any from typing import Any
import httpx import httpx
from fast_langdetect import detect
from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse, Response from fastapi.responses import HTMLResponse, Response
from fastapi.security import HTTPBasic, HTTPBasicCredentials, HTTPBearer, HTTPAuthorizationCredentials from fastapi.security import (
HTTPAuthorizationCredentials,
HTTPBasic,
HTTPBasicCredentials,
HTTPBearer,
)
from pydantic import BaseModel
from slowapi.errors import RateLimitExceeded from slowapi.errors import RateLimitExceeded
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from alpine_bits_python.schemas import ReservationData from alpine_bits_python.schemas import ReservationData
from fast_langdetect import detect
from pydantic import BaseModel
from .alpinebits_server import ( from .alpinebits_server import (
AlpineBitsActionName, AlpineBitsActionName,
@@ -292,9 +297,7 @@ async def lifespan(app: FastAPI):
) )
# Hook up the stats collector to the report scheduler # Hook up the stats collector to the report scheduler
report_scheduler.set_stats_collector(stats_collector.collect_stats) report_scheduler.set_stats_collector(stats_collector.collect_stats)
_LOGGER.info( _LOGGER.info("Stats collector initialized and hooked up to report scheduler")
"Stats collector initialized and hooked up to report scheduler"
)
# Start daily report scheduler # Start daily report scheduler
report_scheduler.start() report_scheduler.start()
@@ -422,9 +425,7 @@ async def detect_language(
if token not in valid_tokens: if token not in valid_tokens:
# Log sanitized token (first TOKEN_LOG_LENGTH chars) for security # Log sanitized token (first TOKEN_LOG_LENGTH chars) for security
sanitized_token = ( sanitized_token = (
token[:TOKEN_LOG_LENGTH] + "..." token[:TOKEN_LOG_LENGTH] + "..." if len(token) > TOKEN_LOG_LENGTH else token
if len(token) > TOKEN_LOG_LENGTH
else token
) )
_LOGGER.warning("Invalid token attempt: %s", sanitized_token) _LOGGER.warning("Invalid token attempt: %s", sanitized_token)
raise HTTPException( raise HTTPException(
@@ -439,43 +440,38 @@ async def detect_language(
_LOGGER.info("Language detection results: %s", results) _LOGGER.info("Language detection results: %s", results)
# Filter for Italian (it) or German (de) # Filter for Italian (it) or German (de)
italian_german_results = [r for r in results if r.get('lang') in ['it', 'de']] italian_german_results = [r for r in results if r.get("lang") in ["it", "de"]]
if italian_german_results: if italian_german_results:
# Return the best match between Italian and German # Return the best match between Italian and German
best_match = italian_german_results[0] best_match = italian_german_results[0]
return LanguageDetectionResponse(
language_code=best_match['lang'],
score=best_match.get('score', 0.0)
)
else:
# If neither Italian nor German detected in top 2, check all results
all_results = detect(data.text, k=10)
italian_german_all = [r for r in all_results if r.get('lang') in ['it', 'de']]
if italian_german_all: return_value = "Italienisch" if best_match["lang"] == "it" else "Deutsch"
best_match = italian_german_all[0]
return LanguageDetectionResponse(
language_code=best_match['lang'],
score=best_match.get('score', 0.0)
)
# Default to German if no clear detection
_LOGGER.warning(
"Could not detect Italian or German in text: %s, defaulting to 'de'",
data.text[:100]
)
return LanguageDetectionResponse( return LanguageDetectionResponse(
language_code='de', language_code=return_value, score=best_match.get("score", 0.0)
score=0.0
) )
# If neither Italian nor German detected in top 2, check all results
all_results = detect(data.text, k=10)
italian_german_all = [r for r in all_results if r.get("lang") in ["it", "de"]]
if italian_german_all:
best_match = italian_german_all[0]
return_value = "Italienisch" if best_match["lang"] == "it" else "Deutsch"
return LanguageDetectionResponse(
language_code=return_value, score=best_match.get("score", 0.0)
)
# Default to German if no clear detection
_LOGGER.warning(
"Could not detect Italian or German in text: %s, defaulting to 'de'",
data.text[:100],
)
return LanguageDetectionResponse(language_code="Deutsch", score=0.0)
except Exception as e: except Exception as e:
_LOGGER.exception("Error detecting language: %s", e) _LOGGER.exception("Error detecting language: %s", e)
raise HTTPException( raise HTTPException(status_code=500, detail=f"Error detecting language: {e!s}")
status_code=500,
detail=f"Error detecting language: {str(e)}"
)
# Extracted business logic for handling Wix form submissions # Extracted business logic for handling Wix form submissions