Skip to content

Commit ca8d0d5

Browse files
committed
api: add who_can_call_me config option
1 parent fdb583b commit ca8d0d5

File tree

4 files changed

+72
-20
lines changed

4 files changed

+72
-20
lines changed

deltachat-ffi/deltachat.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,10 @@ char* dc_get_blobdir (const dc_context_t* context);
516516
* - `webxdc_realtime_enabled` = Whether the realtime APIs should be enabled.
517517
* 0 = WebXDC realtime API is disabled and behaves as noop.
518518
* 1 = WebXDC realtime API is enabled (default).
519+
* - `who_can_call_me` = Who can cause call notifications.
520+
* 0 = Everybody (except explicitly blocked contacts),
521+
* 1 = Contacts (default, does not include contact requests),
522+
* 2 = Nobody (calls never result in a notification).
519523
*
520524
* If you want to retrieve a value, use dc_get_config().
521525
*

src/calls.rs

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! This means, the "Call ID" is a "Message ID" - similar to Webxdc IDs.
55
use crate::chat::ChatIdBlocked;
66
use crate::chat::{Chat, ChatId, send_msg};
7+
use crate::config::Config;
78
use crate::constants::{Blocked, Chattype};
89
use crate::contact::ContactId;
910
use crate::context::{Context, WeakContext};
@@ -16,6 +17,8 @@ use crate::net::dns::lookup_host_with_cache;
1617
use crate::param::Param;
1718
use crate::tools::{normalize_text, time};
1819
use anyhow::{Context as _, Result, ensure};
20+
use deltachat_derive::{FromSql, ToSql};
21+
use num_traits::FromPrimitive;
1922
use sdp::SessionDescription;
2023
use serde::Serialize;
2124
use std::io::Cursor;
@@ -348,26 +351,34 @@ impl Context {
348351
false
349352
}
350353
};
351-
if let Some(chat_id_blocked) =
352-
ChatIdBlocked::lookup_by_contact(self, from_id).await?
353-
{
354-
match chat_id_blocked.blocked {
355-
Blocked::Not => {
356-
self.emit_event(EventType::IncomingCall {
357-
msg_id: call.msg.id,
358-
chat_id: call.msg.chat_id,
359-
place_call_info: call.place_call_info.to_string(),
360-
has_video,
361-
});
362-
}
363-
Blocked::Yes | Blocked::Request => {
364-
// Do not notify about incoming calls
365-
// from contact requests and blocked contacts.
366-
//
367-
// User can still access the call and accept it
368-
// via the chat in case of contact requests.
369-
}
370-
}
354+
let can_call_me = match who_can_call_me(self).await? {
355+
WhoCanCallMe::Contacts => ChatIdBlocked::lookup_by_contact(self, from_id)
356+
.await?
357+
.is_some_and(|chat_id_blocked| {
358+
match chat_id_blocked.blocked {
359+
Blocked::Not => true,
360+
Blocked::Yes | Blocked::Request => {
361+
// Do not notify about incoming calls
362+
// from contact requests and blocked contacts.
363+
//
364+
// User can still access the call and accept it
365+
// via the chat in case of contact requests.
366+
false
367+
}
368+
}
369+
}),
370+
WhoCanCallMe::Everybody => ChatIdBlocked::lookup_by_contact(self, from_id)
371+
.await?
372+
.is_none_or(|chat_id_blocked| chat_id_blocked.blocked != Blocked::Yes),
373+
WhoCanCallMe::Nobody => false,
374+
};
375+
if can_call_me {
376+
self.emit_event(EventType::IncomingCall {
377+
msg_id: call.msg.id,
378+
chat_id: call.msg.chat_id,
379+
place_call_info: call.place_call_info.to_string(),
380+
has_video,
381+
});
371382
}
372383
let wait = call.remaining_ring_seconds();
373384
let context = self.get_weak_context();
@@ -712,5 +723,32 @@ pub async fn ice_servers(context: &Context) -> Result<String> {
712723
}
713724
}
714725

726+
/// "Who can call me" config options.
727+
#[derive(
728+
Debug, Default, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql,
729+
)]
730+
#[repr(u8)]
731+
pub enum WhoCanCallMe {
732+
/// Everybody can call me if they are not blocked.
733+
///
734+
/// This includes contact requests.
735+
Everybody = 0,
736+
737+
/// Every contact who is not blocked and not a contact request, can call.
738+
#[default]
739+
Contacts = 1,
740+
741+
/// Nobody can call me.
742+
Nobody = 2,
743+
}
744+
745+
/// Returns currently configuration of the "who can call me" option.
746+
async fn who_can_call_me(context: &Context) -> Result<WhoCanCallMe> {
747+
let who_can_call_me =
748+
WhoCanCallMe::from_i32(context.get_config_int(Config::WhoCanCallMe).await?)
749+
.unwrap_or_default();
750+
Ok(who_can_call_me)
751+
}
752+
715753
#[cfg(test)]
716754
mod calls_tests;

src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@ pub enum Config {
446446
/// Protected Email".
447447
#[strum(props(default = "1"))]
448448
StdHeaderProtectionComposing,
449+
450+
/// Who can call me.
451+
///
452+
/// The options are from the `WhoCanCallMe` enum.
453+
#[strum(props(default = "1"))]
454+
WhoCanCallMe,
449455
}
450456

451457
impl Config {

src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,10 @@ impl Context {
954954
"show_emails",
955955
self.get_config_int(Config::ShowEmails).await?.to_string(),
956956
);
957+
res.insert(
958+
"who_can_call_me",
959+
self.get_config_int(Config::WhoCanCallMe).await?.to_string(),
960+
);
957961
res.insert(
958962
"download_limit",
959963
self.get_config_int(Config::DownloadLimit)

0 commit comments

Comments
 (0)