Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/phonic/bun_inbound_sip/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# deps
node_modules/
11 changes: 11 additions & 0 deletions examples/phonic/bun_inbound_sip/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
To install dependencies:
```sh
bun install
```

To run:
```sh
bun run dev
```

open http://localhost:3000
767 changes: 767 additions & 0 deletions examples/phonic/bun_inbound_sip/bun.lock

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions examples/phonic/bun_inbound_sip/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "my-app",
"scripts": {
"dev": "bun run src/index.ts"
},
"dependencies": {
"@livekit/rtc-node": "/Users/shubhrakantiganguly/development/node-sdks/packages/livekit-rtc",
"hono": "^4.8.5",
"livekit-server-sdk": "/Users/shubhrakantiganguly/development/node-sdks/packages/livekit-server-sdk"
},
"devDependencies": {
"@types/bun": "latest"
}
}
71 changes: 71 additions & 0 deletions examples/phonic/bun_inbound_sip/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Room } from '@livekit/rtc-node';
import { Hono } from 'hono';
import { AccessToken, WebhookReceiver } from 'livekit-server-sdk';

const livekitUrl = process.env.LIVEKIT_URL!;
const livekitApiKey = process.env.LIVEKIT_API_KEY!;
const livekitApiSecret = process.env.LIVEKIT_API_SECRET!;

const livekitReceiver = new WebhookReceiver(livekitApiKey, livekitApiSecret);
const connectToLivekitRoom = async ({ roomName }: { roomName: string }) => {
const token = new AccessToken(livekitApiKey, livekitApiSecret, {
identity: 'phonic-sts-websocket',
});

token.addGrant({
room: roomName,
roomJoin: true,
roomCreate: true,
canPublish: true,
});

const jwt = await token.toJwt();
console.log(`Created JWT for room ${roomName} \n\n`);
const room = new Room();
console.log(`Created Livekit room ${roomName} \n\n`);
await room.connect(livekitUrl, jwt);
console.log(`Connected to room ${roomName} \n\n`);

return {
data: room,
error: null,
};
};

const app = new Hono();

// Basic route
app.post('/v1/conversations/inbound_call', async (c) => {
const bodyString = await c.req.text();
const authHeader = c.req.header('Authorization');
const event = await livekitReceiver.receive(bodyString, authHeader);

console.log(`Received event: ${event.event}`);
if (event.event !== 'room_started' || !event.room?.name.startsWith('call')) {
// Not the event that we're interested. Just return success is true.
console.log(`Not the event that we're interested. Just return success is true. \n\n`);
return c.json({ success: true });
}

const roomName = event.room.name;
const roomResult = await connectToLivekitRoom({ roomName });

if (roomResult.error !== null) {
console.log(`Failed to connect to room ${roomName}: ${roomResult.error} \n\n`);
return c.json(roomResult.error, 500);
}

const room = roomResult.data;
room.disconnect();

console.log(`Disconnected from room ${roomName} \n\n`);

return c.text('Received event ', 200);
});

console.log(`Listening on http://localhost:3510`);

Bun.serve({
port: 3510,
fetch: app.fetch,
});
7 changes: 7 additions & 0 deletions examples/phonic/bun_inbound_sip/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"strict": true,
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
}
}
8 changes: 8 additions & 0 deletions examples/phonic/ngrok.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '3'
tunnels:
python-inbound-sip:
addr: 3000
proto: http
bun-inbound-sip:
addr: 3510
proto: http
1 change: 1 addition & 0 deletions examples/phonic/python_inbound_sip/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
75 changes: 75 additions & 0 deletions examples/phonic/python_inbound_sip/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import os
from livekit import api, rtc
from aiohttp import web


livekit_url = os.environ["LIVEKIT_URL"]
livekit_api_key = os.environ["LIVEKIT_API_KEY"]
livekit_api_secret = os.environ["LIVEKIT_API_SECRET"]

token_verifier = api.TokenVerifier(livekit_api_key, livekit_api_secret)
webhook_receiver = api.WebhookReceiver(token_verifier)


async def connect_to_livekit_room(room_name: str):
"""Connect to a LiveKit room, similar to the Node.js version"""
try:
# Create access token
access_token = api.AccessToken(livekit_api_key, livekit_api_secret)
access_token.with_identity("phonic-sts-websocket")
access_token.with_grants(
api.VideoGrants(
room=room_name,
room_join=True,
room_create=True,
can_publish=True,
)
)

jwt = access_token.to_jwt()
print(f"Created JWT for room {room_name} \n\n")

room = rtc.Room()
print(f"Created Livekit room {room_name} \n\n")

await room.connect(livekit_url, jwt)
print(f"Connected to room {room_name} \n\n")

return {"data": room, "error": None}
except Exception as e:
return {"data": None, "error": str(e)}


async def handle_webhook(request):
auth_token = request.headers.get("Authorization")
if not auth_token:
return web.Response(status=401)

body = await request.read()
event = webhook_receiver.receive(body.decode("utf-8"), auth_token)
print(f"Received event: {event.event}")

if (
event.event != "room_started"
or not event.room
or not event.room.name.startswith("call")
):
# Not the event that we're interested. Just return success is true.
print("Not the event that we're interested. Just return success is true. \n\n")
return web.json_response({"success": True})

room_name = event.room.name
room_result = await connect_to_livekit_room(room_name)

if room_result["error"] is not None:
print(f"Failed to connect to room {room_name}: {room_result['error']} \n\n")
return web.json_response(room_result["error"], status=500)

return web.Response(text="Received event ", status=200)


if __name__ == "__main__":
app = web.Application()
app.router.add_post("/v1/conversations/inbound_call", handle_webhook)
print("Listening on http://localhost:3000")
web.run_app(app, port=3000)
11 changes: 11 additions & 0 deletions examples/phonic/python_inbound_sip/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[project]
name = "python-inbound-sip"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"aiohttp>=3.8.0",
"livekit>=1.0.7",
"livekit-api>=1.0.3",
]
Loading
Loading