Message States, Tauri, Global and Local Settings

This commit is contained in:
Alex Emmet 2026-06-03 20:55:15 +02:00
commit a4ec766351
2 changed files with 376 additions and 153 deletions

162
Cargo.lock generated
View file

@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de7fa236829ba0841304542f7614c42b80fca007455315c45c785ccfa873a85b"
dependencies = [
"actix-rt",
"bitflags 2.11.1",
"bitflags 2.12.1",
"bytes",
"crossbeam-channel",
"futures-core",
@ -31,7 +31,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"bytes",
"futures-core",
"futures-sink",
@ -54,7 +54,7 @@ dependencies = [
"actix-tls",
"actix-utils",
"base64",
"bitflags 2.11.1",
"bitflags 2.12.1",
"brotli",
"bytes",
"bytestring",
@ -211,7 +211,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"smallvec",
"socket2 0.6.3",
"socket2 0.6.4",
"time",
"tracing",
"url",
@ -474,9 +474,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.11.1"
version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
[[package]]
name = "block-buffer"
@ -498,9 +498,9 @@ dependencies = [
[[package]]
name = "brotli"
version = "8.0.2"
version = "8.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560"
checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@ -509,9 +509,9 @@ dependencies = [
[[package]]
name = "brotli-decompressor"
version = "5.0.0"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@ -570,9 +570,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.62"
version = "1.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
dependencies = [
"find-msvc-tools",
"jobserver",
@ -699,9 +699,9 @@ dependencies = [
[[package]]
name = "compact_str"
version = "0.9.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a"
checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab"
dependencies = [
"castaway",
"cfg-if",
@ -832,7 +832,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"crossterm_winapi",
"derive_more",
"document-features",
@ -1039,9 +1039,9 @@ dependencies = [
[[package]]
name = "displaydoc"
version = "0.2.5"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
dependencies = [
"proc-macro2",
"quote",
@ -1421,7 +1421,7 @@ dependencies = [
"fnv",
"futures-core",
"futures-sink",
"http 1.4.0",
"http 1.4.1",
"indexmap",
"slab",
"tokio",
@ -1479,7 +1479,7 @@ dependencies = [
"base64",
"bytes",
"headers-core",
"http 1.4.0",
"http 1.4.1",
"httpdate",
"mime",
"sha1 0.10.6",
@ -1491,7 +1491,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4"
dependencies = [
"http 1.4.0",
"http 1.4.1",
]
[[package]]
@ -1543,9 +1543,9 @@ dependencies = [
[[package]]
name = "http"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0"
dependencies = [
"bytes",
"itoa",
@ -1558,7 +1558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http 1.4.0",
"http 1.4.1",
]
[[package]]
@ -1569,7 +1569,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
"http 1.4.0",
"http 1.4.1",
"http-body",
"pin-project-lite",
]
@ -1597,16 +1597,16 @@ dependencies = [
[[package]]
name = "hyper"
version = "1.9.0"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"
checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
dependencies = [
"atomic-waker",
"bytes",
"futures-channel",
"futures-core",
"h2 0.4.14",
"http 1.4.0",
"http 1.4.1",
"http-body",
"httparse",
"httpdate",
@ -1623,7 +1623,7 @@ version = "0.27.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f"
dependencies = [
"http 1.4.0",
"http 1.4.1",
"hyper",
"hyper-util",
"rustls",
@ -1642,14 +1642,14 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.4.0",
"http 1.4.1",
"http-body",
"hyper",
"ipnet",
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.3",
"socket2 0.6.4",
"system-configuration",
"tokio",
"tower-service",
@ -2276,7 +2276,7 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
]
[[package]]
@ -2325,9 +2325,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.29"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f"
[[package]]
name = "lru"
@ -2366,9 +2366,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.8.0"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
[[package]]
name = "memmem"
@ -2419,9 +2419,9 @@ dependencies = [
[[package]]
name = "mio"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
dependencies = [
"libc",
"log",
@ -2452,7 +2452,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"cfg-if",
"cfg_aliases",
"libc",
@ -2544,7 +2544,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
]
[[package]]
@ -2622,7 +2622,7 @@ version = "0.10.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"cfg-if",
"foreign-types",
"libc",
@ -3073,7 +3073,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
"socket2 0.6.3",
"socket2 0.6.4",
"thiserror 2.0.18",
"tokio",
"tracing",
@ -3111,7 +3111,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2 0.6.3",
"socket2 0.6.4",
"tracing",
"windows-sys 0.60.2",
]
@ -3239,7 +3239,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"compact_str",
"hashbrown 0.16.1",
"indoc",
@ -3291,7 +3291,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"hashbrown 0.16.1",
"indoc",
"instability",
@ -3323,7 +3323,7 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
]
[[package]]
@ -3363,16 +3363,16 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "reqwest"
version = "0.13.3"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"h2 0.4.14",
"http 1.4.0",
"http 1.4.1",
"http-body",
"http-body-util",
"hyper",
@ -3429,7 +3429,7 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
@ -3468,7 +3468,7 @@ version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"errno",
"libc",
"linux-raw-sys",
@ -3493,9 +3493,9 @@ dependencies = [
[[package]]
name = "rustls-native-certs"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63"
checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d"
dependencies = [
"openssl-probe",
"rustls-pki-types",
@ -3609,7 +3609,7 @@ version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@ -3744,9 +3744,9 @@ dependencies = [
[[package]]
name = "shlex"
version = "1.3.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "signal-hook"
@ -3831,9 +3831,9 @@ dependencies = [
[[package]]
name = "socket2"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
dependencies = [
"libc",
"windows-sys 0.61.2",
@ -3841,9 +3841,9 @@ dependencies = [
[[package]]
name = "sqlite-wasm-rs"
version = "0.5.4"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdd578e94101503d97e2b286bbf8db2135035ca24b2ce4cbf3f9e2fb2bbf1eee"
checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75"
dependencies = [
"cc",
"js-sys",
@ -3976,7 +3976,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@ -4033,7 +4033,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7"
dependencies = [
"anyhow",
"base64",
"bitflags 2.11.1",
"bitflags 2.12.1",
"fancy-regex",
"filedescriptor",
"finl_unicode",
@ -4177,7 +4177,7 @@ dependencies = [
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.6.3",
"socket2 0.6.4",
"tokio-macros",
"windows-sys 0.61.2",
]
@ -4261,10 +4261,10 @@ version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"bytes",
"futures-util",
"http 1.4.0",
"http 1.4.1",
"http-body",
"pin-project-lite",
"tower",
@ -4326,7 +4326,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ttp-core"
version = "0.1.0"
source = "git+https://git.methanium.net/Tensamin/TTP.git#886edbf51d26636e46745c3637b80610df82f5dc"
source = "git+https://git.methanium.net/Tensamin/TTP.git#23438fa8f884e6ad0d32ca1004c0dedcce0cc8d2"
dependencies = [
"base64",
"byteorder",
@ -4339,7 +4339,7 @@ dependencies = [
[[package]]
name = "ttp-native"
version = "0.1.0"
source = "git+https://git.methanium.net/Tensamin/TTP.git#886edbf51d26636e46745c3637b80610df82f5dc"
source = "git+https://git.methanium.net/Tensamin/TTP.git#23438fa8f884e6ad0d32ca1004c0dedcce0cc8d2"
dependencies = [
"quinn",
"rustls",
@ -4358,7 +4358,7 @@ checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
dependencies = [
"bytes",
"data-encoding",
"http 1.4.0",
"http 1.4.1",
"httparse",
"log",
"native-tls",
@ -4369,9 +4369,9 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.20.0"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
[[package]]
name = "ucd-trie"
@ -4393,9 +4393,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-segmentation"
version = "1.13.2"
version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
[[package]]
name = "unicode-truncate"
@ -4468,9 +4468,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.23.1"
version = "1.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7"
dependencies = [
"atomic",
"getrandom 0.4.2",
@ -4527,7 +4527,7 @@ dependencies = [
"bytes",
"futures-util",
"headers",
"http 1.4.0",
"http 1.4.1",
"http-body",
"http-body-util",
"log",
@ -4652,7 +4652,7 @@ version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags 2.11.1",
"bitflags 2.12.1",
"hashbrown 0.15.5",
"indexmap",
"semver",
@ -5191,7 +5191,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags 2.11.1",
"bitflags 2.12.1",
"indexmap",
"log",
"serde",
@ -5241,7 +5241,7 @@ dependencies = [
"rustls-native-certs",
"rustls-pki-types",
"sha2 0.11.0",
"socket2 0.6.3",
"socket2 0.6.4",
"thiserror 2.0.18",
"time",
"tokio",
@ -5327,18 +5327,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.48"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.48"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639"
dependencies = [
"proc-macro2",
"quote",

View file

@ -2,14 +2,13 @@ use dashmap::DashMap;
use iota_logger::{log, log_cv_in, log_cv_out, log_t};
use iota_state::{ACTIVE_TASKS, SHUTDOWN};
use iota_storage::users::contact::Contact;
use iota_storage::util::chat_files::{MessageState, change_message_state};
use iota_storage::util::chats_util::{get_user, mod_user};
use iota_storage::util::chat_files::{self, MessageState, change_message_state};
use iota_storage::util::chats_util::{self, get_user, mod_user};
use iota_storage::util::communities_util::CommunitiesUtil;
use iota_storage::util::config_util::CONFIG;
use iota_storage::util::{chat_files, chats_util};
use iota_util::crypto_helper;
use iota_util::crypto_util::{DataFormat, SecurePayload};
use iota_util::file_util::{get_children, load_file, save_file};
use iota_util::file_util::{get_children, has_file, load_file, save_file};
use json::JsonValue;
use std::collections::HashMap;
use std::sync::{Arc, LazyLock};
@ -21,6 +20,18 @@ use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue};
use ttp_native::{Policy, Receiver, SendMode, Sender};
use uuid::Uuid;
// Helper function to check if read receipts are enabled globally
async fn is_read_receipts_enabled() -> bool {
// Check global config for read receipts setting
// Default to true if not set
let conf = CONFIG.read().await;
let value = conf.get("read_receipts_enabled");
match value {
JsonValue::Boolean(b) => *b,
_ => true,
}
}
// ============================================================================
// Configuration
// ============================================================================
@ -933,7 +944,7 @@ impl OmikronConnection {
// Attempt delivery and await a response from the local client
let user_resp = self
.clone()
.await_response(&user_forward, Some(Duration::from_secs(10)))
.await_response(&user_forward, Some(Duration::from_secs(3)))
.await;
if let Ok(user_resp) = user_resp {
@ -959,23 +970,25 @@ impl OmikronConnection {
ms.clone(),
);
// notify original sender about the delivered/read state
self.send_message(
&CommunicationValue::new(CommunicationType::message_state)
.with_id(cv.get_id())
.with_receiver(sender_id as u64)
.with_sender(receiver_id as u64)
.add_data(
DataTypes::chat_partner_id,
DataValue::Number(receiver_id as i64),
)
.add_data(DataTypes::send_time, DataValue::Number(timestamp_i64))
.add_data(
DataTypes::message_state,
DataValue::Str(ms.as_str().to_string()),
),
)
.await;
// notify original sender about the delivered/read state (if read receipts are enabled)
if is_read_receipts_enabled().await {
self.send_message(
&CommunicationValue::new(CommunicationType::message_state)
.with_id(cv.get_id())
.with_receiver(sender_id as u64)
.with_sender(receiver_id as u64)
.add_data(
DataTypes::chat_partner_id,
DataValue::Number(receiver_id as i64),
)
.add_data(DataTypes::send_time, DataValue::Number(timestamp_i64))
.add_data(
DataTypes::message_state,
DataValue::Str(ms.as_str().to_string()),
),
)
.await;
}
} else {
// Delivery failed or timed out; mark as Sent
let _ = chat_files::change_message_state(
@ -1072,7 +1085,7 @@ impl OmikronConnection {
let user_resp = self
.clone()
.await_response(&user_forward, Some(Duration::from_secs(10)))
.await_response(&user_forward, Some(Duration::from_secs(3)))
.await;
if let Ok(user_resp) = user_resp {
@ -1089,22 +1102,25 @@ impl OmikronConnection {
ms.clone(),
);
self.send_message(
&CommunicationValue::new(CommunicationType::message_state)
.with_id(cv.get_id())
.with_receiver(*sender_id)
.with_sender(*receiver_id)
.add_data(DataTypes::send_time, DataValue::Number(timestamp))
.add_data(
DataTypes::chat_partner_id,
DataValue::Number(*sender_id as i64),
)
.add_data(
DataTypes::message_state,
DataValue::Str(ms.as_str().to_string()),
),
)
.await;
// notify original sender about the delivered/read state (if read receipts are enabled)
if is_read_receipts_enabled().await {
self.send_message(
&CommunicationValue::new(CommunicationType::message_state)
.with_id(cv.get_id())
.with_receiver(*sender_id)
.with_sender(*receiver_id)
.add_data(DataTypes::send_time, DataValue::Number(timestamp))
.add_data(
DataTypes::chat_partner_id,
DataValue::Number(*sender_id as i64),
)
.add_data(
DataTypes::message_state,
DataValue::Str(ms.as_str().to_string()),
),
)
.await;
}
} else {
// Delivery timed out/failed — update stored state and notify sender with numeric timestamp
let _ = chat_files::change_message_state(
@ -1306,20 +1322,145 @@ impl OmikronConnection {
return;
}
if cv.is_type(CommunicationType::settings_save) {
if cv.is_type(CommunicationType::global_settings_save) {
let my_id = cv.get_sender();
let settings_name = cv.get_data(DataTypes::settings_name).as_str().unwrap();
let settings_value = cv.get_data(DataTypes::payload).as_str().unwrap();
let Some(settings_value) = cv.get_data(DataTypes::payload).as_str() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing settings payload".to_string()),
);
self.send_message(&response).await;
return;
};
save_file(
&format!("users/{}/settings/", my_id),
&format!("users/{}", my_id),
"global.settings",
settings_value,
);
let mut response = CommunicationValue::new(CommunicationType::global_settings_save)
.with_receiver(my_id)
.with_id(cv.get_id());
if let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() {
response = response.add_data(DataTypes::session_id, DataValue::Number(session_id));
}
self.send_message(&response).await;
return;
}
if cv.is_type(CommunicationType::global_settings_load) {
let my_id = cv.get_sender();
let path = format!("users/{}", my_id);
let name = "global.settings";
if !has_file(&path, name) {
let mut response = CommunicationValue::new(CommunicationType::error_not_found)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(DataTypes::path, DataValue::Str(name.to_string()));
if let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() {
response =
response.add_data(DataTypes::session_id, DataValue::Number(session_id));
}
self.send_message(&response).await;
return;
}
let settings_value_str = load_file(&path, name);
let mut response = CommunicationValue::new(CommunicationType::global_settings_load)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(DataTypes::payload, DataValue::Str(settings_value_str));
if let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() {
response = response.add_data(DataTypes::session_id, DataValue::Number(session_id));
}
self.send_message(&response).await;
return;
}
if cv.is_type(CommunicationType::settings_save) {
let my_id = cv.get_sender();
let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing session_id".to_string()),
);
self.send_message(&response).await;
return;
};
let Some(settings_name) = cv.get_data(DataTypes::settings_name).as_str() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing settings_name".to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
};
let Some(settings_value) = cv.get_data(DataTypes::payload).as_str() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing settings payload".to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
};
if !settings_name
.chars()
.all(|c| c.is_alphanumeric() || c == '_' || c == '-' || c == '.')
|| settings_name.contains("..")
{
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Invalid settings_name".to_string()),
)
.add_data(
DataTypes::settings_name,
DataValue::Str(settings_name.to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
}
save_file(
&format!("users/{}/settings/{}/", my_id, session_id),
&format!("{}.settings", settings_name),
&settings_value,
settings_value,
);
let response = CommunicationValue::new(CommunicationType::settings_save)
.with_receiver(my_id)
.with_id(cv.get_id());
.with_id(cv.get_id())
.add_data(
DataTypes::settings_name,
DataValue::Str(settings_name.to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
@ -1327,16 +1468,76 @@ impl OmikronConnection {
if cv.is_type(CommunicationType::settings_load) {
let my_id = cv.get_sender();
let settings_name = cv.get_data(DataTypes::settings_name).as_string().unwrap();
let settings_value_str = load_file(
&format!("users/{}/settings/", my_id),
&format!("{}.settings", settings_name),
);
let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing session_id".to_string()),
);
self.send_message(&response).await;
return;
};
let Some(settings_name) = cv.get_data(DataTypes::settings_name).as_str() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing settings_name".to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
};
if !settings_name
.chars()
.all(|c| c.is_alphanumeric() || c == '_' || c == '-' || c == '.')
|| settings_name.contains("..")
{
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Invalid settings_name".to_string()),
)
.add_data(
DataTypes::settings_name,
DataValue::Str(settings_name.to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
}
let settings_file = format!("{}.settings", settings_name);
let settings_path = format!("users/{}/settings/{}/", my_id, session_id);
if !has_file(&settings_path, &settings_file) {
let response = CommunicationValue::new(CommunicationType::error_not_found)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::settings_name,
DataValue::Str(settings_name.to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
}
let settings_value_str = load_file(&settings_path, &settings_file);
let response = CommunicationValue::new(CommunicationType::settings_load)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(DataTypes::payload, DataValue::Str(settings_value_str))
.add_data(DataTypes::settings_name, DataValue::Str(settings_name));
.add_data(
DataTypes::settings_name,
DataValue::Str(settings_name.to_string()),
)
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
@ -1344,7 +1545,19 @@ impl OmikronConnection {
if cv.is_type(CommunicationType::settings_list) {
let my_id = cv.get_sender();
let settings = get_children(&format!("users/{}/settings/", my_id));
let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() else {
let response = CommunicationValue::new(CommunicationType::error_invalid_data)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(
DataTypes::message,
DataValue::Str("Missing session_id".to_string()),
);
self.send_message(&response).await;
return;
};
let settings = get_children(&format!("users/{}/settings/{}/", my_id, session_id));
let mut settings_json = Vec::new();
for s in settings {
let s = s.replace(".settings", "");
@ -1356,7 +1569,8 @@ impl OmikronConnection {
let response = CommunicationValue::new(CommunicationType::settings_list)
.with_id(cv.get_id())
.with_receiver(my_id)
.add_data(DataTypes::settings, DataValue::Array(settings_json));
.add_data(DataTypes::settings, DataValue::Array(settings_json))
.add_data(DataTypes::session_id, DataValue::Number(session_id));
self.send_message(&response).await;
return;
@ -1365,29 +1579,38 @@ impl OmikronConnection {
async fn handle_challenge(&self, cv: &CommunicationValue) {
let conf = CONFIG.read().await;
let private_key = conf.get_private_key().unwrap();
let Some(private_key) = conf.get_private_key() else {
drop(conf);
log_t!("omikron_challenge_decryption_failed");
*self.auth_failure.write().await = Some(
"Challenge decryption failed: no private key configured on this Iota.".to_string(),
);
return;
};
drop(conf);
let omikron_public_key = cv.get_data(DataTypes::public_key).as_str().unwrap();
let encrypted_challenge = cv.get_data(DataTypes::challenge).as_str().unwrap();
let solved_challenge = {
if let Ok(decrypted) = SecurePayload::new(
encrypted_challenge,
DataFormat::Base64,
crypto_helper::load_secret_key(&private_key).unwrap(),
) {
if let Ok(decrypted) = decrypted
.decrypt_x448(crypto_helper::load_public_key(omikron_public_key).unwrap())
{
Some(decrypted)
} else {
None
}
} else {
None
}
let Some(omikron_public_key) = cv.get_data(DataTypes::public_key).as_str() else {
log_t!("omikron_challenge_decryption_failed");
return;
};
let Some(encrypted_challenge) = cv.get_data(DataTypes::challenge).as_str() else {
log_t!("omikron_challenge_decryption_failed");
return;
};
let Some(secret_key) = crypto_helper::load_secret_key(&private_key) else {
log_t!("omikron_challenge_decryption_failed");
return;
};
let Some(pub_key) = crypto_helper::load_public_key(omikron_public_key) else {
log_t!("omikron_challenge_decryption_failed");
return;
};
let solved_challenge =
SecurePayload::new(encrypted_challenge, DataFormat::Base64, secret_key)
.ok()
.and_then(|decrypted| decrypted.decrypt_x448(pub_key).ok());
if let Some(decrypted) = solved_challenge {
let solved = decrypted.export(DataFormat::Raw);