sms_sender.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import datetime
  2. from typing import Annotated
  3. from uuid import UUID
  4. from fastapi import APIRouter, Depends, HTTPException, Query, Request
  5. from sqlalchemy import select
  6. from sqlalchemy.orm import Session
  7. from app.api import deps
  8. from app.core.config import settings
  9. from app.models import ServerStatus, Sms, User
  10. from app.schemas.responses import EnumServerStatus, SMSResponse, SMSServerStatus
  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.require_super_admin),
  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)
  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.require_super_admin),
  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.require_super_admin),
  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))
  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.require_super_admin),
  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.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.require_super_admin),
  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.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. )