mirror of
https://github.com/chatmail/core.git
synced 2026-05-07 08:56:30 +03:00
api(jsonrpc): add state attribute to call info
Existing boolean attributes removed.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use deltachat::calls::{call_state, CallState};
|
||||||
use deltachat::context::Context;
|
use deltachat::context::Context;
|
||||||
use deltachat::message::MsgId;
|
use deltachat::message::MsgId;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@@ -8,46 +9,79 @@ use typescript_type_def::TypeDef;
|
|||||||
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
|
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
|
||||||
#[serde(rename = "CallInfo", rename_all = "camelCase")]
|
#[serde(rename = "CallInfo", rename_all = "camelCase")]
|
||||||
pub struct JsonrpcCallInfo {
|
pub struct JsonrpcCallInfo {
|
||||||
/// True if the call is an incoming call.
|
|
||||||
pub is_incoming: bool,
|
|
||||||
|
|
||||||
/// True if the call should not ring anymore.
|
|
||||||
pub is_stale: bool,
|
|
||||||
|
|
||||||
/// True if the call is accepted.
|
|
||||||
pub is_accepted: bool,
|
|
||||||
|
|
||||||
/// True if the call has been ended.
|
|
||||||
pub is_ended: bool,
|
|
||||||
|
|
||||||
/// Call duration in seconds.
|
|
||||||
pub duration: i64,
|
|
||||||
|
|
||||||
/// SDP offer.
|
/// SDP offer.
|
||||||
///
|
///
|
||||||
/// Can be used to manually answer the call
|
/// Can be used to manually answer the call
|
||||||
/// even if incoming call event was missed.
|
/// even if incoming call event was missed.
|
||||||
pub sdp_offer: String,
|
pub sdp_offer: String,
|
||||||
|
|
||||||
|
/// Call state.
|
||||||
|
///
|
||||||
|
/// For example, if the call is accepted, active, cancelled, declined etc.
|
||||||
|
pub state: JsonrpcCallState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonrpcCallInfo {
|
impl JsonrpcCallInfo {
|
||||||
pub async fn from_msg_id(context: &Context, msg_id: MsgId) -> Result<JsonrpcCallInfo> {
|
pub async fn from_msg_id(context: &Context, msg_id: MsgId) -> Result<JsonrpcCallInfo> {
|
||||||
let call_info = context.load_call_by_id(msg_id).await?;
|
let call_info = context.load_call_by_id(msg_id).await?;
|
||||||
|
|
||||||
let is_incoming = call_info.is_incoming();
|
|
||||||
let is_stale = call_info.is_stale();
|
|
||||||
let is_accepted = call_info.is_accepted();
|
|
||||||
let is_ended = call_info.is_ended();
|
|
||||||
let duration = call_info.duration_seconds();
|
|
||||||
let sdp_offer = call_info.place_call_info.clone();
|
let sdp_offer = call_info.place_call_info.clone();
|
||||||
|
let state = JsonrpcCallState::from_msg_id(context, msg_id).await?;
|
||||||
|
|
||||||
Ok(JsonrpcCallInfo {
|
Ok(JsonrpcCallInfo { sdp_offer, state })
|
||||||
is_incoming,
|
}
|
||||||
is_stale,
|
}
|
||||||
is_accepted,
|
|
||||||
is_ended,
|
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
|
||||||
duration,
|
#[serde(rename = "CallState", tag = "kind")]
|
||||||
sdp_offer,
|
pub enum JsonrpcCallState {
|
||||||
})
|
/// Fresh incoming or outgoing call that is still ringing.
|
||||||
|
///
|
||||||
|
/// There is no separate state for outgoing call
|
||||||
|
/// that has been dialled but not ringing on the other side yet
|
||||||
|
/// as we don't know whether the other side received our call.
|
||||||
|
Alerting,
|
||||||
|
|
||||||
|
/// Active call.
|
||||||
|
Active,
|
||||||
|
|
||||||
|
/// Completed call that was once active
|
||||||
|
/// and then was terminated for any reason.
|
||||||
|
Completed {
|
||||||
|
/// Call duration in seconds.
|
||||||
|
duration: i64,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Incoming call that was not picked up within a timeout
|
||||||
|
/// or was explicitly ended by the caller before we picked up.
|
||||||
|
Missed,
|
||||||
|
|
||||||
|
/// Incoming call that was explicitly ended on our side
|
||||||
|
/// before picking up or outgoing call
|
||||||
|
/// that was declined before the timeout.
|
||||||
|
Declined,
|
||||||
|
|
||||||
|
/// Outgoing call that has been cancelled on our side
|
||||||
|
/// before receiving a response.
|
||||||
|
///
|
||||||
|
/// Incoming calls cannot be cancelled,
|
||||||
|
/// on the receiver side cancelled calls
|
||||||
|
/// usually result in missed calls.
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsonrpcCallState {
|
||||||
|
pub async fn from_msg_id(context: &Context, msg_id: MsgId) -> Result<JsonrpcCallState> {
|
||||||
|
let call_state = call_state(context, msg_id).await?;
|
||||||
|
|
||||||
|
let jsonrpc_call_state = match call_state {
|
||||||
|
CallState::Alerting => JsonrpcCallState::Alerting,
|
||||||
|
CallState::Active => JsonrpcCallState::Active,
|
||||||
|
CallState::Completed { duration } => JsonrpcCallState::Completed { duration },
|
||||||
|
CallState::Missed => JsonrpcCallState::Missed,
|
||||||
|
CallState::Declined => JsonrpcCallState::Declined,
|
||||||
|
CallState::Cancelled => JsonrpcCallState::Cancelled,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(jsonrpc_call_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,23 +10,27 @@ def test_calls(acfactory) -> None:
|
|||||||
alice_contact_bob = alice.create_contact(bob, "Bob")
|
alice_contact_bob = alice.create_contact(bob, "Bob")
|
||||||
alice_chat_bob = alice_contact_bob.create_chat()
|
alice_chat_bob = alice_contact_bob.create_chat()
|
||||||
outgoing_call_message = alice_chat_bob.place_outgoing_call(place_call_info)
|
outgoing_call_message = alice_chat_bob.place_outgoing_call(place_call_info)
|
||||||
|
assert outgoing_call_message.get_call_info().state.kind == "Alerting"
|
||||||
|
|
||||||
incoming_call_event = bob.wait_for_event(EventType.INCOMING_CALL)
|
incoming_call_event = bob.wait_for_event(EventType.INCOMING_CALL)
|
||||||
assert incoming_call_event.place_call_info == place_call_info
|
assert incoming_call_event.place_call_info == place_call_info
|
||||||
assert not incoming_call_event.has_video # Cannot be parsed as SDP, so false by default
|
assert not incoming_call_event.has_video # Cannot be parsed as SDP, so false by default
|
||||||
incoming_call_message = Message(bob, incoming_call_event.msg_id)
|
incoming_call_message = Message(bob, incoming_call_event.msg_id)
|
||||||
assert not incoming_call_message.get_call_info().is_accepted
|
assert incoming_call_message.get_call_info().state.kind == "Alerting"
|
||||||
|
|
||||||
incoming_call_message.accept_incoming_call(accept_call_info)
|
incoming_call_message.accept_incoming_call(accept_call_info)
|
||||||
assert incoming_call_message.get_call_info().is_accepted
|
|
||||||
assert incoming_call_message.get_call_info().sdp_offer == place_call_info
|
assert incoming_call_message.get_call_info().sdp_offer == place_call_info
|
||||||
|
assert incoming_call_message.get_call_info().state.kind == "Active"
|
||||||
outgoing_call_accepted_event = alice.wait_for_event(EventType.OUTGOING_CALL_ACCEPTED)
|
outgoing_call_accepted_event = alice.wait_for_event(EventType.OUTGOING_CALL_ACCEPTED)
|
||||||
assert outgoing_call_accepted_event.accept_call_info == accept_call_info
|
assert outgoing_call_accepted_event.accept_call_info == accept_call_info
|
||||||
|
assert outgoing_call_message.get_call_info().state.kind == "Active"
|
||||||
|
|
||||||
outgoing_call_message.end_call()
|
outgoing_call_message.end_call()
|
||||||
|
assert outgoing_call_message.get_call_info().state.kind == "Completed"
|
||||||
|
|
||||||
end_call_event = bob.wait_for_event(EventType.CALL_ENDED)
|
end_call_event = bob.wait_for_event(EventType.CALL_ENDED)
|
||||||
assert end_call_event.msg_id == outgoing_call_message.id
|
assert end_call_event.msg_id == outgoing_call_message.id
|
||||||
|
assert incoming_call_message.get_call_info().state.kind == "Completed"
|
||||||
|
|
||||||
|
|
||||||
def test_video_call(acfactory) -> None:
|
def test_video_call(acfactory) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user