-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add chat API support #278
Add chat API support #278
Changes from all commits
adf8da0
e83ea78
4c84ea9
76749ef
23bf1d7
52a57f2
b71846b
3183086
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@livekit/rtc-node": patch | ||
--- | ||
|
||
Add chat API support |
+4 −1 | .gitignore | |
+55 −2 | Cargo.lock | |
+2 −2 | examples/play_from_disk/change-sophie.wav | |
+6 −0 | livekit-api/src/services/sip.rs | |
+1 −1 | livekit-ffi/Cargo.toml | |
+6 −0 | livekit-ffi/protocol/ffi.proto | |
+37 −0 | livekit-ffi/protocol/room.proto | |
+27 −2 | livekit-ffi/src/conversion/room.rs | |
+80 −4 | livekit-ffi/src/livekit.proto.rs | |
+0 −3 | livekit-ffi/src/server/mod.rs | |
+28 −0 | livekit-ffi/src/server/requests.rs | |
+73 −1 | livekit-ffi/src/server/room.rs | |
+5 −1 | livekit-protocol/Cargo.toml | |
+1 −1 | livekit-protocol/protocol | |
+366 −4 | livekit-protocol/src/livekit.rs | |
+6,004 −3,293 | livekit-protocol/src/livekit.serde.rs | |
+1 −0 | livekit/Cargo.toml | |
+29 −1 | livekit/src/proto.rs | |
+32 −0 | livekit/src/room/mod.rs | |
+56 −2 | livekit/src/room/participant/local_participant.rs | |
+9 −1 | livekit/src/rtc_engine/mod.rs | |
+15 −2 | livekit/src/rtc_engine/rtc_session.rs | |
+44 −19 | soxr-sys/src/lib.rs | |
+0 −3 | webrtc-sys/build.rs |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,8 @@ | |
// SPDX-License-Identifier: Apache-2.0 | ||
import { FfiClient, FfiHandle } from './ffi_client.js'; | ||
import type { OwnedParticipant, ParticipantInfo, ParticipantKind } from './proto/participant_pb.js'; | ||
import type { | ||
import { | ||
ChatMessage as ChatMessageModel, | ||
PublishDataCallback, | ||
PublishDataResponse, | ||
PublishSipDtmfCallback, | ||
|
@@ -12,6 +13,8 @@ import type { | |
PublishTrackResponse, | ||
PublishTranscriptionCallback, | ||
PublishTranscriptionResponse, | ||
SendChatMessageCallback, | ||
SendChatMessageResponse, | ||
SetLocalAttributesCallback, | ||
SetLocalAttributesResponse, | ||
SetLocalMetadataCallback, | ||
|
@@ -23,11 +26,13 @@ import type { | |
UnpublishTrackResponse, | ||
} from './proto/room_pb.js'; | ||
import { | ||
EditChatMessageRequest, | ||
TranscriptionSegment as ProtoTranscriptionSegment, | ||
PublishDataRequest, | ||
PublishSipDtmfRequest, | ||
PublishTrackRequest, | ||
PublishTranscriptionRequest, | ||
SendChatMessageRequest, | ||
SetLocalAttributesRequest, | ||
SetLocalMetadataRequest, | ||
SetLocalNameRequest, | ||
|
@@ -37,6 +42,7 @@ import type { LocalTrack } from './track.js'; | |
import type { RemoteTrackPublication, TrackPublication } from './track_publication.js'; | ||
import { LocalTrackPublication } from './track_publication.js'; | ||
import type { Transcription } from './transcription.js'; | ||
import { ChatMessage } from './types.js'; | ||
|
||
export abstract class Participant { | ||
/** @internal */ | ||
|
@@ -185,6 +191,77 @@ export class LocalParticipant extends Participant { | |
}); | ||
} | ||
|
||
/** | ||
* | ||
*/ | ||
async sendChatMessage( | ||
text: string, | ||
destinationIdentities?: Array<string>, | ||
senderIdentity?: string, | ||
): Promise<ChatMessage> { | ||
const req = new SendChatMessageRequest({ | ||
localParticipantHandle: this.ffi_handle.handle, | ||
message: text, | ||
destinationIdentities, | ||
senderIdentity, | ||
}); | ||
|
||
const res = FfiClient.instance.request<SendChatMessageResponse>({ | ||
message: { case: 'sendChatMessage', value: req }, | ||
}); | ||
|
||
const cb = await FfiClient.instance.waitFor<SendChatMessageCallback>((ev) => { | ||
return ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId; | ||
}); | ||
|
||
if (cb.error) { | ||
throw new Error(cb.error); | ||
} | ||
const { id, timestamp, editTimestamp, message } = cb.chatMessage; | ||
return { id, timestamp: Number(timestamp), editTimestamp: Number(editTimestamp), message }; | ||
} | ||
|
||
/** | ||
* Sends a chat message to participants in the room | ||
* | ||
* @param text - The text content of the chat message. | ||
* @param destinationIdentities - An optional array of recipient identities to whom the message will be sent. If omitted, the message is broadcast to all participants. | ||
* @param senderIdentity - An optional identity of the sender. If omitted, the default sender identity is used. | ||
* | ||
*/ | ||
async editChatMessage( | ||
editText: string, | ||
originalMessage: ChatMessage, | ||
destinationIdentities?: Array<string>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems kinda weird that you can give different values here than to the original. this might also cause participants who join a call after an initial message is sent but before an edit to receive the edit and maybe have strange behavior? not sure if there's an easy way to solve though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, had the same feeling and opted to omit destinationIdentites on client-sdk-js altogether for now because of that |
||
senderIdentity?: string, | ||
): Promise<ChatMessage> { | ||
const req = new EditChatMessageRequest({ | ||
localParticipantHandle: this.ffi_handle.handle, | ||
editText, | ||
originalMessage: new ChatMessageModel({ | ||
...originalMessage, | ||
timestamp: BigInt(originalMessage.timestamp), | ||
editTimestamp: BigInt(originalMessage.editTimestamp), | ||
}), | ||
destinationIdentities, | ||
senderIdentity, | ||
}); | ||
|
||
const res = FfiClient.instance.request<SendChatMessageResponse>({ | ||
message: { case: 'editChatMessage', value: req }, | ||
}); | ||
|
||
const cb = await FfiClient.instance.waitFor<SendChatMessageCallback>((ev) => { | ||
return ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId; | ||
}); | ||
|
||
if (cb.error) { | ||
throw new Error(cb.error); | ||
} | ||
const { id, timestamp, editTimestamp, message } = cb.chatMessage; | ||
return { id, timestamp: Number(timestamp), editTimestamp: Number(editTimestamp), message }; | ||
} | ||
|
||
async updateName(name: string) { | ||
const req = new SetLocalNameRequest({ | ||
localParticipantHandle: this.ffi_handle.handle, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this default to all? Worth adding docstrings