basic creation
This commit is contained in:
parent
8b072325d8
commit
e15b2b407a
14 changed files with 1258 additions and 8 deletions
307
Cargo.lock
generated
307
Cargo.lock
generated
|
|
@ -7,8 +7,11 @@ name = "Iota"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
|
"futures-util",
|
||||||
"json",
|
"json",
|
||||||
|
"tokio",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -32,6 +35,12 @@ version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
|
@ -116,12 +125,27 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.10.1"
|
version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
|
@ -193,6 +217,17 @@ version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
|
@ -212,6 +247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-macro",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
|
@ -229,6 +265,17 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
|
@ -347,6 +394,16 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "json"
|
name = "json"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
|
@ -359,6 +416,16 @@ version = "0.2.175"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.27"
|
version = "0.4.27"
|
||||||
|
|
@ -400,7 +467,7 @@ checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||||
"windows-sys",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -418,6 +485,29 @@ version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
|
|
@ -495,7 +585,30 @@ version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.3.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.17.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom 0.2.16",
|
||||||
|
"libc",
|
||||||
|
"untrusted",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -504,6 +617,39 @@ version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.23.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"rustls-webpki",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pki-types"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
|
||||||
|
dependencies = [
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.103.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.22"
|
version = "1.0.22"
|
||||||
|
|
@ -516,6 +662,12 @@ version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
|
|
@ -581,6 +733,21 @@ dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
|
|
@ -600,9 +767,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.106"
|
version = "2.0.106"
|
||||||
|
|
@ -651,11 +824,13 @@ dependencies = [
|
||||||
"io-uring",
|
"io-uring",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
"slab",
|
"slab",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -669,6 +844,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.26.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-tungstenite"
|
name = "tokio-tungstenite"
|
||||||
version = "0.27.0"
|
version = "0.27.0"
|
||||||
|
|
@ -677,8 +862,12 @@ checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
|
"webpki-roots 0.26.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -741,6 +930,8 @@ dependencies = [
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
"rand",
|
"rand",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
"sha1",
|
"sha1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
|
|
@ -758,12 +949,29 @@ version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf-8"
|
name = "utf-8"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.3",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
|
@ -785,6 +993,91 @@ dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.26.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
|
||||||
|
dependencies = [
|
||||||
|
"webpki-roots 1.0.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.59.0"
|
version = "0.59.0"
|
||||||
|
|
@ -883,3 +1176,9 @@ dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||||
|
|
|
||||||
15
Cargo.toml
15
Cargo.toml
|
|
@ -4,6 +4,19 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio-tungstenite = "*"
|
|
||||||
json = "*"
|
json = "*"
|
||||||
axum = "*"
|
axum = "*"
|
||||||
|
futures-util = "*"
|
||||||
|
|
||||||
|
[dependencies.tokio-tungstenite]
|
||||||
|
version = "*"
|
||||||
|
default-features = false
|
||||||
|
features = ["rustls-tls-webpki-roots"]
|
||||||
|
|
||||||
|
[dependencies.tokio]
|
||||||
|
version = "*"
|
||||||
|
features = ["full"]
|
||||||
|
|
||||||
|
[dependencies.uuid]
|
||||||
|
version = "*"
|
||||||
|
features = ["v4"]
|
||||||
|
|
|
||||||
243
src/data/communication.rs
Normal file
243
src/data/communication.rs
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
use json::{object, JsonValue};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum DataTypes {
|
||||||
|
ErrorType,
|
||||||
|
ChatPartnerId,
|
||||||
|
IotaId,
|
||||||
|
UserId,
|
||||||
|
UserIds,
|
||||||
|
UserState,
|
||||||
|
UserStates,
|
||||||
|
UserPings,
|
||||||
|
CallState,
|
||||||
|
ScreenShare,
|
||||||
|
PrivateKeyHash,
|
||||||
|
Accepted,
|
||||||
|
AcceptedProfiles,
|
||||||
|
DeniedProfiles,
|
||||||
|
MessageContent,
|
||||||
|
MessageChunk,
|
||||||
|
SendTime,
|
||||||
|
GetTime,
|
||||||
|
GetVariant,
|
||||||
|
SharedSecretOwn,
|
||||||
|
SharedSecretOther,
|
||||||
|
SharedSecretSign,
|
||||||
|
SharedSecret,
|
||||||
|
CallId,
|
||||||
|
CallName,
|
||||||
|
CallSecretSha,
|
||||||
|
CallSecret,
|
||||||
|
SharedCallSecret,
|
||||||
|
StartDate,
|
||||||
|
EndDate,
|
||||||
|
ReceiverId,
|
||||||
|
SenderId,
|
||||||
|
Signature,
|
||||||
|
Signed,
|
||||||
|
Message,
|
||||||
|
LastPing,
|
||||||
|
PingIota,
|
||||||
|
PingClients,
|
||||||
|
Matches,
|
||||||
|
Omikron,
|
||||||
|
LoadedMessages,
|
||||||
|
MessageAmount,
|
||||||
|
Position,
|
||||||
|
Name,
|
||||||
|
Path,
|
||||||
|
Codec,
|
||||||
|
Function,
|
||||||
|
Payload,
|
||||||
|
Result,
|
||||||
|
Interactables,
|
||||||
|
WantToWatch,
|
||||||
|
Watcher,
|
||||||
|
CreatedAt,
|
||||||
|
Username,
|
||||||
|
Display,
|
||||||
|
Avatar,
|
||||||
|
About,
|
||||||
|
Status,
|
||||||
|
PublicKey,
|
||||||
|
SubLevel,
|
||||||
|
SubEnd,
|
||||||
|
CommunityAddress,
|
||||||
|
Challenge,
|
||||||
|
CommunityTitle,
|
||||||
|
Communities,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum CommunicationType {
|
||||||
|
Error,
|
||||||
|
Success,
|
||||||
|
Message,
|
||||||
|
MessageLive,
|
||||||
|
MessageOtherIota,
|
||||||
|
MessageChunk,
|
||||||
|
MessageGet,
|
||||||
|
ChangeConfirm,
|
||||||
|
ConfirmReceive,
|
||||||
|
ConfirmRead,
|
||||||
|
GetChats,
|
||||||
|
GetStates,
|
||||||
|
AddCommunity,
|
||||||
|
RemoveCommunity,
|
||||||
|
GetCommunities,
|
||||||
|
Challenge,
|
||||||
|
ChallengeResponse,
|
||||||
|
Register,
|
||||||
|
RegisterResponse,
|
||||||
|
Identification,
|
||||||
|
IdentificationResponse,
|
||||||
|
Ping,
|
||||||
|
Pong,
|
||||||
|
AddChat,
|
||||||
|
SendChat,
|
||||||
|
IotaConnected,
|
||||||
|
IotaClosed,
|
||||||
|
ClientChanged,
|
||||||
|
ClientConnected,
|
||||||
|
ClientClosed,
|
||||||
|
PublicKey,
|
||||||
|
PrivateKey,
|
||||||
|
WebrtcSdp,
|
||||||
|
WebrtcIce,
|
||||||
|
StartStream,
|
||||||
|
EndStream,
|
||||||
|
WatchStream,
|
||||||
|
GetCall,
|
||||||
|
NewCall,
|
||||||
|
CallInvite,
|
||||||
|
EndCall,
|
||||||
|
Function,
|
||||||
|
Update,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum LogLevel {
|
||||||
|
Important = 2,
|
||||||
|
Normal = 1,
|
||||||
|
Debug = 0,
|
||||||
|
None = -1,
|
||||||
|
DebugOnly = -2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LogValue {
|
||||||
|
pub message: String,
|
||||||
|
pub log_level: LogLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogValue {
|
||||||
|
pub fn new(message: impl Into<String>, log_level: LogLevel) -> Self {
|
||||||
|
Self {
|
||||||
|
message: message.into(),
|
||||||
|
log_level,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_json(&self) -> JsonValue {
|
||||||
|
object! {
|
||||||
|
message: self.message.clone(),
|
||||||
|
log_level: self.log_level.clone() as i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CommunicationValue {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub comm_type: CommunicationType,
|
||||||
|
pub log_value: Option<LogValue>,
|
||||||
|
pub sender: Option<Uuid>,
|
||||||
|
pub receiver: Option<Uuid>,
|
||||||
|
pub data: HashMap<DataTypes, JsonValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommunicationValue {
|
||||||
|
pub fn new(comm_type: CommunicationType) -> Self {
|
||||||
|
Self {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
comm_type,
|
||||||
|
log_value: None,
|
||||||
|
sender: None,
|
||||||
|
receiver: None,
|
||||||
|
data: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_log(mut self, log: LogValue) -> Self {
|
||||||
|
self.log_value = Some(log);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_sender(mut self, sender: Uuid) -> Self {
|
||||||
|
self.sender = Some(sender);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_receiver(mut self, receiver: Uuid) -> Self {
|
||||||
|
self.receiver = Some(receiver);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_data(mut self, key: DataTypes, value: JsonValue) -> Self {
|
||||||
|
self.data.insert(key, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_json(&self) -> JsonValue {
|
||||||
|
let mut jdata = object!{};
|
||||||
|
for (k, v) in &self.data {
|
||||||
|
jdata[&format!("{:?}", k)] = v.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
object! {
|
||||||
|
id: self.id.to_string(),
|
||||||
|
type: format!("{:?}", self.comm_type),
|
||||||
|
sender: self.sender.map(|u| u.to_string()).unwrap_or_default(),
|
||||||
|
receiver: self.receiver.map(|u| u.to_string()).unwrap_or_default(),
|
||||||
|
log: self.log_value.as_ref().map(|l| l.to_json()).unwrap_or(JsonValue::Null),
|
||||||
|
data: jdata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_json(json_str: &str) -> Result<Self, String> {
|
||||||
|
let parsed = json::parse(json_str).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let message_id = parsed["id"].as_str()
|
||||||
|
.and_then(|s| Uuid::parse_str(s).ok())
|
||||||
|
.unwrap_or_else(|| Uuid::new_v4());
|
||||||
|
|
||||||
|
let comm_type = match parsed["type"].as_str() {
|
||||||
|
Some("Message") => CommunicationType::Message,
|
||||||
|
Some("Success") => CommunicationType::Success,
|
||||||
|
_ => CommunicationType::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
let sender = parsed["sender"].as_str().and_then(|s| Uuid::parse_str(s).ok());
|
||||||
|
let receiver = parsed["receiver"].as_str().and_then(|s| Uuid::parse_str(s).ok());
|
||||||
|
|
||||||
|
let log_value = if parsed["log"].is_object() {
|
||||||
|
Some(LogValue::new(
|
||||||
|
parsed["log"]["message"].as_str().unwrap_or("").to_string(),
|
||||||
|
LogLevel::Normal,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
id: message_id,
|
||||||
|
comm_type,
|
||||||
|
log_value,
|
||||||
|
sender,
|
||||||
|
receiver,
|
||||||
|
data: HashMap::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/data/mod.rs
Normal file
1
src/data/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod communication;
|
||||||
15
src/main.rs
15
src/main.rs
|
|
@ -1,5 +1,16 @@
|
||||||
use json;
|
use json::{self, JsonValue};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
mod data;
|
||||||
|
mod omikron;
|
||||||
|
|
||||||
|
use crate::omikron::omikronConnection::{OmikronConnection};
|
||||||
|
use crate::data::communication::{CommunicationValue, LogLevel, LogValue, CommunicationType, DataTypes};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
let omikron = OmikronConnection::new();
|
||||||
|
rt.block_on(async {
|
||||||
|
omikron.connect().await;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
src/omikron/mod.rs
Normal file
1
src/omikron/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod omikronConnection;
|
||||||
147
src/omikron/omikronConnection.rs
Normal file
147
src/omikron/omikronConnection.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
use futures_util::{SinkExt, StreamExt};
|
||||||
|
use tokio_tungstenite::tungstenite::Utf8Bytes;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use tokio::net::TcpStream;
|
||||||
|
use tokio::time::{sleep, Duration};
|
||||||
|
use tokio_tungstenite::{
|
||||||
|
client_async,
|
||||||
|
tungstenite::protocol::Message,
|
||||||
|
MaybeTlsStream,
|
||||||
|
WebSocketStream,
|
||||||
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct OmikronConnection {
|
||||||
|
writer: Arc<Mutex<Option<futures_util::stream::SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>>>>,
|
||||||
|
waiting: Arc<Mutex<HashMap<Uuid, Box<dyn Fn(String) + Send>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OmikronConnection {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
writer: Arc::new(Mutex::new(None)),
|
||||||
|
waiting: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connect(&self) {
|
||||||
|
loop {
|
||||||
|
match connect_async("wss://tensamin.methanium.net/ws/iota/").await {
|
||||||
|
Ok((ws_stream, _)) => {
|
||||||
|
println!("[Omikron] Connected to server");
|
||||||
|
|
||||||
|
// Split into writer + reader
|
||||||
|
let (write_half, read_half) = ws_stream.split();
|
||||||
|
*self.writer.lock().await = Some(write_half);
|
||||||
|
|
||||||
|
// Spawn listener with read_half
|
||||||
|
self.spawn_listener(read_half);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!(
|
||||||
|
"[Omikron] Connection failed: {}. Retrying in 2s...",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
sleep(Duration::from_secs(2)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn close(&self) {
|
||||||
|
let mut writer = self.writer.lock().await;
|
||||||
|
if let Some(mut ws) = writer.take() {
|
||||||
|
let _ = ws.close().await;
|
||||||
|
}
|
||||||
|
println!("[Omikron] Connection closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_listener(
|
||||||
|
&self,
|
||||||
|
mut read_half: futures_util::stream::SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
|
||||||
|
) {
|
||||||
|
let waiting = self.waiting.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Some(msg) = read_half.next().await {
|
||||||
|
match msg {
|
||||||
|
Ok(Message::Text(text)) => {
|
||||||
|
println!("[Omikron] Message received: {}", text);
|
||||||
|
|
||||||
|
if text.contains("\"type\":\"pong\"") {
|
||||||
|
println!("[Omikron] Pong received");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example: trigger callback if message_id is present
|
||||||
|
if let Some(id_pos) = text.find("\"message_id\":\"") {
|
||||||
|
let s = &text[id_pos + 14..];
|
||||||
|
if let Some(end) = s.find('"') {
|
||||||
|
let mid = &s[..end];
|
||||||
|
if let Ok(uuid) = Uuid::parse_str(mid) {
|
||||||
|
if let Some(callback) =
|
||||||
|
waiting.lock().await.remove(&uuid)
|
||||||
|
{
|
||||||
|
callback(text.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Message::Close(frame)) => {
|
||||||
|
println!("[Omikron] Closed: {:?}", frame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("[Omikron] Error: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_message(&self, msg: &str) {
|
||||||
|
let mut guard = self.writer.lock().await;
|
||||||
|
if let Some(writer) = guard.as_mut() {
|
||||||
|
let utf8: Utf8Bytes = Utf8Bytes::from(msg.to_string());
|
||||||
|
if let Err(e) = writer.send(Message::Text(utf8)).await {
|
||||||
|
println!("[Omikron] Send failed: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_answer<F>(&self, message_id: Uuid, callback: F)
|
||||||
|
where
|
||||||
|
F: Fn(String) + Send + 'static,
|
||||||
|
{
|
||||||
|
tokio::spawn({
|
||||||
|
let waiting = self.waiting.clone();
|
||||||
|
async move {
|
||||||
|
waiting.lock().await.insert(message_id, Box::new(callback));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let omikron = OmikronConnection::new();
|
||||||
|
omikron.connect().await;
|
||||||
|
|
||||||
|
let identification = r#"{
|
||||||
|
"type": "identification",
|
||||||
|
"iota_id": "iota-12345",
|
||||||
|
"user_ids": ["user1", "user2"]
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
omikron.send_message(identification).await;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_secs(30)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/users/contact.rs
Normal file
0
src/users/contact.rs
Normal file
1
src/users/mod.rs
Normal file
1
src/users/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod contact;
|
||||||
212
src/util/chatFiles.rs
Normal file
212
src/util/chatFiles.rs
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
|
||||||
|
use json::{self, Value};
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum MessageState {
|
||||||
|
Read,
|
||||||
|
Received,
|
||||||
|
Sending,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageState {
|
||||||
|
fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
MessageState::Read => "READ",
|
||||||
|
MessageState::Received => "RECEIVED",
|
||||||
|
MessageState::Sending => "SENDING",
|
||||||
|
MessageState::Error => "ERROR",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ChatFiles;
|
||||||
|
|
||||||
|
impl ChatFiles {
|
||||||
|
fn load_file(dir: &str, file_name: &str) -> String {
|
||||||
|
let path = Path::new(dir).join(file_name);
|
||||||
|
if let Ok(mut f) = File::open(&path) {
|
||||||
|
let mut content = String::new();
|
||||||
|
let _ = f.read_to_string(&mut content);
|
||||||
|
content
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_file(dir: &str, file_name: &str, content: &str) -> std::io::Result<()> {
|
||||||
|
fs::create_dir_all(dir)?;
|
||||||
|
let path = Path::new(dir).join(file_name);
|
||||||
|
let mut file = File::create(path)?;
|
||||||
|
file.write_all(content.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_message(
|
||||||
|
send_time: i64,
|
||||||
|
storage_owner_is_sender: bool,
|
||||||
|
storage_owner: Uuid,
|
||||||
|
external_user: Uuid,
|
||||||
|
message: &str,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
let user_dir = format!("users/{}/chats/{}", storage_owner, external_user);
|
||||||
|
|
||||||
|
let mut chunk_index = 0;
|
||||||
|
let mut message_chunk = array![];
|
||||||
|
|
||||||
|
// find latest chunk not full (max 800 msgs)
|
||||||
|
loop {
|
||||||
|
let file_name = format!("msgs_{}.json", chunk_index);
|
||||||
|
let file_content = Self::load_file(&user_dir, &file_name);
|
||||||
|
|
||||||
|
if !file_content.is_empty() {
|
||||||
|
if let Ok(current_chunk) = json::parse(&file_content) {
|
||||||
|
if current_chunk.len() < 800 {
|
||||||
|
message_chunk = current_chunk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chunk_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let json_obj = object! {
|
||||||
|
"message_time" => send_time,
|
||||||
|
"message_content" => message,
|
||||||
|
"sender_is_me" => storage_owner_is_sender,
|
||||||
|
"message_state" => MessageState::Sending.as_str()
|
||||||
|
};
|
||||||
|
message_chunk.push(json_obj).unwrap();
|
||||||
|
|
||||||
|
Self::save_file(&user_dir, &format!("msgs_{}.json", chunk_index), &message_chunk.dump())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change_message_state(
|
||||||
|
storage_owner: Uuid,
|
||||||
|
external_user: Uuid,
|
||||||
|
timestamp: i64,
|
||||||
|
new_state: MessageState,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
let user_dir = format!("users/{}/chats/{}", storage_owner, external_user);
|
||||||
|
let path = Path::new(&user_dir);
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let entries = fs::read_dir(path)?;
|
||||||
|
for entry in entries {
|
||||||
|
let entry = entry?;
|
||||||
|
let fname = entry.file_name();
|
||||||
|
let fname_str = fname.to_string_lossy();
|
||||||
|
|
||||||
|
if fname_str.starts_with("msgs_") && fname_str.ends_with(".json") {
|
||||||
|
let file_content = Self::load_file(&user_dir, &fname_str);
|
||||||
|
if file_content.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(mut chunk) = json::parse(&file_content) {
|
||||||
|
let mut modified = false;
|
||||||
|
for i in 0..chunk.len() {
|
||||||
|
if chunk[i]["message_time"].as_i64() == Some(timestamp) {
|
||||||
|
chunk[i]["message_state"] = JsonValue::from(new_state.as_str());
|
||||||
|
modified = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if modified {
|
||||||
|
Self::save_file(&user_dir, &fname_str, &chunk.dump())?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_messages(
|
||||||
|
storage_owner: Uuid,
|
||||||
|
external_user: Uuid,
|
||||||
|
loaded_messages: usize,
|
||||||
|
amount: usize,
|
||||||
|
) -> JsonValue {
|
||||||
|
let user_dir = format!("users/{}/chats/{}", storage_owner, external_user);
|
||||||
|
let path = Path::new(&user_dir);
|
||||||
|
let mut messages = array![];
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut latest_chunk_index: i32 = -1;
|
||||||
|
if let Ok(entries) = fs::read_dir(path) {
|
||||||
|
for entry in entries.flatten() {
|
||||||
|
let fname = entry.file_name();
|
||||||
|
let fname_str = fname.to_string_lossy();
|
||||||
|
if fname_str.starts_with("msgs_") && fname_str.ends_with(".json") {
|
||||||
|
if let Some(num) = fname_str
|
||||||
|
.strip_prefix("msgs_")
|
||||||
|
.and_then(|s| s.strip_suffix(".json"))
|
||||||
|
{
|
||||||
|
if let Ok(index) = num.parse::<i32>() {
|
||||||
|
if index > latest_chunk_index {
|
||||||
|
latest_chunk_index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if latest_chunk_index == -1 {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut to_skip = loaded_messages;
|
||||||
|
let mut needed = amount;
|
||||||
|
|
||||||
|
for chunk_index in (0..=latest_chunk_index).rev() {
|
||||||
|
if needed == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let file_name = format!("msgs_{}.json", chunk_index);
|
||||||
|
let file_content = Self::load_file(&user_dir, &file_name);
|
||||||
|
if file_content.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Ok(chunk) = json::parse(&file_content) {
|
||||||
|
for i in (0..chunk.len()).rev() {
|
||||||
|
if needed == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if to_skip > 0 {
|
||||||
|
to_skip -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
messages.push(chunk[i].clone()).unwrap();
|
||||||
|
needed -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let owner = Uuid::new_v4();
|
||||||
|
let external = Uuid::new_v4();
|
||||||
|
|
||||||
|
ChatFiles::add_message(1234567890, true, owner, external, "Hello!").unwrap();
|
||||||
|
ChatFiles::change_message_state(owner, external, 1234567890, MessageState::Read).unwrap();
|
||||||
|
let msgs = ChatFiles::get_messages(owner, external, 0, 10);
|
||||||
|
|
||||||
|
println!("Messages: {}", msgs.dump());
|
||||||
|
}
|
||||||
91
src/util/chatsUtil.rs
Normal file
91
src/util/chatsUtil.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
use json::{self, Value};
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::users::Contact::Contact; // assuming you have a Contact struct in a module
|
||||||
|
|
||||||
|
pub struct ChatsUtil;
|
||||||
|
|
||||||
|
impl ChatsUtil {
|
||||||
|
fn load_file(dir: &str, file_name: &str) -> String {
|
||||||
|
let path = Path::new(dir).join(file_name);
|
||||||
|
if let Ok(mut f) = File::open(&path) {
|
||||||
|
let mut content = String::new();
|
||||||
|
let _ = f.read_to_string(&mut content);
|
||||||
|
content
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_file(dir: &str, file_name: &str, content: &str) -> std::io::Result<()> {
|
||||||
|
fs::create_dir_all(dir)?;
|
||||||
|
let path = Path::new(dir).join(file_name);
|
||||||
|
let mut file = File::create(path)?;
|
||||||
|
file.write_all(content.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mod_user(storage_owner: Uuid, contact: Contact) -> std::io::Result<()> {
|
||||||
|
let dir = format!("users/{}/contacts/", storage_owner);
|
||||||
|
let file_name = "contacts.json";
|
||||||
|
let s = Self::load_file(&dir, file_name);
|
||||||
|
|
||||||
|
let mut contacts = if !s.is_empty() {
|
||||||
|
json::parse(&s).unwrap_or(array![])
|
||||||
|
} else {
|
||||||
|
array![]
|
||||||
|
};
|
||||||
|
|
||||||
|
for i in 0..contacts.len() {
|
||||||
|
if contacts[i]["userID"].as_str() == Some(&contact.user_id.to_string()) {
|
||||||
|
contacts.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contacts.push(contact.to_json()).unwrap();
|
||||||
|
Self::save_file(&dir, file_name, &contacts.dump())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_user(storage_owner: Uuid, user_id: Uuid) -> Option<Contact> {
|
||||||
|
let dir = format!("users/{}/contacts/", storage_owner);
|
||||||
|
let file_name = "contacts.json";
|
||||||
|
let s = Self::load_file(&dir, file_name);
|
||||||
|
if s.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(contacts) = json::parse(&s) {
|
||||||
|
for i in 0..contacts.len() {
|
||||||
|
if let Some(uid) = contacts[i]["userID"].as_str() {
|
||||||
|
if Uuid::parse_str(uid).ok()? == user_id {
|
||||||
|
return Contact::from_json(&contacts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_users(storage_owner: Uuid) -> Value {
|
||||||
|
let dir = format!("/users/{}/contacts/", storage_owner);
|
||||||
|
let file_name = "contacts.json";
|
||||||
|
let s = Self::load_file(&dir, file_name);
|
||||||
|
|
||||||
|
let mut contacts_out = array![];
|
||||||
|
if !s.is_empty() {
|
||||||
|
if let Ok(contacts) = json::parse(&s) {
|
||||||
|
for i in 0..contacts.len() {
|
||||||
|
if let Some(c) = Contact::from_json(&contacts[i]) {
|
||||||
|
contacts_out.push(c.info()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contacts_out
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/util/configUtil.rs
Normal file
65
src/util/configUtil.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
use json::JsonValue;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::files::Files;
|
||||||
|
|
||||||
|
pub struct ConfigUtil {
|
||||||
|
pub config: JsonValue,
|
||||||
|
pub unique: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigUtil {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
config: JsonValue::new_object(),
|
||||||
|
unique: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_file(path: &str) -> String {
|
||||||
|
if let Ok(mut f) = File::open(path) {
|
||||||
|
let mut content = String::new();
|
||||||
|
let _ = f.read_to_string(&mut content);
|
||||||
|
content
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_file(path: &str, content: &str) -> std::io::Result<()> {
|
||||||
|
if let Some(parent) = Path::new(path).parent() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
let mut file = File::create(path)?;
|
||||||
|
file.write_all(content.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&mut self) {
|
||||||
|
let s = Self::load_file(Files::MAIN);
|
||||||
|
if !s.is_empty() {
|
||||||
|
self.config = json::parse(&s).unwrap_or(JsonValue::new_object());
|
||||||
|
}
|
||||||
|
if self.config.has("port") {
|
||||||
|
if let Some(port) = self.config["port"].as_i32() {
|
||||||
|
// Set community manager port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change(&mut self, key: &str, value: JsonValue) {
|
||||||
|
self.config[key] = value;
|
||||||
|
self.unique = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self) {
|
||||||
|
if self.unique {
|
||||||
|
let _ = self.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> std::io::Result<()> {
|
||||||
|
Self::save_file(Files::MAIN, &self.config.dump())
|
||||||
|
}
|
||||||
|
}
|
||||||
162
src/util/fileUtil.rs
Normal file
162
src/util/fileUtil.rs
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::process;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
use std::fmt::Write as FmtWrite;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub struct FileUtil;
|
||||||
|
|
||||||
|
impl FileUtil {
|
||||||
|
pub fn delete_file(path: &str, name: &str) -> bool {
|
||||||
|
let dir = Path::new(&Self::get_jar_directory()).join(path);
|
||||||
|
let file = dir.join(name);
|
||||||
|
if !file.exists() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fs::remove_file(file).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_directory(path: &str) -> bool {
|
||||||
|
let dir = Path::new(&Self::get_jar_directory()).join(path);
|
||||||
|
Self::delete_dir_recursive(&dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_dir_recursive(directory: &Path) -> bool {
|
||||||
|
if !directory.exists() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Err(e) = fs::remove_dir_all(directory) {
|
||||||
|
println!("[IMPORTANT] Couldn't delete directory {}: {}", directory.display(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_user_directory(user_id: Uuid) {
|
||||||
|
let user_dir = Path::new(&Self::get_jar_directory())
|
||||||
|
.join("users")
|
||||||
|
.join(user_id.to_string());
|
||||||
|
let _ = Self::delete_dir_recursive(&user_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_file(path: &str, name: &str) -> String {
|
||||||
|
let dir = Path::new(&Self::get_jar_directory()).join(path);
|
||||||
|
let file_path = dir.join(name);
|
||||||
|
|
||||||
|
if !dir.exists() {
|
||||||
|
if let Err(e) = fs::create_dir_all(&dir) {
|
||||||
|
println!("[IMPORTANT] Couldn't create directories: {}", e);
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !file_path.exists() {
|
||||||
|
if let Err(e) = File::create(&file_path) {
|
||||||
|
println!("[IMPORTANT] Couldn't create file: {}", e);
|
||||||
|
}
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut content = String::new();
|
||||||
|
if let Ok(mut f) = File::open(&file_path) {
|
||||||
|
let _ = f.read_to_string(&mut content);
|
||||||
|
}
|
||||||
|
content
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_file(path: &str, name: &str, value: &str) {
|
||||||
|
let dir = Path::new(&Self::get_jar_directory()).join(path);
|
||||||
|
let file_path = dir.join(name);
|
||||||
|
|
||||||
|
if !dir.exists() {
|
||||||
|
if let Err(e) = fs::create_dir_all(&dir) {
|
||||||
|
println!("[IMPORTANT] Couldn't create directories: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = fs::write(&file_path, value) {
|
||||||
|
println!("[IMPORTANT] Couldn't write file {}: {}", file_path.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_jar_directory() -> String {
|
||||||
|
// In Rust, use current_exe as a proxy for JAR directory
|
||||||
|
let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from("."));
|
||||||
|
exe.parent()
|
||||||
|
.unwrap_or(Path::new("."))
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn used_space() -> u64 {
|
||||||
|
Self::get_directory_size(&PathBuf::from(Self::get_jar_directory()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_directory_size(directory: &Path) -> u64 {
|
||||||
|
let mut size = 0;
|
||||||
|
for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) {
|
||||||
|
let path = entry.path();
|
||||||
|
if path.is_file() {
|
||||||
|
if let Ok(metadata) = path.metadata() {
|
||||||
|
size += path
|
||||||
|
.file_name()
|
||||||
|
.unwrap_or(OsStr::new(""))
|
||||||
|
.len() as u64;
|
||||||
|
size += metadata.len();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_designed_storage(user_id: Uuid) -> String {
|
||||||
|
let user_dir = Path::new(&Self::get_jar_directory())
|
||||||
|
.join("users")
|
||||||
|
.join(user_id.to_string());
|
||||||
|
Self::design_byte(Self::get_directory_size(&user_dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn design_byte(bytes: u64) -> String {
|
||||||
|
let mut hr_size = format!("{:.2}B", bytes as f64);
|
||||||
|
let k = bytes as f64 / 1024.0;
|
||||||
|
let m = k / 1024.0;
|
||||||
|
let g = m / 1024.0;
|
||||||
|
let t = g / 1024.0;
|
||||||
|
|
||||||
|
if t >= 1.0 {
|
||||||
|
hr_size = format!("{:.2}TB", t);
|
||||||
|
} else if g >= 1.0 {
|
||||||
|
hr_size = format!("{:.2}GB", g);
|
||||||
|
} else if m >= 1.0 {
|
||||||
|
hr_size = format!("{:.2}MB", m);
|
||||||
|
} else if k >= 1.0 {
|
||||||
|
hr_size = format!("{:.2}KB", k);
|
||||||
|
}
|
||||||
|
hr_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_used_ram() -> String {
|
||||||
|
// Rust has no direct Runtime like Java.
|
||||||
|
// As a placeholder, read process memory usage from sysinfo.
|
||||||
|
use sysinfo::{System, SystemExt, ProcessExt};
|
||||||
|
|
||||||
|
let mut sys = System::new_all();
|
||||||
|
sys.refresh_all();
|
||||||
|
if let Some(process) = sys.process(process::id() as i32) {
|
||||||
|
let used = process.memory() * 1024; // kB to bytes
|
||||||
|
let total = sys.total_memory() * 1024;
|
||||||
|
return format!(
|
||||||
|
"{}/{}",
|
||||||
|
Self::design_byte(used),
|
||||||
|
Self::design_byte(total)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"Unknown".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/util/mod.rs
Normal file
4
src/util/mod.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod fileUtil;
|
||||||
|
pub mod chatFiles;
|
||||||
|
pub mod configUtil;
|
||||||
|
pub mod chatsUtil;
|
||||||
Loading…
Reference in a new issue