Skip to content

Commit de75aa3

Browse files
committed
dailyco component naming for LLM reading
1 parent 93b55c7 commit de75aa3

File tree

20 files changed

+316
-205
lines changed

20 files changed

+316
-205
lines changed

IMPLEMENTATION_STATUS.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
### 1. Platform Abstraction Layer (`server/reflector/video_platforms/`)
66
- **base.py**: Abstract interface defining all platform operations
77
- **whereby.py**: Whereby implementation wrapping existing functionality
8-
- **dailyco.py**: Daily.co client implementation (ready for testing when credentials available)
8+
- **daily.py**: Daily client implementation (ready for testing when credentials available)
99
- **mock.py**: Mock implementation for unit testing
1010
- **registry.py**: Platform registration and discovery
1111
- **factory.py**: Factory methods for creating platform clients
@@ -18,27 +18,27 @@
1818
### 3. Configuration
1919
- **Settings**: Added Daily.co configuration variables
2020
- **Feature Flags**:
21-
- `DAILYCO_MIGRATION_ENABLED`: Master switch for migration
22-
- `DAILYCO_MIGRATION_ROOM_IDS`: List of specific rooms to migrate
21+
- `DAILY_MIGRATION_ENABLED`: Master switch for migration
22+
- `DAILY_MIGRATION_ROOM_IDS`: List of specific rooms to migrate
2323
- `DEFAULT_VIDEO_PLATFORM`: Default platform when migration enabled
2424

2525
### 4. Backend API Updates
2626
- **Room Creation**: Now assigns platform based on feature flags
2727
- **Meeting Creation**: Uses platform abstraction instead of direct Whereby calls
2828
- **Response Models**: Include platform field
29-
- **Webhook Handler**: Added Daily.co webhook endpoint at `/v1/dailyco_webhook`
29+
- **Webhook Handler**: Added Daily webhook endpoint at `/v1/daily/webhook`
3030

3131
### 5. Frontend Components (`www/app/[roomName]/components/`)
3232
- **RoomContainer.tsx**: Platform-agnostic container that routes to appropriate component
3333
- **WherebyRoom.tsx**: Extracted existing Whereby functionality with consent management
34-
- **DailyCoRoom.tsx**: Daily.co implementation using DailyIframe
34+
- **DailyRoom.tsx**: Daily implementation using DailyIframe
3535
- **Dependencies**: Added `@daily-co/daily-js` and `@daily-co/daily-react`
3636

3737
## How It Works
3838

3939
1. **Platform Selection**:
40-
- If `DAILYCO_MIGRATION_ENABLED=false` → Always use Whereby
41-
- If enabled and room ID in `DAILYCO_MIGRATION_ROOM_IDS` → Use Daily.co
40+
- If `DAILY_MIGRATION_ENABLED=false` → Always use Whereby
41+
- If enabled and room ID in `DAILY_MIGRATION_ROOM_IDS` → Use Daily
4242
- Otherwise → Use `DEFAULT_VIDEO_PLATFORM`
4343

4444
2. **Meeting Creation Flow**:
@@ -59,11 +59,11 @@
5959

6060
1. **Set Environment Variables**:
6161
```bash
62-
DAILYCO_API_KEY=your-key
63-
DAILYCO_WEBHOOK_SECRET=your-secret
64-
DAILYCO_SUBDOMAIN=your-subdomain
65-
AWS_DAILYCO_S3_BUCKET=your-bucket
66-
AWS_DAILYCO_ROLE_ARN=your-role
62+
DAILY_API_KEY=your-key
63+
DAILY_WEBHOOK_SECRET=your-secret
64+
DAILY_SUBDOMAIN=your-subdomain
65+
AWS_DAILY_S3_BUCKET=your-bucket
66+
AWS_DAILY_ROLE_ARN=your-role
6767
```
6868

6969
2. **Run Database Migration**:
@@ -75,13 +75,13 @@
7575
3. **Test Platform Creation**:
7676
```python
7777
from reflector.video_platforms.factory import create_platform_client
78-
client = create_platform_client("dailyco")
78+
client = create_platform_client("daily")
7979
# Test operations...
8080
```
8181

8282
### 6. Testing & Validation (`server/tests/`)
8383
- **test_video_platforms.py**: Comprehensive unit tests for all platform clients
84-
- **test_dailyco_webhook.py**: Integration tests for Daily.co webhook handling
84+
- **test_daily_webhook.py**: Integration tests for Daily webhook handling
8585
- **utils/video_platform_test_utils.py**: Testing utilities and helpers
8686
- **Mock Testing**: Full test coverage using mock platform client
8787
- **Webhook Testing**: HMAC signature validation and event processing tests
@@ -106,10 +106,10 @@ Daily.co webhooks are configured via API (no dashboard interface). Use the Daily
106106
```bash
107107
# Configure webhook endpoint
108108
curl -X POST https://api.daily.co/v1/webhook-endpoints \
109-
-H "Authorization: Bearer ${DAILYCO_API_KEY}" \
109+
-H "Authorization: Bearer ${DAILY_API_KEY}" \
110110
-H "Content-Type: application/json" \
111111
-d '{
112-
"url": "https://yourdomain.com/v1/dailyco_webhook",
112+
"url": "https://yourdomain.com/v1/daily/webhook",
113113
"events": [
114114
"participant.joined",
115115
"participant.left",
@@ -166,7 +166,7 @@ Daily.co uses HMAC-SHA256 for webhook verification:
166166
import hmac
167167
import hashlib
168168

169-
def verify_dailyco_webhook(body: bytes, signature: str, secret: str) -> bool:
169+
def verify_webhook_signature(body: bytes, signature: str) -> bool:
170170
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
171171
return hmac.compare_digest(expected, signature)
172172
```
@@ -200,10 +200,10 @@ async def process_recording_from_url(recording_url: str, meeting_id: str, record
200200
uv run pytest tests/test_video_platforms.py -v
201201

202202
# Run webhook integration tests
203-
uv run pytest tests/test_dailyco_webhook.py -v
203+
uv run pytest tests/test_daily_webhook.py -v
204204

205205
# Run with coverage
206-
uv run pytest tests/test_video_platforms.py tests/test_dailyco_webhook.py --cov=reflector.video_platforms --cov=reflector.views.dailyco
206+
uv run pytest tests/test_video_platforms.py tests/test_daily_webhook.py --cov=reflector.video_platforms --cov=reflector.views.daily
207207
```
208208

209209
### Manual Testing with Mock Platform
@@ -231,7 +231,7 @@ print(f"Created meeting: {meeting.room_url}")
231231

232232
```python
233233
# Test webhook payload processing
234-
from reflector.views.dailyco import dailyco_webhook
234+
from reflector.views.daily import webhook
235235
from reflector.worker.process import process_recording_from_url
236236

237237
# Simulate webhook event

PLAN.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ This plan outlines a systematic migration from Whereby to Daily.co, focusing on
1919
- [ ] Create Daily.co account and obtain API credentials (PENDING - User to provide)
2020
- [x] Add environment variables to `.env` files:
2121
```bash
22-
DAILYCO_API_KEY=your-api-key
23-
DAILYCO_WEBHOOK_SECRET=your-webhook-secret
24-
DAILYCO_SUBDOMAIN=your-subdomain
25-
AWS_DAILYCO_ROLE_ARN=arn:aws:iam::xxx:role/dailyco-recording
22+
DAILY_API_KEY=your-api-key
23+
DAILY_WEBHOOK_SECRET=your-webhook-secret
24+
DAILY_SUBDOMAIN=your-subdomain
25+
AWS_DAILY_ROLE_ARN=arn:aws:iam::xxx:role/daily-recording
2626
```
2727
- [ ] Set up Daily.co webhook endpoint in dashboard (PENDING - Credentials needed)
2828
- [ ] Configure S3 bucket permissions for Daily.co (PENDING - Credentials needed)
@@ -45,8 +45,8 @@ This plan outlines a systematic migration from Whereby to Daily.co, focusing on
4545

4646
- [x] Implement feature flag in backend settings:
4747
```python
48-
DAILYCO_MIGRATION_ENABLED = env.bool("DAILYCO_MIGRATION_ENABLED", False)
49-
DAILYCO_MIGRATION_ROOM_IDS = env.list("DAILYCO_MIGRATION_ROOM_IDS", [])
48+
DAILY_MIGRATION_ENABLED = env.bool("DAILY_MIGRATION_ENABLED", False)
49+
DAILY_MIGRATION_ROOM_IDS = env.list("DAILY_MIGRATION_ROOM_IDS", [])
5050
```
5151
- [x] Add platform selection logic to room creation
5252
- [ ] Create admin UI to toggle platform per room (FUTURE - Not in Phase 1)
@@ -66,7 +66,7 @@ This plan outlines a systematic migration from Whereby to Daily.co, focusing on
6666
### 2.1 Webhook Handler
6767
**Owner**: Backend Developer
6868

69-
- [x] Create `server/reflector/views/dailyco.py` webhook endpoint
69+
- [x] Create `server/reflector/views/daily.py` webhook endpoint at `/v1/daily/webhook`
7070
- [x] Implement HMAC signature verification
7171
- [x] Handle events:
7272
- `participant.joined`
@@ -111,13 +111,13 @@ This plan outlines a systematic migration from Whereby to Daily.co, focusing on
111111
// www/app/[roomName]/components/RoomContainer.tsx
112112
export default function RoomContainer({ params }) {
113113
const platform = meeting.response.platform || "whereby";
114-
if (platform === 'dailyco') {
115-
return <DailyCoRoom meeting={meeting.response} />
114+
if (platform === 'daily') {
115+
return <DailyRoom meeting={meeting.response} />
116116
}
117117
return <WherebyRoom meeting={meeting.response} />
118118
}
119119
```
120-
- [x] Implement `DailyCoRoom` component with:
120+
- [x] Implement `DailyRoom` component with:
121121
- Call initialization using DailyIframe
122122
- Recording consent flow
123123
- Leave meeting handling

server/reflector/app.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from reflector.logger import logger
1313
from reflector.metrics import metrics_init
1414
from reflector.settings import settings
15-
from reflector.views.dailyco import router as dailyco_router
15+
from reflector.views.daily import router as daily_router
1616
from reflector.views.meetings import router as meetings_router
1717
from reflector.views.rooms import router as rooms_router
1818
from reflector.views.rtc_offer import router as rtc_offer_router
@@ -87,7 +87,7 @@ async def lifespan(app: FastAPI):
8787
app.include_router(user_router, prefix="/v1")
8888
app.include_router(zulip_router, prefix="/v1")
8989
app.include_router(whereby_router, prefix="/v1")
90-
app.include_router(dailyco_router, prefix="/v1")
90+
app.include_router(daily_router, prefix="/v1/daily")
9191
add_pagination(app)
9292

9393
# prepare celery

server/reflector/db/meetings.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
from datetime import datetime
2-
from typing import TYPE_CHECKING, Literal
2+
from typing import Literal
33

44
import sqlalchemy as sa
55
from fastapi import HTTPException
66
from pydantic import BaseModel, Field
77

88
from reflector.db import database, metadata
99
from reflector.db.rooms import Room
10+
from reflector.settings import Platform
1011
from reflector.utils import generate_uuid4
1112

12-
if TYPE_CHECKING:
13-
from reflector.video_platforms.base import Platform
14-
1513
meetings = sa.Table(
1614
"meeting",
1715
metadata,
@@ -88,7 +86,7 @@ class Meeting(BaseModel):
8886
"none", "prompt", "automatic", "automatic-2nd-participant"
8987
] = "automatic-2nd-participant"
9088
num_clients: int = 0
91-
platform: "Platform" = "whereby"
89+
platform: Platform = "whereby"
9290

9391

9492
class MeetingController:

server/reflector/settings.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
from typing import Literal
2+
13
from pydantic_settings import BaseSettings, SettingsConfigDict
24

5+
Platform = Literal["whereby", "daily"]
6+
37

48
class Settings(BaseSettings):
59
model_config = SettingsConfigDict(
@@ -101,18 +105,18 @@ class Settings(BaseSettings):
101105
AWS_PROCESS_RECORDING_QUEUE_URL: str | None = None
102106
SQS_POLLING_TIMEOUT_SECONDS: int = 60
103107

104-
# Daily.co integration
105-
DAILYCO_API_KEY: str | None = None
106-
DAILYCO_WEBHOOK_SECRET: str | None = None
107-
DAILYCO_SUBDOMAIN: str | None = None
108-
AWS_DAILYCO_S3_BUCKET: str | None = None
109-
AWS_DAILYCO_S3_REGION: str = "us-west-2"
110-
AWS_DAILYCO_ROLE_ARN: str | None = None
108+
# Daily integration
109+
DAILY_API_KEY: str | None = None
110+
DAILY_WEBHOOK_SECRET: str | None = None
111+
DAILY_SUBDOMAIN: str | None = None
112+
AWS_DAILY_S3_BUCKET: str | None = None
113+
AWS_DAILY_S3_REGION: str = "us-west-2"
114+
AWS_DAILY_ROLE_ARN: str | None = None
111115

112116
# Video platform migration feature flags
113-
DAILYCO_MIGRATION_ENABLED: bool = True
114-
DAILYCO_MIGRATION_ROOM_IDS: list[str] = []
115-
DEFAULT_VIDEO_PLATFORM: str = "dailyco"
117+
DAILY_MIGRATION_ENABLED: bool = True
118+
DAILY_MIGRATION_ROOM_IDS: list[str] = []
119+
DEFAULT_VIDEO_PLATFORM: Platform = "daily"
116120

117121
# Zulip integration
118122
ZULIP_REALM: str | None = None

server/reflector/video_platforms/base.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@
66

77
from reflector.db.rooms import Room
88

9-
# Supported video platforms
10-
Platform = Literal["whereby", "dailyco"]
9+
Platform = Literal["whereby", "daily"]
1110

11+
RecordingType = Literal["none", "local", "cloud"]
1212

13-
class MeetingData(BaseModel):
14-
"""Standardized meeting data returned by all platforms."""
1513

14+
class MeetingData(BaseModel):
1615
meeting_id: str
1716
room_name: str
1817
room_url: str
1918
host_room_url: str
2019
platform: Platform
21-
extra_data: Dict[str, Any] = {} # Platform-specific data
20+
extra_data: Dict[str, Any] = {}
2221

2322

2423
class VideoPlatformConfig(BaseModel):

server/reflector/video_platforms/dailyco.py renamed to server/reflector/video_platforms/daily.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
import hmac
22
from datetime import datetime
33
from hashlib import sha256
4+
from http import HTTPStatus
45
from typing import Any, Dict, Optional
56

67
import httpx
78

89
from reflector.db.rooms import Room
910

10-
from .base import MeetingData, VideoPlatformClient, VideoPlatformConfig
11+
from .base import MeetingData, Platform, RecordingType, VideoPlatformClient, VideoPlatformConfig
1112

1213

13-
class DailyCoClient(VideoPlatformClient):
14-
"""Daily.co video platform implementation."""
15-
16-
PLATFORM_NAME = "dailyco"
17-
TIMEOUT = 10 # seconds
14+
class DailyClient(VideoPlatformClient):
15+
PLATFORM_NAME: Platform = "daily"
16+
TIMEOUT = 10
1817
BASE_URL = "https://api.daily.co/v1"
18+
TIMESTAMP_FORMAT = "%Y%m%d%H%M%S"
19+
RECORDING_NONE: RecordingType = "none"
20+
RECORDING_CLOUD: RecordingType = "cloud"
1921

2022
def __init__(self, config: VideoPlatformConfig):
2123
super().__init__(config)
@@ -28,14 +30,14 @@ async def create_meeting(
2830
self, room_name_prefix: str, end_date: datetime, room: Room
2931
) -> MeetingData:
3032
"""Create a Daily.co room."""
31-
room_name = f"{room_name_prefix}-{datetime.now().strftime('%Y%m%d%H%M%S')}"
33+
room_name = f"{room_name_prefix}-{datetime.now().strftime(self.TIMESTAMP_FORMAT)}"
3234

3335
data = {
3436
"name": room_name,
3537
"privacy": "private" if room.is_locked else "public",
3638
"properties": {
3739
"enable_recording": room.recording_type
38-
if room.recording_type != "none"
40+
if room.recording_type != self.RECORDING_NONE
3941
else False,
4042
"enable_chat": True,
4143
"enable_screenshare": True,
@@ -46,7 +48,7 @@ async def create_meeting(
4648
}
4749

4850
# Configure S3 bucket for cloud recordings
49-
if room.recording_type == "cloud" and self.config.s3_bucket:
51+
if room.recording_type == self.RECORDING_CLOUD and self.config.s3_bucket:
5052
data["properties"]["recordings_bucket"] = {
5153
"bucket_name": self.config.s3_bucket,
5254
"bucket_region": self.config.s3_region,
@@ -107,7 +109,7 @@ async def delete_room(self, room_name: str) -> bool:
107109
timeout=self.TIMEOUT,
108110
)
109111
# Daily.co returns 200 for success, 404 if room doesn't exist
110-
return response.status_code in (200, 404)
112+
return response.status_code in (HTTPStatus.OK, HTTPStatus.NOT_FOUND)
111113

112114
async def upload_logo(self, room_name: str, logo_path: str) -> bool:
113115
"""Daily.co doesn't support custom logos per room - this is a no-op."""

server/reflector/video_platforms/factory.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ def get_platform_config(platform: Platform) -> VideoPlatformConfig:
1919
aws_access_key_id=settings.AWS_WHEREBY_ACCESS_KEY_ID,
2020
aws_access_key_secret=settings.AWS_WHEREBY_ACCESS_KEY_SECRET,
2121
)
22-
elif platform == "dailyco":
22+
elif platform == "daily":
2323
return VideoPlatformConfig(
24-
api_key=settings.DAILYCO_API_KEY or "",
25-
webhook_secret=settings.DAILYCO_WEBHOOK_SECRET or "",
26-
subdomain=settings.DAILYCO_SUBDOMAIN,
27-
s3_bucket=settings.AWS_DAILYCO_S3_BUCKET,
28-
s3_region=settings.AWS_DAILYCO_S3_REGION,
29-
aws_role_arn=settings.AWS_DAILYCO_ROLE_ARN,
24+
api_key=settings.DAILY_API_KEY or "",
25+
webhook_secret=settings.DAILY_WEBHOOK_SECRET or "",
26+
subdomain=settings.DAILY_SUBDOMAIN,
27+
s3_bucket=settings.AWS_DAILY_S3_BUCKET,
28+
s3_region=settings.AWS_DAILY_S3_REGION,
29+
aws_role_arn=settings.AWS_DAILY_ROLE_ARN,
3030
)
3131
else:
3232
raise ValueError(f"Unknown platform: {platform}")
@@ -40,13 +40,13 @@ def create_platform_client(platform: Platform) -> VideoPlatformClient:
4040

4141
def get_platform_for_room(room_id: Optional[str] = None) -> Platform:
4242
"""Determine which platform to use for a room based on feature flags."""
43-
# If Daily.co migration is disabled, always use Whereby
44-
if not settings.DAILYCO_MIGRATION_ENABLED:
43+
# If Daily migration is disabled, always use Whereby
44+
if not settings.DAILY_MIGRATION_ENABLED:
4545
return "whereby"
4646

47-
# If a specific room is in the migration list, use Daily.co
48-
if room_id and room_id in settings.DAILYCO_MIGRATION_ROOM_IDS:
49-
return "dailyco"
47+
# If a specific room is in the migration list, use Daily
48+
if room_id and room_id in settings.DAILY_MIGRATION_ROOM_IDS:
49+
return "daily"
5050

5151
# Otherwise use the default platform
5252
return settings.DEFAULT_VIDEO_PLATFORM

0 commit comments

Comments
 (0)