mirror of
https://github.com/chatmail/core.git
synced 2026-05-05 06:16:30 +03:00
api: add call_info() JSON-RPC API
This commit is contained in:
@@ -48,6 +48,7 @@ pub mod types;
|
|||||||
|
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use types::account::Account;
|
use types::account::Account;
|
||||||
|
use types::calls::JsonrpcCallInfo;
|
||||||
use types::chat::FullChat;
|
use types::chat::FullChat;
|
||||||
use types::contact::{ContactObject, VcardContact};
|
use types::contact::{ContactObject, VcardContact};
|
||||||
use types::events::Event;
|
use types::events::Event;
|
||||||
@@ -2117,6 +2118,13 @@ impl CommandApi {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns information about the call.
|
||||||
|
async fn call_info(&self, account_id: u32, msg_id: u32) -> Result<JsonrpcCallInfo> {
|
||||||
|
let ctx = self.get_context(account_id).await?;
|
||||||
|
let call_info = JsonrpcCallInfo::from_msg_id(&ctx, MsgId::new(msg_id)).await?;
|
||||||
|
Ok(call_info)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns JSON with ICE servers, to be used for WebRTC video calls.
|
/// Returns JSON with ICE servers, to be used for WebRTC video calls.
|
||||||
async fn ice_servers(&self, account_id: u32) -> Result<String> {
|
async fn ice_servers(&self, account_id: u32) -> Result<String> {
|
||||||
let ctx = self.get_context(account_id).await?;
|
let ctx = self.get_context(account_id).await?;
|
||||||
|
|||||||
53
deltachat-jsonrpc/src/api/types/calls.rs
Normal file
53
deltachat-jsonrpc/src/api/types/calls.rs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use deltachat::context::Context;
|
||||||
|
use deltachat::message::MsgId;
|
||||||
|
use serde::Serialize;
|
||||||
|
use typescript_type_def::TypeDef;
|
||||||
|
|
||||||
|
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
|
||||||
|
#[serde(rename = "CallInfo", rename_all = "camelCase")]
|
||||||
|
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.
|
||||||
|
///
|
||||||
|
/// Can be used to manually answer the call
|
||||||
|
/// even if incoming call event was missed.
|
||||||
|
pub sdp_offer: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl 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 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();
|
||||||
|
|
||||||
|
Ok(JsonrpcCallInfo {
|
||||||
|
is_incoming,
|
||||||
|
is_stale,
|
||||||
|
is_accepted,
|
||||||
|
is_ended,
|
||||||
|
duration,
|
||||||
|
sdp_offer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod account;
|
pub mod account;
|
||||||
|
pub mod calls;
|
||||||
pub mod chat;
|
pub mod chat;
|
||||||
pub mod chat_list;
|
pub mod chat_list;
|
||||||
pub mod contact;
|
pub mod contact;
|
||||||
|
|||||||
@@ -110,3 +110,7 @@ class Message:
|
|||||||
def end_call(self):
|
def end_call(self):
|
||||||
"""Ends incoming or outgoing call."""
|
"""Ends incoming or outgoing call."""
|
||||||
self._rpc.end_call(self.account.id, self.id)
|
self._rpc.end_call(self.account.id, self.id)
|
||||||
|
|
||||||
|
def get_call_info(self) -> AttrDict:
|
||||||
|
"""Return information about the call."""
|
||||||
|
return AttrDict(self._rpc.call_info(self.account.id, self.id))
|
||||||
|
|||||||
@@ -15,8 +15,11 @@ def test_calls(acfactory) -> None:
|
|||||||
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
|
||||||
|
|
||||||
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
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
20
src/calls.rs
20
src/calls.rs
@@ -52,11 +52,13 @@ pub struct CallInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CallInfo {
|
impl CallInfo {
|
||||||
fn is_incoming(&self) -> bool {
|
/// Returns true if the call is an incoming call.
|
||||||
|
pub fn is_incoming(&self) -> bool {
|
||||||
self.msg.from_id != ContactId::SELF
|
self.msg.from_id != ContactId::SELF
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_stale(&self) -> bool {
|
/// Returns true if the call should not ring anymore.
|
||||||
|
pub fn is_stale(&self) -> bool {
|
||||||
self.remaining_ring_seconds() <= 0
|
self.remaining_ring_seconds() <= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ impl CallInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn update_text_duration(&self, context: &Context) -> Result<()> {
|
async fn update_text_duration(&self, context: &Context) -> Result<()> {
|
||||||
let minutes = self.get_duration_seconds() / 60;
|
let minutes = self.duration_seconds() / 60;
|
||||||
let duration = match minutes {
|
let duration = match minutes {
|
||||||
0 => "<1 minute".to_string(),
|
0 => "<1 minute".to_string(),
|
||||||
1 => "1 minute".to_string(),
|
1 => "1 minute".to_string(),
|
||||||
@@ -102,7 +104,8 @@ impl CallInfo {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_accepted(&self) -> bool {
|
/// Returns true if the call is accepted.
|
||||||
|
pub fn is_accepted(&self) -> bool {
|
||||||
self.msg.param.exists(CALL_ACCEPTED_TIMESTAMP)
|
self.msg.param.exists(CALL_ACCEPTED_TIMESTAMP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,11 +115,13 @@ impl CallInfo {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ended(&self) -> bool {
|
/// Returns true if the call is ended.
|
||||||
|
pub fn is_ended(&self) -> bool {
|
||||||
self.msg.param.exists(CALL_ENDED_TIMESTAMP)
|
self.msg.param.exists(CALL_ENDED_TIMESTAMP)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_duration_seconds(&self) -> i64 {
|
/// Returns call duration in seconds.
|
||||||
|
pub fn duration_seconds(&self) -> i64 {
|
||||||
if let (Some(start), Some(end)) = (
|
if let (Some(start), Some(end)) = (
|
||||||
self.msg.param.get_i64(CALL_ACCEPTED_TIMESTAMP),
|
self.msg.param.get_i64(CALL_ACCEPTED_TIMESTAMP),
|
||||||
self.msg.param.get_i64(CALL_ENDED_TIMESTAMP),
|
self.msg.param.get_i64(CALL_ENDED_TIMESTAMP),
|
||||||
@@ -358,7 +363,8 @@ impl Context {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_call_by_id(&self, call_id: MsgId) -> Result<CallInfo> {
|
/// Loads information about the call given its ID.
|
||||||
|
pub async fn load_call_by_id(&self, call_id: MsgId) -> Result<CallInfo> {
|
||||||
let call = Message::load_from_db(self, call_id).await?;
|
let call = Message::load_from_db(self, call_id).await?;
|
||||||
self.load_call_by_message(call)
|
self.load_call_by_message(call)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user