Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/legal-paths-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"github.com/livekit/protocol": minor
---

Utilities for phone number functionality
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ require (
github.com/nats-io/nats.go v1.43.0 // indirect
github.com/nats-io/nkeys v0.4.11 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/nyaruka/phonenumbers v1.6.5 // indirect
github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v3 v3.0.6 // indirect
github.com/pion/ice/v4 v4.0.10 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nyaruka/phonenumbers v1.6.5 h1:aBCaUhfpRA7hU6fsXk+p7KF1aNx4nQlq9hGeo2qdFg8=
github.com/nyaruka/phonenumbers v1.6.5/go.mod h1:7gjs+Lchqm49adhAKB5cdcng5ZXgt6x7Jgvi0ZorUtU=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
Expand Down
198 changes: 129 additions & 69 deletions livekit/livekit_phone_number.pb.go

Large diffs are not rendered by default.

128 changes: 66 additions & 62 deletions livekit/livekit_phone_number.twirp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion protobufs/livekit_phone_number.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ enum PhoneNumberStatus {
PHONE_NUMBER_STATUS_RELEASED = 3; // Number has been released
}

// Phone number type enumeration
enum PhoneNumberType {
PHONE_NUMBER_TYPE_UNKNOWN = 0; // Default value - unknown or parsing error
PHONE_NUMBER_TYPE_MOBILE = 1; // Mobile phone number
PHONE_NUMBER_TYPE_LOCAL = 2; // Local/fixed line number
PHONE_NUMBER_TYPE_TOLL_FREE = 3; // Toll-free number
}

// Public Phone Number Service - External API for phone number management
service PhoneNumberService {
// Search available phone numbers in inventory
Expand Down Expand Up @@ -123,7 +131,7 @@ message PhoneNumber {
string e164_format = 2; // Phone number in E.164 format (e.g., "+14155552671")
string country_code = 3; // Country code (e.g., "US")
string area_code = 4; // Area code (e.g., "415")
string number_type = 5; // Number type (e.g., local, toll-free, national, mobile)
PhoneNumberType number_type = 5; // Number type (mobile, local, toll-free, unknown)
string locality = 6; // City/locality (e.g., "San Francisco")
string region = 7; // State/region (e.g., "CA")
double spam_score = 8; // Spam score for fraud detection
Expand Down
55 changes: 55 additions & 0 deletions sip/phonenumber.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package sip

import (
"github.com/livekit/protocol/livekit"
"github.com/nyaruka/phonenumbers"
)

// ExtractAreaCode extracts the area code from a phone number using the phonenumbers library
func ExtractAreaCode(phoneNumber string) string {
// Parse the phone number without defaulting to any country
num, err := phonenumbers.Parse(phoneNumber, "")
if err != nil {
// If parsing fails, fall back to empty string
return ""
}

// Get the country code
countryCode := phonenumbers.GetRegionCodeForNumber(num)

// Only handle US numbers for now
if countryCode != "US" {
return ""
}

// Get the national number and extract first 3 digits (area code for US)
nationalNumber := phonenumbers.GetNationalSignificantNumber(num)
if len(nationalNumber) < 3 {
return ""
}
return nationalNumber[:3]
}

// DetermineNumberType determines the phone number type using the phonenumbers library
func DetermineNumberType(phoneNumber string) livekit.PhoneNumberType {
// Parse the phone number without defaulting to any country
num, err := phonenumbers.Parse(phoneNumber, "")
if err != nil {
// If parsing fails, fall back to unknown
return livekit.PhoneNumberType_PHONE_NUMBER_TYPE_UNKNOWN
}

numberType := phonenumbers.GetNumberType(num)

// We are excluding a bunch of number types for now
switch numberType {
case phonenumbers.MOBILE:
return livekit.PhoneNumberType_PHONE_NUMBER_TYPE_MOBILE
case phonenumbers.FIXED_LINE:
return livekit.PhoneNumberType_PHONE_NUMBER_TYPE_LOCAL
case phonenumbers.TOLL_FREE:
return livekit.PhoneNumberType_PHONE_NUMBER_TYPE_TOLL_FREE
default:
return livekit.PhoneNumberType_PHONE_NUMBER_TYPE_UNKNOWN
}
}
2 changes: 2 additions & 0 deletions utils/guid/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ const (
CloudAgentSecretPrefix = "CAS_"
CloudAgentWorkerPrefix = "CAW_"
AgentGatewayPrefix = "GW_"
CarrierPrefix = "CR_"
PhoneNumberPrefix = "PN_"
)

var guidGeneratorPool = sync.Pool{
Expand Down
Loading