mirror of
https://github.com/chatmail/core.git
synced 2026-05-06 16:36:59 +03:00
Allow sending a raw webxdc status update (#4386)
- create new api endpoint Co-authored-by: bjoern <r10s@b44t.com> * renaming function --------- Co-authored-by: septias <xxsebastian.kleahnxx@gmail.com> Co-authored-by: bjoern <r10s@b44t.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- jsonrpc: `ChatListItemFetchResult` gets new properties: `summary_preview_image`, `last_message_type` and `last_message_id`
|
- jsonrpc: `ChatListItemFetchResult` gets new properties: `summary_preview_image`, `last_message_type` and `last_message_id`
|
||||||
|
- New rust API `send_webxdc_status_update_struct` to send a `StatusUpdateItem`
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- BREAKING: jsonrpc:
|
- BREAKING: jsonrpc:
|
||||||
|
|||||||
107
src/webxdc.rs
107
src/webxdc.rs
@@ -4,6 +4,7 @@ use std::convert::TryFrom;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, ensure, format_err, Result};
|
use anyhow::{anyhow, bail, ensure, format_err, Result};
|
||||||
|
|
||||||
use deltachat_derive::FromSql;
|
use deltachat_derive::FromSql;
|
||||||
use lettre_email::mime;
|
use lettre_email::mime;
|
||||||
use lettre_email::PartBuilder;
|
use lettre_email::PartBuilder;
|
||||||
@@ -143,17 +144,25 @@ struct StatusUpdates {
|
|||||||
|
|
||||||
/// Update items as sent on the wire and as stored in the database.
|
/// Update items as sent on the wire and as stored in the database.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub(crate) struct StatusUpdateItem {
|
pub struct StatusUpdateItem {
|
||||||
pub(crate) payload: Value,
|
/// The playload of the status update.
|
||||||
|
pub payload: Value,
|
||||||
|
|
||||||
|
/// Optional short info message that will be displayed in the chat.
|
||||||
|
/// For example "Alice added an item" or "Bob voted for option x".
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub(crate) info: Option<String>,
|
pub info: Option<String>,
|
||||||
|
|
||||||
|
/// The new name of the editing document.
|
||||||
|
/// This is not needed if the webxdc doesn't edit documents.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub(crate) document: Option<String>,
|
pub document: Option<String>,
|
||||||
|
|
||||||
|
/// Optional summary of the status update which will be shown next to the
|
||||||
|
/// app icon. This should be short and can be something like "8 votes"
|
||||||
|
/// for a voting app.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub(crate) summary: Option<String>,
|
pub summary: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update items as passed to the UIs.
|
/// Update items as passed to the UIs.
|
||||||
@@ -230,14 +239,14 @@ impl Context {
|
|||||||
let valid = match async_zip::read::fs::ZipFileReader::new(path).await {
|
let valid = match async_zip::read::fs::ZipFileReader::new(path).await {
|
||||||
Ok(archive) => {
|
Ok(archive) => {
|
||||||
if find_zip_entry(archive.file(), "index.html").is_none() {
|
if find_zip_entry(archive.file(), "index.html").is_none() {
|
||||||
info!(self, "{} misses index.html", filename);
|
warn!(self, "{} misses index.html", filename);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
info!(self, "{} cannot be opened as zip-file", filename);
|
warn!(self, "{} cannot be opened as zip-file", filename);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -289,23 +298,11 @@ impl Context {
|
|||||||
async fn create_status_update_record(
|
async fn create_status_update_record(
|
||||||
&self,
|
&self,
|
||||||
instance: &mut Message,
|
instance: &mut Message,
|
||||||
update_str: &str,
|
status_update_item: StatusUpdateItem,
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
can_info_msg: bool,
|
can_info_msg: bool,
|
||||||
from_id: ContactId,
|
from_id: ContactId,
|
||||||
) -> Result<StatusUpdateSerial> {
|
) -> Result<StatusUpdateSerial> {
|
||||||
let update_str = strip_rtlo_characters(update_str.trim());
|
|
||||||
if update_str.is_empty() {
|
|
||||||
bail!("create_status_update_record: empty update.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let status_update_item: StatusUpdateItem =
|
|
||||||
if let Ok(item) = serde_json::from_str::<StatusUpdateItem>(&update_str) {
|
|
||||||
item
|
|
||||||
} else {
|
|
||||||
bail!("create_status_update_record: no valid update item.");
|
|
||||||
};
|
|
||||||
|
|
||||||
if can_info_msg {
|
if can_info_msg {
|
||||||
if let Some(ref info) = status_update_item.info {
|
if let Some(ref info) = status_update_item.info {
|
||||||
if let Some(info_msg_id) =
|
if let Some(info_msg_id) =
|
||||||
@@ -404,6 +401,26 @@ impl Context {
|
|||||||
instance_msg_id: MsgId,
|
instance_msg_id: MsgId,
|
||||||
update_str: &str,
|
update_str: &str,
|
||||||
descr: &str,
|
descr: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
let status_update_item: StatusUpdateItem =
|
||||||
|
if let Ok(item) = serde_json::from_str::<StatusUpdateItem>(update_str) {
|
||||||
|
item
|
||||||
|
} else {
|
||||||
|
bail!("create_status_update_record: no valid update item.");
|
||||||
|
};
|
||||||
|
|
||||||
|
self.send_webxdc_status_update_struct(instance_msg_id, status_update_item, descr)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends a status update for an webxdc instance.
|
||||||
|
/// Also see [Self::send_webxdc_status_update]
|
||||||
|
pub async fn send_webxdc_status_update_struct(
|
||||||
|
&self,
|
||||||
|
instance_msg_id: MsgId,
|
||||||
|
status_update: StatusUpdateItem,
|
||||||
|
descr: &str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut instance = Message::load_from_db(self, instance_msg_id).await?;
|
let mut instance = Message::load_from_db(self, instance_msg_id).await?;
|
||||||
if instance.viewtype != Viewtype::Webxdc {
|
if instance.viewtype != Viewtype::Webxdc {
|
||||||
@@ -420,10 +437,10 @@ impl Context {
|
|||||||
MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft
|
MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft
|
||||||
);
|
);
|
||||||
|
|
||||||
let status_update_serial = self
|
let status_update_serial: StatusUpdateSerial = self
|
||||||
.create_status_update_record(
|
.create_status_update_record(
|
||||||
&mut instance,
|
&mut instance,
|
||||||
update_str,
|
status_update,
|
||||||
create_smeared_timestamp(self),
|
create_smeared_timestamp(self),
|
||||||
send_now,
|
send_now,
|
||||||
ContactId::SELF,
|
ContactId::SELF,
|
||||||
@@ -552,7 +569,7 @@ impl Context {
|
|||||||
for update_item in updates.updates {
|
for update_item in updates.updates {
|
||||||
self.create_status_update_record(
|
self.create_status_update_record(
|
||||||
&mut instance,
|
&mut instance,
|
||||||
&serde_json::to_string(&update_item)?,
|
update_item,
|
||||||
timestamp,
|
timestamp,
|
||||||
can_info_msg,
|
can_info_msg,
|
||||||
from_id,
|
from_id,
|
||||||
@@ -801,6 +818,8 @@ impl Message {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::chat::{
|
use crate::chat::{
|
||||||
add_contact_to_chat, create_broadcast_list, create_group_chat, forward_msgs,
|
add_contact_to_chat, create_broadcast_list, create_group_chat, forward_msgs,
|
||||||
@@ -1235,7 +1254,12 @@ mod tests {
|
|||||||
let update_id1 = t
|
let update_id1 = t
|
||||||
.create_status_update_record(
|
.create_status_update_record(
|
||||||
&mut instance,
|
&mut instance,
|
||||||
"\n\n{\"payload\": {\"foo\":\"bar\"}}\n",
|
StatusUpdateItem {
|
||||||
|
payload: json!({"foo": "bar"}),
|
||||||
|
info: None,
|
||||||
|
document: None,
|
||||||
|
summary: None,
|
||||||
|
},
|
||||||
1640178619,
|
1640178619,
|
||||||
true,
|
true,
|
||||||
ContactId::SELF,
|
ContactId::SELF,
|
||||||
@@ -1248,19 +1272,15 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert!(t
|
assert!(t
|
||||||
.create_status_update_record(&mut instance, "\n\n\n", 1640178619, true, ContactId::SELF)
|
.send_webxdc_status_update(instance.id, "\n\n\n", "")
|
||||||
.await
|
.await
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
assert!(t
|
assert!(t
|
||||||
.create_status_update_record(
|
.send_webxdc_status_update(instance.id, "bad json", "")
|
||||||
&mut instance,
|
|
||||||
"bad json",
|
|
||||||
1640178619,
|
|
||||||
true,
|
|
||||||
ContactId::SELF
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
t.get_webxdc_status_updates(instance.id, StatusUpdateSerial(0))
|
t.get_webxdc_status_updates(instance.id, StatusUpdateSerial(0))
|
||||||
.await?,
|
.await?,
|
||||||
@@ -1270,7 +1290,12 @@ mod tests {
|
|||||||
let update_id2 = t
|
let update_id2 = t
|
||||||
.create_status_update_record(
|
.create_status_update_record(
|
||||||
&mut instance,
|
&mut instance,
|
||||||
r#"{"payload" : { "foo2":"bar2"}}"#,
|
StatusUpdateItem {
|
||||||
|
payload: json!({"foo2": "bar2"}),
|
||||||
|
info: None,
|
||||||
|
document: None,
|
||||||
|
summary: None,
|
||||||
|
},
|
||||||
1640178619,
|
1640178619,
|
||||||
true,
|
true,
|
||||||
ContactId::SELF,
|
ContactId::SELF,
|
||||||
@@ -1282,7 +1307,12 @@ mod tests {
|
|||||||
);
|
);
|
||||||
t.create_status_update_record(
|
t.create_status_update_record(
|
||||||
&mut instance,
|
&mut instance,
|
||||||
r#"{"payload":true}"#,
|
StatusUpdateItem {
|
||||||
|
payload: Value::Bool(true),
|
||||||
|
info: None,
|
||||||
|
document: None,
|
||||||
|
summary: None,
|
||||||
|
},
|
||||||
1640178619,
|
1640178619,
|
||||||
true,
|
true,
|
||||||
ContactId::SELF,
|
ContactId::SELF,
|
||||||
@@ -1296,13 +1326,10 @@ mod tests {
|
|||||||
{"payload":true,"serial":3,"max_serial":3}]"#
|
{"payload":true,"serial":3,"max_serial":3}]"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let _update_id3 = t
|
t.send_webxdc_status_update(
|
||||||
.create_status_update_record(
|
instance.id,
|
||||||
&mut instance,
|
|
||||||
r#"{"payload" : 1, "sender": "that is not used"}"#,
|
r#"{"payload" : 1, "sender": "that is not used"}"#,
|
||||||
1640178619,
|
"",
|
||||||
true,
|
|
||||||
ContactId::SELF,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Reference in New Issue
Block a user