sms_sender.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import datetime
  2. from typing import Annotated
  3. from uuid import UUID
  4. from fastapi import APIRouter, Depends, Query, HTTPException, Request
  5. from sqlalchemy import select
  6. from sqlalchemy.orm import Session
  7. from app.core.config import settings
  8. from app.models import User, Sms, ServerStatus
  9. from app.schemas.responses import SMSResponse, SMSServerStatus, EnumServerStatus
  10. from app.api import deps
  11. router = APIRouter(prefix="/sms-sender", tags=["sms_sender"])
  12. @router.get("/sms/to-send", response_model=list[SMSResponse])
  13. async def list_sms_to_send(
  14. current_user: User = Depends(deps.get_current_user),
  15. session: Session = Depends(deps.get_session),
  16. max_delay: Annotated[
  17. int | None, Query(description="the maximum delay a sms should be send with")
  18. ] = 10,
  19. ):
  20. """List sms that should be send by now"""
  21. now = datetime.datetime.now()
  22. min_sending_time = now - datetime.timedelta(minutes=max_delay)
  23. results = session.execute(
  24. select(Sms).where(
  25. (Sms.sending_time > min_sending_time)
  26. & (Sms.sending_time < now)
  27. & (Sms.send_time == None) # noqa: E711
  28. )
  29. )
  30. return results.scalars().all()
  31. @router.post("/sms/send-now/{sms_id}", response_model=SMSResponse)
  32. async def send_sms_now(
  33. request: Request,
  34. sms_id: UUID,
  35. current_user: User = Depends(deps.get_current_user),
  36. session: Session = Depends(deps.get_session),
  37. ):
  38. """Update the SMS to be sent now"""
  39. sms = session.get(Sms, sms_id)
  40. if sms is None:
  41. raise HTTPException(status_code=404, detail="SMS not found")
  42. elif sms.send_time is not None:
  43. raise HTTPException(status_code=400, detail="SMS has already been sent")
  44. else:
  45. sms.send_time = datetime.datetime.now()
  46. session.commit()
  47. await update_status(request, current_user, session)
  48. return sms
  49. @router.get("/sms/not-send", response_model=list[SMSResponse])
  50. async def list_not_sent(
  51. current_user: User = Depends(deps.get_current_user),
  52. session: Session = Depends(deps.get_session),
  53. ):
  54. """List sms that are not sent"""
  55. results = session.execute(select(Sms).where((Sms.send_time == None))) # noqa: E711
  56. return results.scalars().all()
  57. @router.get("/sms/future", response_model=list[SMSResponse])
  58. async def list_future_sms(
  59. current_user: User = Depends(deps.get_current_user),
  60. session: Session = Depends(deps.get_session),
  61. ):
  62. """List sms that should be sent in the future"""
  63. results = session.execute(select(Sms).where(Sms.sending_time > datetime.datetime.now()))
  64. return results.scalars().all()
  65. @router.post("/status")
  66. async def update_status(
  67. request: Request,
  68. current_user: User = Depends(deps.get_current_user),
  69. session: Session = Depends(deps.get_session),
  70. ):
  71. """Update the status of the SMS server"""
  72. status = session.query(ServerStatus).filter_by(id=1).first()
  73. if not status:
  74. status = ServerStatus(id=1)
  75. status.host = request.client.host
  76. status.updated_at = datetime.datetime.now(datetime.timezone.utc)
  77. status.user_agent = request.headers.get("user-agent", "unknown")
  78. session.add(status)
  79. session.commit()
  80. return {"message": "Status updated successfully"}
  81. INACTIVITY_THRESHOLD_SECONDS = 180
  82. @router.get("/status", response_model=SMSServerStatus)
  83. async def get_status(
  84. current_user: User = Depends(deps.get_current_user),
  85. session: Session = Depends(deps.get_session),
  86. ):
  87. """Get the latest status of the SMS server"""
  88. status: ServerStatus | None = session.query(ServerStatus).filter_by(id=1).first()
  89. now = datetime.datetime.now(datetime.timezone.utc)
  90. if not status:
  91. return SMSServerStatus(
  92. updated_at=now, host="N/A", user_agent="N/A", message=EnumServerStatus.INVALID
  93. )
  94. else:
  95. msg = (
  96. EnumServerStatus.INACTIVE
  97. if (now - status.updated_at).total_seconds()
  98. > settings.INACTIVITY_SMS_SENDER_THRESHOLD_SECONDS
  99. else EnumServerStatus.ACTIVE
  100. )
  101. return SMSServerStatus(
  102. updated_at=status.updated_at.isoformat(),
  103. host=status.host,
  104. user_agent=status.user_agent,
  105. message=msg,
  106. )