Add twilio connector (#1254)

* Add twilio connector

* empty lines

* solve comments

* Make optional field consistent with whatsapp connector

* Remove stream direction, add call direction

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
cnderrauber
2025-10-16 10:41:55 +08:00
committed by GitHub
parent 0236ffc17f
commit 8cf58ff15a
9 changed files with 852 additions and 90 deletions
+18 -12
View File
@@ -38,34 +38,39 @@ var File_livekit_connector_proto protoreflect.FileDescriptor
const file_livekit_connector_proto_rawDesc = "" +
"\n" +
"\x17livekit_connector.proto\x12\alivekit\x1a livekit_connector_whatsapp.proto2\x90\x03\n" +
"\x17livekit_connector.proto\x12\alivekit\x1a livekit_connector_whatsapp.proto\x1a\x1elivekit_connector_twilio.proto2\xec\x03\n" +
"\tConnector\x12W\n" +
"\x10DialWhatsAppCall\x12 .livekit.DialWhatsAppCallRequest\x1a!.livekit.DialWhatsAppCallResponse\x12i\n" +
"\x16DisconnectWhatsAppCall\x12&.livekit.DisconnectWhatsAppCallRequest\x1a'.livekit.DisconnectWhatsAppCallResponse\x12`\n" +
"\x13ConnectWhatsAppCall\x12#.livekit.ConnectWhatsAppCallRequest\x1a$.livekit.ConnectWhatsAppCallResponse\x12]\n" +
"\x12AcceptWhatsAppCall\x12\".livekit.AcceptWhatsAppCallRequest\x1a#.livekit.AcceptWhatsAppCallResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3"
"\x12AcceptWhatsAppCall\x12\".livekit.AcceptWhatsAppCallRequest\x1a#.livekit.AcceptWhatsAppCallResponse\x12Z\n" +
"\x11ConnectTwilioCall\x12!.livekit.ConnectTwilioCallRequest\x1a\".livekit.ConnectTwilioCallResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3"
var file_livekit_connector_proto_goTypes = []any{
(*DialWhatsAppCallRequest)(nil), // 0: livekit.DialWhatsAppCallRequest
(*DisconnectWhatsAppCallRequest)(nil), // 1: livekit.DisconnectWhatsAppCallRequest
(*ConnectWhatsAppCallRequest)(nil), // 2: livekit.ConnectWhatsAppCallRequest
(*AcceptWhatsAppCallRequest)(nil), // 3: livekit.AcceptWhatsAppCallRequest
(*DialWhatsAppCallResponse)(nil), // 4: livekit.DialWhatsAppCallResponse
(*DisconnectWhatsAppCallResponse)(nil), // 5: livekit.DisconnectWhatsAppCallResponse
(*ConnectWhatsAppCallResponse)(nil), // 6: livekit.ConnectWhatsAppCallResponse
(*AcceptWhatsAppCallResponse)(nil), // 7: livekit.AcceptWhatsAppCallResponse
(*ConnectTwilioCallRequest)(nil), // 4: livekit.ConnectTwilioCallRequest
(*DialWhatsAppCallResponse)(nil), // 5: livekit.DialWhatsAppCallResponse
(*DisconnectWhatsAppCallResponse)(nil), // 6: livekit.DisconnectWhatsAppCallResponse
(*ConnectWhatsAppCallResponse)(nil), // 7: livekit.ConnectWhatsAppCallResponse
(*AcceptWhatsAppCallResponse)(nil), // 8: livekit.AcceptWhatsAppCallResponse
(*ConnectTwilioCallResponse)(nil), // 9: livekit.ConnectTwilioCallResponse
}
var file_livekit_connector_proto_depIdxs = []int32{
0, // 0: livekit.Connector.DialWhatsAppCall:input_type -> livekit.DialWhatsAppCallRequest
1, // 1: livekit.Connector.DisconnectWhatsAppCall:input_type -> livekit.DisconnectWhatsAppCallRequest
2, // 2: livekit.Connector.ConnectWhatsAppCall:input_type -> livekit.ConnectWhatsAppCallRequest
3, // 3: livekit.Connector.AcceptWhatsAppCall:input_type -> livekit.AcceptWhatsAppCallRequest
4, // 4: livekit.Connector.DialWhatsAppCall:output_type -> livekit.DialWhatsAppCallResponse
5, // 5: livekit.Connector.DisconnectWhatsAppCall:output_type -> livekit.DisconnectWhatsAppCallResponse
6, // 6: livekit.Connector.ConnectWhatsAppCall:output_type -> livekit.ConnectWhatsAppCallResponse
7, // 7: livekit.Connector.AcceptWhatsAppCall:output_type -> livekit.AcceptWhatsAppCallResponse
4, // [4:8] is the sub-list for method output_type
0, // [0:4] is the sub-list for method input_type
4, // 4: livekit.Connector.ConnectTwilioCall:input_type -> livekit.ConnectTwilioCallRequest
5, // 5: livekit.Connector.DialWhatsAppCall:output_type -> livekit.DialWhatsAppCallResponse
6, // 6: livekit.Connector.DisconnectWhatsAppCall:output_type -> livekit.DisconnectWhatsAppCallResponse
7, // 7: livekit.Connector.ConnectWhatsAppCall:output_type -> livekit.ConnectWhatsAppCallResponse
8, // 8: livekit.Connector.AcceptWhatsAppCall:output_type -> livekit.AcceptWhatsAppCallResponse
9, // 9: livekit.Connector.ConnectTwilioCall:output_type -> livekit.ConnectTwilioCallResponse
5, // [5:10] is the sub-list for method output_type
0, // [0:5] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -77,6 +82,7 @@ func file_livekit_connector_proto_init() {
return
}
file_livekit_connector_whatsapp_proto_init()
file_livekit_connector_twilio_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
+299 -17
View File
@@ -34,6 +34,8 @@ type Connector interface {
ConnectWhatsAppCall(context.Context, *ConnectWhatsAppCallRequest) (*ConnectWhatsAppCallResponse, error)
AcceptWhatsAppCall(context.Context, *AcceptWhatsAppCallRequest) (*AcceptWhatsAppCallResponse, error)
ConnectTwilioCall(context.Context, *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error)
}
// =========================
@@ -42,7 +44,7 @@ type Connector interface {
type connectorProtobufClient struct {
client HTTPClient
urls [4]string
urls [5]string
interceptor twirp.Interceptor
opts twirp.ClientOptions
}
@@ -70,11 +72,12 @@ func NewConnectorProtobufClient(baseURL string, client HTTPClient, opts ...twirp
// Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method>
serviceURL := sanitizeBaseURL(baseURL)
serviceURL += baseServicePath(pathPrefix, "livekit", "Connector")
urls := [4]string{
urls := [5]string{
serviceURL + "DialWhatsAppCall",
serviceURL + "DisconnectWhatsAppCall",
serviceURL + "ConnectWhatsAppCall",
serviceURL + "AcceptWhatsAppCall",
serviceURL + "ConnectTwilioCall",
}
return &connectorProtobufClient{
@@ -269,13 +272,59 @@ func (c *connectorProtobufClient) callAcceptWhatsAppCall(ctx context.Context, in
return out, nil
}
func (c *connectorProtobufClient) ConnectTwilioCall(ctx context.Context, in *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
ctx = ctxsetters.WithPackageName(ctx, "livekit")
ctx = ctxsetters.WithServiceName(ctx, "Connector")
ctx = ctxsetters.WithMethodName(ctx, "ConnectTwilioCall")
caller := c.callConnectTwilioCall
if c.interceptor != nil {
caller = func(ctx context.Context, req *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
resp, err := c.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*ConnectTwilioCallRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*ConnectTwilioCallRequest) when calling interceptor")
}
return c.callConnectTwilioCall(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*ConnectTwilioCallResponse)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*ConnectTwilioCallResponse) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
return caller(ctx, in)
}
func (c *connectorProtobufClient) callConnectTwilioCall(ctx context.Context, in *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
out := new(ConnectTwilioCallResponse)
ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[4], in, out)
if err != nil {
twerr, ok := err.(twirp.Error)
if !ok {
twerr = twirp.InternalErrorWith(err)
}
callClientError(ctx, c.opts.Hooks, twerr)
return nil, err
}
callClientResponseReceived(ctx, c.opts.Hooks)
return out, nil
}
// =====================
// Connector JSON Client
// =====================
type connectorJSONClient struct {
client HTTPClient
urls [4]string
urls [5]string
interceptor twirp.Interceptor
opts twirp.ClientOptions
}
@@ -303,11 +352,12 @@ func NewConnectorJSONClient(baseURL string, client HTTPClient, opts ...twirp.Cli
// Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method>
serviceURL := sanitizeBaseURL(baseURL)
serviceURL += baseServicePath(pathPrefix, "livekit", "Connector")
urls := [4]string{
urls := [5]string{
serviceURL + "DialWhatsAppCall",
serviceURL + "DisconnectWhatsAppCall",
serviceURL + "ConnectWhatsAppCall",
serviceURL + "AcceptWhatsAppCall",
serviceURL + "ConnectTwilioCall",
}
return &connectorJSONClient{
@@ -502,6 +552,52 @@ func (c *connectorJSONClient) callAcceptWhatsAppCall(ctx context.Context, in *Ac
return out, nil
}
func (c *connectorJSONClient) ConnectTwilioCall(ctx context.Context, in *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
ctx = ctxsetters.WithPackageName(ctx, "livekit")
ctx = ctxsetters.WithServiceName(ctx, "Connector")
ctx = ctxsetters.WithMethodName(ctx, "ConnectTwilioCall")
caller := c.callConnectTwilioCall
if c.interceptor != nil {
caller = func(ctx context.Context, req *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
resp, err := c.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*ConnectTwilioCallRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*ConnectTwilioCallRequest) when calling interceptor")
}
return c.callConnectTwilioCall(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*ConnectTwilioCallResponse)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*ConnectTwilioCallResponse) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
return caller(ctx, in)
}
func (c *connectorJSONClient) callConnectTwilioCall(ctx context.Context, in *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
out := new(ConnectTwilioCallResponse)
ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[4], in, out)
if err != nil {
twerr, ok := err.(twirp.Error)
if !ok {
twerr = twirp.InternalErrorWith(err)
}
callClientError(ctx, c.opts.Hooks, twerr)
return nil, err
}
callClientResponseReceived(ctx, c.opts.Hooks)
return out, nil
}
// ========================
// Connector Server Handler
// ========================
@@ -611,6 +707,9 @@ func (s *connectorServer) ServeHTTP(resp http.ResponseWriter, req *http.Request)
case "AcceptWhatsAppCall":
s.serveAcceptWhatsAppCall(ctx, resp, req)
return
case "ConnectTwilioCall":
s.serveConnectTwilioCall(ctx, resp, req)
return
default:
msg := fmt.Sprintf("no handler for path %q", req.URL.Path)
s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path))
@@ -1338,6 +1437,186 @@ func (s *connectorServer) serveAcceptWhatsAppCallProtobuf(ctx context.Context, r
callResponseSent(ctx, s.hooks)
}
func (s *connectorServer) serveConnectTwilioCall(ctx context.Context, resp http.ResponseWriter, req *http.Request) {
header := req.Header.Get("Content-Type")
i := strings.Index(header, ";")
if i == -1 {
i = len(header)
}
switch strings.TrimSpace(strings.ToLower(header[:i])) {
case "application/json":
s.serveConnectTwilioCallJSON(ctx, resp, req)
case "application/protobuf":
s.serveConnectTwilioCallProtobuf(ctx, resp, req)
default:
msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type"))
twerr := badRouteError(msg, req.Method, req.URL.Path)
s.writeError(ctx, resp, twerr)
}
}
func (s *connectorServer) serveConnectTwilioCallJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) {
var err error
ctx = ctxsetters.WithMethodName(ctx, "ConnectTwilioCall")
ctx, err = callRequestRouted(ctx, s.hooks)
if err != nil {
s.writeError(ctx, resp, err)
return
}
d := json.NewDecoder(req.Body)
rawReqBody := json.RawMessage{}
if err := d.Decode(&rawReqBody); err != nil {
s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err)
return
}
reqContent := new(ConnectTwilioCallRequest)
unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true}
if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil {
s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err)
return
}
handler := s.Connector.ConnectTwilioCall
if s.interceptor != nil {
handler = func(ctx context.Context, req *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
resp, err := s.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*ConnectTwilioCallRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*ConnectTwilioCallRequest) when calling interceptor")
}
return s.Connector.ConnectTwilioCall(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*ConnectTwilioCallResponse)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*ConnectTwilioCallResponse) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
// Call service method
var respContent *ConnectTwilioCallResponse
func() {
defer ensurePanicResponses(ctx, resp, s.hooks)
respContent, err = handler(ctx, reqContent)
}()
if err != nil {
s.writeError(ctx, resp, err)
return
}
if respContent == nil {
s.writeError(ctx, resp, twirp.InternalError("received a nil *ConnectTwilioCallResponse and nil error while calling ConnectTwilioCall. nil responses are not supported"))
return
}
ctx = callResponsePrepared(ctx, s.hooks)
marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults}
respBytes, err := marshaler.Marshal(respContent)
if err != nil {
s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response"))
return
}
ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK)
resp.Header().Set("Content-Type", "application/json")
resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes)))
resp.WriteHeader(http.StatusOK)
if n, err := resp.Write(respBytes); err != nil {
msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error())
twerr := twirp.NewError(twirp.Unknown, msg)
ctx = callError(ctx, s.hooks, twerr)
}
callResponseSent(ctx, s.hooks)
}
func (s *connectorServer) serveConnectTwilioCallProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) {
var err error
ctx = ctxsetters.WithMethodName(ctx, "ConnectTwilioCall")
ctx, err = callRequestRouted(ctx, s.hooks)
if err != nil {
s.writeError(ctx, resp, err)
return
}
buf, err := io.ReadAll(req.Body)
if err != nil {
s.handleRequestBodyError(ctx, resp, "failed to read request body", err)
return
}
reqContent := new(ConnectTwilioCallRequest)
if err = proto.Unmarshal(buf, reqContent); err != nil {
s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded"))
return
}
handler := s.Connector.ConnectTwilioCall
if s.interceptor != nil {
handler = func(ctx context.Context, req *ConnectTwilioCallRequest) (*ConnectTwilioCallResponse, error) {
resp, err := s.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*ConnectTwilioCallRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*ConnectTwilioCallRequest) when calling interceptor")
}
return s.Connector.ConnectTwilioCall(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*ConnectTwilioCallResponse)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*ConnectTwilioCallResponse) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
// Call service method
var respContent *ConnectTwilioCallResponse
func() {
defer ensurePanicResponses(ctx, resp, s.hooks)
respContent, err = handler(ctx, reqContent)
}()
if err != nil {
s.writeError(ctx, resp, err)
return
}
if respContent == nil {
s.writeError(ctx, resp, twirp.InternalError("received a nil *ConnectTwilioCallResponse and nil error while calling ConnectTwilioCall. nil responses are not supported"))
return
}
ctx = callResponsePrepared(ctx, s.hooks)
respBytes, err := proto.Marshal(respContent)
if err != nil {
s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response"))
return
}
ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK)
resp.Header().Set("Content-Type", "application/protobuf")
resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes)))
resp.WriteHeader(http.StatusOK)
if n, err := resp.Write(respBytes); err != nil {
msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error())
twerr := twirp.NewError(twirp.Unknown, msg)
ctx = callError(ctx, s.hooks, twerr)
}
callResponseSent(ctx, s.hooks)
}
func (s *connectorServer) ServiceDescriptor() ([]byte, int) {
return twirpFileDescriptor7, 0
}
@@ -1354,20 +1633,23 @@ func (s *connectorServer) PathPrefix() string {
}
var twirpFileDescriptor7 = []byte{
// 238 bytes of a gzipped FileDescriptorProto
// 273 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0xc9, 0x2c, 0x4b,
0xcd, 0xce, 0x2c, 0x89, 0x4f, 0xce, 0xcf, 0xcb, 0x4b, 0x4d, 0x2e, 0xc9, 0x2f, 0xd2, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x4a, 0x48, 0x29, 0x60, 0xa8, 0x88, 0x2f, 0xcf, 0x48, 0x2c,
0x29, 0x4e, 0x2c, 0x28, 0x80, 0x28, 0x35, 0x9a, 0xc0, 0xcc, 0xc5, 0xe9, 0x0c, 0x93, 0x14, 0x0a,
0xe7, 0x12, 0x70, 0xc9, 0x4c, 0xcc, 0x09, 0x07, 0xa9, 0x71, 0x2c, 0x28, 0x70, 0x4e, 0xcc, 0xc9,
0x11, 0x52, 0xd0, 0x83, 0x1a, 0xa2, 0x87, 0x2e, 0x15, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x22,
0xa5, 0x88, 0x47, 0x45, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0xaa, 0x50, 0x26, 0x97, 0x98, 0x4b, 0x66,
0x31, 0xd4, 0x15, 0x28, 0xc6, 0xab, 0x21, 0x69, 0xc6, 0xa6, 0x00, 0x66, 0x89, 0x3a, 0x41, 0x75,
0x50, 0xab, 0x12, 0xb8, 0x84, 0x9d, 0xb1, 0xd8, 0xa3, 0x0c, 0xd7, 0xef, 0x8c, 0xdb, 0x12, 0x15,
0xfc, 0x8a, 0xa0, 0x36, 0xc4, 0x72, 0x09, 0x39, 0x26, 0x27, 0xa7, 0x16, 0xa0, 0x5a, 0xa0, 0x04,
0xd7, 0x8b, 0x29, 0x09, 0x33, 0x5f, 0x19, 0xaf, 0x1a, 0x88, 0xf1, 0x4e, 0x6e, 0x51, 0xca, 0xe9,
0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x50, 0x0d, 0xfa, 0xe0, 0xe8, 0x4a,
0xce, 0xcf, 0x81, 0x09, 0xac, 0x62, 0xe2, 0xf5, 0xc9, 0x2c, 0x4b, 0xf5, 0xce, 0x2c, 0xd1, 0x0b,
0x00, 0x49, 0xbd, 0x62, 0xe2, 0x83, 0xf2, 0xad, 0xac, 0xc0, 0x02, 0x49, 0x6c, 0x60, 0x2d, 0xc6,
0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x7c, 0x2f, 0xe1, 0x27, 0x02, 0x00, 0x00,
0x29, 0x4e, 0x2c, 0x28, 0x80, 0x28, 0x95, 0x92, 0xc3, 0x54, 0x51, 0x52, 0x9e, 0x99, 0x93, 0x99,
0x0f, 0x91, 0x37, 0x7a, 0xc3, 0xcc, 0xc5, 0xe9, 0x0c, 0x93, 0x12, 0x0a, 0xe7, 0x12, 0x70, 0xc9,
0x4c, 0xcc, 0x09, 0x07, 0x99, 0xe1, 0x58, 0x50, 0xe0, 0x9c, 0x98, 0x93, 0x23, 0xa4, 0xa0, 0x07,
0x35, 0x42, 0x0f, 0x5d, 0x2a, 0x28, 0xb5, 0xb0, 0x34, 0xb5, 0xb8, 0x44, 0x4a, 0x11, 0x8f, 0x8a,
0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0xa1, 0x4c, 0x2e, 0x31, 0x97, 0xcc, 0x62, 0xa8, 0x1b, 0x50,
0x8c, 0x57, 0x43, 0xd2, 0x8c, 0x4d, 0x01, 0xcc, 0x12, 0x75, 0x82, 0xea, 0xa0, 0x56, 0x25, 0x70,
0x09, 0x3b, 0x63, 0xb1, 0x47, 0x19, 0xae, 0xdf, 0x19, 0xb7, 0x25, 0x2a, 0xf8, 0x15, 0x41, 0x6d,
0x88, 0xe5, 0x12, 0x72, 0x4c, 0x4e, 0x4e, 0x2d, 0x40, 0xb5, 0x40, 0x09, 0xae, 0x17, 0x53, 0x12,
0x66, 0xbe, 0x32, 0x5e, 0x35, 0x50, 0xe3, 0xa3, 0xb8, 0x04, 0xa1, 0xb6, 0x87, 0x80, 0x63, 0x0a,
0x6c, 0xba, 0x22, 0xba, 0xcb, 0x10, 0x72, 0x30, 0xc3, 0x95, 0xf0, 0x29, 0x81, 0x98, 0xed, 0xe4,
0x16, 0xa5, 0x9c, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x0f, 0x55, 0xaf,
0x0f, 0x4e, 0x0a, 0xc9, 0xf9, 0x39, 0x30, 0x81, 0x55, 0x4c, 0xbc, 0x3e, 0x99, 0x65, 0xa9, 0xde,
0x99, 0x25, 0x7a, 0x01, 0x20, 0xa9, 0x57, 0x4c, 0x7c, 0x50, 0xbe, 0x95, 0x15, 0x58, 0x20, 0x89,
0x0d, 0xac, 0xc5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x18, 0x8d, 0x1d, 0x42, 0xa3, 0x02, 0x00,
0x00,
}
+317
View File
@@ -0,0 +1,317 @@
// Copyright 2025 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v4.23.4
// source: livekit_connector_twilio.proto
package livekit
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type ConnectTwilioCallRequest_TwilioCallDirection int32
const (
ConnectTwilioCallRequest_TWILIO_CALL_DIRECTION_INBOUND ConnectTwilioCallRequest_TwilioCallDirection = 0
ConnectTwilioCallRequest_TWILIO_CALL_DIRECTION_OUTBOUND ConnectTwilioCallRequest_TwilioCallDirection = 1
)
// Enum value maps for ConnectTwilioCallRequest_TwilioCallDirection.
var (
ConnectTwilioCallRequest_TwilioCallDirection_name = map[int32]string{
0: "TWILIO_CALL_DIRECTION_INBOUND",
1: "TWILIO_CALL_DIRECTION_OUTBOUND",
}
ConnectTwilioCallRequest_TwilioCallDirection_value = map[string]int32{
"TWILIO_CALL_DIRECTION_INBOUND": 0,
"TWILIO_CALL_DIRECTION_OUTBOUND": 1,
}
)
func (x ConnectTwilioCallRequest_TwilioCallDirection) Enum() *ConnectTwilioCallRequest_TwilioCallDirection {
p := new(ConnectTwilioCallRequest_TwilioCallDirection)
*p = x
return p
}
func (x ConnectTwilioCallRequest_TwilioCallDirection) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ConnectTwilioCallRequest_TwilioCallDirection) Descriptor() protoreflect.EnumDescriptor {
return file_livekit_connector_twilio_proto_enumTypes[0].Descriptor()
}
func (ConnectTwilioCallRequest_TwilioCallDirection) Type() protoreflect.EnumType {
return &file_livekit_connector_twilio_proto_enumTypes[0]
}
func (x ConnectTwilioCallRequest_TwilioCallDirection) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ConnectTwilioCallRequest_TwilioCallDirection.Descriptor instead.
func (ConnectTwilioCallRequest_TwilioCallDirection) EnumDescriptor() ([]byte, []int) {
return file_livekit_connector_twilio_proto_rawDescGZIP(), []int{0, 0}
}
type ConnectTwilioCallRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The Direction of the call
TwilioCallDirection ConnectTwilioCallRequest_TwilioCallDirection `protobuf:"varint,1,opt,name=twilio_call_direction,json=twilioCallDirection,proto3,enum=livekit.ConnectTwilioCallRequest_TwilioCallDirection" json:"twilio_call_direction,omitempty"`
// What LiveKit room should this call be connected to
RoomName string `protobuf:"bytes,2,opt,name=room_name,json=roomName,proto3" json:"room_name,omitempty"`
// Optional agents to dispatch the call to
Agents []*RoomAgentDispatch `protobuf:"bytes,3,rep,name=agents,proto3" json:"agents,omitempty"`
// Optional identity of the participant in LiveKit room
ParticipantIdentity string `protobuf:"bytes,4,opt,name=participant_identity,json=participantIdentity,proto3" json:"participant_identity,omitempty"`
// Optional name of the participant in LiveKit room
ParticipantName string `protobuf:"bytes,5,opt,name=participant_name,json=participantName,proto3" json:"participant_name,omitempty"`
// Optional user-defined metadata. Will be attached to a created Participant in the room.
ParticipantMetadata string `protobuf:"bytes,6,opt,name=participant_metadata,json=participantMetadata,proto3" json:"participant_metadata,omitempty"`
// Optional user-defined attributes. Will be attached to a created Participant in the room.
ParticipantAttributes map[string]string `protobuf:"bytes,7,rep,name=participant_attributes,json=participantAttributes,proto3" json:"participant_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
// Country where the call terminates as ISO 3166-1 alpha-2 (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). This will be used by the livekit infrastructure to route calls.
DestinationCountry string `protobuf:"bytes,8,opt,name=destination_country,json=destinationCountry,proto3" json:"destination_country,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ConnectTwilioCallRequest) Reset() {
*x = ConnectTwilioCallRequest{}
mi := &file_livekit_connector_twilio_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ConnectTwilioCallRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ConnectTwilioCallRequest) ProtoMessage() {}
func (x *ConnectTwilioCallRequest) ProtoReflect() protoreflect.Message {
mi := &file_livekit_connector_twilio_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ConnectTwilioCallRequest.ProtoReflect.Descriptor instead.
func (*ConnectTwilioCallRequest) Descriptor() ([]byte, []int) {
return file_livekit_connector_twilio_proto_rawDescGZIP(), []int{0}
}
func (x *ConnectTwilioCallRequest) GetTwilioCallDirection() ConnectTwilioCallRequest_TwilioCallDirection {
if x != nil {
return x.TwilioCallDirection
}
return ConnectTwilioCallRequest_TWILIO_CALL_DIRECTION_INBOUND
}
func (x *ConnectTwilioCallRequest) GetRoomName() string {
if x != nil {
return x.RoomName
}
return ""
}
func (x *ConnectTwilioCallRequest) GetAgents() []*RoomAgentDispatch {
if x != nil {
return x.Agents
}
return nil
}
func (x *ConnectTwilioCallRequest) GetParticipantIdentity() string {
if x != nil {
return x.ParticipantIdentity
}
return ""
}
func (x *ConnectTwilioCallRequest) GetParticipantName() string {
if x != nil {
return x.ParticipantName
}
return ""
}
func (x *ConnectTwilioCallRequest) GetParticipantMetadata() string {
if x != nil {
return x.ParticipantMetadata
}
return ""
}
func (x *ConnectTwilioCallRequest) GetParticipantAttributes() map[string]string {
if x != nil {
return x.ParticipantAttributes
}
return nil
}
func (x *ConnectTwilioCallRequest) GetDestinationCountry() string {
if x != nil {
return x.DestinationCountry
}
return ""
}
type ConnectTwilioCallResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The websocket URL which twilio media stream will connect to
ConnectUrl string `protobuf:"bytes,1,opt,name=connect_url,json=connectUrl,proto3" json:"connect_url,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ConnectTwilioCallResponse) Reset() {
*x = ConnectTwilioCallResponse{}
mi := &file_livekit_connector_twilio_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ConnectTwilioCallResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ConnectTwilioCallResponse) ProtoMessage() {}
func (x *ConnectTwilioCallResponse) ProtoReflect() protoreflect.Message {
mi := &file_livekit_connector_twilio_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ConnectTwilioCallResponse.ProtoReflect.Descriptor instead.
func (*ConnectTwilioCallResponse) Descriptor() ([]byte, []int) {
return file_livekit_connector_twilio_proto_rawDescGZIP(), []int{1}
}
func (x *ConnectTwilioCallResponse) GetConnectUrl() string {
if x != nil {
return x.ConnectUrl
}
return ""
}
var File_livekit_connector_twilio_proto protoreflect.FileDescriptor
const file_livekit_connector_twilio_proto_rawDesc = "" +
"\n" +
"\x1elivekit_connector_twilio.proto\x12\alivekit\x1a\x1clivekit_agent_dispatch.proto\"\xb5\x05\n" +
"\x18ConnectTwilioCallRequest\x12i\n" +
"\x15twilio_call_direction\x18\x01 \x01(\x0e25.livekit.ConnectTwilioCallRequest.TwilioCallDirectionR\x13twilioCallDirection\x12\x1b\n" +
"\troom_name\x18\x02 \x01(\tR\broomName\x122\n" +
"\x06agents\x18\x03 \x03(\v2\x1a.livekit.RoomAgentDispatchR\x06agents\x121\n" +
"\x14participant_identity\x18\x04 \x01(\tR\x13participantIdentity\x12)\n" +
"\x10participant_name\x18\x05 \x01(\tR\x0fparticipantName\x121\n" +
"\x14participant_metadata\x18\x06 \x01(\tR\x13participantMetadata\x12s\n" +
"\x16participant_attributes\x18\a \x03(\v2<.livekit.ConnectTwilioCallRequest.ParticipantAttributesEntryR\x15participantAttributes\x12/\n" +
"\x13destination_country\x18\b \x01(\tR\x12destinationCountry\x1aH\n" +
"\x1aParticipantAttributesEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\\\n" +
"\x13TwilioCallDirection\x12!\n" +
"\x1dTWILIO_CALL_DIRECTION_INBOUND\x10\x00\x12\"\n" +
"\x1eTWILIO_CALL_DIRECTION_OUTBOUND\x10\x01\"<\n" +
"\x19ConnectTwilioCallResponse\x12\x1f\n" +
"\vconnect_url\x18\x01 \x01(\tR\n" +
"connectUrlBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3"
var (
file_livekit_connector_twilio_proto_rawDescOnce sync.Once
file_livekit_connector_twilio_proto_rawDescData []byte
)
func file_livekit_connector_twilio_proto_rawDescGZIP() []byte {
file_livekit_connector_twilio_proto_rawDescOnce.Do(func() {
file_livekit_connector_twilio_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_livekit_connector_twilio_proto_rawDesc), len(file_livekit_connector_twilio_proto_rawDesc)))
})
return file_livekit_connector_twilio_proto_rawDescData
}
var file_livekit_connector_twilio_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_livekit_connector_twilio_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_livekit_connector_twilio_proto_goTypes = []any{
(ConnectTwilioCallRequest_TwilioCallDirection)(0), // 0: livekit.ConnectTwilioCallRequest.TwilioCallDirection
(*ConnectTwilioCallRequest)(nil), // 1: livekit.ConnectTwilioCallRequest
(*ConnectTwilioCallResponse)(nil), // 2: livekit.ConnectTwilioCallResponse
nil, // 3: livekit.ConnectTwilioCallRequest.ParticipantAttributesEntry
(*RoomAgentDispatch)(nil), // 4: livekit.RoomAgentDispatch
}
var file_livekit_connector_twilio_proto_depIdxs = []int32{
0, // 0: livekit.ConnectTwilioCallRequest.twilio_call_direction:type_name -> livekit.ConnectTwilioCallRequest.TwilioCallDirection
4, // 1: livekit.ConnectTwilioCallRequest.agents:type_name -> livekit.RoomAgentDispatch
3, // 2: livekit.ConnectTwilioCallRequest.participant_attributes:type_name -> livekit.ConnectTwilioCallRequest.ParticipantAttributesEntry
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_livekit_connector_twilio_proto_init() }
func file_livekit_connector_twilio_proto_init() {
if File_livekit_connector_twilio_proto != nil {
return
}
file_livekit_agent_dispatch_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_livekit_connector_twilio_proto_rawDesc), len(file_livekit_connector_twilio_proto_rawDesc)),
NumEnums: 1,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_livekit_connector_twilio_proto_goTypes,
DependencyIndexes: file_livekit_connector_twilio_proto_depIdxs,
EnumInfos: file_livekit_connector_twilio_proto_enumTypes,
MessageInfos: file_livekit_connector_twilio_proto_msgTypes,
}.Build()
File_livekit_connector_twilio_proto = out.File
file_livekit_connector_twilio_proto_goTypes = nil
file_livekit_connector_twilio_proto_depIdxs = nil
}
+3 -2
View File
@@ -52,12 +52,13 @@ func Proto() error {
"livekit_phone_number.proto",
"livekit_connector.proto",
"livekit_connector_whatsapp.proto",
"livekit_connector_twilio.proto",
}
agentProtoFiles := []string{
"agent/livekit_agent_session.proto",
}
protoFiles := []string{
"livekit_agent.proto",
"livekit_analytics.proto",
@@ -173,7 +174,7 @@ func Proto() error {
return err
}
}
fmt.Println("generating grpc protobuf")
args = append([]string{
"--go_out", ".",
+4 -1
View File
@@ -20,6 +20,7 @@ option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_connector_whatsapp.proto";
import "livekit_connector_twilio.proto";
service Connector {
rpc DialWhatsAppCall(DialWhatsAppCallRequest) returns (DialWhatsAppCallResponse);
@@ -29,4 +30,6 @@ service Connector {
rpc ConnectWhatsAppCall(ConnectWhatsAppCallRequest) returns (ConnectWhatsAppCallResponse);
rpc AcceptWhatsAppCall(AcceptWhatsAppCallRequest) returns (AcceptWhatsAppCallResponse);
}
rpc ConnectTwilioCall(ConnectTwilioCallRequest) returns (ConnectTwilioCallResponse);
}
+52
View File
@@ -0,0 +1,52 @@
// Copyright 2025 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_agent_dispatch.proto";
message ConnectTwilioCallRequest {
enum TwilioCallDirection {
TWILIO_CALL_DIRECTION_INBOUND = 0;
TWILIO_CALL_DIRECTION_OUTBOUND = 1;
}
// The Direction of the call
TwilioCallDirection twilio_call_direction = 1;
// What LiveKit room should this call be connected to
string room_name = 2;
// Optional agents to dispatch the call to
repeated RoomAgentDispatch agents = 3;
// Optional identity of the participant in LiveKit room
string participant_identity= 4;
// Optional name of the participant in LiveKit room
string participant_name = 5;
// Optional user-defined metadata. Will be attached to a created Participant in the room.
string participant_metadata = 6;
// Optional user-defined attributes. Will be attached to a created Participant in the room.
map<string, string> participant_attributes = 7;
// Country where the call terminates as ISO 3166-1 alpha-2 (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). This will be used by the livekit infrastructure to route calls.
string destination_country = 8;
}
message ConnectTwilioCallResponse {
// The websocket URL which twilio media stream will connect to
string connect_url = 1;
}
+11 -1
View File
@@ -20,6 +20,7 @@ option go_package = "github.com/livekit/protocol/rpc";
import "options.proto";
import "livekit_connector_whatsapp.proto";
import "livekit_connector_twilio.proto";
import "rpc/common.proto";
service ConnectorInternal {
@@ -30,6 +31,10 @@ service ConnectorInternal {
rpc AcceptWhatsAppCall(InternalAcceptWhatsAppCallRequest) returns (livekit.AcceptWhatsAppCallResponse) {
option (psrpc.options).topics = true;
};
rpc ConnectTwilioCall(InternalConnectTwilioCallRequest) returns (livekit.ConnectTwilioCallResponse) {
option (psrpc.options).topics = true;
};
}
service ConnectorHandler {
@@ -62,4 +67,9 @@ message InternalDialWhatsAppCallRequest {
message InternalAcceptWhatsAppCallRequest {
livekit.AcceptWhatsAppCallRequest request = 1;
InternalRoomJoinInfo room_join_info = 2;
}
}
message InternalConnectTwilioCallRequest {
livekit.ConnectTwilioCallRequest request = 1;
InternalRoomJoinInfo room_join_info = 2;
}
+94 -31
View File
@@ -141,20 +141,76 @@ func (x *InternalAcceptWhatsAppCallRequest) GetRoomJoinInfo() *InternalRoomJoinI
return nil
}
type InternalConnectTwilioCallRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Request *livekit.ConnectTwilioCallRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"`
RoomJoinInfo *InternalRoomJoinInfo `protobuf:"bytes,2,opt,name=room_join_info,json=roomJoinInfo,proto3" json:"room_join_info,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *InternalConnectTwilioCallRequest) Reset() {
*x = InternalConnectTwilioCallRequest{}
mi := &file_rpc_connector_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *InternalConnectTwilioCallRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InternalConnectTwilioCallRequest) ProtoMessage() {}
func (x *InternalConnectTwilioCallRequest) ProtoReflect() protoreflect.Message {
mi := &file_rpc_connector_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use InternalConnectTwilioCallRequest.ProtoReflect.Descriptor instead.
func (*InternalConnectTwilioCallRequest) Descriptor() ([]byte, []int) {
return file_rpc_connector_proto_rawDescGZIP(), []int{2}
}
func (x *InternalConnectTwilioCallRequest) GetRequest() *livekit.ConnectTwilioCallRequest {
if x != nil {
return x.Request
}
return nil
}
func (x *InternalConnectTwilioCallRequest) GetRoomJoinInfo() *InternalRoomJoinInfo {
if x != nil {
return x.RoomJoinInfo
}
return nil
}
var File_rpc_connector_proto protoreflect.FileDescriptor
const file_rpc_connector_proto_rawDesc = "" +
"\n" +
"\x13rpc/connector.proto\x12\x03rpc\x1a\roptions.proto\x1a livekit_connector_whatsapp.proto\x1a\x10rpc/common.proto\"\x9e\x01\n" +
"\x13rpc/connector.proto\x12\x03rpc\x1a\roptions.proto\x1a livekit_connector_whatsapp.proto\x1a\x1elivekit_connector_twilio.proto\x1a\x10rpc/common.proto\"\x9e\x01\n" +
"\x1fInternalDialWhatsAppCallRequest\x12:\n" +
"\arequest\x18\x01 \x01(\v2 .livekit.DialWhatsAppCallRequestR\arequest\x12?\n" +
"\x0eroom_join_info\x18\x02 \x01(\v2\x19.rpc.InternalRoomJoinInfoR\froomJoinInfo\"\xa2\x01\n" +
"!InternalAcceptWhatsAppCallRequest\x12<\n" +
"\arequest\x18\x01 \x01(\v2\".livekit.AcceptWhatsAppCallRequestR\arequest\x12?\n" +
"\x0eroom_join_info\x18\x02 \x01(\v2\x19.rpc.InternalRoomJoinInfoR\froomJoinInfo2\xe3\x01\n" +
"\x0eroom_join_info\x18\x02 \x01(\v2\x19.rpc.InternalRoomJoinInfoR\froomJoinInfo\"\xa0\x01\n" +
" InternalConnectTwilioCallRequest\x12;\n" +
"\arequest\x18\x01 \x01(\v2!.livekit.ConnectTwilioCallRequestR\arequest\x12?\n" +
"\x0eroom_join_info\x18\x02 \x01(\v2\x19.rpc.InternalRoomJoinInfoR\froomJoinInfo2\xcb\x02\n" +
"\x11ConnectorInternal\x12c\n" +
"\x10DialWhatsAppCall\x12$.rpc.InternalDialWhatsAppCallRequest\x1a!.livekit.DialWhatsAppCallResponse\"\x06\xb2\x89\x01\x02\x10\x01\x12i\n" +
"\x12AcceptWhatsAppCall\x12&.rpc.InternalAcceptWhatsAppCallRequest\x1a#.livekit.AcceptWhatsAppCallResponse\"\x06\xb2\x89\x01\x02\x10\x012\x98\x02\n" +
"\x12AcceptWhatsAppCall\x12&.rpc.InternalAcceptWhatsAppCallRequest\x1a#.livekit.AcceptWhatsAppCallResponse\"\x06\xb2\x89\x01\x02\x10\x01\x12f\n" +
"\x11ConnectTwilioCall\x12%.rpc.InternalConnectTwilioCallRequest\x1a\".livekit.ConnectTwilioCallResponse\"\x06\xb2\x89\x01\x02\x10\x012\x98\x02\n" +
"\x10ConnectorHandler\x12|\n" +
"\x13ConnectWhatsAppCall\x12#.livekit.ConnectWhatsAppCallRequest\x1a$.livekit.ConnectWhatsAppCallResponse\"\x1a\xb2\x89\x01\x16\x10\x01\x1a\x12\x12\x10whatsapp_call_id\x12\x85\x01\n" +
"\x16DisconnectWhatsAppCall\x12&.livekit.DisconnectWhatsAppCallRequest\x1a'.livekit.DisconnectWhatsAppCallResponse\"\x1a\xb2\x89\x01\x16\x10\x01\x1a\x12\x12\x10whatsapp_call_idB!Z\x1fgithub.com/livekit/protocol/rpcb\x06proto3"
@@ -171,38 +227,45 @@ func file_rpc_connector_proto_rawDescGZIP() []byte {
return file_rpc_connector_proto_rawDescData
}
var file_rpc_connector_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_rpc_connector_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_rpc_connector_proto_goTypes = []any{
(*InternalDialWhatsAppCallRequest)(nil), // 0: rpc.InternalDialWhatsAppCallRequest
(*InternalAcceptWhatsAppCallRequest)(nil), // 1: rpc.InternalAcceptWhatsAppCallRequest
(*livekit.DialWhatsAppCallRequest)(nil), // 2: livekit.DialWhatsAppCallRequest
(*InternalRoomJoinInfo)(nil), // 3: rpc.InternalRoomJoinInfo
(*livekit.AcceptWhatsAppCallRequest)(nil), // 4: livekit.AcceptWhatsAppCallRequest
(*livekit.ConnectWhatsAppCallRequest)(nil), // 5: livekit.ConnectWhatsAppCallRequest
(*livekit.DisconnectWhatsAppCallRequest)(nil), // 6: livekit.DisconnectWhatsAppCallRequest
(*livekit.DialWhatsAppCallResponse)(nil), // 7: livekit.DialWhatsAppCallResponse
(*livekit.AcceptWhatsAppCallResponse)(nil), // 8: livekit.AcceptWhatsAppCallResponse
(*livekit.ConnectWhatsAppCallResponse)(nil), // 9: livekit.ConnectWhatsAppCallResponse
(*livekit.DisconnectWhatsAppCallResponse)(nil), // 10: livekit.DisconnectWhatsAppCallResponse
(*InternalConnectTwilioCallRequest)(nil), // 2: rpc.InternalConnectTwilioCallRequest
(*livekit.DialWhatsAppCallRequest)(nil), // 3: livekit.DialWhatsAppCallRequest
(*InternalRoomJoinInfo)(nil), // 4: rpc.InternalRoomJoinInfo
(*livekit.AcceptWhatsAppCallRequest)(nil), // 5: livekit.AcceptWhatsAppCallRequest
(*livekit.ConnectTwilioCallRequest)(nil), // 6: livekit.ConnectTwilioCallRequest
(*livekit.ConnectWhatsAppCallRequest)(nil), // 7: livekit.ConnectWhatsAppCallRequest
(*livekit.DisconnectWhatsAppCallRequest)(nil), // 8: livekit.DisconnectWhatsAppCallRequest
(*livekit.DialWhatsAppCallResponse)(nil), // 9: livekit.DialWhatsAppCallResponse
(*livekit.AcceptWhatsAppCallResponse)(nil), // 10: livekit.AcceptWhatsAppCallResponse
(*livekit.ConnectTwilioCallResponse)(nil), // 11: livekit.ConnectTwilioCallResponse
(*livekit.ConnectWhatsAppCallResponse)(nil), // 12: livekit.ConnectWhatsAppCallResponse
(*livekit.DisconnectWhatsAppCallResponse)(nil), // 13: livekit.DisconnectWhatsAppCallResponse
}
var file_rpc_connector_proto_depIdxs = []int32{
2, // 0: rpc.InternalDialWhatsAppCallRequest.request:type_name -> livekit.DialWhatsAppCallRequest
3, // 1: rpc.InternalDialWhatsAppCallRequest.room_join_info:type_name -> rpc.InternalRoomJoinInfo
4, // 2: rpc.InternalAcceptWhatsAppCallRequest.request:type_name -> livekit.AcceptWhatsAppCallRequest
3, // 3: rpc.InternalAcceptWhatsAppCallRequest.room_join_info:type_name -> rpc.InternalRoomJoinInfo
0, // 4: rpc.ConnectorInternal.DialWhatsAppCall:input_type -> rpc.InternalDialWhatsAppCallRequest
1, // 5: rpc.ConnectorInternal.AcceptWhatsAppCall:input_type -> rpc.InternalAcceptWhatsAppCallRequest
5, // 6: rpc.ConnectorHandler.ConnectWhatsAppCall:input_type -> livekit.ConnectWhatsAppCallRequest
6, // 7: rpc.ConnectorHandler.DisconnectWhatsAppCall:input_type -> livekit.DisconnectWhatsAppCallRequest
7, // 8: rpc.ConnectorInternal.DialWhatsAppCall:output_type -> livekit.DialWhatsAppCallResponse
8, // 9: rpc.ConnectorInternal.AcceptWhatsAppCall:output_type -> livekit.AcceptWhatsAppCallResponse
9, // 10: rpc.ConnectorHandler.ConnectWhatsAppCall:output_type -> livekit.ConnectWhatsAppCallResponse
10, // 11: rpc.ConnectorHandler.DisconnectWhatsAppCall:output_type -> livekit.DisconnectWhatsAppCallResponse
8, // [8:12] is the sub-list for method output_type
4, // [4:8] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
3, // 0: rpc.InternalDialWhatsAppCallRequest.request:type_name -> livekit.DialWhatsAppCallRequest
4, // 1: rpc.InternalDialWhatsAppCallRequest.room_join_info:type_name -> rpc.InternalRoomJoinInfo
5, // 2: rpc.InternalAcceptWhatsAppCallRequest.request:type_name -> livekit.AcceptWhatsAppCallRequest
4, // 3: rpc.InternalAcceptWhatsAppCallRequest.room_join_info:type_name -> rpc.InternalRoomJoinInfo
6, // 4: rpc.InternalConnectTwilioCallRequest.request:type_name -> livekit.ConnectTwilioCallRequest
4, // 5: rpc.InternalConnectTwilioCallRequest.room_join_info:type_name -> rpc.InternalRoomJoinInfo
0, // 6: rpc.ConnectorInternal.DialWhatsAppCall:input_type -> rpc.InternalDialWhatsAppCallRequest
1, // 7: rpc.ConnectorInternal.AcceptWhatsAppCall:input_type -> rpc.InternalAcceptWhatsAppCallRequest
2, // 8: rpc.ConnectorInternal.ConnectTwilioCall:input_type -> rpc.InternalConnectTwilioCallRequest
7, // 9: rpc.ConnectorHandler.ConnectWhatsAppCall:input_type -> livekit.ConnectWhatsAppCallRequest
8, // 10: rpc.ConnectorHandler.DisconnectWhatsAppCall:input_type -> livekit.DisconnectWhatsAppCallRequest
9, // 11: rpc.ConnectorInternal.DialWhatsAppCall:output_type -> livekit.DialWhatsAppCallResponse
10, // 12: rpc.ConnectorInternal.AcceptWhatsAppCall:output_type -> livekit.AcceptWhatsAppCallResponse
11, // 13: rpc.ConnectorInternal.ConnectTwilioCall:output_type -> livekit.ConnectTwilioCallResponse
12, // 14: rpc.ConnectorHandler.ConnectWhatsAppCall:output_type -> livekit.ConnectWhatsAppCallResponse
13, // 15: rpc.ConnectorHandler.DisconnectWhatsAppCall:output_type -> livekit.DisconnectWhatsAppCallResponse
11, // [11:16] is the sub-list for method output_type
6, // [6:11] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_rpc_connector_proto_init() }
@@ -217,7 +280,7 @@ func file_rpc_connector_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_rpc_connector_proto_rawDesc), len(file_rpc_connector_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumMessages: 3,
NumExtensions: 0,
NumServices: 2,
},
+54 -26
View File
@@ -14,6 +14,7 @@ import (
"github.com/livekit/psrpc/version"
)
import livekit10 "github.com/livekit/protocol/livekit"
import livekit11 "github.com/livekit/protocol/livekit"
var _ = version.PsrpcVersion_0_7
@@ -26,6 +27,8 @@ type ConnectorInternalClient interface {
AcceptWhatsAppCall(ctx context.Context, topic string, req *InternalAcceptWhatsAppCallRequest, opts ...psrpc.RequestOption) (*livekit10.AcceptWhatsAppCallResponse, error)
ConnectTwilioCall(ctx context.Context, topic string, req *InternalConnectTwilioCallRequest, opts ...psrpc.RequestOption) (*livekit11.ConnectTwilioCallResponse, error)
// Close immediately, without waiting for pending RPCs
Close()
}
@@ -38,6 +41,8 @@ type ConnectorInternalServerImpl interface {
DialWhatsAppCall(context.Context, *InternalDialWhatsAppCallRequest) (*livekit10.DialWhatsAppCallResponse, error)
AcceptWhatsAppCall(context.Context, *InternalAcceptWhatsAppCallRequest) (*livekit10.AcceptWhatsAppCallResponse, error)
ConnectTwilioCall(context.Context, *InternalConnectTwilioCallRequest) (*livekit11.ConnectTwilioCallResponse, error)
}
// ==================================
@@ -49,6 +54,8 @@ type ConnectorInternalServer interface {
DeregisterDialWhatsAppCallTopic(topic string)
RegisterAcceptWhatsAppCallTopic(topic string) error
DeregisterAcceptWhatsAppCallTopic(topic string)
RegisterConnectTwilioCallTopic(topic string) error
DeregisterConnectTwilioCallTopic(topic string)
// Close and wait for pending RPCs to complete
Shutdown()
@@ -74,6 +81,7 @@ func NewConnectorInternalClient(bus psrpc.MessageBus, opts ...psrpc.ClientOption
sd.RegisterMethod("DialWhatsAppCall", false, false, true, true)
sd.RegisterMethod("AcceptWhatsAppCall", false, false, true, true)
sd.RegisterMethod("ConnectTwilioCall", false, false, true, true)
rpcClient, err := client.NewRPCClient(sd, bus, opts...)
if err != nil {
@@ -93,6 +101,10 @@ func (c *connectorInternalClient) AcceptWhatsAppCall(ctx context.Context, topic
return client.RequestSingle[*livekit10.AcceptWhatsAppCallResponse](ctx, c.client, "AcceptWhatsAppCall", []string{topic}, req, opts...)
}
func (c *connectorInternalClient) ConnectTwilioCall(ctx context.Context, topic string, req *InternalConnectTwilioCallRequest, opts ...psrpc.RequestOption) (*livekit11.ConnectTwilioCallResponse, error) {
return client.RequestSingle[*livekit11.ConnectTwilioCallResponse](ctx, c.client, "ConnectTwilioCall", []string{topic}, req, opts...)
}
func (s *connectorInternalClient) Close() {
s.client.Close()
}
@@ -118,6 +130,7 @@ func NewConnectorInternalServer(svc ConnectorInternalServerImpl, bus psrpc.Messa
sd.RegisterMethod("DialWhatsAppCall", false, false, true, true)
sd.RegisterMethod("AcceptWhatsAppCall", false, false, true, true)
sd.RegisterMethod("ConnectTwilioCall", false, false, true, true)
return &connectorInternalServer{
svc: svc,
rpc: s,
@@ -140,6 +153,14 @@ func (s *connectorInternalServer) DeregisterAcceptWhatsAppCallTopic(topic string
s.rpc.DeregisterHandler("AcceptWhatsAppCall", []string{topic})
}
func (s *connectorInternalServer) RegisterConnectTwilioCallTopic(topic string) error {
return server.RegisterHandler(s.rpc, "ConnectTwilioCall", []string{topic}, s.svc.ConnectTwilioCall, nil)
}
func (s *connectorInternalServer) DeregisterConnectTwilioCallTopic(topic string) {
s.rpc.DeregisterHandler("ConnectTwilioCall", []string{topic})
}
func (s *connectorInternalServer) Shutdown() {
s.rpc.Close(false)
}
@@ -162,6 +183,10 @@ func (UnimplementedConnectorInternalServer) AcceptWhatsAppCall(context.Context,
return nil, psrpc.ErrUnimplemented
}
func (UnimplementedConnectorInternalServer) ConnectTwilioCall(context.Context, *InternalConnectTwilioCallRequest) (*livekit11.ConnectTwilioCallResponse, error) {
return nil, psrpc.ErrUnimplemented
}
// =================================
// ConnectorHandler Client Interface
// =================================
@@ -308,30 +333,33 @@ func (UnimplementedConnectorHandlerServer) DisconnectWhatsAppCall(context.Contex
}
var psrpcFileDescriptor12 = []byte{
// 391 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x3f, 0x6f, 0xda, 0x40,
0x18, 0xc6, 0x75, 0x54, 0xa2, 0xd2, 0xf5, 0x8f, 0xdc, 0x43, 0x42, 0xd4, 0x0b, 0xe0, 0x22, 0xda,
0xc9, 0x96, 0xe8, 0x56, 0x55, 0xaa, 0x28, 0x0c, 0xa5, 0xa3, 0x97, 0x48, 0x59, 0x2c, 0x73, 0x1c,
0xe1, 0x92, 0xf3, 0xbd, 0x97, 0xf3, 0x91, 0x2c, 0x59, 0x33, 0xf0, 0x0d, 0x32, 0x65, 0xc8, 0x47,
0xe0, 0x2b, 0xe5, 0x8b, 0x44, 0xc1, 0x3e, 0x82, 0x89, 0x0d, 0x4b, 0x36, 0xdf, 0xeb, 0xe7, 0x7d,
0x9e, 0xdf, 0x3d, 0xb2, 0x71, 0x43, 0x2b, 0x1a, 0x50, 0x90, 0x92, 0x51, 0x03, 0xda, 0x57, 0x1a,
0x0c, 0x90, 0x77, 0x5a, 0x51, 0xf7, 0x13, 0x28, 0xc3, 0x41, 0xa6, 0xd9, 0xcc, 0xed, 0x08, 0x7e,
0xc5, 0x2e, 0xb8, 0x89, 0xb6, 0xe2, 0xe8, 0x7a, 0x11, 0x9b, 0x34, 0x56, 0x2a, 0x57, 0x38, 0x99,
0x55, 0x92, 0x80, 0xcc, 0x26, 0xde, 0x3d, 0xc2, 0xed, 0x89, 0x34, 0x4c, 0xcb, 0x58, 0x8c, 0x79,
0x2c, 0x4e, 0x9e, 0x17, 0x86, 0x4a, 0x8d, 0x62, 0x21, 0x42, 0x76, 0xb9, 0x64, 0xa9, 0x21, 0xbf,
0xf0, 0x7b, 0x9d, 0x3d, 0xb6, 0x50, 0x07, 0xfd, 0xf8, 0x30, 0xe8, 0xf8, 0x79, 0x92, 0x5f, 0xb1,
0x12, 0xda, 0x05, 0xf2, 0x07, 0x7f, 0xd6, 0x00, 0x49, 0x74, 0x0e, 0x5c, 0x46, 0x5c, 0xce, 0xa1,
0x55, 0xdb, 0x58, 0x7c, 0xf5, 0xb5, 0xa2, 0xbe, 0x4d, 0x0e, 0x01, 0x92, 0xff, 0xc0, 0xe5, 0x44,
0xce, 0x21, 0xfc, 0xa8, 0x77, 0x4e, 0xde, 0x03, 0xc2, 0x5d, 0x2b, 0x1b, 0x52, 0xca, 0x94, 0x29,
0x43, 0xfc, 0xbd, 0x8f, 0xe8, 0x6d, 0x11, 0x2b, 0x97, 0xde, 0x0e, 0x72, 0xf0, 0x88, 0xf0, 0x97,
0x91, 0x2d, 0xdd, 0xea, 0x09, 0xc5, 0xce, 0x7e, 0x3f, 0xa4, 0x57, 0xb0, 0xac, 0xa8, 0xcf, 0xed,
0x1e, 0x28, 0x38, 0x55, 0x20, 0x53, 0xe6, 0xd5, 0xd7, 0x2b, 0x54, 0x73, 0x10, 0xe1, 0x98, 0xbc,
0xbe, 0x21, 0xe9, 0x17, 0x62, 0x2a, 0x2b, 0x70, 0xbf, 0x1d, 0xac, 0xa9, 0x18, 0x35, 0xb8, 0xab,
0x61, 0x67, 0x7b, 0xcb, 0x7f, 0xb1, 0x9c, 0x09, 0xa6, 0xc9, 0x0d, 0x6e, 0xe4, 0xb3, 0x02, 0xc0,
0x8b, 0x71, 0xc9, 0x5b, 0x9b, 0xde, 0x3b, 0x2c, 0xca, 0xe3, 0xdd, 0xf5, 0x0a, 0x35, 0x1d, 0xe4,
0x12, 0xe2, 0xd8, 0xcf, 0x39, 0xa2, 0xb1, 0x10, 0x11, 0x9f, 0x91, 0x5b, 0x84, 0x9b, 0x63, 0x9e,
0xd2, 0x12, 0x82, 0xfe, 0x4e, 0x87, 0x65, 0x02, 0x0b, 0xf1, 0xfd, 0xa8, 0xee, 0x38, 0xc7, 0xdf,
0xee, 0x69, 0xfb, 0x8c, 0x9b, 0xc5, 0x72, 0xea, 0x53, 0x48, 0x82, 0xdc, 0x30, 0xd8, 0xfc, 0x62,
0x14, 0x44, 0xa0, 0x15, 0x9d, 0xd6, 0x37, 0xa7, 0x9f, 0x4f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5c,
0xdc, 0xdc, 0x82, 0xcf, 0x03, 0x00, 0x00,
// 444 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4f, 0x8f, 0x94, 0x30,
0x18, 0xc6, 0x53, 0x4c, 0xd6, 0xa4, 0xfe, 0x09, 0x76, 0x93, 0xcd, 0xca, 0xc1, 0x05, 0x76, 0x5d,
0x3d, 0x41, 0x32, 0xde, 0xd4, 0xc4, 0xac, 0xb3, 0x07, 0xd7, 0x23, 0x31, 0x31, 0xf1, 0x42, 0xd8,
0x6e, 0xc7, 0xa9, 0x96, 0xbe, 0xb5, 0x74, 0x9c, 0x8b, 0x57, 0x0f, 0xf3, 0x0d, 0x3c, 0x19, 0xe3,
0x47, 0x98, 0xaf, 0xe1, 0x97, 0x32, 0x02, 0xc5, 0x81, 0x01, 0xe6, 0x32, 0x37, 0x5a, 0x9e, 0xf7,
0x7d, 0x7e, 0x7d, 0x9f, 0x02, 0x3e, 0xd4, 0x8a, 0xc6, 0x14, 0xa4, 0x64, 0xd4, 0x80, 0x8e, 0x94,
0x06, 0x03, 0xe4, 0x96, 0x56, 0xd4, 0xbb, 0x07, 0xca, 0x70, 0x90, 0x45, 0xb5, 0xe7, 0xf9, 0x82,
0x7f, 0x65, 0x9f, 0xb9, 0x49, 0x1b, 0x71, 0xba, 0x9c, 0x67, 0xa6, 0xc8, 0x94, 0xaa, 0x15, 0x8f,
0xb6, 0x15, 0x66, 0xc9, 0x05, 0x87, 0xfa, 0xbd, 0x5b, 0x59, 0xe5, 0x39, 0xc8, 0x6a, 0x27, 0xfc,
0x89, 0xf0, 0xc9, 0x95, 0x34, 0x4c, 0xcb, 0x4c, 0x5c, 0xf2, 0x4c, 0xbc, 0xff, 0xd7, 0xf0, 0x42,
0xa9, 0x69, 0x26, 0x44, 0xc2, 0xbe, 0x2c, 0x58, 0x61, 0xc8, 0x73, 0x7c, 0x5b, 0x57, 0x8f, 0xc7,
0xc8, 0x47, 0x4f, 0xef, 0x4c, 0xfc, 0xa8, 0xf6, 0x89, 0x06, 0x4a, 0x12, 0x5b, 0x40, 0x5e, 0xe1,
0xfb, 0x1a, 0x20, 0x4f, 0x3f, 0x01, 0x97, 0x29, 0x97, 0x33, 0x38, 0x76, 0xca, 0x16, 0x0f, 0x23,
0xad, 0x68, 0x64, 0x9d, 0x13, 0x80, 0xfc, 0x2d, 0x70, 0x79, 0x25, 0x67, 0x90, 0xdc, 0xd5, 0x1b,
0xab, 0xf0, 0x37, 0xc2, 0x81, 0x95, 0x5d, 0x50, 0xca, 0x94, 0xe9, 0x43, 0x7c, 0xd9, 0x45, 0x0c,
0x1b, 0xc4, 0xc1, 0xa2, 0x3d, 0x42, 0xfe, 0x42, 0xd8, 0xb7, 0xb2, 0x69, 0x35, 0xfa, 0x77, 0xe5,
0xdc, 0x37, 0x19, 0x5f, 0x74, 0x19, 0x83, 0x86, 0x71, 0xa8, 0x66, 0x7f, 0x88, 0x93, 0x3f, 0x0e,
0x7e, 0x30, 0xb5, 0xb7, 0xc2, 0xea, 0x09, 0xc5, 0x6e, 0x37, 0x42, 0x72, 0xd6, 0x6a, 0x39, 0x90,
0xb0, 0x17, 0x8c, 0xdc, 0x81, 0x42, 0x81, 0x2c, 0x58, 0x78, 0xb0, 0x5e, 0x21, 0xc7, 0x45, 0x84,
0x63, 0xb2, 0x1d, 0x02, 0x39, 0x6f, 0xd9, 0x0c, 0xa6, 0xe4, 0x9d, 0x8e, 0x26, 0xd9, 0xb1, 0x9a,
0x35, 0x87, 0xfc, 0x3f, 0x4b, 0xf2, 0xb8, 0xe5, 0x34, 0x34, 0x6b, 0x2f, 0x1c, 0x8b, 0xa3, 0xed,
0x33, 0xf9, 0xe1, 0x60, 0xb7, 0x99, 0xe6, 0x9b, 0x4c, 0xde, 0x08, 0xa6, 0xc9, 0x37, 0x7c, 0x58,
0xef, 0xb5, 0x0e, 0x7a, 0xda, 0xed, 0xdb, 0x77, 0xca, 0xb3, 0x71, 0x51, 0x6d, 0xef, 0xad, 0x57,
0xe8, 0xc8, 0x45, 0x1e, 0x21, 0xae, 0xfd, 0xf2, 0x53, 0x9a, 0x09, 0x91, 0xf2, 0x1b, 0xf2, 0x1d,
0xe1, 0xa3, 0x4b, 0x5e, 0xd0, 0x1e, 0x82, 0xf3, 0x8d, 0xac, 0xfa, 0x04, 0x16, 0xe2, 0xc9, 0x4e,
0xdd, 0x6e, 0x8e, 0xd7, 0xc1, 0x87, 0x93, 0x8f, 0xdc, 0xcc, 0x17, 0xd7, 0x11, 0x85, 0x3c, 0xae,
0x1b, 0xc6, 0xe5, 0xdf, 0x86, 0x82, 0x88, 0xb5, 0xa2, 0xd7, 0x07, 0xe5, 0xea, 0xd9, 0xdf, 0x00,
0x00, 0x00, 0xff, 0xff, 0x7b, 0xb1, 0x7d, 0x3e, 0xfa, 0x04, 0x00, 0x00,
}