Log generic webhook for now
This commit is contained in:
@@ -33,7 +33,6 @@ from .db import Base, get_database_url
|
|||||||
from .db import Customer as DBCustomer
|
from .db import Customer as DBCustomer
|
||||||
from .db import Reservation as DBReservation
|
from .db import Reservation as DBReservation
|
||||||
from .logging_config import get_logger, setup_logging
|
from .logging_config import get_logger, setup_logging
|
||||||
from .reservation_service import ReservationService
|
|
||||||
from .rate_limit import (
|
from .rate_limit import (
|
||||||
BURST_RATE_LIMIT,
|
BURST_RATE_LIMIT,
|
||||||
DEFAULT_RATE_LIMIT,
|
DEFAULT_RATE_LIMIT,
|
||||||
@@ -42,6 +41,7 @@ from .rate_limit import (
|
|||||||
limiter,
|
limiter,
|
||||||
webhook_limiter,
|
webhook_limiter,
|
||||||
)
|
)
|
||||||
|
from .reservation_service import ReservationService
|
||||||
|
|
||||||
# Configure logging - will be reconfigured during lifespan with actual config
|
# Configure logging - will be reconfigured during lifespan with actual config
|
||||||
_LOGGER = get_logger(__name__)
|
_LOGGER = get_logger(__name__)
|
||||||
@@ -137,7 +137,7 @@ async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel)
|
|||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Created directory owner: uid:%s, gid:%s",
|
"Created directory owner: uid:%s, gid:%s",
|
||||||
stat_info.st_uid,
|
stat_info.st_uid,
|
||||||
stat_info.st_gid
|
stat_info.st_gid,
|
||||||
)
|
)
|
||||||
_LOGGER.info("Directory mode: %s", oct(stat_info.st_mode)[-3:])
|
_LOGGER.info("Directory mode: %s", oct(stat_info.st_mode)[-3:])
|
||||||
log_filename = f"{logs_dir}/alpinebits_push_{hotel_id}_{reservation.unique_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xml"
|
log_filename = f"{logs_dir}/alpinebits_push_{hotel_id}_{reservation.unique_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xml"
|
||||||
@@ -159,20 +159,20 @@ async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel)
|
|||||||
)
|
)
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Push event fired to %s for hotel %s, status: %s",
|
"Push event fired to %s for hotel %s, status: %s",
|
||||||
push_endpoint['url'],
|
push_endpoint["url"],
|
||||||
hotel['hotel_id'],
|
hotel["hotel_id"],
|
||||||
resp.status_code
|
resp.status_code,
|
||||||
)
|
)
|
||||||
|
|
||||||
if resp.status_code not in [200, 201, 202]:
|
if resp.status_code not in [200, 201, 202]:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Push endpoint returned non-success status %s: %s",
|
"Push endpoint returned non-success status %s: %s",
|
||||||
resp.status_code,
|
resp.status_code,
|
||||||
resp.text
|
resp.text,
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_LOGGER.exception("Push event failed for hotel %s: %s", hotel['hotel_id'], e)
|
_LOGGER.exception("Push event failed for hotel %s: %s", hotel["hotel_id"], e)
|
||||||
# Optionally implement retry logic here@asynccontextmanager
|
# Optionally implement retry logic here@asynccontextmanager
|
||||||
|
|
||||||
|
|
||||||
@@ -528,9 +528,7 @@ async def process_generic_webhook_submission(
|
|||||||
hotel_name = hotel_data.get("hotelname")
|
hotel_name = hotel_data.get("hotelname")
|
||||||
|
|
||||||
if not hotel_code:
|
if not hotel_code:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning("No hotel_code provided in webhook data, using default")
|
||||||
"No hotel_code provided in webhook data, using default"
|
|
||||||
)
|
|
||||||
hotel_code = request.app.state.config.get("default_hotel_code", "123")
|
hotel_code = request.app.state.config.get("default_hotel_code", "123")
|
||||||
|
|
||||||
if not hotel_name:
|
if not hotel_name:
|
||||||
@@ -553,8 +551,7 @@ async def process_generic_webhook_submission(
|
|||||||
|
|
||||||
if not start_date_str or not end_date_str:
|
if not start_date_str or not end_date_str:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=400,
|
status_code=400, detail="Missing required dates (anreise/abreise)"
|
||||||
detail="Missing required dates (anreise/abreise)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -568,9 +565,7 @@ async def process_generic_webhook_submission(
|
|||||||
end_date_str,
|
end_date_str,
|
||||||
e,
|
e,
|
||||||
)
|
)
|
||||||
raise HTTPException(
|
raise HTTPException(status_code=400, detail=f"Invalid date format: {e}") from e
|
||||||
status_code=400, detail=f"Invalid date format: {e}"
|
|
||||||
) from e
|
|
||||||
|
|
||||||
# Extract room/guest info
|
# Extract room/guest info
|
||||||
num_adults = int(form_data.get("erwachsene", 2))
|
num_adults = int(form_data.get("erwachsene", 2))
|
||||||
@@ -586,9 +581,7 @@ async def process_generic_webhook_submission(
|
|||||||
try:
|
try:
|
||||||
children_ages.append(int(age_str))
|
children_ages.append(int(age_str))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning("Invalid age value for child %d: %s", i, age_str)
|
||||||
"Invalid age value for child %d: %s", i, age_str
|
|
||||||
)
|
|
||||||
|
|
||||||
# Extract tracking information
|
# Extract tracking information
|
||||||
utm_source = tracking_data.get("utm_source")
|
utm_source = tracking_data.get("utm_source")
|
||||||
@@ -608,9 +601,7 @@ async def process_generic_webhook_submission(
|
|||||||
submission_time = datetime.fromisoformat(submission_time[:-1])
|
submission_time = datetime.fromisoformat(submission_time[:-1])
|
||||||
elif "+" in submission_time:
|
elif "+" in submission_time:
|
||||||
# Remove timezone info (e.g., +02:00)
|
# Remove timezone info (e.g., +02:00)
|
||||||
submission_time = datetime.fromisoformat(
|
submission_time = datetime.fromisoformat(submission_time.split("+")[0])
|
||||||
submission_time.split("+")[0]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
submission_time = datetime.fromisoformat(submission_time)
|
submission_time = datetime.fromisoformat(submission_time)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -673,9 +664,7 @@ async def process_generic_webhook_submission(
|
|||||||
reservation = ReservationData(**reservation_kwargs)
|
reservation = ReservationData(**reservation_kwargs)
|
||||||
|
|
||||||
if reservation.md5_unique_id is None:
|
if reservation.md5_unique_id is None:
|
||||||
raise HTTPException(
|
raise HTTPException(status_code=400, detail="Failed to generate md5_unique_id")
|
||||||
status_code=400, detail="Failed to generate md5_unique_id"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Use ReservationService to create reservation
|
# Use ReservationService to create reservation
|
||||||
reservation_service = ReservationService(db)
|
reservation_service = ReservationService(db)
|
||||||
@@ -693,9 +682,7 @@ async def process_generic_webhook_submission(
|
|||||||
await dispatcher.dispatch_for_hotel(
|
await dispatcher.dispatch_for_hotel(
|
||||||
"form_processed", hotel_code, db_customer, db_reservation
|
"form_processed", hotel_code, db_customer, db_reservation
|
||||||
)
|
)
|
||||||
_LOGGER.info(
|
_LOGGER.info("Dispatched form_processed event for hotel %s", hotel_code)
|
||||||
"Dispatched form_processed event for hotel %s", hotel_code
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"No hotel_code in reservation, skipping push notifications"
|
"No hotel_code in reservation, skipping push notifications"
|
||||||
@@ -704,13 +691,10 @@ async def process_generic_webhook_submission(
|
|||||||
# Create task and store reference to prevent garbage collection
|
# Create task and store reference to prevent garbage collection
|
||||||
task = asyncio.create_task(push_event())
|
task = asyncio.create_task(push_event())
|
||||||
# Add done callback to log any exceptions
|
# Add done callback to log any exceptions
|
||||||
task.add_done_callback(
|
task.add_done_callback(lambda t: t.exception() if not t.cancelled() else None)
|
||||||
lambda t: t.exception() if not t.cancelled() else None
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Successfully processed generic webhook: customer_id=%s, "
|
"Successfully processed generic webhook: customer_id=%s, reservation_id=%s",
|
||||||
"reservation_id=%s",
|
|
||||||
db_customer.id,
|
db_customer.id,
|
||||||
db_reservation.id,
|
db_reservation.id,
|
||||||
)
|
)
|
||||||
@@ -791,11 +775,13 @@ async def handle_wix_form(
|
|||||||
logs_dir = Path("logs/errors")
|
logs_dir = Path("logs/errors")
|
||||||
await asyncio.to_thread(logs_dir.mkdir, parents=True, mode=0o755, exist_ok=True)
|
await asyncio.to_thread(logs_dir.mkdir, parents=True, mode=0o755, exist_ok=True)
|
||||||
|
|
||||||
log_filename = logs_dir / f"wix_error_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
log_filename = (
|
||||||
|
logs_dir / f"wix_error_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
||||||
|
)
|
||||||
await asyncio.to_thread(
|
await asyncio.to_thread(
|
||||||
log_filename.write_text,
|
log_filename.write_text,
|
||||||
json.dumps(log_entry, indent=2, default=str, ensure_ascii=False),
|
json.dumps(log_entry, indent=2, default=str, ensure_ascii=False),
|
||||||
encoding="utf-8"
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER.error("Error data logged to: %s", log_filename)
|
_LOGGER.error("Error data logged to: %s", log_filename)
|
||||||
@@ -832,11 +818,13 @@ async def handle_wix_form_test(
|
|||||||
logs_dir = Path("logs/errors")
|
logs_dir = Path("logs/errors")
|
||||||
await asyncio.to_thread(logs_dir.mkdir, parents=True, mode=0o755, exist_ok=True)
|
await asyncio.to_thread(logs_dir.mkdir, parents=True, mode=0o755, exist_ok=True)
|
||||||
|
|
||||||
log_filename = logs_dir / f"wix_test_error_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
log_filename = (
|
||||||
|
logs_dir / f"wix_test_error_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
||||||
|
)
|
||||||
await asyncio.to_thread(
|
await asyncio.to_thread(
|
||||||
log_filename.write_text,
|
log_filename.write_text,
|
||||||
json.dumps(log_entry, indent=2, default=str, ensure_ascii=False),
|
json.dumps(log_entry, indent=2, default=str, ensure_ascii=False),
|
||||||
encoding="utf-8"
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER.error("Error data logged to: %s", log_filename)
|
_LOGGER.error("Error data logged to: %s", log_filename)
|
||||||
@@ -866,9 +854,7 @@ async def handle_generic_webhook(
|
|||||||
body = await request.body()
|
body = await request.body()
|
||||||
|
|
||||||
if not body:
|
if not body:
|
||||||
raise HTTPException(
|
raise HTTPException(status_code=400, detail="ERROR: No content provided")
|
||||||
status_code=400, detail="ERROR: No content provided"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check if content is gzip compressed
|
# Check if content is gzip compressed
|
||||||
content_encoding = request.headers.get("content-encoding", "").lower()
|
content_encoding = request.headers.get("content-encoding", "").lower()
|
||||||
@@ -894,6 +880,22 @@ async def handle_generic_webhook(
|
|||||||
detail=f"ERROR: Invalid JSON content: {e}",
|
detail=f"ERROR: Invalid JSON content: {e}",
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
if True:
|
||||||
|
# log to file for now
|
||||||
|
logs_dir = Path("logs/generic_webhooks")
|
||||||
|
await asyncio.to_thread(
|
||||||
|
logs_dir.mkdir, parents=True, mode=0o755, exist_ok=True
|
||||||
|
)
|
||||||
|
log_filename = (
|
||||||
|
logs_dir
|
||||||
|
/ f"generic_webhook_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
||||||
|
)
|
||||||
|
await asyncio.to_thread(
|
||||||
|
log_filename.write_text,
|
||||||
|
json.dumps(data, indent=2, default=str, ensure_ascii=False),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
# Process the webhook data and save to database
|
# Process the webhook data and save to database
|
||||||
await process_generic_webhook_submission(request, data, db_session)
|
await process_generic_webhook_submission(request, data, db_session)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user