mirror of
https://github.com/chatmail/core.git
synced 2026-04-06 23:52:11 +03:00
Compare commits
7 Commits
link2xt/st
...
hpk/underd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92de732686 | ||
|
|
aa36cfd581 | ||
|
|
1a04180ef6 | ||
|
|
58db2d41ee | ||
|
|
c2790521c6 | ||
|
|
e0768f5f37 | ||
|
|
1b860372cc |
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,47 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [2.46.0] - 2026-03-19
|
||||
|
||||
### API-Changes
|
||||
|
||||
- [**breaking**] remove functions for sending and receiving Autocrypt Setup Message.
|
||||
- Add `list_transports_ex()` and `set_transport_unpublished()` functions.
|
||||
|
||||
### Features / Changes
|
||||
|
||||
- add `IncomingCallAccepted.from_this_device`.
|
||||
- mark messages as "fresh".
|
||||
- decode `dcaccount://` URLs and error out on empty URLs early.
|
||||
- enable anonymous OpenPGP key IDs.
|
||||
- tls: do not verify TLS certificates for hostnames starting with `_`.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Mark call message as seen when accepting/declining a call ([#7842](https://github.com/chatmail/core/pull/7842)).
|
||||
- do not send MDNs for hidden messages.
|
||||
- call sync_all() instead of sync_data() when writing accounts.toml.
|
||||
- fsync() the rename() of accounts.toml.
|
||||
- count recipients by Intended Recipient Fingerprints.
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- deps: bump zizmorcore/zizmor-action from 0.5.0 to 0.5.2.
|
||||
- cargo: bump astral-tokio-tar from 0.5.6 to 0.6.0.
|
||||
- deps: bump actions/upload-artifact from 6 to 7.
|
||||
- cargo: bump blake3 from 1.8.2 to 1.8.3.
|
||||
- add constant_time_eq 0.3.1 to deny.toml.
|
||||
|
||||
### Refactor
|
||||
|
||||
- use re-exported rustls::pki_types.
|
||||
- import tokio_rustls::rustls.
|
||||
- Move transport_tests to their own file.
|
||||
|
||||
### Tests
|
||||
|
||||
- Shift time even more in flaky test_sync_broadcast_and_send_message.
|
||||
- test markfresh_chat()
|
||||
|
||||
## [2.45.0] - 2026-03-14
|
||||
|
||||
### API-Changes
|
||||
@@ -7949,4 +7907,3 @@ https://github.com/chatmail/core/pulls?q=is%3Apr+is%3Aclosed
|
||||
[2.43.0]: https://github.com/chatmail/core/compare/v2.42.0..v2.43.0
|
||||
[2.44.0]: https://github.com/chatmail/core/compare/v2.43.0..v2.44.0
|
||||
[2.45.0]: https://github.com/chatmail/core/compare/v2.44.0..v2.45.0
|
||||
[2.46.0]: https://github.com/chatmail/core/compare/v2.45.0..v2.46.0
|
||||
|
||||
67
Cargo.lock
generated
67
Cargo.lock
generated
@@ -470,9 +470,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
@@ -497,16 +497,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.8.3"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d"
|
||||
checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"constant_time_eq 0.4.2",
|
||||
"cpufeatures",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -964,12 +963,6 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.5.0"
|
||||
@@ -1123,7 +1116,7 @@ version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"crossterm_winapi",
|
||||
"parking_lot",
|
||||
"rustix 0.38.44",
|
||||
@@ -1307,7 +1300,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"astral-tokio-tar",
|
||||
@@ -1416,7 +1409,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-jsonrpc"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel 2.5.0",
|
||||
@@ -1437,7 +1430,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-repl"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deltachat",
|
||||
@@ -1453,7 +1446,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-rpc-server"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deltachat",
|
||||
@@ -1482,7 +1475,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat_ffi"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deltachat",
|
||||
@@ -3032,7 +3025,7 @@ dependencies = [
|
||||
"arrayvec",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"constant_time_eq 0.3.1",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3276,7 +3269,7 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"libc",
|
||||
"redox_syscall 0.5.12",
|
||||
]
|
||||
@@ -3596,7 +3589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0800eae8638a299eaa67476e1c6b6692922273e0f7939fd188fc861c837b9cd2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"byteorder",
|
||||
"libc",
|
||||
"log",
|
||||
@@ -3691,7 +3684,7 @@ version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@@ -3866,7 +3859,7 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3937,7 +3930,7 @@ version = "0.10.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
@@ -4399,7 +4392,7 @@ version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
@@ -4615,11 +4608,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proptest"
|
||||
version = "1.10.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532"
|
||||
checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"num-traits",
|
||||
"rand 0.9.2",
|
||||
"rand_chacha 0.9.0",
|
||||
@@ -4903,7 +4896,7 @@ version = "0.5.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5090,7 +5083,7 @@ version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
@@ -5134,7 +5127,7 @@ version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.14",
|
||||
@@ -5147,7 +5140,7 @@ version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
@@ -5211,7 +5204,7 @@ version = "16.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62fd9ca5ebc709e8535e8ef7c658eb51457987e48c98ead2be482172accc408d"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if",
|
||||
"clipboard-win",
|
||||
"fd-lock",
|
||||
@@ -5338,7 +5331,7 @@ version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@@ -5657,7 +5650,7 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5942,7 +5935,7 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
@@ -7225,7 +7218,7 @@ version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
edition = "2024"
|
||||
license = "MPL-2.0"
|
||||
rust-version = "1.88"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat_ffi"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
description = "Deltachat FFI"
|
||||
edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat-jsonrpc"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
description = "DeltaChat JSON-RPC API"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
@@ -23,9 +23,8 @@ use deltachat::ephemeral::Timer;
|
||||
use deltachat::imex;
|
||||
use deltachat::location;
|
||||
use deltachat::message::{
|
||||
self, delete_msgs_ex, dont_truncate_long_messages, get_existing_msg_ids,
|
||||
get_msg_read_receipt_count, get_msg_read_receipts, markseen_msgs, Message, MessageState, MsgId,
|
||||
Viewtype,
|
||||
self, delete_msgs_ex, get_existing_msg_ids, get_msg_read_receipt_count, get_msg_read_receipts,
|
||||
markseen_msgs, Message, MessageState, MsgId, Viewtype,
|
||||
};
|
||||
use deltachat::peer_channels::{
|
||||
leave_webxdc_realtime, send_webxdc_realtime_advertisement, send_webxdc_realtime_data,
|
||||
@@ -1435,15 +1434,6 @@ impl CommandApi {
|
||||
MsgId::new(message_id).get_html(&ctx).await
|
||||
}
|
||||
|
||||
/// Opt out of truncating long messages when loading.
|
||||
///
|
||||
/// Should be used by the UIs that can handle long text messages.
|
||||
async fn dont_truncate_long_messages(&self, account_id: u32) -> Result<()> {
|
||||
let ctx = self.get_context(account_id).await?;
|
||||
dont_truncate_long_messages(&ctx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// get multiple messages in one call,
|
||||
/// if loading one message fails the error is stored in the result object in it's place.
|
||||
///
|
||||
|
||||
@@ -54,5 +54,5 @@
|
||||
},
|
||||
"type": "module",
|
||||
"types": "dist/deltachat.d.ts",
|
||||
"version": "2.47.0-dev"
|
||||
"version": "2.46.0-dev"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat-repl"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
license = "MPL-2.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/chatmail/core"
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "deltachat-rpc-client"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
license = "MPL-2.0"
|
||||
description = "Python client for Delta Chat core JSON-RPC interface"
|
||||
classifiers = [
|
||||
|
||||
@@ -9,6 +9,7 @@ import platform
|
||||
import random
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.parse
|
||||
from typing import AsyncGenerator, Optional
|
||||
|
||||
import execnet
|
||||
@@ -283,8 +284,16 @@ def alice_and_remote_bob(tmp_path, acfactory, get_core_python_env):
|
||||
channel = gw.remote_exec(remote_bob_loop)
|
||||
cm = os.environ.get("CHATMAIL_DOMAIN")
|
||||
|
||||
# Build a dclogin QR code for the remote bob account.
|
||||
# Using dclogin scheme with ic=3&sc=3 allows old cores
|
||||
# to accept invalid certificates for underscore-prefixed domains.
|
||||
addr, password = acfactory.get_credentials()
|
||||
dclogin_qr = f"dclogin://{urllib.parse.quote(addr, safe='@')}?p={urllib.parse.quote(password)}&v=1"
|
||||
if cm and cm.startswith("_"):
|
||||
dclogin_qr += "&ic=3&sc=3"
|
||||
|
||||
# trigger getting an online account on bob's side
|
||||
channel.send((accounts_dir, str(rpc_server_path), cm))
|
||||
channel.send((accounts_dir, str(rpc_server_path), dclogin_qr))
|
||||
|
||||
# meanwhile get a local alice account
|
||||
alice = acfactory.get_online_account()
|
||||
@@ -316,10 +325,8 @@ def remote_bob_loop(channel):
|
||||
import os
|
||||
|
||||
from deltachat_rpc_client import DeltaChat, Rpc
|
||||
from deltachat_rpc_client.pytestplugin import ACFactory
|
||||
|
||||
accounts_dir, rpc_server_path, chatmail_domain = channel.receive()
|
||||
os.environ["CHATMAIL_DOMAIN"] = chatmail_domain
|
||||
accounts_dir, rpc_server_path, dclogin_qr = channel.receive()
|
||||
|
||||
# older core versions don't support specifying rpc_server_path
|
||||
# so we can't just pass `rpc_server_path` argument to Rpc constructor
|
||||
@@ -330,8 +337,14 @@ def remote_bob_loop(channel):
|
||||
with rpc:
|
||||
dc = DeltaChat(rpc)
|
||||
channel.send(dc.rpc.get_system_info()["deltachat_core_version"])
|
||||
acfactory = ACFactory(dc)
|
||||
bob = acfactory.get_online_account()
|
||||
|
||||
# Configure account using dclogin scheme directly,
|
||||
# avoiding the old ACFactory which doesn't handle
|
||||
# underscore-prefixed domains' TLS on older cores.
|
||||
bob = dc.add_account()
|
||||
bob.set_config_from_qr(dclogin_qr)
|
||||
bob.bring_online()
|
||||
|
||||
alice_vcard = channel.receive()
|
||||
[alice_contact] = bob.import_vcard(alice_vcard)
|
||||
ns = {"bob": bob, "bob_contact_alice": alice_contact}
|
||||
|
||||
@@ -37,7 +37,11 @@ class DirectImap:
|
||||
host = user.rsplit("@")[-1]
|
||||
pw = self.account.get_config("mail_pw")
|
||||
|
||||
self.conn = MailBox(host, port, ssl_context=ssl.create_default_context())
|
||||
ssl_context = ssl.create_default_context()
|
||||
if host.startswith("_"):
|
||||
ssl_context.check_hostname = False
|
||||
ssl_context.verify_mode = ssl.CERT_NONE
|
||||
self.conn = MailBox(host, port, ssl_context=ssl_context)
|
||||
self.conn.login(user, pw)
|
||||
|
||||
self.select_folder("INBOX")
|
||||
|
||||
@@ -109,7 +109,7 @@ def test_delivery_status_failed(acfactory: ACFactory) -> None:
|
||||
assert failing_message.get_snapshot().state == const.MessageState.OUT_FAILED
|
||||
|
||||
|
||||
def test_download_on_demand(acfactory: ACFactory) -> None:
|
||||
def test_download_on_demand(acfactory: ACFactory, data) -> None:
|
||||
"""
|
||||
Test if download on demand emits chatlist update events.
|
||||
This is only needed for last message in chat, but finding that out is too expensive, so it's always emitted
|
||||
@@ -127,7 +127,7 @@ def test_download_on_demand(acfactory: ACFactory) -> None:
|
||||
msg.get_snapshot().chat.accept()
|
||||
bob.get_chat_by_id(chat_id).send_message(
|
||||
"Hello World, this message is bigger than 5 bytes",
|
||||
file="../test-data/image/screenshot.jpg",
|
||||
file=data.get_path("image/screenshot.jpg"),
|
||||
)
|
||||
|
||||
message = alice.wait_for_incoming_msg()
|
||||
|
||||
@@ -36,7 +36,7 @@ def test_qr_setup_contact(alice_and_remote_bob, version) -> None:
|
||||
|
||||
def test_send_and_receive_message(alice_and_remote_bob) -> None:
|
||||
"""Test other-core Bob profile can send a message to Alice on current core."""
|
||||
alice, alice_contact_bob, remote_eval = alice_and_remote_bob("2.20.0")
|
||||
alice, alice_contact_bob, remote_eval = alice_and_remote_bob("2.24.0")
|
||||
|
||||
remote_eval("bob_contact_alice.create_chat().send_text('hello')")
|
||||
|
||||
@@ -46,7 +46,7 @@ def test_send_and_receive_message(alice_and_remote_bob) -> None:
|
||||
|
||||
def test_second_device(acfactory, alice_and_remote_bob) -> None:
|
||||
"""Test setting up current version as a second device for old version."""
|
||||
_alice, alice_contact_bob, remote_eval = alice_and_remote_bob("2.20.0")
|
||||
_alice, alice_contact_bob, remote_eval = alice_and_remote_bob("2.24.0")
|
||||
|
||||
remote_eval("locals().setdefault('future', bob._rpc.provide_backup.future(bob.id))")
|
||||
qr = remote_eval("bob._rpc.get_backup_qr(bob.id)")
|
||||
|
||||
@@ -17,6 +17,13 @@ import pytest
|
||||
from deltachat_rpc_client import EventType
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _xfail_underscore_domain():
|
||||
domain = os.environ.get("CHATMAIL_DOMAIN", "")
|
||||
if domain.startswith("_"):
|
||||
pytest.xfail("Iroh tests are expected to fail on underscore domains (self-signed TLS certificates)")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def path_to_webxdc(request):
|
||||
p = request.path.parent.parent.parent.joinpath("test-data/webxdc/chess.xdc")
|
||||
|
||||
@@ -120,7 +120,7 @@ def test_change_address(acfactory) -> None:
|
||||
assert sender_addr2 == new_alice_addr
|
||||
|
||||
|
||||
def test_download_on_demand(acfactory) -> None:
|
||||
def test_download_on_demand(acfactory, data) -> None:
|
||||
alice, bob = acfactory.get_online_accounts(2)
|
||||
alice.set_config("download_limit", "1")
|
||||
|
||||
@@ -131,7 +131,7 @@ def test_download_on_demand(acfactory) -> None:
|
||||
|
||||
alice.create_chat(bob)
|
||||
chat_bob_alice = bob.create_chat(alice)
|
||||
chat_bob_alice.send_message(file="../test-data/image/screenshot.jpg")
|
||||
chat_bob_alice.send_message(file=data.get_path("image/screenshot.jpg"))
|
||||
msg = alice.wait_for_incoming_msg()
|
||||
snapshot = msg.get_snapshot()
|
||||
assert snapshot.download_state == DownloadState.AVAILABLE
|
||||
|
||||
@@ -141,10 +141,9 @@ def test_qr_securejoin_broadcast(acfactory, all_devices_online):
|
||||
|
||||
def wait_for_broadcast_messages(ac):
|
||||
snapshot1 = ac.wait_for_incoming_msg().get_snapshot()
|
||||
assert snapshot1.text == "You joined the channel."
|
||||
|
||||
snapshot2 = ac.wait_for_incoming_msg().get_snapshot()
|
||||
assert snapshot2.text == "Hello everyone!"
|
||||
texts = {snapshot1.text, snapshot2.text}
|
||||
assert texts == {"You joined the channel.", "Hello everyone!"}
|
||||
|
||||
chat = get_broadcast(ac)
|
||||
assert snapshot1.chat_id == chat.id
|
||||
|
||||
@@ -97,8 +97,11 @@ def test_lowercase_address(acfactory) -> None:
|
||||
|
||||
def test_configure_ip(acfactory) -> None:
|
||||
addr, password = acfactory.get_credentials()
|
||||
domain = addr.rsplit("@")[-1]
|
||||
if domain.startswith("_"):
|
||||
pytest.skip("Underscore domains accept invalid certificates")
|
||||
account = acfactory.get_unconfigured_account()
|
||||
ip_address = socket.gethostbyname(addr.rsplit("@")[-1])
|
||||
ip_address = socket.gethostbyname(domain)
|
||||
|
||||
with pytest.raises(JsonRpcError):
|
||||
account.add_or_update_transport(
|
||||
@@ -1012,7 +1015,8 @@ def test_configured_imap_certificate_checks(acfactory):
|
||||
alice = acfactory.new_configured_account()
|
||||
|
||||
# Certificate checks should be configured (not None)
|
||||
assert "cert_strict" in alice.get_info().used_transport_settings
|
||||
info = alice.get_info()
|
||||
assert "cert_automatic" in info.used_transport_settings
|
||||
|
||||
# "cert_old_automatic" is the value old Delta Chat core versions used
|
||||
# to mean user entered "imap_certificate_checks=0" (Automatic)
|
||||
@@ -1361,7 +1365,7 @@ def test_synchronize_member_list_on_group_rejoin(acfactory, log):
|
||||
assert msg.get_snapshot().chat.num_contacts() == 2
|
||||
|
||||
|
||||
def test_large_message(acfactory) -> None:
|
||||
def test_large_message(acfactory, data) -> None:
|
||||
"""
|
||||
Test sending large message without download limit set,
|
||||
so it is sent with pre-message but downloaded without user interaction.
|
||||
@@ -1371,7 +1375,7 @@ def test_large_message(acfactory) -> None:
|
||||
alice_chat_bob = alice.create_chat(bob)
|
||||
alice_chat_bob.send_message(
|
||||
"Hello World, this message is bigger than 5 bytes",
|
||||
file="../test-data/image/screenshot.jpg",
|
||||
file=data.get_path("image/screenshot.jpg"),
|
||||
)
|
||||
|
||||
msg = bob.wait_for_incoming_msg()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
def test_webxdc(acfactory) -> None:
|
||||
def test_webxdc(acfactory, data) -> None:
|
||||
alice, bob = acfactory.get_online_accounts(2)
|
||||
|
||||
alice_contact_bob = alice.create_contact(bob, "Bob")
|
||||
alice_chat_bob = alice_contact_bob.create_chat()
|
||||
alice_chat_bob.send_message(text="Let's play chess!", file="../test-data/webxdc/chess.xdc")
|
||||
alice_chat_bob.send_message(text="Let's play chess!", file=data.get_path("webxdc/chess.xdc"))
|
||||
|
||||
event = bob.wait_for_incoming_msg_event()
|
||||
bob_chat_alice = bob.get_chat_by_id(event.chat_id)
|
||||
@@ -41,12 +41,12 @@ def test_webxdc(acfactory) -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_webxdc_insert_lots_of_updates(acfactory) -> None:
|
||||
def test_webxdc_insert_lots_of_updates(acfactory, data) -> None:
|
||||
alice, bob = acfactory.get_online_accounts(2)
|
||||
|
||||
alice_contact_bob = alice.create_contact(bob, "Bob")
|
||||
alice_chat_bob = alice_contact_bob.create_chat()
|
||||
message = alice_chat_bob.send_message(text="Let's play chess!", file="../test-data/webxdc/chess.xdc")
|
||||
message = alice_chat_bob.send_message(text="Let's play chess!", file=data.get_path("webxdc/chess.xdc"))
|
||||
|
||||
for i in range(2000):
|
||||
message.send_webxdc_status_update({"payload": str(i)}, "description")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat-rpc-server"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
description = "DeltaChat JSON-RPC server"
|
||||
edition = "2021"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
},
|
||||
"type": "module",
|
||||
"types": "index.d.ts",
|
||||
"version": "2.47.0-dev"
|
||||
"version": "2.46.0-dev"
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ ignore = [
|
||||
skip = [
|
||||
{ name = "async-channel", version = "1.9.0" },
|
||||
{ name = "bitflags", version = "1.3.2" },
|
||||
{ name = "constant_time_eq", version = "0.3.1" },
|
||||
{ name = "derive_more-impl", version = "1.0.0" },
|
||||
{ name = "derive_more", version = "1.0.0" },
|
||||
{ name = "event-listener", version = "2.5.3" },
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "deltachat"
|
||||
version = "2.47.0-dev"
|
||||
version = "2.46.0-dev"
|
||||
license = "MPL-2.0"
|
||||
description = "Python bindings for the Delta Chat Core library using CFFI against the Rust-implemented libdeltachat"
|
||||
readme = "README.rst"
|
||||
|
||||
@@ -1 +1 @@
|
||||
2026-03-19
|
||||
2026-03-14
|
||||
13
src/chat.rs
13
src/chat.rs
@@ -50,7 +50,7 @@ use crate::sync::{self, Sync::*, SyncData};
|
||||
use crate::tools::{
|
||||
IsNoneOrEmpty, SystemTime, buf_compress, create_broadcast_secret, create_id,
|
||||
create_outgoing_rfc724_mid, create_smeared_timestamp, create_smeared_timestamps, get_abs_path,
|
||||
gm2local_offset, normalize_text, smeared_time, time,
|
||||
gm2local_offset, normalize_text, smeared_time, time, truncate_msg_text,
|
||||
};
|
||||
use crate::webxdc::StatusUpdateSerial;
|
||||
|
||||
@@ -1742,6 +1742,7 @@ impl Chat {
|
||||
///
|
||||
/// If `update_msg_id` is set, that record is reused;
|
||||
/// if `update_msg_id` is None, a new record is created.
|
||||
#[expect(clippy::arithmetic_side_effects)]
|
||||
async fn prepare_msg_raw(
|
||||
&mut self,
|
||||
context: &Context,
|
||||
@@ -1886,8 +1887,7 @@ impl Chat {
|
||||
EphemeralTimer::Enabled { duration } => time().saturating_add(duration.into()),
|
||||
};
|
||||
|
||||
let msg_text = msg.text.clone();
|
||||
|
||||
let (msg_text, was_truncated) = truncate_msg_text(context, msg.text.clone()).await?;
|
||||
let new_mime_headers = if msg.has_html() {
|
||||
msg.param.get(Param::SendHtml).map(|s| s.to_string())
|
||||
} else {
|
||||
@@ -1900,6 +1900,13 @@ impl Chat {
|
||||
html_part.write_part(cursor).ok();
|
||||
String::from_utf8_lossy(&buffer).to_string()
|
||||
});
|
||||
let new_mime_headers = new_mime_headers.or_else(|| match was_truncated {
|
||||
// We need to add some headers so that they are stripped before formatting HTML by
|
||||
// `MsgId::get_html()`, not a part of the actual text. Let's add "Content-Type", it's
|
||||
// anyway a useful metadata about the stored text.
|
||||
true => Some("Content-Type: text/plain; charset=utf-8\r\n\r\n".to_string() + &msg.text),
|
||||
false => None,
|
||||
});
|
||||
let new_mime_headers = match new_mime_headers {
|
||||
Some(h) => Some(tokio::task::block_in_place(move || {
|
||||
buf_compress(h.as_bytes())
|
||||
|
||||
@@ -227,18 +227,7 @@ impl WeakContext {
|
||||
pub struct InnerContext {
|
||||
/// Blob directory path
|
||||
pub(crate) blobdir: PathBuf,
|
||||
|
||||
pub(crate) sql: Sql,
|
||||
|
||||
/// True if long text messages should be truncated
|
||||
/// and full message HTML added.
|
||||
///
|
||||
/// This should be set by the UIs that cannot handle
|
||||
/// long messages but can display HTML messages.
|
||||
///
|
||||
/// Ignored for bots, bots never get truncated messages.
|
||||
pub(crate) truncate_long_messages: AtomicBool,
|
||||
|
||||
pub(crate) smeared_timestamp: SmearedTimestamp,
|
||||
/// The global "ongoing" process state.
|
||||
///
|
||||
@@ -502,7 +491,6 @@ impl Context {
|
||||
blobdir,
|
||||
running_state: RwLock::new(Default::default()),
|
||||
sql: Sql::new(dbfile),
|
||||
truncate_long_messages: AtomicBool::new(true),
|
||||
smeared_timestamp: SmearedTimestamp::new(),
|
||||
oauth2_mutex: Mutex::new(()),
|
||||
wrong_pw_warning_mutex: Mutex::new(()),
|
||||
|
||||
17
src/html.rs
17
src/html.rs
@@ -30,7 +30,7 @@ impl Message {
|
||||
/// The corresponding ffi-function is `dc_msg_has_html()`.
|
||||
/// To get the HTML-code of the message, use `MsgId.get_html()`.
|
||||
pub fn has_html(&self) -> bool {
|
||||
self.mime_modified || self.full_text.is_some()
|
||||
self.mime_modified
|
||||
}
|
||||
|
||||
/// Set HTML-part part of a message that is about to be sent.
|
||||
@@ -279,19 +279,8 @@ impl MsgId {
|
||||
Ok((parser, _)) => Ok(Some(parser.html)),
|
||||
}
|
||||
} else {
|
||||
let msg = Message::load_from_db(context, self).await?;
|
||||
if let Some(full_text) = &msg.full_text {
|
||||
let html = PlainText {
|
||||
text: full_text.clone(),
|
||||
flowed: false,
|
||||
delsp: false,
|
||||
}
|
||||
.to_html();
|
||||
Ok(Some(html))
|
||||
} else {
|
||||
warn!(context, "get_html: no mime for {}", self);
|
||||
Ok(None)
|
||||
}
|
||||
warn!(context, "get_html: no mime for {}", self);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use anyhow::{Context as _, Result, ensure, format_err};
|
||||
use deltachat_contact_tools::{VcardContact, parse_vcard};
|
||||
@@ -35,9 +34,10 @@ use crate::reaction::get_msg_reactions;
|
||||
use crate::sql;
|
||||
use crate::summary::Summary;
|
||||
use crate::sync::SyncData;
|
||||
use crate::tools::create_outgoing_rfc724_mid;
|
||||
use crate::tools::{
|
||||
buf_compress, buf_decompress, create_outgoing_rfc724_mid, get_filebytes, get_filemeta,
|
||||
gm2local_offset, read_file, sanitize_filename, time, timestamp_to_str, truncate_msg_text,
|
||||
buf_compress, buf_decompress, get_filebytes, get_filemeta, gm2local_offset, read_file,
|
||||
sanitize_filename, time, timestamp_to_str,
|
||||
};
|
||||
|
||||
/// Message ID, including reserved IDs.
|
||||
@@ -431,13 +431,7 @@ pub struct Message {
|
||||
pub(crate) timestamp_rcvd: i64,
|
||||
pub(crate) ephemeral_timer: EphemeralTimer,
|
||||
pub(crate) ephemeral_timestamp: i64,
|
||||
|
||||
/// Message text, possibly truncated if the message is large.
|
||||
pub(crate) text: String,
|
||||
|
||||
/// Full text if the message text is truncated.
|
||||
pub(crate) full_text: Option<String>,
|
||||
|
||||
/// Text that is added to the end of Message.text
|
||||
///
|
||||
/// Currently used for adding the download information on pre-messages
|
||||
@@ -562,7 +556,6 @@ impl Message {
|
||||
}
|
||||
_ => String::new(),
|
||||
};
|
||||
|
||||
let msg = Message {
|
||||
id: row.get("id")?,
|
||||
rfc724_mid: row.get::<_, String>("rfc724mid")?,
|
||||
@@ -587,7 +580,6 @@ impl Message {
|
||||
original_msg_id: row.get("original_msg_id")?,
|
||||
mime_modified: row.get("mime_modified")?,
|
||||
text,
|
||||
full_text: None,
|
||||
additional_text: String::new(),
|
||||
subject: row.get("subject")?,
|
||||
param: row.get::<_, String>("param")?.parse().unwrap_or_default(),
|
||||
@@ -605,15 +597,6 @@ impl Message {
|
||||
.with_context(|| format!("failed to load message {id} from the database"))?;
|
||||
|
||||
if let Some(msg) = &mut msg {
|
||||
if !msg.mime_modified {
|
||||
let (truncated_text, was_truncated) =
|
||||
truncate_msg_text(context, msg.text.clone()).await?;
|
||||
if was_truncated {
|
||||
msg.full_text = Some(msg.text.clone());
|
||||
msg.text = truncated_text;
|
||||
}
|
||||
}
|
||||
|
||||
msg.additional_text =
|
||||
Self::get_additional_text(context, msg.download_state, &msg.param).await?;
|
||||
}
|
||||
@@ -2399,22 +2382,5 @@ impl Viewtype {
|
||||
}
|
||||
}
|
||||
|
||||
/// Opt out of truncating long messages.
|
||||
///
|
||||
/// After calling this function, long messages
|
||||
/// will not be truncated during loading.
|
||||
///
|
||||
/// UIs should call this function if they
|
||||
/// can handle long messages by cutting them
|
||||
/// and displaying "Show full message" option.
|
||||
///
|
||||
/// Has no effect for bots which never
|
||||
/// truncate messages when loading.
|
||||
pub fn dont_truncate_long_messages(context: &Context) {
|
||||
context
|
||||
.truncate_long_messages
|
||||
.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod message_tests;
|
||||
|
||||
@@ -32,7 +32,9 @@ use crate::message::{self, Message, MsgId, Viewtype, get_vcard_summary, set_msg_
|
||||
use crate::param::{Param, Params};
|
||||
use crate::simplify::{SimplifiedText, simplify};
|
||||
use crate::sync::SyncItems;
|
||||
use crate::tools::{get_filemeta, parse_receive_headers, smeared_time, time, validate_id};
|
||||
use crate::tools::{
|
||||
get_filemeta, parse_receive_headers, smeared_time, time, truncate_msg_text, validate_id,
|
||||
};
|
||||
use crate::{chatlist_events, location, tools};
|
||||
|
||||
/// Public key extracted from `Autocrypt-Gossip`
|
||||
@@ -1470,6 +1472,12 @@ impl MimeMessage {
|
||||
(simplified_txt, top_quote)
|
||||
};
|
||||
|
||||
let (simplified_txt, was_truncated) =
|
||||
truncate_msg_text(context, simplified_txt).await?;
|
||||
if was_truncated {
|
||||
self.is_mime_modified = was_truncated;
|
||||
}
|
||||
|
||||
if !simplified_txt.is_empty() || simplified_quote.is_some() {
|
||||
let mut part = Part {
|
||||
dehtml_failed,
|
||||
|
||||
@@ -1286,12 +1286,12 @@ async fn test_mime_modified_large_plain() -> Result<()> {
|
||||
|
||||
{
|
||||
let mimemsg = MimeMessage::from_bytes(&t, long_txt.as_ref()).await?;
|
||||
assert!(!mimemsg.is_mime_modified);
|
||||
assert!(mimemsg.parts[0].msg.matches("just repeated").count() == REPEAT_CNT);
|
||||
assert_eq!(
|
||||
mimemsg.parts[0].msg.len() + 1,
|
||||
REPEAT_TXT.len() * REPEAT_CNT
|
||||
assert!(mimemsg.is_mime_modified);
|
||||
assert!(
|
||||
mimemsg.parts[0].msg.matches("just repeated").count()
|
||||
<= DC_DESIRED_TEXT_LEN / REPEAT_TXT.len()
|
||||
);
|
||||
assert!(mimemsg.parts[0].msg.len() <= DC_DESIRED_TEXT_LEN + DC_ELLIPSIS.len());
|
||||
}
|
||||
|
||||
for draft in [false, true] {
|
||||
|
||||
@@ -829,7 +829,7 @@ pub(crate) async fn login_param_from_account_qr(
|
||||
..Default::default()
|
||||
},
|
||||
smtp: Default::default(),
|
||||
certificate_checks: EnteredCertificateChecks::Strict,
|
||||
certificate_checks: EnteredCertificateChecks::Automatic,
|
||||
oauth2: false,
|
||||
};
|
||||
return Ok(param);
|
||||
|
||||
@@ -754,6 +754,39 @@ async fn test_decode_empty_account() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_decode_account_underscore_domain() -> Result<()> {
|
||||
let ctx = TestContext::new().await;
|
||||
|
||||
// Underscore domain is kept as-is.
|
||||
let qr = check_qr(&ctx.ctx, "dcaccount:_example.org").await?;
|
||||
assert_eq!(
|
||||
qr,
|
||||
Qr::Account {
|
||||
domain: "_example.org".to_string()
|
||||
}
|
||||
);
|
||||
|
||||
// Verify login params use Automatic for underscore domain.
|
||||
// The TLS layer handles underscore domains via NoCertificateVerification in Rustls.
|
||||
let param = login_param_from_account_qr(&ctx.ctx, "dcaccount:_example.org").await?;
|
||||
assert!(param.addr.ends_with("@_example.org"));
|
||||
assert_eq!(
|
||||
param.certificate_checks,
|
||||
EnteredCertificateChecks::Automatic
|
||||
);
|
||||
|
||||
// Regular domain also uses Automatic.
|
||||
let param = login_param_from_account_qr(&ctx.ctx, "dcaccount:example.org").await?;
|
||||
assert!(param.addr.ends_with("@example.org"));
|
||||
assert_eq!(
|
||||
param.certificate_checks,
|
||||
EnteredCertificateChecks::Automatic
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_decode_tg_socks_proxy() -> Result<()> {
|
||||
let t = TestContext::new().await;
|
||||
|
||||
@@ -3585,17 +3585,39 @@ async fn test_big_forwarded_with_big_attachment() -> Result<()> {
|
||||
.starts_with("this text with 42 chars is just repeated.")
|
||||
);
|
||||
assert!(msg.get_text().ends_with("[...]"));
|
||||
assert!(msg.has_html());
|
||||
let html = msg.id.get_html(t).await?.unwrap();
|
||||
assert_eq!(
|
||||
html.matches("this text with 42 chars is just repeated.")
|
||||
.count(),
|
||||
128
|
||||
);
|
||||
assert!(!msg.has_html());
|
||||
|
||||
let msg = Message::load_from_db(t, rcvd.msg_ids[2]).await?;
|
||||
assert_eq!(msg.get_viewtype(), Viewtype::File);
|
||||
assert!(!msg.has_html());
|
||||
assert!(msg.has_html());
|
||||
let html = msg.id.get_html(t).await?.unwrap();
|
||||
let tail = html
|
||||
.split_once("Hello!")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_once("From: AAA")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_once("aaa@example.org")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_once("To: Alice")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_once("alice@example.org")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_once("Subject: Some subject")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_once("Date: Fri, 2 Jun 2023 12:29:17 +0000")
|
||||
.unwrap()
|
||||
.1;
|
||||
assert_eq!(
|
||||
tail.matches("this text with 42 chars is just repeated.")
|
||||
.count(),
|
||||
128
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ use std::mem;
|
||||
use std::ops::{AddAssign, Deref};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::from_utf8;
|
||||
use std::sync::atomic::Ordering;
|
||||
// If a time value doesn't need to be sent to another host, saved to the db or otherwise used across
|
||||
// program restarts, a monotonically nondecreasing clock (`Instant`) should be used. But as
|
||||
// `Instant` may use `libc::clock_gettime(CLOCK_MONOTONIC)`, e.g. on Android, and does not advance
|
||||
@@ -140,9 +139,7 @@ pub(crate) fn truncate_by_lines(
|
||||
///
|
||||
/// Returns the resulting text and a bool telling whether a truncation was done.
|
||||
pub(crate) async fn truncate_msg_text(context: &Context, text: String) -> Result<(String, bool)> {
|
||||
if !context.truncate_long_messages.load(Ordering::Relaxed)
|
||||
|| context.get_config_bool(Config::Bot).await?
|
||||
{
|
||||
if context.get_config_bool(Config::Bot).await? {
|
||||
return Ok((text, false));
|
||||
}
|
||||
// Truncate text if it has too many lines
|
||||
|
||||
Reference in New Issue
Block a user