mirror of
https://github.com/chatmail/core.git
synced 2026-05-06 06:46:35 +03:00
api: add JSON-RPC APIs for location streaming
New API stop_sending_locations() only available in JSON-RPC stops location streaming in all accounts and chats.
This commit is contained in:
@@ -22,6 +22,9 @@ use deltachat::context::get_info;
|
|||||||
use deltachat::ephemeral::Timer;
|
use deltachat::ephemeral::Timer;
|
||||||
use deltachat::imex;
|
use deltachat::imex;
|
||||||
use deltachat::location;
|
use deltachat::location;
|
||||||
|
use deltachat::location::is_sending_locations;
|
||||||
|
use deltachat::location::is_sending_locations_to_chat;
|
||||||
|
use deltachat::location::send_locations_to_chat;
|
||||||
use deltachat::message::{
|
use deltachat::message::{
|
||||||
self, delete_msgs_ex, get_existing_msg_ids, get_msg_read_receipt_count, get_msg_read_receipts,
|
self, delete_msgs_ex, get_existing_msg_ids, get_msg_read_receipt_count, get_msg_read_receipts,
|
||||||
markseen_msgs, Message, MessageState, MsgId, Viewtype,
|
markseen_msgs, Message, MessageState, MsgId, Viewtype,
|
||||||
@@ -2120,6 +2123,21 @@ impl CommandApi {
|
|||||||
// locations
|
// locations
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
|
|
||||||
|
/// Sets current location.
|
||||||
|
///
|
||||||
|
/// Returns true if location streaming is currently
|
||||||
|
/// enabled and locations should be updated.
|
||||||
|
///
|
||||||
|
/// Location is represented as latitude and longitude in degrees
|
||||||
|
/// and horizontal accuracy in meters.
|
||||||
|
async fn set_location(&self, latitude: f64, longitude: f64, accuracy: f64) -> Result<bool> {
|
||||||
|
self.accounts
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
|
.set_location(latitude, longitude, accuracy)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_locations(
|
async fn get_locations(
|
||||||
&self,
|
&self,
|
||||||
account_id: u32,
|
account_id: u32,
|
||||||
@@ -2142,6 +2160,39 @@ impl CommandApi {
|
|||||||
Ok(locations.into_iter().map(|l| l.into()).collect())
|
Ok(locations.into_iter().map(|l| l.into()).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enables location streaming in chat identified by `chat_id` for `seconds` seconds.
|
||||||
|
///
|
||||||
|
/// Pass 0 as the number of seconds to disable location streaming in the chat.
|
||||||
|
async fn send_locations_to_chat(
|
||||||
|
&self,
|
||||||
|
account_id: u32,
|
||||||
|
chat_id: u32,
|
||||||
|
seconds: i64,
|
||||||
|
) -> Result<()> {
|
||||||
|
let ctx = self.get_context(account_id).await?;
|
||||||
|
let chat_id = ChatId::new(chat_id);
|
||||||
|
send_locations_to_chat(&ctx, chat_id, seconds).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether any chat is sending locations.
|
||||||
|
async fn is_sending_locations(&self, account_id: u32) -> Result<bool> {
|
||||||
|
let ctx = self.get_context(account_id).await?;
|
||||||
|
is_sending_locations(&ctx).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether `chat_id` is sending locations.
|
||||||
|
async fn is_sending_locations_to_chat(&self, account_id: u32, chat_id: u32) -> Result<bool> {
|
||||||
|
let ctx = self.get_context(account_id).await?;
|
||||||
|
let chat_id = ChatId::new(chat_id);
|
||||||
|
is_sending_locations_to_chat(&ctx, chat_id).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stops sending locations to all chats.
|
||||||
|
async fn stop_sending_locations(&self) -> Result<()> {
|
||||||
|
self.accounts.read().await.stop_sending_locations().await
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
// webxdc
|
// webxdc
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
|
|||||||
@@ -495,3 +495,7 @@ class Account:
|
|||||||
"""Return ICE servers for WebRTC configuration."""
|
"""Return ICE servers for WebRTC configuration."""
|
||||||
ice_servers_json = self._rpc.ice_servers(self.id)
|
ice_servers_json = self._rpc.ice_servers(self.id)
|
||||||
return json.loads(ice_servers_json)
|
return json.loads(ice_servers_json)
|
||||||
|
|
||||||
|
def is_sending_locations(self) -> bool:
|
||||||
|
"""Return True if sending locations to any chat."""
|
||||||
|
return self._rpc.is_sending_locations(self.id)
|
||||||
|
|||||||
@@ -277,6 +277,16 @@ class Chat:
|
|||||||
"""Remove profile image of this chat."""
|
"""Remove profile image of this chat."""
|
||||||
self._rpc.set_chat_profile_image(self.account.id, self.id, None)
|
self._rpc.set_chat_profile_image(self.account.id, self.id, None)
|
||||||
|
|
||||||
|
def send_locations(self, seconds) -> None:
|
||||||
|
"""Enable location streaming in the chat for the given number of seconds.
|
||||||
|
|
||||||
|
Pass 0 to disable location streaming."""
|
||||||
|
self._rpc.send_locations_to_chat(self.account.id, self.id, seconds)
|
||||||
|
|
||||||
|
def is_sending_locations(self) -> bool:
|
||||||
|
"""Return True if sending locations to this chat."""
|
||||||
|
return self._rpc.is_sending_locations_to_chat(self.account.id, self.id)
|
||||||
|
|
||||||
def get_locations(
|
def get_locations(
|
||||||
self,
|
self,
|
||||||
contact: Optional[Contact] = None,
|
contact: Optional[Contact] = None,
|
||||||
|
|||||||
@@ -59,3 +59,11 @@ class DeltaChat:
|
|||||||
def set_translations(self, translations: dict[str, str]) -> None:
|
def set_translations(self, translations: dict[str, str]) -> None:
|
||||||
"""Set stock translation strings."""
|
"""Set stock translation strings."""
|
||||||
self.rpc.set_stock_strings(translations)
|
self.rpc.set_stock_strings(translations)
|
||||||
|
|
||||||
|
def set_location(self, latitude, longitude, accuracy) -> bool:
|
||||||
|
"""Set location, return True if location streaming should continue."""
|
||||||
|
return self.rpc.set_location(latitude, longitude, accuracy)
|
||||||
|
|
||||||
|
def stop_sending_locations(self) -> None:
|
||||||
|
"""Stop sending locations to all chats."""
|
||||||
|
return self.rpc.stop_sending_locations()
|
||||||
|
|||||||
32
deltachat-rpc-client/tests/test_location.py
Normal file
32
deltachat-rpc-client/tests/test_location.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
def test_set_location(dc, acfactory) -> None:
|
||||||
|
# Try setting location without any accounts.
|
||||||
|
assert not dc.set_location(1.0, 2.0, 0.1)
|
||||||
|
|
||||||
|
# Create one account that does not stream,
|
||||||
|
# set location.
|
||||||
|
acfactory.new_configured_account()
|
||||||
|
assert not dc.set_location(3.0, 4.0, 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_send_locations_to_chat(dc, acfactory):
|
||||||
|
alice, bob = acfactory.get_online_accounts(2)
|
||||||
|
|
||||||
|
assert not alice.is_sending_locations()
|
||||||
|
alice_chat_bob = alice.create_chat(bob)
|
||||||
|
assert not alice_chat_bob.is_sending_locations()
|
||||||
|
|
||||||
|
# Test starting and stopping location streaming in a chat.
|
||||||
|
alice_chat_bob.send_locations(3600)
|
||||||
|
assert alice.is_sending_locations()
|
||||||
|
assert alice_chat_bob.is_sending_locations()
|
||||||
|
alice_chat_bob.send_locations(0)
|
||||||
|
assert not alice.is_sending_locations()
|
||||||
|
assert not alice_chat_bob.is_sending_locations()
|
||||||
|
|
||||||
|
# Test stop_sending_locations() for all accounts and chats.
|
||||||
|
alice_chat_bob.send_locations(3600)
|
||||||
|
assert alice.is_sending_locations()
|
||||||
|
assert alice_chat_bob.is_sending_locations()
|
||||||
|
dc.stop_sending_locations()
|
||||||
|
assert not alice.is_sending_locations()
|
||||||
|
assert not alice_chat_bob.is_sending_locations()
|
||||||
@@ -22,6 +22,8 @@ use tokio::time::{Duration, sleep};
|
|||||||
|
|
||||||
use crate::context::{Context, ContextBuilder};
|
use crate::context::{Context, ContextBuilder};
|
||||||
use crate::events::{Event, EventEmitter, EventType, Events};
|
use crate::events::{Event, EventEmitter, EventType, Events};
|
||||||
|
use crate::location;
|
||||||
|
use crate::location::stop_sending_locations;
|
||||||
use crate::log::warn;
|
use crate::log::warn;
|
||||||
use crate::push::PushSubscriber;
|
use crate::push::PushSubscriber;
|
||||||
use crate::stock_str::StockStrings;
|
use crate::stock_str::StockStrings;
|
||||||
@@ -536,6 +538,27 @@ impl Accounts {
|
|||||||
self.push_subscriber.set_device_token(token).await;
|
self.push_subscriber.set_device_token(token).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets location for all accounts.
|
||||||
|
///
|
||||||
|
/// Returns true if location should still be streamed.
|
||||||
|
pub async fn set_location(&self, latitude: f64, longitude: f64, accuracy: f64) -> Result<bool> {
|
||||||
|
let mut continue_streaming = false;
|
||||||
|
for account in self.accounts.values() {
|
||||||
|
if location::set(account, latitude, longitude, accuracy).await? {
|
||||||
|
continue_streaming = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(continue_streaming)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stops sending locations to all chats.
|
||||||
|
pub async fn stop_sending_locations(&self) -> Result<()> {
|
||||||
|
for account in self.accounts.values() {
|
||||||
|
stop_sending_locations(account).await?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration file name.
|
/// Configuration file name.
|
||||||
|
|||||||
@@ -327,6 +327,29 @@ pub async fn is_sending_locations_to_chat(context: &Context, chat_id: ChatId) ->
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a list of chats in which location streaming is enabled.
|
||||||
|
async fn get_chats_with_location_streaming(context: &Context) -> Result<Vec<ChatId>> {
|
||||||
|
context
|
||||||
|
.sql
|
||||||
|
.query_map_vec(
|
||||||
|
"SELECT id FROM chats WHERE locations_send_until>?",
|
||||||
|
(time(),),
|
||||||
|
|row| {
|
||||||
|
let chat_id: ChatId = row.get(0)?;
|
||||||
|
Ok(chat_id)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stop sending locations in all chats.
|
||||||
|
pub async fn stop_sending_locations(context: &Context) -> Result<()> {
|
||||||
|
for chat_id in get_chats_with_location_streaming(context).await? {
|
||||||
|
send_locations_to_chat(context, chat_id, 0).await?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets current location of the user device.
|
/// Sets current location of the user device.
|
||||||
pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64) -> Result<bool> {
|
pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64) -> Result<bool> {
|
||||||
if latitude == 0.0 && longitude == 0.0 {
|
if latitude == 0.0 && longitude == 0.0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user