twilio notifications (#9)

* twilio

* phone number validation

* enforce user preference

---------

Co-authored-by: Kartik Sarangmath <kartiksarangmath@Kartiks-MacBook-Air.local>
This commit is contained in:
ksarangmath
2025-07-18 00:46:56 -07:00
committed by GitHub
parent 526963b25f
commit 741cfa1f82
16 changed files with 818 additions and 61 deletions

View File

@@ -0,0 +1,68 @@
"""Add notification preferences to users table
Revision ID: 84cd4a8c9a18
Revises: ae5dce0d9dd3
Create Date: 2025-07-12 18:36:07.840763
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = "84cd4a8c9a18"
down_revision: Union[str, None] = "ae5dce0d9dd3"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
# Add columns with server defaults for existing rows
op.add_column(
"users",
sa.Column(
"push_notifications_enabled",
sa.Boolean(),
nullable=False,
server_default="true",
),
)
op.add_column(
"users",
sa.Column(
"email_notifications_enabled",
sa.Boolean(),
nullable=False,
server_default="false",
),
)
op.add_column(
"users",
sa.Column(
"sms_notifications_enabled",
sa.Boolean(),
nullable=False,
server_default="false",
),
)
op.add_column(
"users", sa.Column("phone_number", sa.String(length=20), nullable=True)
)
op.add_column(
"users", sa.Column("notification_email", sa.String(length=255), nullable=True)
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("users", "notification_email")
op.drop_column("users", "phone_number")
op.drop_column("users", "sms_notifications_enabled")
op.drop_column("users", "email_notifications_enabled")
op.drop_column("users", "push_notifications_enabled")
# ### end Alembic commands ###

View File

@@ -98,6 +98,13 @@ class Settings(BaseSettings):
enterprise_plan_agent_limit: int = -1 # Unlimited
enterprise_plan_price: float = 500
# Twilio Configuration
twilio_account_sid: str = ""
twilio_auth_token: str = ""
twilio_from_phone_number: str = "" # Format: +1234567890
twilio_sendgrid_api_key: str = "" # For email notifications via SendGrid
twilio_from_email: str = "" # Sender email address
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")

View File

@@ -37,6 +37,17 @@ class User(Base):
default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)
)
# Notification preferences
push_notifications_enabled: Mapped[bool] = mapped_column(default=True)
email_notifications_enabled: Mapped[bool] = mapped_column(default=True)
sms_notifications_enabled: Mapped[bool] = mapped_column(default=False)
phone_number: Mapped[str | None] = mapped_column(
String(20), default=None
) # E.164 format
notification_email: Mapped[str | None] = mapped_column(
String(255), default=None
) # Defaults to email if not set
# Relationships
agent_instances: Mapped[list["AgentInstance"]] = relationship(
"AgentInstance", back_populates="user"