Compare commits
No commits in common. "main" and "main" have entirely different histories.
|
@ -2,113 +2,11 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.65.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.22",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.1"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
|
||||
checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
|
@ -116,73 +14,35 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.13.1"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
|
||||
checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 1.0.85",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.13.1"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
|
||||
checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 1.0.85",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
@ -191,220 +51,92 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
version = "0.2.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
|
||||
|
||||
[[package]]
|
||||
name = "libcwtch"
|
||||
version = "0.8.0"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"chrono",
|
||||
"hex-literal",
|
||||
"libc",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"serde_with",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.63"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.6"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.133"
|
||||
version = "1.0.127"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.133"
|
||||
version = "1.0.127"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||
checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.85",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.75"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
|
||||
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "1.11.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad6056b4cb69b6e43e3a0f055def223380baecc99da683884f205bf347f7c4b3"
|
||||
checksum = "062b87e45d8f26714eacfaef0ed9a583e2bfd50ebd96bdd3c200733bd5758e2c"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
"serde",
|
||||
|
@ -413,33 +145,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "1.5.1"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e"
|
||||
checksum = "98c1fcca18d55d1763e1c16873c4bde0ac3ef75179a28c7b372917e0494625be"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.85",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -448,96 +163,17 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.85"
|
||||
version = "1.0.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
||||
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
|
||||
dependencies = [
|
||||
"either",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -1,23 +1,16 @@
|
|||
[package]
|
||||
name = "libcwtch"
|
||||
version = "0.8.0"
|
||||
version = "0.1.0"
|
||||
authors = ["Dan Ballard <dan@mindstab.net>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
description = "libcwtch is an interface to a Cwtch app that allows creating of profiles to communicate with contacts over the Cwtch protocol"
|
||||
repository = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs"
|
||||
readme = "README.md"
|
||||
documentation = "https://docs.rs/libcwtch/"
|
||||
|
||||
[build-dependencies]
|
||||
hex-literal = "0.3.4"
|
||||
sha2 = "0.10.1"
|
||||
bindgen = "0.65.1"
|
||||
documentation = "https://docs.rs/libcwtch/0.1.0/libcwtch/"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0.127", features = ["derive"] }
|
||||
serde_with = { version = "1.10.0" }
|
||||
serde_repr = "0.1"
|
||||
chrono = "0.4.19"
|
||||
|
|
16
README.md
16
README.md
|
@ -1,6 +1,6 @@
|
|||
# libCwtch-rs
|
||||
|
||||
Rust bindings for [libCwtch autobindings](https://git.openprivacy.ca/cwtch.im/autobindings/)
|
||||
Rust bindings for [libCwtch](https://git.openprivacy.ca/cwtch.im/libcwtch-go/)
|
||||
|
||||
Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes tor is on $PATH)
|
||||
|
||||
|
@ -8,12 +8,16 @@ Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes
|
|||
|
||||
### Updating libCwtch and bingings.rs with Bindgen
|
||||
|
||||
```
|
||||
cargo install bindgen
|
||||
```
|
||||
|
||||
libCwtch.so version is specified in build.rs. If updating, also download the corresponding libCwtch.h and delete
|
||||
the 'preamble from import "C"' section as it imports headers required for the C lib to compile
|
||||
but that we don't want to create rust bindings for (like importing stdlib.h). `cargo build` automatically calls
|
||||
`bindgen` for us and will regenerate `src/cwtchlib_go/bindings.rs` if libCwtch.h has changed.
|
||||
but that we don't want to create rust bindings for (like importing stdlib.h). Then:
|
||||
|
||||
While developing you can use the `LCG_DIR` environment variable to specify the directory containing a local `libCwtch.so`
|
||||
library to override the default one.
|
||||
```
|
||||
bindgen libCwtch.h -o src/cwtchlib_go/bindings.rs
|
||||
```
|
||||
|
||||
This is useful in cases where you are adding or updating APIs prior to a release.
|
||||
### Todo
|
||||
|
|
67
build.rs
67
build.rs
|
@ -1,63 +1,16 @@
|
|||
use std::{env, io};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use hex_literal::hex;
|
||||
use sha2::{Digest, Sha512};
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
println!("cargo:rustc-flags=-L {}", out_dir.to_str().unwrap());
|
||||
println!("cargo:rustc-link-lib=Cwtch");
|
||||
|
||||
// Do not fetch lib on docs.rs as it cannot, build will fail, docs won't build
|
||||
// https://docs.rs/about/builds
|
||||
if std::env::var("DOCS_RS").is_err() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
println!("cargo:rustc-flags=-L {}", out_dir.to_str().unwrap());
|
||||
println!("cargo:rustc-link-lib=Cwtch");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=libCwtch.h");
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=libCwtch.h");
|
||||
|
||||
|
||||
// The bindgen::Builder is the main entry point
|
||||
// to bindgen, and lets you build up options for
|
||||
// the resulting bindings.
|
||||
let bindings = bindgen::Builder::default()
|
||||
// The input header we would like to generate
|
||||
// bindings for.
|
||||
.header("libCwtch.h")
|
||||
// Tell cargo to invalidate the built crate whenever any of the
|
||||
// included header files changed.
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
// Finish the builder and generate the bindings.
|
||||
.generate()
|
||||
// Unwrap the Result and panic on failure.
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
// Write the bindings to the $OUT_DIR/bindings.rs file.
|
||||
let out_path = PathBuf::from("src/cwtchlib_go");
|
||||
bindings
|
||||
.write_to_file(out_path.join("bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
|
||||
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so");
|
||||
if std::env::var("LCG_DIR").is_err() {
|
||||
Command::new("wget")
|
||||
.arg("https://git.openprivacy.ca/cwtch.im/autobindings/releases/download/v0.0.12/libCwtch.x64.so")
|
||||
.arg("-O")
|
||||
.arg(lib_cwtch_path.clone())
|
||||
.output()
|
||||
.expect("failed to download libCwtch.x64.so");
|
||||
|
||||
let mut hasher = Sha512::new();
|
||||
let mut file = fs::File::open(&lib_cwtch_path).expect("could not open lib to hash");
|
||||
io::copy(&mut file, &mut hasher).expect("failed to copy file into hasher");
|
||||
let hash_bytes = hasher.finalize();
|
||||
|
||||
assert_eq!(hash_bytes[..], hex!("a3742e0cdedc00eb3673063b100b7596b05bdc9bb68a0fba6fd2423c9a41f1653597c4d44ba3877be08cbb5bba2806435830061ab3517cdd4472a18c7557d9c7")[..]);
|
||||
} else {
|
||||
let local_lcg = Path::new(std::env::var("LCG_DIR").unwrap().as_str()).join("libCwtch.so");
|
||||
fs::copy(local_lcg, lib_cwtch_path).expect("could not find local lcg");
|
||||
}
|
||||
}
|
||||
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so");
|
||||
// https://git.openprivacy.ca/cwtch.im/libcwtch-go/releases v1.2.0
|
||||
Command::new("wget").arg("https://git.openprivacy.ca/attachments/e77c69f0-9487-4808-bc23-092d943bc4a6").arg("-O").arg(lib_cwtch_path).output().expect("failed to download libCwtch.so");
|
||||
}
|
|
@ -1,52 +1,54 @@
|
|||
use std::thread;
|
||||
use std::{thread};
|
||||
|
||||
use libcwtch;
|
||||
use libcwtch::structs::*;
|
||||
use libcwtch::CwtchLib;
|
||||
use libcwtch::event::Event;
|
||||
use libcwtch::structs::{*};
|
||||
|
||||
fn main() {
|
||||
let bot_home = "example_cwtch_dir";
|
||||
let bot_home: String = "example_cwtch_dir".to_string();
|
||||
match std::fs::remove_dir_all(&bot_home) {
|
||||
// this will always error on first run as we haven't created the directory, it's just a function to clear it on successive runs, so this error is to be ignored
|
||||
Err(_e) => (),
|
||||
_ => (),
|
||||
}
|
||||
std::fs::create_dir_all(&bot_home).expect("Error creating bot_home directory");
|
||||
std::fs::create_dir_all(&bot_home).unwrap();
|
||||
|
||||
let cwtch = libcwtch::new_cwtchlib_go();
|
||||
println!("start_cwtch");
|
||||
let ret = cwtch.start_cwtch(bot_home, "");
|
||||
let ret = cwtch.start_cwtch(bot_home.as_str(), "");
|
||||
println!("start_cwtch returned {}", ret);
|
||||
|
||||
let event_loop_handle = thread::spawn(move || {
|
||||
loop {
|
||||
let event = cwtch.get_appbus_event();
|
||||
println!("event: {:?}", event);
|
||||
let event_str = cwtch.get_appbus_event();
|
||||
println!("event: {}", event_str);
|
||||
|
||||
match event {
|
||||
Event::CwtchStarted => {
|
||||
let event: CwtchEvent = serde_json::from_str(&event_str).unwrap();
|
||||
match event.event_type.as_str() {
|
||||
"CwtchStarted" => {
|
||||
println!("event CwtchStarted!");
|
||||
println!("Creating bot");
|
||||
cwtch.create_profile("Echobot", "be gay do crime", true);
|
||||
}
|
||||
Event::NewPeer { profile_id, tag, created, name, default_picture, picture, online, profile_data } => {
|
||||
println!(
|
||||
"\n***** {} at {} *****\n",
|
||||
name, profile_id.as_str()
|
||||
);
|
||||
cwtch.create_profile("Echobot", "be gay do crime");
|
||||
},
|
||||
"NewPeer" => {
|
||||
println!("\n***** {} at {} *****\n", event.data["name"], event.data["Identity"]);
|
||||
|
||||
// process json for profile, contacts and servers...else {
|
||||
let profile = profile_data;
|
||||
let profile = Profile::new(&event.data["Identity"], &event.data["name"], &event.data["picture"], &event.data["ContactsJson"], &event.data["ServerList"]);
|
||||
print!("profile: {:?}", profile);
|
||||
}
|
||||
Event::NewMessageFromPeer { profile_id, conversation_id, contact_id: contact, nick, timestamp_received, message, notification, picture } => {
|
||||
let response = MessageWrapper { o: message.o.into(), d: message.d };
|
||||
cwtch.send_message( &profile_id, conversation_id, &response);
|
||||
"NewMessageFromPeer" => {
|
||||
let to = event.data["ProfileOnion"].to_string();
|
||||
let conversation = event.data["RemotePeer"].to_string();
|
||||
let message: Message = serde_json::from_str(event.data["Data"].as_str()).unwrap();
|
||||
|
||||
let response = Message{o:1, d:message.d};
|
||||
let response_json = serde_json::to_string(&response).unwrap();
|
||||
cwtch.send_message(to.as_str(), conversation.as_str(), response_json.as_str());
|
||||
}
|
||||
_ => eprintln!("unhandled event!"),
|
||||
_ => println!("unhandled event!"),
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
event_loop_handle.join().expect("Error running event loop");
|
||||
event_loop_handle.join().unwrap();
|
||||
}
|
||||
|
|
107
libCwtch.h
107
libCwtch.h
|
@ -1,11 +1,11 @@
|
|||
/* Code generated by cmd/cgo; DO NOT EDIT. */
|
||||
|
||||
/* package git.openprivacy.ca/cwtch.im/cwtch-autobindings */
|
||||
/* package git.openprivacy.ca/cwtch.im/libcwtch-go */
|
||||
|
||||
|
||||
#line 1 "cgo-builtin-export-prolog"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stddef.h> /* for ptrdiff_t below */
|
||||
|
||||
#ifndef GO_CGO_EXPORT_PROLOGUE_H
|
||||
#define GO_CGO_EXPORT_PROLOGUE_H
|
||||
|
@ -32,17 +32,11 @@ typedef long long GoInt64;
|
|||
typedef unsigned long long GoUint64;
|
||||
typedef GoInt64 GoInt;
|
||||
typedef GoUint64 GoUint;
|
||||
typedef size_t GoUintptr;
|
||||
typedef __SIZE_TYPE__ GoUintptr;
|
||||
typedef float GoFloat32;
|
||||
typedef double GoFloat64;
|
||||
#ifdef _MSC_VER
|
||||
#include <complex.h>
|
||||
typedef _Fcomplex GoComplex64;
|
||||
typedef _Dcomplex GoComplex128;
|
||||
#else
|
||||
typedef float _Complex GoComplex64;
|
||||
typedef double _Complex GoComplex128;
|
||||
#endif
|
||||
|
||||
/*
|
||||
static assertion to make sure the file is being used on architecture
|
||||
|
@ -66,73 +60,44 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// Dangerous function. Should only be used as documented in `MEMORY.md`
|
||||
//
|
||||
extern void c_FreePointer(char* ptr);
|
||||
extern int c_Started();
|
||||
extern int c_StartCwtch(char* dir_c, int len, char* tor_c, int torLen);
|
||||
extern void c_ReconnectCwtchForeground();
|
||||
|
||||
// A generic method for Rebroadcasting App Events from a UI
|
||||
extern void c_SendAppEvent(char* json_ptr, int json_len);
|
||||
|
||||
// A generic method for Rebroadcasting Profile Events from a UI
|
||||
extern void c_SendProfileEvent(char* onion_ptr, int onion_len, char* json_ptr, int json_len);
|
||||
|
||||
// the pointer returned from this function **must** be freed using c_Free
|
||||
//
|
||||
extern char* c_GetAppBusEvent();
|
||||
extern void c_ReconnectCwtchForeground();
|
||||
extern void c_ShutdownCwtch();
|
||||
extern void c_SetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern char* c_GetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len);
|
||||
extern void c_SetConversationAttribute(char* profile_ptr, int profile_len, int conversation_id, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern char* c_GetConversationAttribute(char* profile_ptr, int profile_len, int conversation_id, char* key_ptr, int key_len);
|
||||
extern void c_CreateProfile(char* nick_ptr, int nick_len, char* pass_ptr, int pass_len);
|
||||
extern void c_LoadProfiles(char* passwordPtr, int passwordLen);
|
||||
extern void c_AcceptContact(char* profilePtr, int profileLen, char* handlePtr, int handleLen);
|
||||
extern void c_RejectInvite(char* profilePtr, int profileLen, char* handlePtr, int handleLen);
|
||||
extern void c_BlockContact(char* profilePtr, int profileLen, char* handlePtr, int handleLen);
|
||||
extern void c_UpdateMessageFlags(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, int mIdx, long unsigned int message_flags);
|
||||
|
||||
// the pointer returned from this function **must** be Freed by c_Free
|
||||
extern char* c_GetMessage(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, int message_index);
|
||||
|
||||
// the pointer returned from this function **must** be freed by calling c_Free
|
||||
extern char* c_GetMessagesByContentHash(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, char* contenthash_ptr, int contenthash_len);
|
||||
|
||||
// Dangerous function. Should only be used as documented in `MEMORY.md`
|
||||
extern void c_FreePointer(char* ptr);
|
||||
extern void c_SendMessage(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, char* msg_ptr, int msg_len);
|
||||
extern void c_SendInvitation(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, char* target_ptr, int target_len);
|
||||
extern void c_ResetTor();
|
||||
extern void c_UpdateSettings(char* json_ptr, int json_len);
|
||||
extern char* c_GetDebugInfo();
|
||||
extern void c_ActivatePeerEngine(char* onion_ptr, int onion_len);
|
||||
extern void c_DeactivatePeerEngine(char* onion_ptr, int onion_len);
|
||||
extern void c_ConfigureConnections(char* onion_ptr, int onion_len, char listen1, char peers2, char servers3);
|
||||
extern void c_CreateProfile(char* name_ptr, int name_len, char* password_ptr, int password_len, char autostart4);
|
||||
extern void c_LoadProfiles(char* password_ptr, int password_len);
|
||||
extern void c_DeleteProfile(char* onion_ptr, int onion_len, char* password_ptr, int password_len);
|
||||
extern char* c_ImportProfile(char* file5_ptr, int file5_len, char* password_ptr, int password_len);
|
||||
extern void c_ChangePassword(char* onion_ptr, int onion_len, char* current6_ptr, int current6_len, char* newPassword7_ptr, int newPassword7_len, char* newPasswordAgain8_ptr, int newPasswordAgain8_len);
|
||||
extern void c_ExportProfile(char* onion_ptr, int onion_len, char* file9_ptr, int file9_len);
|
||||
extern char* c_ImportBundle(char* onion_ptr, int onion_len, char* bundle10_ptr, int bundle10_len);
|
||||
extern void c_ArchiveConversation(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_AcceptConversation(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_BlockConversation(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_UnblockConversation(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_DeleteConversation(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_PeerWithOnion(char* onion_ptr, int onion_len, char* handle11_ptr, int handle11_len);
|
||||
extern void c_DisconnectFromPeer(char* onion_ptr, int onion_len, char* handle12_ptr, int handle12_len);
|
||||
extern char* c_GetConversationAccessControlList(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_UpdateConversationAccessControlList(char* onion_ptr, int onion_len, int conversation, char* json13_ptr, int json13_len);
|
||||
extern char* c_SearchConversations(char* onion_ptr, int onion_len, char* pattern14_ptr, int pattern14_len);
|
||||
extern char* c_SendMessage(char* onion_ptr, int onion_len, int conversation, char* msg15_ptr, int msg15_len);
|
||||
extern char* c_GetMessageById(char* onion_ptr, int onion_len, int conversation, int message_id);
|
||||
extern char* c_GetMessageByContentHash(char* onion_ptr, int onion_len, int conversation, char* contentHash16_ptr, int contentHash16_len);
|
||||
extern char* c_GetMessages(char* onion_ptr, int onion_len, int conversation, int index, unsigned int count);
|
||||
extern char* c_SendInviteMessage(char* onion_ptr, int onion_len, int conversation, int target);
|
||||
extern void c_UpdateMessageAttribute(char* onion_ptr, int onion_len, int conversation, int channel_id, int message_id, char* attributeKey17_ptr, int attributeKey17_len, char* attributeValue18_ptr, int attributeValue18_len);
|
||||
extern void c_StartGroup(char* onion_ptr, int onion_len, char* name19_ptr, int name19_len, char* server20_ptr, int server20_len);
|
||||
extern void c_QueueJoinServer(char* onion_ptr, int onion_len, char* handle21_ptr, int handle21_len);
|
||||
extern void c_DisconnectFromServer(char* onion_ptr, int onion_len, char* handle22_ptr, int handle22_len);
|
||||
extern void c_PublishServerUpdate(char* onion_ptr, int onion_len);
|
||||
extern void c_GetServerInfoList(char* onion_ptr, int onion_len);
|
||||
extern void c_DeleteServerInfo(char* onion_ptr, int onion_len, char* serverOnion23_ptr, int serverOnion23_len);
|
||||
extern void c_DownloadFileDefaultLimit(char* onion_ptr, int onion_len, int conversation, char* filepath24_ptr, int filepath24_len, char* manifest25_ptr, int manifest25_len, char* filekey26_ptr, int filekey26_len);
|
||||
extern void c_RestartFileShare(char* onion_ptr, int onion_len, char* filekey27_ptr, int filekey27_len);
|
||||
extern void c_StopFileShare(char* onion_ptr, int onion_len, char* filekey28_ptr, int filekey28_len);
|
||||
extern void c_CheckDownloadStatus(char* onion_ptr, int onion_len, char* filekey29_ptr, int filekey29_len);
|
||||
extern void c_VerifyOrResumeDownloadDefaultLimit(char* onion_ptr, int onion_len, int conversation, char* filekey30_ptr, int filekey30_len);
|
||||
extern char* c_ShareFile(char* onion_ptr, int onion_len, int conversation, char* filepath31_ptr, int filepath31_len);
|
||||
extern char* c_GetSharedFiles(char* onion_ptr, int onion_len, int conversation);
|
||||
extern void c_CreateServer(char* password_ptr, int password_len, char* description32_ptr, int description32_len, char autostart33);
|
||||
extern void c_SetServerAttribute(char* handle34_ptr, int handle34_len, char* key35_ptr, int key35_len, char* val36_ptr, int val36_len);
|
||||
extern void c_LoadServers(char* password_ptr, int password_len);
|
||||
extern void c_LaunchServers();
|
||||
extern void c_LaunchServer(char* handle37_ptr, int handle37_len);
|
||||
extern void c_StopServer(char* handle38_ptr, int handle38_len);
|
||||
extern void c_StopServers();
|
||||
extern void c_DestroyServers();
|
||||
extern void c_DeleteServer(char* handle39_ptr, int handle39_len, char* password_ptr, int password_len);
|
||||
extern void c_CreateGroup(char* profile_ptr, int profile_len, char* server_ptr, int server_len, char* name_ptr, int name_len);
|
||||
extern void c_DeleteProfile(char* profile_ptr, int profile_len, char* password_ptr, int password_len);
|
||||
extern void c_ArchiveConversation(char* profile_ptr, int profile_len, char* contact_ptr, int contact_len);
|
||||
extern void c_DeleteContact(char* profile_ptr, int profile_len, char* hanlde_ptr, int handle_len);
|
||||
extern void c_ImportBundle(char* profile_ptr, int profile_len, char* bundle_ptr, int bundle_len);
|
||||
extern void c_SetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern void c_SetContactAttribute(char* profile_ptr, int profile_len, char* contact_ptr, int contact_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern void c_SetGroupAttribute(char* profile_ptr, int profile_len, char* group_ptr, int group_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern void c_ShutdownCwtch();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -3,70 +3,51 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CString};
|
||||
use std::ffi::{CStr};
|
||||
|
||||
use super::CwtchLib;
|
||||
use super::{CwtchLib};
|
||||
use crate::cwtchlib_go::bindings;
|
||||
use crate::{ConversationID, CwtchError, FileKey, ProfileIdentity, ServerIdentity, structs::*};
|
||||
use crate::event::Event;
|
||||
|
||||
type c_bool = core::ffi::c_char;
|
||||
|
||||
fn from_c_bool(b: c_bool) -> bool {
|
||||
b == 1
|
||||
}
|
||||
|
||||
fn to_c_bool(b: bool) -> c_bool {
|
||||
if b { 1 } else { 0 }
|
||||
}
|
||||
|
||||
struct c_str_wrap {
|
||||
raw: *mut core::ffi::c_char,
|
||||
len: i32,
|
||||
raw: *mut i8,
|
||||
len: i32
|
||||
}
|
||||
|
||||
impl c_str_wrap {
|
||||
pub fn new(str: &str) -> c_str_wrap {
|
||||
let cs = match CString::new(str) {
|
||||
Ok(s) => s,
|
||||
Err(_) => CString::new("").unwrap(),
|
||||
Err(_) => CString::new("").unwrap()
|
||||
};
|
||||
c_str_wrap {
|
||||
len: cs.as_bytes().len() as i32,
|
||||
raw: cs.into_raw(),
|
||||
}
|
||||
c_str_wrap { len: cs.as_bytes().len() as i32, raw: cs.into_raw() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for c_str_wrap {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
drop(CString::from_raw(self.raw));
|
||||
}
|
||||
unsafe { CString::from_raw(self.raw); }
|
||||
}
|
||||
}
|
||||
|
||||
// c_bind handles setting up c string arguments and freeing them
|
||||
// c_bind!( $fn_name ( [ $string_args: &str],* [ $non_string_args : $type ],* ) $c_function -> $return_type? )
|
||||
// c_bind!( $fn_name ( [ $string_args ]* ; [ $non_string_args : $type ]* ) $c_function -> $return_type? )
|
||||
macro_rules! c_bind {
|
||||
// No return
|
||||
($func_name:ident ($($str1:ident: &str),* ; $($args:ident: $t:ty),* ; $($str2:ident: &str),*) $bind_fn:ident) => {
|
||||
fn $func_name(&self, $($str1: &str, )* $($args: $t, )* $($str2: &str, )*) {
|
||||
$(let $str1 = c_str_wrap::new($str1);)*
|
||||
$(let $str2 = c_str_wrap::new($str2);)*
|
||||
// macro for returnless fns
|
||||
($func_name:ident ($($str:ident),* ; $($arg:ident: $t:ty),*) $bind_fn:ident) => {
|
||||
fn $func_name(&self, $($str: &str, )* $($arg: $t, )*) {
|
||||
$(let $str = c_str_wrap::new($str);)*
|
||||
unsafe {
|
||||
bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
|
||||
bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
|
||||
}
|
||||
}
|
||||
};
|
||||
// String return
|
||||
($func_name:ident ($($str1:ident: &str),* ; $($args:ident: $t:ty),* ; $($str2:ident: &str),*) $bind_fn:ident -> String) => {
|
||||
fn $func_name(&self, $($str1: &str, )* $($args: $t, )* $($str2: &str, )*) -> String {
|
||||
$(let $str1 = c_str_wrap::new($str1);)*
|
||||
$(let $str2 = c_str_wrap::new($str2);)*
|
||||
// macro for str returning fns
|
||||
($func_name:ident ($($str:ident),* ; $($arg:ident: $t:ty),* ) $bind_fn:ident -> String) => {
|
||||
fn $func_name(&self, $($str: &str, )* $($arg: $t, )*) -> String {
|
||||
$(let $str = c_str_wrap::new($str);)*
|
||||
unsafe {
|
||||
let result_ptr = bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
|
||||
let result_ptr = bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
|
||||
let result = match CStr::from_ptr(result_ptr).to_str() {
|
||||
Ok(s) => s.to_owned(),
|
||||
Err(_) => "".to_string()
|
||||
|
@ -77,13 +58,12 @@ macro_rules! c_bind {
|
|||
}
|
||||
}
|
||||
};
|
||||
// Non String return
|
||||
($func_name:ident ($($str1:ident: &str),* ; $($args:ident: $t:ty),* ; $($str2:ident: &str),*) $bind_fn:ident -> $bind_fn_ty:ty) => {
|
||||
fn $func_name(&self, $($str1: &str, )* $($args: t, )* $($str2: &str, )*) -> $bind_fn_ty {
|
||||
$(let $str1 = c_str_wrap::new($str1);)*
|
||||
$(let $str2 = c_str_wrap::new($str2);)*
|
||||
// macro for value returning fns
|
||||
($func_name:ident ($($str:ident),* ; $($arg:ident: $t:ty),* ) $bind_fn:ident -> $bind_fn_ty:ty) => {
|
||||
fn $func_name(&self, $($str: &str, )* $($arg: $t, )*) -> $bind_fn_ty {
|
||||
$(let $str = c_str_wrap::new($str);)*
|
||||
unsafe {
|
||||
let result = bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
|
||||
let result = bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -92,278 +72,37 @@ macro_rules! c_bind {
|
|||
|
||||
pub struct CwtchLibGo {}
|
||||
|
||||
// Some bindings are going to be wrapped so we can handle their returns and give most rust idiomatic returns (esp for json returning apis)
|
||||
// so we pre define the real binding here as a _helper function and in the impl for CwtchLib define the wrapper
|
||||
impl CwtchLibGo {
|
||||
c_bind!(_peer_with(profile: &str, new_peer: &str;;) c_PeerWithOnion);
|
||||
c_bind!(_update_settings(settings_json: &str;;) c_UpdateSettings);
|
||||
c_bind!(_get_profile_attribute(profile: &str, key: &str;;) c_GetProfileAttribute -> String);
|
||||
c_bind!(_get_conversation_attribute(profile: &str; conversation_id: i32; key: &str) c_GetConversationAttribute -> String);
|
||||
c_bind!(_get_appbus_event(;;) c_GetAppBusEvent -> String);
|
||||
c_bind!(_configure_connections(profile: &str; listen: c_bool, peers: c_bool, servers: c_bool;) c_ConfigureConnections);
|
||||
c_bind!(_create_profile(nick: &str, pass: &str; autostart: c_bool;) c_CreateProfile);
|
||||
c_bind!(_activate_peer_engine(profile: &str;;) c_ActivatePeerEngine);
|
||||
c_bind!(_deactivate_peer_engine(profile: &str;;) c_DeactivatePeerEngine);
|
||||
c_bind!(_accept_conversation(profile: &str ; conversation_id: i32; ) c_AcceptConversation);
|
||||
c_bind!(_block_conversation(profile: &str ; conversation_id: i32; ) c_BlockConversation);
|
||||
c_bind!(_unblock_conversation(profile: &str ; conversation_id: i32; ) c_UnblockConversation);
|
||||
c_bind!(_disconnect_from_peer(profile: &str, peer_address: &str;;) c_DisconnectFromPeer);
|
||||
c_bind!(_search_conversations(profile: &str, pattern: &str;;) c_SearchConversations -> String);
|
||||
c_bind!(_get_conversation_access_control_list(profile: &str; conversation_id: i32;) c_GetConversationAccessControlList -> String);
|
||||
c_bind!(_update_conversation_access_control_list(profile: &str; conversation_id: i32; acl: &str) c_UpdateConversationAccessControlList);
|
||||
c_bind!(_get_message_by_id(profile: &str ; conversation_id: i32, message_id: i32 ;) c_GetMessageById -> String);
|
||||
c_bind!(_get_message_by_content_hash(profile: &str ; conversation_id: i32 ; hash: &str) c_GetMessageByContentHash -> String);
|
||||
c_bind!(_get_messages(profile: &str; conversation_id: i32, message_index: i32, count: u32 ;) c_GetMessages -> String);
|
||||
c_bind!(_send_message(profile: &str; conversation_id: i32; msg: &str) c_SendMessage -> String);
|
||||
c_bind!(_send_invite_message(profile: &str; conversation_id: i32, target_id: i32;) c_SendInviteMessage -> String);
|
||||
c_bind!(_share_file(profile: &str; conversation_id: i32; file_path: &str) c_ShareFile -> String);
|
||||
c_bind!(_get_shared_files(profile: &str; conversaion_id: i32;) c_GetSharedFiles -> String);
|
||||
c_bind!(_restart_fileshare(profile: &str, file_key: &str;;) c_RestartFileShare);
|
||||
c_bind!(_stop_fileshare(profile: &str, file_key: &str;;) c_StopFileShare);
|
||||
c_bind!(_download_file_default_limit(profile: &str; conversation_id: i32; file_path: &str, manifest_path: &str, file_key: &str) c_DownloadFileDefaultLimit);
|
||||
c_bind!(_check_download_status(profile: &str, file_key: &str;;) c_CheckDownloadStatus);
|
||||
c_bind!(_verify_or_resume_download(profile: &str; conversation_id: i32; file_key: &str) c_VerifyOrResumeDownloadDefaultLimit);
|
||||
c_bind!(_start_group(profile: &str, name: &str, server: &str;;) c_StartGroup);
|
||||
c_bind!(_queue_join_server(profile: &str, server: &str;;) c_QueueJoinServer);
|
||||
c_bind!(_disconnect_from_server(profile: &str, server: &str;;) c_DisconnectFromServer);
|
||||
c_bind!(_publish_server_update(profile: &str;;) c_PublishServerUpdate);
|
||||
c_bind!(_get_server_info_list(profile: &str;;) c_GetServerInfoList);
|
||||
c_bind!(_delete_server_info(profile: &str, server: &str;;) c_DeleteServerInfo);
|
||||
c_bind!(_delete_profile(profile: &str, pass: &str;;) c_DeleteProfile);
|
||||
c_bind!(_archive_conversation(profile: &str; conversation_id: i32;) c_ArchiveConversation);
|
||||
c_bind!(_delete_conversation(profile: &str; conversation_id: i32;) c_DeleteConversation);
|
||||
c_bind!(_import_bundle(profile: &str, bundle: &str;;) c_ImportBundle);
|
||||
c_bind!(_set_profile_attribute(profile: &str, key: &str, val: &str;;) c_SetProfileAttribute);
|
||||
c_bind!(_set_conversation_attribute(profile: &str; conversation_id: i32; key: &str, val: &str) c_SetConversationAttribute);
|
||||
c_bind!(_update_message_attribute(profile: &str; conversation_id: i32, channel_id: i32, message_id: i32; key: &str, val: &str) c_UpdateMessageAttribute);
|
||||
c_bind!(_change_password(profile: &str, old_pass: &str, new_pass: &str, new_pass_again: &str;;) c_ChangePassword);
|
||||
c_bind!(_export_profile(profile: &str, filename: &str;;) c_ExportProfile);
|
||||
c_bind!(_create_server(password: &str, description: &str; autostart: c_bool;) c_CreateServer);
|
||||
c_bind!(_delete_server(server: &str, current_password: &str;;) c_DeleteServer);
|
||||
c_bind!(_launch_server(server: &str;;) c_LaunchServer);
|
||||
c_bind!(_stop_server(server: &str;;) c_StopServer);
|
||||
c_bind!(_set_server_attribute(server: &str, key: &str, val: &str;;) c_SetServerAttribute);
|
||||
c_bind!(send_profile_event(profile, event_json;) c_SendProfileEvent);
|
||||
}
|
||||
|
||||
impl CwtchLib for CwtchLibGo {
|
||||
c_bind!(start_cwtch(app_dir: &str, tor_path: &str;;) c_StartCwtch -> i32);
|
||||
c_bind!(started(;;) c_Started -> i32);
|
||||
fn update_settings(&self, settings: &Settings) {
|
||||
let settings_json = match serde_json::to_string(settings) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return,
|
||||
};
|
||||
self._update_settings(&settings_json)
|
||||
}
|
||||
c_bind!(reconnect_cwtch_foreground(;;) c_ReconnectCwtchForeground);
|
||||
fn create_profile(&self, nick: &str, pass: &str, autostart: bool) {
|
||||
self._create_profile(nick, pass, to_c_bool(autostart))
|
||||
}
|
||||
|
||||
fn activate_peer_engine(&self, profile: &ProfileIdentity) {
|
||||
self._activate_peer_engine(profile.as_str())
|
||||
}
|
||||
fn deactivate_peer_engine(&self, profile: &ProfileIdentity) {
|
||||
self._deactivate_peer_engine(profile.as_str())
|
||||
}
|
||||
fn configure_connections(&self, profile: &ProfileIdentity, listen: bool, peers: bool, servers: bool) {
|
||||
self._configure_connections(profile.as_str(), to_c_bool(listen), to_c_bool(peers), to_c_bool(servers))
|
||||
}
|
||||
fn search_conversations(&self, profile: &ProfileIdentity, pattern: &str) -> String {
|
||||
self._search_conversations(profile.as_str(), pattern)
|
||||
}
|
||||
|
||||
fn get_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID) -> Result<ACL, CwtchError> {
|
||||
let json = self._get_conversation_access_control_list(profile.as_str(), conversation_id.into());
|
||||
|
||||
match serde_json::from_str(&json) {
|
||||
Ok(acl) => Ok(acl),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID, acl: ACL) {
|
||||
match serde_json::to_string(&acl) {
|
||||
Ok(acl_json) => self._update_conversation_access_control_list(profile.as_str(), conversation_id.into(), &acl_json),
|
||||
Err(_) => return,
|
||||
};
|
||||
}
|
||||
|
||||
c_bind!(load_profiles(pass: &str;;) c_LoadProfiles);
|
||||
fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
|
||||
self._accept_conversation(profile.as_str(), conversation_id.into())
|
||||
}
|
||||
|
||||
fn peer_with(&self, profile: &ProfileIdentity, new_peer_address: &str) {
|
||||
self._peer_with(profile.as_str(), new_peer_address)
|
||||
}
|
||||
|
||||
fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
|
||||
self._block_conversation(String::from(profile).as_str(), conversation_id.into())
|
||||
}
|
||||
fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
|
||||
self._unblock_conversation(String::from(profile).as_str(), conversation_id.into())
|
||||
}
|
||||
fn disconnect_from_peer(&self, profile: &ProfileIdentity, peer_id: &str) {
|
||||
self._disconnect_from_peer(profile.as_str(), peer_id)
|
||||
}
|
||||
|
||||
fn get_message_by_id(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_id: i32) -> String {
|
||||
self._get_message_by_id(String::from(profile).as_str(), conversation_id.into(), message_id)
|
||||
}
|
||||
fn get_message_by_content_hash(&self, profile: &ProfileIdentity, conversation_id: ConversationID, hash: &str) -> String {
|
||||
self._get_message_by_content_hash(String::from(profile).as_str(), conversation_id.into(), hash)
|
||||
}
|
||||
fn get_messages(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_index: i32, count: u32) -> String {
|
||||
self._get_messages(String::from(profile).as_str(), conversation_id.into(), message_index, count)
|
||||
}
|
||||
fn send_message_raw(&self, profile: &ProfileIdentity, conversation_id: ConversationID, msg: &str) -> String {
|
||||
self._send_message(String::from(profile).as_str(), conversation_id.into(), msg)
|
||||
}
|
||||
fn send_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message: &MessageWrapper) -> Result<String, CwtchError> {
|
||||
match serde_json::to_string(&message) {
|
||||
Ok(message_json) => Ok(self._send_message(&String::from(profile), conversation_id.into(), &message_json)),
|
||||
Err(e) => Err(format!("Error parsing json response: {}", e.to_string()))
|
||||
}
|
||||
}
|
||||
fn send_invite_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, target_id: i32) -> String {
|
||||
self._send_invite_message(String::from(profile).as_str(), conversation_id.into(), target_id)
|
||||
}
|
||||
fn share_file(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str) -> String {
|
||||
self._share_file(String::from(profile).as_str(), conversation_id.into(), file_path)
|
||||
}
|
||||
fn get_shared_files(&self, profile: &ProfileIdentity, conversaion_id: ConversationID) -> Vec<SharedFile> {
|
||||
let json = self._get_shared_files(profile.as_str(), conversaion_id.into());
|
||||
|
||||
match serde_json::from_str(&json) {
|
||||
Ok(l) => l,
|
||||
Err(_) => vec!(),
|
||||
}
|
||||
}
|
||||
fn download_file_default_limit(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str, manifest_path: &str, file_key: &FileKey) {
|
||||
self._download_file_default_limit(String::from(profile).as_str(), conversation_id.into(), file_path, manifest_path, String::from(file_key).as_str())
|
||||
}
|
||||
fn restart_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey) {
|
||||
self._restart_fileshare(profile.as_str(), file_key.as_str())
|
||||
}
|
||||
fn stop_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey) {
|
||||
self._stop_fileshare(profile.as_str(), file_key.as_str())
|
||||
}
|
||||
fn check_download_status(&self, profile: &ProfileIdentity, file_key: &FileKey) {
|
||||
self._check_download_status(String::from(profile).as_str(), String::from(file_key).as_str())
|
||||
}
|
||||
fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: &FileKey) {
|
||||
self._verify_or_resume_download(String::from(profile).as_str(), conversation_id.into(), String::from(file_key).as_str())
|
||||
}
|
||||
|
||||
c_bind!(start_cwtch(app_dir, tor_path;) c_StartCwtch -> i32);
|
||||
c_bind!(send_app_event(event_json;) c_SendAppEvent);
|
||||
c_bind!(get_appbus_event(;) c_GetAppBusEvent -> String);
|
||||
c_bind!(create_profile(nick, pass;) c_CreateProfile);
|
||||
c_bind!(load_profiles(pass;) c_LoadProfiles);
|
||||
c_bind!(accept_contact(profile, contact;) c_AcceptContact);
|
||||
c_bind!(reject_invite(profile, contact;) c_RejectInvite);
|
||||
c_bind!(block_contact(profile, contact;) c_BlockContact);
|
||||
c_bind!(update_message_flags(profile, contact; message_id: i32, message_flags: u64) c_UpdateMessageFlags);
|
||||
c_bind!(get_message(profile, contact; message_index: i32) c_GetMessage -> String);
|
||||
c_bind!(get_message_by_content_hash(profile, contact, hash;) c_GetMessagesByContentHash -> String);
|
||||
c_bind!(send_message(profile, contact, msg;) c_SendMessage);
|
||||
c_bind!(send_invitation(profile, contact, target;) c_SendInvitation);
|
||||
fn reset_tor(&self) {
|
||||
unsafe {
|
||||
bindings::c_ResetTor();
|
||||
}
|
||||
unsafe { bindings::c_ResetTor(); }
|
||||
}
|
||||
fn start_group(&self, profile: &ProfileIdentity, server: &str, name: &str) {
|
||||
self._start_group(String::from(profile).as_str(), server, name)
|
||||
}
|
||||
fn queue_join_server(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
|
||||
self._queue_join_server(profile.as_str(), server.as_str())
|
||||
}
|
||||
fn disconnect_from_server(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
|
||||
self._disconnect_from_server(profile.as_str(), server.as_str())
|
||||
}
|
||||
fn publish_server_update(&self, profile: &ProfileIdentity) {
|
||||
self._publish_server_update(profile.as_str())
|
||||
}
|
||||
fn get_server_info_list(&self, profile: &ProfileIdentity) {
|
||||
self._get_server_info_list(profile.as_str())
|
||||
}
|
||||
fn delete_server_info(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
|
||||
self._delete_server_info(profile.as_str(), server.as_str())
|
||||
}
|
||||
fn delete_profile(&self, profile: &ProfileIdentity, pass: &str) {
|
||||
self._delete_profile(String::from(profile).as_str(), pass)
|
||||
}
|
||||
fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
|
||||
self._archive_conversation(String::from(profile).as_str(), conversation_id.into())
|
||||
}
|
||||
fn delete_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
|
||||
self._delete_conversation(profile.as_str(), conversation_id.into())
|
||||
}
|
||||
fn import_bundle(&self, profile: &ProfileIdentity, bundle: &str) {
|
||||
self._import_bundle(String::from(profile).as_str(), bundle)
|
||||
}
|
||||
fn set_profile_attribute(&self, profile: &ProfileIdentity, key: &str, val: &str) {
|
||||
self._set_profile_attribute(String::from(profile).as_str(), key, val)
|
||||
}
|
||||
|
||||
fn get_profile_attribute(&self, profile: &ProfileIdentity, key: &str) -> Result<Option<String>, CwtchError> {
|
||||
let resp = self._get_profile_attribute(String::from(profile).as_str(), key);
|
||||
let attr: Attribute = match serde_json::from_str(&resp) {
|
||||
Ok(attr) => attr,
|
||||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
match attr.exists {
|
||||
true => Ok(Some(attr.value)),
|
||||
false => Ok(None),
|
||||
}
|
||||
}
|
||||
fn set_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str, val: &str) {
|
||||
self._set_conversation_attribute(String::from(profile).as_str(), conversation_id.into(), key, val)
|
||||
}
|
||||
fn get_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str) -> Result<Option<String>, CwtchError> {
|
||||
let resp = self._get_conversation_attribute(String::from(profile).as_str(), conversation_id.into(), key);
|
||||
let attr: Attribute = match serde_json::from_str(&resp) {
|
||||
Ok(attr) => attr,
|
||||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
match attr.exists {
|
||||
true => Ok(Some(attr.value)),
|
||||
false => Ok(None),
|
||||
}
|
||||
}
|
||||
fn update_message_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, channel_id: i32, message_id: i32, key: &str, val: &str) {
|
||||
self._update_message_attribute(String::from(profile).as_str(), conversation_id.into(), channel_id, message_id, key, val)
|
||||
}
|
||||
fn change_password(&self, profile: &ProfileIdentity, old_pass: &str, new_pass: &str, new_pass_again: &str) {
|
||||
self._change_password(String::from(profile).as_str(), old_pass, new_pass, new_pass_again)
|
||||
}
|
||||
fn export_profile(&self, profile: &ProfileIdentity, filename: &str) {
|
||||
self._export_profile(String::from(profile).as_str(), filename)
|
||||
}
|
||||
|
||||
c_bind!(import_profile(filename: &str, password: &str;;) c_ImportProfile -> String);
|
||||
|
||||
c_bind!(create_group(profile, server, name;) c_CreateGroup);
|
||||
c_bind!(delete_profile(profile, pass;) c_DeleteProfile);
|
||||
c_bind!(archive_conversation(profile, contact;) c_ArchiveConversation);
|
||||
c_bind!(delete_contact(profile, group;) c_DeleteContact);
|
||||
c_bind!(import_bundle(profile, bundle;) c_ImportBundle);
|
||||
c_bind!(set_profile_attribute(profile, key, val;) c_SetProfileAttribute);
|
||||
c_bind!(set_contact_attribute(profile, contact, key, val;) c_SetContactAttribute);
|
||||
c_bind!(set_group_attribute(profile, group, key, val;) c_SetGroupAttribute);
|
||||
|
||||
fn shutdown_cwtch(&self) {
|
||||
unsafe {
|
||||
bindings::c_ShutdownCwtch();
|
||||
}
|
||||
}
|
||||
|
||||
c_bind!(load_servers(password: &str;;) c_LoadServers);
|
||||
fn create_server(&self, password: &str, description: &str , autostart: bool) {
|
||||
self._create_server(password, description, to_c_bool(autostart))
|
||||
}
|
||||
fn delete_server(&self, server: ServerIdentity, current_password: &str) {
|
||||
self._delete_server(String::from(server).as_str(), current_password)
|
||||
}
|
||||
c_bind!(launch_servers(;;) c_LaunchServers);
|
||||
fn launch_server(&self, server: ServerIdentity) {
|
||||
self._launch_server(String::from(server).as_str())
|
||||
}
|
||||
fn stop_server(&self, server: ServerIdentity) {
|
||||
self._stop_server(String::from(server).as_str())
|
||||
}
|
||||
c_bind!(stop_servers(;;) c_StopServers);
|
||||
c_bind!(destroy_servers(;;) c_DestroyServers);
|
||||
fn set_server_attribute(&self, server: ServerIdentity, key: &str, val: &str) {
|
||||
self._set_server_attribute(String::from(server).as_str(), key, val)
|
||||
}
|
||||
|
||||
c_bind!(get_debug_info(;;) c_GetDebugInfo -> String);
|
||||
|
||||
fn get_appbus_event(&self) -> Event {
|
||||
let event_json = self._get_appbus_event();
|
||||
let cwtch_event: CwtchEvent = serde_json::from_str(&event_json).expect("Error parsing Cwtch event");
|
||||
Event::from(&cwtch_event)
|
||||
unsafe { bindings::c_ShutdownCwtch(); }
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* automatically generated by rust-bindgen 0.65.1 */
|
||||
/* automatically generated by rust-bindgen 0.58.1 */
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
|
||||
#[repr(C)]
|
||||
|
@ -6,6 +6,7 @@ pub struct __BindgenComplex<T> {
|
|||
pub re: T,
|
||||
pub im: T,
|
||||
}
|
||||
pub type size_t = ::std::os::raw::c_ulong;
|
||||
pub type wchar_t = ::std::os::raw::c_int;
|
||||
#[repr(C)]
|
||||
#[repr(align(16))]
|
||||
|
@ -17,8 +18,6 @@ pub struct max_align_t {
|
|||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_max_align_t() {
|
||||
const UNINIT: ::std::mem::MaybeUninit<max_align_t> = ::std::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<max_align_t>(),
|
||||
32usize,
|
||||
|
@ -30,7 +29,9 @@ fn bindgen_test_layout_max_align_t() {
|
|||
concat!("Alignment of ", stringify!(max_align_t))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).__clang_max_align_nonce1) as usize - ptr as usize },
|
||||
unsafe {
|
||||
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce1 as *const _ as usize
|
||||
},
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -40,7 +41,9 @@ fn bindgen_test_layout_max_align_t() {
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).__clang_max_align_nonce2) as usize - ptr as usize },
|
||||
unsafe {
|
||||
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce2 as *const _ as usize
|
||||
},
|
||||
16usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -58,8 +61,6 @@ pub struct _GoString_ {
|
|||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout__GoString_() {
|
||||
const UNINIT: ::std::mem::MaybeUninit<_GoString_> = ::std::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<_GoString_>(),
|
||||
16usize,
|
||||
|
@ -71,7 +72,7 @@ fn bindgen_test_layout__GoString_() {
|
|||
concat!("Alignment of ", stringify!(_GoString_))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<_GoString_>())).p as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -81,7 +82,7 @@ fn bindgen_test_layout__GoString_() {
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).n) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<_GoString_>())).n as *const _ as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -101,7 +102,7 @@ pub type GoInt64 = ::std::os::raw::c_longlong;
|
|||
pub type GoUint64 = ::std::os::raw::c_ulonglong;
|
||||
pub type GoInt = GoInt64;
|
||||
pub type GoUint = GoUint64;
|
||||
pub type GoUintptr = usize;
|
||||
pub type GoUintptr = ::std::os::raw::c_ulong;
|
||||
pub type GoFloat32 = f32;
|
||||
pub type GoFloat64 = f64;
|
||||
pub type GoComplex64 = __BindgenComplex<f32>;
|
||||
|
@ -118,8 +119,6 @@ pub struct GoInterface {
|
|||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_GoInterface() {
|
||||
const UNINIT: ::std::mem::MaybeUninit<GoInterface> = ::std::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<GoInterface>(),
|
||||
16usize,
|
||||
|
@ -131,7 +130,7 @@ fn bindgen_test_layout_GoInterface() {
|
|||
concat!("Alignment of ", stringify!(GoInterface))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).t) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<GoInterface>())).t as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -141,7 +140,7 @@ fn bindgen_test_layout_GoInterface() {
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<GoInterface>())).v as *const _ as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -160,8 +159,6 @@ pub struct GoSlice {
|
|||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_GoSlice() {
|
||||
const UNINIT: ::std::mem::MaybeUninit<GoSlice> = ::std::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<GoSlice>(),
|
||||
24usize,
|
||||
|
@ -173,7 +170,7 @@ fn bindgen_test_layout_GoSlice() {
|
|||
concat!("Alignment of ", stringify!(GoSlice))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<GoSlice>())).data as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -183,7 +180,7 @@ fn bindgen_test_layout_GoSlice() {
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<GoSlice>())).len as *const _ as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -193,7 +190,7 @@ fn bindgen_test_layout_GoSlice() {
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).cap) as usize - ptr as usize },
|
||||
unsafe { &(*(::std::ptr::null::<GoSlice>())).cap as *const _ as usize },
|
||||
16usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
|
@ -203,12 +200,6 @@ fn bindgen_test_layout_GoSlice() {
|
|||
)
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_FreePointer(ptr: *mut ::std::os::raw::c_char);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_Started() -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_StartCwtch(
|
||||
dir_c: *mut ::std::os::raw::c_char,
|
||||
|
@ -217,14 +208,157 @@ extern "C" {
|
|||
torLen: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ReconnectCwtchForeground();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ShutdownCwtch();
|
||||
pub fn c_SendAppEvent(json_ptr: *mut ::std::os::raw::c_char, json_len: ::std::os::raw::c_int);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SendProfileEvent(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
json_ptr: *mut ::std::os::raw::c_char,
|
||||
json_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_CreateProfile(
|
||||
nick_ptr: *mut ::std::os::raw::c_char,
|
||||
nick_len: ::std::os::raw::c_int,
|
||||
pass_ptr: *mut ::std::os::raw::c_char,
|
||||
pass_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_LoadProfiles(
|
||||
passwordPtr: *mut ::std::os::raw::c_char,
|
||||
passwordLen: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_AcceptContact(
|
||||
profilePtr: *mut ::std::os::raw::c_char,
|
||||
profileLen: ::std::os::raw::c_int,
|
||||
handlePtr: *mut ::std::os::raw::c_char,
|
||||
handleLen: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_RejectInvite(
|
||||
profilePtr: *mut ::std::os::raw::c_char,
|
||||
profileLen: ::std::os::raw::c_int,
|
||||
handlePtr: *mut ::std::os::raw::c_char,
|
||||
handleLen: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_BlockContact(
|
||||
profilePtr: *mut ::std::os::raw::c_char,
|
||||
profileLen: ::std::os::raw::c_int,
|
||||
handlePtr: *mut ::std::os::raw::c_char,
|
||||
handleLen: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_UpdateMessageFlags(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
handle_ptr: *mut ::std::os::raw::c_char,
|
||||
handle_len: ::std::os::raw::c_int,
|
||||
mIdx: ::std::os::raw::c_int,
|
||||
message_flags: ::std::os::raw::c_ulong,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetMessage(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
handle_ptr: *mut ::std::os::raw::c_char,
|
||||
handle_len: ::std::os::raw::c_int,
|
||||
message_index: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetMessagesByContentHash(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
handle_ptr: *mut ::std::os::raw::c_char,
|
||||
handle_len: ::std::os::raw::c_int,
|
||||
contenthash_ptr: *mut ::std::os::raw::c_char,
|
||||
contenthash_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_FreePointer(ptr: *mut ::std::os::raw::c_char);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SendMessage(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
handle_ptr: *mut ::std::os::raw::c_char,
|
||||
handle_len: ::std::os::raw::c_int,
|
||||
msg_ptr: *mut ::std::os::raw::c_char,
|
||||
msg_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SendInvitation(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
handle_ptr: *mut ::std::os::raw::c_char,
|
||||
handle_len: ::std::os::raw::c_int,
|
||||
target_ptr: *mut ::std::os::raw::c_char,
|
||||
target_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ResetTor();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_CreateGroup(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
server_ptr: *mut ::std::os::raw::c_char,
|
||||
server_len: ::std::os::raw::c_int,
|
||||
name_ptr: *mut ::std::os::raw::c_char,
|
||||
name_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeleteProfile(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ArchiveConversation(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
contact_ptr: *mut ::std::os::raw::c_char,
|
||||
contact_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeleteContact(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
hanlde_ptr: *mut ::std::os::raw::c_char,
|
||||
handle_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ImportBundle(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
bundle_ptr: *mut ::std::os::raw::c_char,
|
||||
bundle_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SetProfileAttribute(
|
||||
|
@ -237,18 +371,11 @@ extern "C" {
|
|||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetProfileAttribute(
|
||||
pub fn c_SetContactAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
key_ptr: *mut ::std::os::raw::c_char,
|
||||
key_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SetConversationAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
conversation_id: ::std::os::raw::c_int,
|
||||
contact_ptr: *mut ::std::os::raw::c_char,
|
||||
contact_len: ::std::os::raw::c_int,
|
||||
key_ptr: *mut ::std::os::raw::c_char,
|
||||
key_len: ::std::os::raw::c_int,
|
||||
val_ptr: *mut ::std::os::raw::c_char,
|
||||
|
@ -256,393 +383,17 @@ extern "C" {
|
|||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetConversationAttribute(
|
||||
pub fn c_SetGroupAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
conversation_id: ::std::os::raw::c_int,
|
||||
group_ptr: *mut ::std::os::raw::c_char,
|
||||
group_len: ::std::os::raw::c_int,
|
||||
key_ptr: *mut ::std::os::raw::c_char,
|
||||
key_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ResetTor();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_UpdateSettings(json_ptr: *mut ::std::os::raw::c_char, json_len: ::std::os::raw::c_int);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetDebugInfo() -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ActivatePeerEngine(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
val_ptr: *mut ::std::os::raw::c_char,
|
||||
val_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeactivatePeerEngine(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ConfigureConnections(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
listen1: ::std::os::raw::c_char,
|
||||
peers2: ::std::os::raw::c_char,
|
||||
servers3: ::std::os::raw::c_char,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_CreateProfile(
|
||||
name_ptr: *mut ::std::os::raw::c_char,
|
||||
name_len: ::std::os::raw::c_int,
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
autostart4: ::std::os::raw::c_char,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_LoadProfiles(
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeleteProfile(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ImportProfile(
|
||||
file5_ptr: *mut ::std::os::raw::c_char,
|
||||
file5_len: ::std::os::raw::c_int,
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ChangePassword(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
current6_ptr: *mut ::std::os::raw::c_char,
|
||||
current6_len: ::std::os::raw::c_int,
|
||||
newPassword7_ptr: *mut ::std::os::raw::c_char,
|
||||
newPassword7_len: ::std::os::raw::c_int,
|
||||
newPasswordAgain8_ptr: *mut ::std::os::raw::c_char,
|
||||
newPasswordAgain8_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ExportProfile(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
file9_ptr: *mut ::std::os::raw::c_char,
|
||||
file9_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ImportBundle(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
bundle10_ptr: *mut ::std::os::raw::c_char,
|
||||
bundle10_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ArchiveConversation(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_AcceptConversation(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_BlockConversation(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_UnblockConversation(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeleteConversation(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_PeerWithOnion(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
handle11_ptr: *mut ::std::os::raw::c_char,
|
||||
handle11_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DisconnectFromPeer(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
handle12_ptr: *mut ::std::os::raw::c_char,
|
||||
handle12_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetConversationAccessControlList(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_UpdateConversationAccessControlList(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
json13_ptr: *mut ::std::os::raw::c_char,
|
||||
json13_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SearchConversations(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
pattern14_ptr: *mut ::std::os::raw::c_char,
|
||||
pattern14_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SendMessage(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
msg15_ptr: *mut ::std::os::raw::c_char,
|
||||
msg15_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetMessageById(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
message_id: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetMessageByContentHash(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
contentHash16_ptr: *mut ::std::os::raw::c_char,
|
||||
contentHash16_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetMessages(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
index: ::std::os::raw::c_int,
|
||||
count: ::std::os::raw::c_uint,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SendInviteMessage(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
target: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_UpdateMessageAttribute(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
channel_id: ::std::os::raw::c_int,
|
||||
message_id: ::std::os::raw::c_int,
|
||||
attributeKey17_ptr: *mut ::std::os::raw::c_char,
|
||||
attributeKey17_len: ::std::os::raw::c_int,
|
||||
attributeValue18_ptr: *mut ::std::os::raw::c_char,
|
||||
attributeValue18_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_StartGroup(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
name19_ptr: *mut ::std::os::raw::c_char,
|
||||
name19_len: ::std::os::raw::c_int,
|
||||
server20_ptr: *mut ::std::os::raw::c_char,
|
||||
server20_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_QueueJoinServer(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
handle21_ptr: *mut ::std::os::raw::c_char,
|
||||
handle21_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DisconnectFromServer(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
handle22_ptr: *mut ::std::os::raw::c_char,
|
||||
handle22_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_PublishServerUpdate(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetServerInfoList(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeleteServerInfo(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
serverOnion23_ptr: *mut ::std::os::raw::c_char,
|
||||
serverOnion23_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DownloadFileDefaultLimit(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
filepath24_ptr: *mut ::std::os::raw::c_char,
|
||||
filepath24_len: ::std::os::raw::c_int,
|
||||
manifest25_ptr: *mut ::std::os::raw::c_char,
|
||||
manifest25_len: ::std::os::raw::c_int,
|
||||
filekey26_ptr: *mut ::std::os::raw::c_char,
|
||||
filekey26_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_RestartFileShare(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
filekey27_ptr: *mut ::std::os::raw::c_char,
|
||||
filekey27_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_StopFileShare(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
filekey28_ptr: *mut ::std::os::raw::c_char,
|
||||
filekey28_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_CheckDownloadStatus(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
filekey29_ptr: *mut ::std::os::raw::c_char,
|
||||
filekey29_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_VerifyOrResumeDownloadDefaultLimit(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
filekey30_ptr: *mut ::std::os::raw::c_char,
|
||||
filekey30_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ShareFile(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
filepath31_ptr: *mut ::std::os::raw::c_char,
|
||||
filepath31_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetSharedFiles(
|
||||
onion_ptr: *mut ::std::os::raw::c_char,
|
||||
onion_len: ::std::os::raw::c_int,
|
||||
conversation: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_CreateServer(
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
description32_ptr: *mut ::std::os::raw::c_char,
|
||||
description32_len: ::std::os::raw::c_int,
|
||||
autostart33: ::std::os::raw::c_char,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SetServerAttribute(
|
||||
handle34_ptr: *mut ::std::os::raw::c_char,
|
||||
handle34_len: ::std::os::raw::c_int,
|
||||
key35_ptr: *mut ::std::os::raw::c_char,
|
||||
key35_len: ::std::os::raw::c_int,
|
||||
val36_ptr: *mut ::std::os::raw::c_char,
|
||||
val36_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_LoadServers(
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_LaunchServers();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_LaunchServer(
|
||||
handle37_ptr: *mut ::std::os::raw::c_char,
|
||||
handle37_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_StopServer(
|
||||
handle38_ptr: *mut ::std::os::raw::c_char,
|
||||
handle38_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_StopServers();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DestroyServers();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DeleteServer(
|
||||
handle39_ptr: *mut ::std::os::raw::c_char,
|
||||
handle39_len: ::std::os::raw::c_int,
|
||||
password_ptr: *mut ::std::os::raw::c_char,
|
||||
password_len: ::std::os::raw::c_int,
|
||||
);
|
||||
pub fn c_ShutdownCwtch();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,5 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(deref_nullptr)]
|
||||
|
||||
pub mod bindings;
|
845
src/event.rs
845
src/event.rs
|
@ -1,845 +0,0 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use chrono::prelude::*;
|
||||
use std::convert::From;
|
||||
|
||||
use crate::structs::{ACL, ConnectionState, CwtchEvent, MessageWrapper, Profile, Settings};
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
/// Profile ID used to refer to profiles in Cwtch
|
||||
pub struct ProfileIdentity(String);
|
||||
|
||||
impl From<String> for ProfileIdentity {
|
||||
fn from(x: String) -> Self {
|
||||
ProfileIdentity(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProfileIdentity> for String {
|
||||
fn from(x: ProfileIdentity) -> Self {
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ProfileIdentity {
|
||||
fn from(x: &str) -> Self {
|
||||
ProfileIdentity(x.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ProfileIdentity> for String {
|
||||
fn from(x: &ProfileIdentity) -> Self {
|
||||
x.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ProfileIdentity {
|
||||
/// Get &str of ProfileIdentity String
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
/// Contact ID used to refer to contacts in Cwtch
|
||||
pub struct ContactIdentity(String);
|
||||
|
||||
impl From<String> for ContactIdentity {
|
||||
fn from(x: String) -> Self {
|
||||
ContactIdentity(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl ContactIdentity {
|
||||
/// Get &str of ContactIdentity String
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
/// Conversation ID user to refer to a conversation with a Contact or Group in Cwtch
|
||||
pub struct ConversationID(pub i32) ;
|
||||
|
||||
impl From<i32> for ConversationID {
|
||||
fn from(x: i32) -> Self {
|
||||
ConversationID(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConversationID> for i32 {
|
||||
fn from(x: ConversationID) -> Self {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
/// Group ID used to refer to a Group in Cwtch
|
||||
pub struct GroupID(String) ;
|
||||
|
||||
impl From<String> for GroupID {
|
||||
fn from(x: String) -> Self {
|
||||
GroupID(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupID {
|
||||
/// Get &str of GroupID String
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
/// Server ID user to refer to a server in Cwtch
|
||||
pub struct ServerIdentity(String);
|
||||
|
||||
impl From<String> for ServerIdentity {
|
||||
fn from(x: String) -> Self {
|
||||
ServerIdentity(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ServerIdentity {
|
||||
fn from(x: &str) -> Self {
|
||||
ServerIdentity(x.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ServerIdentity> for String {
|
||||
fn from(x: ServerIdentity) -> Self {
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ServerIdentity {
|
||||
/// Get &str of ServerIdentity String
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
/// FileKey ID user to refer to a file share in Cwtch
|
||||
pub struct FileKey(String);
|
||||
|
||||
impl From<String> for FileKey {
|
||||
fn from(x: String) -> Self {
|
||||
FileKey(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FileKey> for String {
|
||||
fn from(x: FileKey) -> Self {
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&FileKey> for String {
|
||||
fn from(x: &FileKey) -> Self {
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl FileKey {
|
||||
/// Get &str of FileKey String
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Enum for type of notification a UI/client should emit for a new message
|
||||
pub enum MessageNotification {
|
||||
/// means no notification
|
||||
None,
|
||||
/// means emit a notification that a message event happened only
|
||||
SimpleEvent,
|
||||
/// means emit a notification event with Conversation handle included
|
||||
ContactInfo,
|
||||
}
|
||||
|
||||
impl From<String> for MessageNotification {
|
||||
fn from(str: String) -> MessageNotification {
|
||||
match str.as_str() {
|
||||
"None" => MessageNotification::None,
|
||||
"SimpleEvent" => MessageNotification::SimpleEvent,
|
||||
"ContactInfo" => MessageNotification::ContactInfo,
|
||||
_ => MessageNotification::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Enum for results from NetworkCheck plugin on profiles
|
||||
pub enum NetworkCheckStatus {
|
||||
/// There was an error, this profile cannot connect to itself
|
||||
Error,
|
||||
/// Success connecting to self, profile is "online"
|
||||
Success
|
||||
}
|
||||
|
||||
impl From<String> for NetworkCheckStatus {
|
||||
fn from(str: String) -> NetworkCheckStatus {
|
||||
match str.as_str() {
|
||||
"Error" => NetworkCheckStatus::Error,
|
||||
"Success" => NetworkCheckStatus::Success,
|
||||
_ => NetworkCheckStatus::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Enum denoting server storage mode
|
||||
pub enum ServerStorageType {
|
||||
/// indicates some app supplied default password is being used on this server for storage encryption
|
||||
DefaultPassword,
|
||||
/// indicates a user supplied password is being used on this server for storage encryption
|
||||
Password,
|
||||
/// indicates no password and no encryption is being used on server storage
|
||||
NoPassword
|
||||
}
|
||||
|
||||
impl From<String> for ServerStorageType {
|
||||
fn from(str: String) -> ServerStorageType {
|
||||
match str.as_str() {
|
||||
"storage-default-password" => ServerStorageType::DefaultPassword,
|
||||
"storage-password" => ServerStorageType::Password,
|
||||
"storage-no-password" => ServerStorageType::NoPassword,
|
||||
_ => ServerStorageType::DefaultPassword,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Enum used by servers to declare their intent to be running or stopped
|
||||
pub enum ServerIntent {
|
||||
/// a server intends to be running
|
||||
Running,
|
||||
/// a server intends to be stopped
|
||||
Stopped
|
||||
}
|
||||
|
||||
impl From<String> for ServerIntent {
|
||||
fn from(str: String) -> ServerIntent {
|
||||
match str.as_str() {
|
||||
"running" => ServerIntent::Running,
|
||||
"stopped" => ServerIntent::Stopped,
|
||||
_ => ServerIntent::Stopped,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Enum for events from Cwtch appbus
|
||||
pub enum Event {
|
||||
|
||||
// App events
|
||||
|
||||
/// Emited by libcwtch once Cwtch.Start() has been completed successfully, you can start making API calls, lcg is initialized
|
||||
CwtchStarted,
|
||||
/// A new peer has been loaded, details of peer. Identity should be stored so further API calls can be made
|
||||
NewPeer {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// optional client specified tag
|
||||
tag: String,
|
||||
/// is this a newly created profile event, or a load
|
||||
created: bool,
|
||||
/// user supplied name of the profile
|
||||
name: String,
|
||||
/// default picture path
|
||||
default_picture: String,
|
||||
/// user supplied picture path
|
||||
picture: String,
|
||||
/// is the profile online
|
||||
online: String,
|
||||
/// The deserialized profile with contacts and server info
|
||||
profile_data: Result<Profile, String>,
|
||||
},
|
||||
/// Cwtch had an error at the app level (not profile level), usually in response to an API call
|
||||
AppError {
|
||||
/// details of the app error that occured
|
||||
error: String,
|
||||
/// possible data about the error
|
||||
data: String
|
||||
},
|
||||
/// Global settings being emited from lcg, usually in response to them being sent to be saved by client
|
||||
UpdateGlobalSettings {
|
||||
/// map of setting names to values (https://git.openprivacy.ca/cwtch.im/libcwtch-go/src/branch/trunk/utils/settings.go)
|
||||
settings: Settings,
|
||||
},
|
||||
/// A profile has an error, usually emited in response to an API call
|
||||
PeerError {
|
||||
/// details of the peer error that occured
|
||||
error: String
|
||||
},
|
||||
/// A profile was successfully deleted, it is no longer usable
|
||||
PeerDeleted {
|
||||
/// identity of deleted peer
|
||||
profile_id: ProfileIdentity
|
||||
},
|
||||
/// Cwtch is shutting down, stop making API calls
|
||||
Shutdown,
|
||||
/// indicates status of the ACN (tor), usually during boot.
|
||||
ACNStatus {
|
||||
/// the percent of ACN boot (-1 to 100)
|
||||
progress: i8,
|
||||
/// an associated status message from the ACN
|
||||
status: String,
|
||||
},
|
||||
/// Version of the ACN (currently tor)
|
||||
ACNVersion {
|
||||
/// version string from ACN app
|
||||
version: String,
|
||||
},
|
||||
/// Notice from libCwtch that before completing load of a profile a storage migration is occuring so Start will take longer
|
||||
StartingStorageMiragtion,
|
||||
/// Notice from libCwtch that the storage migration is complete, profile being loaded resuming
|
||||
DoneStorageMigration,
|
||||
|
||||
// app server events
|
||||
|
||||
/// A new server has been loaded
|
||||
NewServer {
|
||||
/// identity of server
|
||||
server: ServerIdentity,
|
||||
/// sharable / importable server bundle
|
||||
server_bundle: String,
|
||||
/// user supplied description
|
||||
description: String,
|
||||
/// storage mode the server is using
|
||||
storage_type: ServerStorageType,
|
||||
/// does/should the server auto start on cwtch start
|
||||
autostart: bool,
|
||||
/// is the server running
|
||||
running: bool,
|
||||
},
|
||||
/// Response to request for server intent change, indicating the server is indending the new state
|
||||
ServerIntentUpdate {
|
||||
/// identity of server
|
||||
server: ServerIdentity,
|
||||
/// intent of the server to be running or not
|
||||
intent: ServerIntent,
|
||||
},
|
||||
/// Notice a server was deleted (in response to an API call) and is no longer usable
|
||||
ServerDeleted {
|
||||
/// identity of server
|
||||
server: ServerIdentity,
|
||||
/// was deletion a success
|
||||
success: bool,
|
||||
/// optional error string in case of failure to delete
|
||||
error: Option<String>,
|
||||
},
|
||||
/// Stats info for a server, periodically emited
|
||||
ServerStatsUpdate {
|
||||
/// identity of server
|
||||
server: ServerIdentity,
|
||||
/// count of total messages on the server
|
||||
total_messages: i32,
|
||||
/// count of total current connections to the server
|
||||
connections: i32,
|
||||
},
|
||||
|
||||
// profile events
|
||||
|
||||
/// A new message was received
|
||||
NewMessageFromPeer {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: ConversationID,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// name of contact
|
||||
nick: String,
|
||||
/// time message was received
|
||||
timestamp_received: DateTime<FixedOffset>,
|
||||
/// the message
|
||||
message: MessageWrapper,
|
||||
/// notification instructions (based on settings)
|
||||
notification: MessageNotification,
|
||||
/// path to picture for the contact
|
||||
picture: String,
|
||||
},
|
||||
/// A new contact has been created (imported, added, or contacted by)
|
||||
ContactCreated {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: ConversationID,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// name of group
|
||||
nick: String,
|
||||
/// connection status to group server
|
||||
status: ConnectionState,
|
||||
/// number of unread messages in group
|
||||
unread: i32,
|
||||
/// path to picture for group
|
||||
picture: String,
|
||||
/// path to default picture for group
|
||||
default_picture: String,
|
||||
/// total number of messages in group
|
||||
num_messages: i32,
|
||||
/// has the user accepted the group
|
||||
accepted: bool,
|
||||
/// ACL for the group
|
||||
access_control_list: ACL,
|
||||
/// is the group blocked
|
||||
blocked: bool,
|
||||
/// is the group syncing
|
||||
loading: bool,
|
||||
/// time of last message from the group
|
||||
last_msg_time: DateTime<FixedOffset>,
|
||||
|
||||
},
|
||||
/// A peer has changed state
|
||||
PeerStateChange {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// connection status to contact
|
||||
connection_state: ConnectionState,
|
||||
},
|
||||
/// Notice from the network check plugin, a profile self check test by attempting to connecting to itself
|
||||
NetworkStatus {
|
||||
/// profile the check was performed on
|
||||
profile_id: ProfileIdentity,
|
||||
// it's technically a profile self check
|
||||
/// error if there was one (can be empty)
|
||||
error: String,
|
||||
/// status of profile self connection check
|
||||
status: NetworkCheckStatus,
|
||||
},
|
||||
/// Information from the ACN about a peer
|
||||
ACNInfo {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// key of info
|
||||
key: String,
|
||||
/// data of info
|
||||
data: String,
|
||||
},
|
||||
/// a profile attribute has been updated with a new value
|
||||
UpdatedProfileAttribute {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// attribute key
|
||||
key: String,
|
||||
/// attribute new value
|
||||
value: String,
|
||||
},
|
||||
/// emited to confirm ack of a message succeeded
|
||||
IndexedAcknowledgement {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: i32,
|
||||
/// index of message acked
|
||||
index: i32,
|
||||
},
|
||||
/// emited to signal failure to ack a message
|
||||
IndexedFailure {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: ConversationID,
|
||||
/// index of failure of message to ack
|
||||
index: i32,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// error string
|
||||
error: String,
|
||||
},
|
||||
/// a peer has acked a message
|
||||
PeerAcknowledgement {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// message id this is an ack to
|
||||
event_id: String,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// conversation id
|
||||
conversation_id: i32,
|
||||
},
|
||||
/// New message received on a group
|
||||
NewMessageFromGroup {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: ConversationID,
|
||||
/// time of message
|
||||
timestamp_sent: DateTime<FixedOffset>,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// message index
|
||||
index: i32,
|
||||
/// the message
|
||||
message: MessageWrapper,
|
||||
/// hash of the message
|
||||
content_hash: String,
|
||||
/// path to picture for sender
|
||||
picture: String,
|
||||
/// notification policy (based on settings)
|
||||
notification: MessageNotification,
|
||||
},
|
||||
/// notice a group has been created
|
||||
GroupCreated {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: ConversationID,
|
||||
/// group id
|
||||
group_id: GroupID,
|
||||
/// server the group is on
|
||||
group_server: String,
|
||||
/// name of group
|
||||
group_name: String,
|
||||
/// path to picture for group
|
||||
picture: String,
|
||||
/// Access Control List for group
|
||||
access_control_list: ACL,
|
||||
},
|
||||
/// notice a new group exists
|
||||
NewGroup {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
conversation_id: ConversationID,
|
||||
/// server the group is on
|
||||
group_server: String,
|
||||
/// invite string
|
||||
group_invite: String,
|
||||
/// group name
|
||||
group_name: String,
|
||||
},
|
||||
/// a server connection state has changed
|
||||
ServerStateChange {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// server the group is on
|
||||
group_server: String,
|
||||
/// state of connection to server
|
||||
state: ConnectionState,
|
||||
},
|
||||
/// A getval call to a peer has returned a response
|
||||
NewRetValMessageFromPeer {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// conversation id
|
||||
contact_id: ContactIdentity,
|
||||
/// scope of the val
|
||||
scope: String,
|
||||
/// path of the val (zone.key)
|
||||
path: String,
|
||||
/// does the queried for value exist
|
||||
exists: bool,
|
||||
/// value
|
||||
data: String,
|
||||
/// optional filepath if there was a downloaded component
|
||||
file_path: Option<String>,
|
||||
},
|
||||
/// result of a call to share a file, the filekey and manifest to operate on it
|
||||
ShareManifest {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// filekey
|
||||
filekey: FileKey,
|
||||
/// serialized manifest of the share
|
||||
serialized_manifest: String,
|
||||
},
|
||||
/// Information on a peer fileshare has been received
|
||||
ManifestSizeReceived {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// filekey
|
||||
filekey: FileKey,
|
||||
/// size of manifest received for a share
|
||||
manifest_size: i32,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
},
|
||||
/// An error has occured while trying to parse a peer sharefile
|
||||
ManifestError {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// filekey
|
||||
filekey: FileKey,
|
||||
},
|
||||
/// A peer message about a shared file has been received
|
||||
ManifestReceived {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// filekey
|
||||
filekey: FileKey,
|
||||
/// serialized manifest
|
||||
serialized_manifest: String,
|
||||
},
|
||||
/// a received manfiest has been saved
|
||||
ManifestSaved {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// contact id
|
||||
contact_id: ContactIdentity,
|
||||
/// filekey
|
||||
filekey: FileKey,
|
||||
/// serialized manifest
|
||||
serialized_manifest: String,
|
||||
/// temporary storage path for share download
|
||||
temp_file: String,
|
||||
/// contact suggested share file name
|
||||
name_suggestion: String,
|
||||
},
|
||||
/// periodically emited status updates about an active download of a shared file
|
||||
FileDownloadProgressUpdate {
|
||||
/// identity field
|
||||
profile_id: ProfileIdentity,
|
||||
/// filekey
|
||||
filekey: FileKey,
|
||||
/// progress of download of share in chunks
|
||||
progress: i32,
|
||||
/// size of share in chunks
|
||||
filesize_in_chunks: i32,
|
||||
/// contact suggested name for file
|
||||
name_suggestion: String,
|
||||
},
|
||||
// FileDownloaded, ??
|
||||
|
||||
/// Indicates an event was sent from libCwtch that we don't handle/didn't anticipate
|
||||
/// still passing it on giving the user a chance to react, but should be reported so we can handle it properly
|
||||
ErrUnhandled {
|
||||
/// name of unhandled event
|
||||
name: String,
|
||||
/// map of key:val attributes of unhandled event
|
||||
data: HashMap<String, String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<&CwtchEvent> for Event {
|
||||
fn from(cwtch_event: &CwtchEvent) -> Self {
|
||||
println!("EVENT: {:?}", cwtch_event);
|
||||
match cwtch_event.event_type.as_str() {
|
||||
"CwtchStarted" => Event::CwtchStarted,
|
||||
"NewPeer" => Event::NewPeer {
|
||||
profile_id: cwtch_event.data["Identity"].clone().into(),
|
||||
tag: cwtch_event.data["tag"].clone(),
|
||||
created: cwtch_event.data["Created"] == "true",
|
||||
name: cwtch_event.data["name"].clone(),
|
||||
default_picture: cwtch_event.data["defaultPicture"].clone(),
|
||||
picture: cwtch_event.data["picture"].clone(),
|
||||
online: cwtch_event.data["Online"].clone(),
|
||||
profile_data: Profile::new(
|
||||
cwtch_event.data["Identity"].clone().into(),
|
||||
&cwtch_event.data["name"],
|
||||
&cwtch_event.data["picture"],
|
||||
&cwtch_event.data["ContactsJson"],
|
||||
&cwtch_event.data["ServerList"],
|
||||
)
|
||||
|
||||
},
|
||||
"NewMessageFromPeer" => Event::NewMessageFromPeer {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
|
||||
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
|
||||
nick: cwtch_event.data["Nick"].clone(),
|
||||
timestamp_received: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampReceived"].as_str()).unwrap_or( DateTime::from(Utc::now())),
|
||||
message: MessageWrapper::from_json(&cwtch_event.data["Data"]),
|
||||
notification: MessageNotification::from(cwtch_event.data["notification"].clone()),
|
||||
picture: cwtch_event.data["picture"].clone(),
|
||||
},
|
||||
"PeerError" => Event::PeerError { error: cwtch_event.data["Error"].clone() },
|
||||
"AppError" => Event::AppError {
|
||||
error: match cwtch_event.data.contains_key("Error") {
|
||||
true => cwtch_event.data["Error"].clone(),
|
||||
false => "".to_string()
|
||||
},
|
||||
data: match cwtch_event.data.contains_key("Data") {
|
||||
true => cwtch_event.data["Data"].clone(),
|
||||
false => "".to_string()
|
||||
}
|
||||
},
|
||||
"ContactCreated" => Event::ContactCreated {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
conversation_id: cwtch_event.data["ConversationID"].clone().parse().unwrap_or(-2).into(),
|
||||
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
|
||||
unread: cwtch_event.data["unread"].clone().parse().unwrap_or(0),
|
||||
picture: cwtch_event.data["picture"].clone(),
|
||||
default_picture: cwtch_event.data["defaultPicture"].clone(),
|
||||
num_messages: cwtch_event.data["numMessages"].clone().parse().unwrap_or(0),
|
||||
nick: cwtch_event.data["nick"].clone(),
|
||||
accepted: cwtch_event.data["accepted"].clone().parse().unwrap_or(false),
|
||||
status: ConnectionState::from(cwtch_event.data["status"].as_str()),
|
||||
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
|
||||
blocked: cwtch_event.data["blocked"].clone().parse().unwrap_or(false),
|
||||
loading: cwtch_event.data["loading"].clone().parse().unwrap_or(false),
|
||||
last_msg_time: DateTime::parse_from_rfc3339(cwtch_event.data["lastMsgTime"].as_str()).unwrap_or(DateTime::from(Utc::now())),
|
||||
},
|
||||
"PeerStateChange" => Event::PeerStateChange {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
|
||||
connection_state: ConnectionState::from(cwtch_event.data["ConnectionState"].as_str()),
|
||||
},
|
||||
"UpdateGlobalSettings" => Event::UpdateGlobalSettings {
|
||||
settings: serde_json::from_str(cwtch_event.data["Data"].as_str()).expect("could not parse settings from libCwtch-go"),
|
||||
},
|
||||
"PeerDeleted" => Event::PeerDeleted { profile_id: cwtch_event.data["Identity"].clone().into() },
|
||||
|
||||
"ACNStatus" => Event::ACNStatus {
|
||||
progress: cwtch_event.data["Progress"].parse().unwrap_or(0),
|
||||
status: cwtch_event.data["Status"].clone(),
|
||||
},
|
||||
"ACNVersion" => Event::ACNVersion { version: cwtch_event.data["Data"].clone()},
|
||||
"NetworkError" => Event::NetworkStatus {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
error: cwtch_event.data["Error"].clone(),
|
||||
status: NetworkCheckStatus::from(cwtch_event.data["Status"].clone())
|
||||
},
|
||||
"ACNInfo" => Event::ACNInfo {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
contact_id: cwtch_event.data["Handle"].clone().into(),
|
||||
key: cwtch_event.data["Key"].clone(),
|
||||
data: cwtch_event.data["Data"].clone(),
|
||||
},
|
||||
"UpdatedProfileAttribute" => Event::UpdatedProfileAttribute {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
key: cwtch_event.data["Key"].clone(),
|
||||
value: cwtch_event.data["Data"].clone(),
|
||||
},
|
||||
"IndexedAcknowledgement" => Event::IndexedAcknowledgement {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-1).into(),
|
||||
index: cwtch_event.data["Index"].parse().unwrap_or(-1),
|
||||
},
|
||||
"ShareManifest" => Event::ShareManifest {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
filekey: cwtch_event.data["FileKey"].clone().into(),
|
||||
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
|
||||
},
|
||||
"NewServer" => Event::NewServer {
|
||||
server: cwtch_event.data["Onion"].clone().into(),
|
||||
server_bundle: cwtch_event.data["ServerBundle"].clone(),
|
||||
description: cwtch_event.data["Description"].clone(),
|
||||
storage_type: ServerStorageType::from(cwtch_event.data["StorageType"].clone()),
|
||||
autostart: cwtch_event.data["Autostart"].parse().unwrap_or(false),
|
||||
running: cwtch_event.data["Running"].parse().unwrap_or(false),
|
||||
},
|
||||
"ServerIntentUpdate" => Event::ServerIntentUpdate {
|
||||
server: cwtch_event.data["Identity"].clone().into(),
|
||||
intent: ServerIntent::from(cwtch_event.data["Intent"].clone())
|
||||
},
|
||||
"ServerDeleted" => Event::ServerDeleted {
|
||||
server: cwtch_event.data["Identity"].clone().into(),
|
||||
success: cwtch_event.data["Status"].clone() == "success",
|
||||
error: match cwtch_event.data.get("Error") {
|
||||
Some(e) => Some(e.clone()),
|
||||
None => None,
|
||||
}
|
||||
},
|
||||
"ServerStatsUpdate" => Event::ServerStatsUpdate {
|
||||
server: cwtch_event.data["Identity"].clone().into(),
|
||||
total_messages: cwtch_event.data["TotalMessages"].parse().unwrap_or(0),
|
||||
connections: cwtch_event.data["Connections"].parse().unwrap_or(0),
|
||||
},
|
||||
"ManifestSizeReceived" => Event::ManifestSizeReceived {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
filekey: cwtch_event.data["FileKey"].clone().into(),
|
||||
manifest_size: cwtch_event.data["ManifestSize"].parse().unwrap_or(0),
|
||||
contact_id: cwtch_event.data["Handle"].clone().into(),
|
||||
},
|
||||
"ManifestError" => Event::ManifestError {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
contact_id: cwtch_event.data["Handle"].clone().into(),
|
||||
filekey: cwtch_event.data["FileKey"].clone().into(),
|
||||
},
|
||||
"ManifestReceived" => Event::ManifestReceived {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
contact_id: cwtch_event.data["Handle"].clone().into(),
|
||||
filekey: cwtch_event.data["FileKey"].clone().into(),
|
||||
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
|
||||
},
|
||||
"ManifestSaved" => Event::ManifestSaved {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
contact_id: cwtch_event.data["Handle"].clone().into(),
|
||||
filekey: cwtch_event.data["FileKey"].clone().into(),
|
||||
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
|
||||
temp_file: cwtch_event.data["TempFile"].clone(),
|
||||
name_suggestion: cwtch_event.data["NameSuggestion"].clone(),
|
||||
},
|
||||
"FileDownloadProgressUpdate" => Event::FileDownloadProgressUpdate {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
filekey: cwtch_event.data["FileKey"].clone().into(),
|
||||
progress: cwtch_event.data["Progress"].parse().unwrap_or(0),
|
||||
filesize_in_chunks: cwtch_event.data["FileSizeInChunks"].parse().unwrap_or(0),
|
||||
name_suggestion: cwtch_event.data["NameSuggestion"].clone(),
|
||||
},
|
||||
"PeerAcknowledgement" => Event::PeerAcknowledgement {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
event_id: cwtch_event.data["EventID"].clone(),
|
||||
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
|
||||
conversation_id: cwtch_event.data.get("ConversationID").unwrap_or(&"0".to_string()).parse().unwrap_or(0)
|
||||
},
|
||||
"NewMessageFromGroup" => Event::NewMessageFromGroup {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
timestamp_sent: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampSent"].as_str()).unwrap_or( DateTime::from(Utc::now())),
|
||||
index: cwtch_event.data["RemotePeer"].parse().unwrap_or(-1),
|
||||
content_hash: cwtch_event.data["ContentHash"].clone(),
|
||||
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
|
||||
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
|
||||
message: MessageWrapper::from_json(&cwtch_event.data["Data"]),
|
||||
notification: MessageNotification::from(cwtch_event.data["notification"].clone()),
|
||||
picture: cwtch_event.data["picture"].clone(),
|
||||
},
|
||||
"GroupCreated" => Event::GroupCreated {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
|
||||
group_id: cwtch_event.data["GroupID"].clone().into(),
|
||||
group_server: cwtch_event.data["GroupServer"].clone(),
|
||||
group_name: cwtch_event.data["GroupName"].clone(),
|
||||
picture: cwtch_event.data["picture"].clone(),
|
||||
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
|
||||
},
|
||||
"NewGroup" => Event::NewGroup {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
|
||||
group_server: cwtch_event.data["GroupServer"].clone(),
|
||||
group_name: cwtch_event.data["GroupName"].clone(),
|
||||
group_invite: cwtch_event.data["GroupInvite"].clone(),
|
||||
},
|
||||
"ServerStateChange" => Event::ServerStateChange {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
group_server: cwtch_event.data["GroupServer"].clone(),
|
||||
state: ConnectionState::from(cwtch_event.data["ConnectionState"].as_str()),
|
||||
},
|
||||
"NewRetValMessageFromPeer" => Event::NewRetValMessageFromPeer {
|
||||
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
|
||||
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
|
||||
scope: cwtch_event.data["Scope"].clone(),
|
||||
path: cwtch_event.data["Path"].clone(),
|
||||
exists: cwtch_event.data["Exists"].parse().unwrap_or(false),
|
||||
data: cwtch_event.data["Data"].clone(),
|
||||
file_path: match cwtch_event.data.get("FilePath") {
|
||||
Some(fp) => Some(fp.to_string()),
|
||||
None => None,
|
||||
},
|
||||
},
|
||||
|
||||
_ => Event::ErrUnhandled {
|
||||
name: cwtch_event.event_type.to_string(),
|
||||
data: cwtch_event.data.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
209
src/lib.rs
209
src/lib.rs
|
@ -3,227 +3,82 @@
|
|||
#![doc(html_root_url = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs")]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use crate::event::{ConversationID, Event, FileKey, ProfileIdentity, ServerIdentity};
|
||||
use crate::structs::{ACL, MessageWrapper, Settings, SharedFile};
|
||||
|
||||
mod bindings_go;
|
||||
mod cwtchlib_go;
|
||||
mod bindings_go;
|
||||
|
||||
/// Basic structs using data from Cwtch and for deserializing JSON and serializing to JSON to communicate with Cwtch
|
||||
pub mod structs;
|
||||
/// Additional structs for advnaced event handling and converstion helpers
|
||||
pub mod event;
|
||||
|
||||
/// Error type for Cwtch lib related errors, intended for use with Result
|
||||
pub type CwtchError = String;
|
||||
|
||||
/// Interface to a Cwtch app with API matching libcwtch
|
||||
pub trait CwtchLib {
|
||||
/// Start a cwtch application using app_dir to store all user profile data and looking to tor_path to find tor to run
|
||||
fn start_cwtch(&self, app_dir: &str, tor_path: &str) -> i32;
|
||||
|
||||
/// Return 1 if cwtch has been started and 0 if not
|
||||
fn started(&self) -> i32;
|
||||
|
||||
/// Like StartCwtch, but StartCwtch has already been called so we don't need to restart Tor etc (probably)
|
||||
/// Do need to re-send initial state tho, eg profiles that are already loaded (used by android when ui state is lost)
|
||||
fn reconnect_cwtch_foreground(&self);
|
||||
|
||||
/// Save and update the settings based on this settings
|
||||
fn update_settings(&self, settings: &Settings);
|
||||
|
||||
/// Activate the networking engine of a profile so it can send and listen to/for messages
|
||||
fn activate_peer_engine(&self, profile: &ProfileIdentity);
|
||||
|
||||
/// Deactivate the networking engine of a profile so it cannot send and listen to/for messages
|
||||
fn deactivate_peer_engine(&self, profile: &ProfileIdentity);
|
||||
/// Send json of a structs::CwtchEvent to the cwtch app bus
|
||||
fn send_app_event(&self, event_json: &str);
|
||||
|
||||
/// Pull json of a structs::CwtchEvent off the appbus for responding to
|
||||
fn get_appbus_event(&self) -> Event;
|
||||
|
||||
/// configure a peer's connection settings, listen for incoming connections, connect to peers and connect to servers.
|
||||
fn configure_connections(&self, profile: &ProfileIdentity, listen: bool, peers: bool, servers: bool);
|
||||
fn get_appbus_event(&self, ) -> String;
|
||||
|
||||
/// Create a new profile encrypted with pass
|
||||
fn create_profile(&self, nick: &str, pass: &str, autostart: bool);
|
||||
fn create_profile(&self, nick: &str, pass: &str);
|
||||
|
||||
/// Load any profiles encrypted by pass
|
||||
fn load_profiles(&self, pass: &str);
|
||||
|
||||
/// Cause profile to accept conversation
|
||||
fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
|
||||
/// Cause profile to accept contact
|
||||
fn accept_contact(&self, profile: &str, contact: &str);
|
||||
|
||||
/// Cause profile to block conversation
|
||||
fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
|
||||
/// Cause profile to reject contact
|
||||
fn reject_invite(&self, profile: &str, contact: &str);
|
||||
|
||||
/// Cause profile to unblock conversation
|
||||
fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
|
||||
/// Cause profile to block contact
|
||||
fn block_contact(&self, profile: &str, contact: &str);
|
||||
|
||||
/// Attempt to peer with a a new peer
|
||||
fn peer_with(&self, profile: &ProfileIdentity, new_peer_address: &str);
|
||||
/// Cause profile to update contact's message to have it's flags updated
|
||||
fn update_message_flags(&self, profile: &str, contact: &str, message_id: i32, message_flags: u64);
|
||||
|
||||
/// manually disconnect from a conversation
|
||||
fn disconnect_from_peer(&self, profile: &ProfileIdentity, peer_id: &str);
|
||||
/// Get a specific message for contact of profile by index
|
||||
fn get_message(&self, profile: &str, contact: &str, message_index: i32) -> String;
|
||||
|
||||
/// starts a search process on a profile for pattern. returns a searchID that resulting SearchResult messages will have
|
||||
fn search_conversations(&self, profile: &ProfileIdentity, pattern: &str) -> String;
|
||||
/// Get a specific message for contact of profile by hash
|
||||
fn get_message_by_content_hash(&self, profile: &str, contact: &str, hash: &str) -> String;
|
||||
|
||||
/// Get an ACL for a conversation
|
||||
fn get_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID) -> Result<ACL, CwtchError>;
|
||||
/// Send json of a structs::Message from profile to contact
|
||||
fn send_message(&self, profile: &str, contact: &str, msg: &str);
|
||||
|
||||
/// Update a conversation's ACL
|
||||
fn update_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID, acl: ACL);
|
||||
|
||||
/// Get a specific message for a conversation by its id
|
||||
fn get_message_by_id(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_id: i32) -> String;
|
||||
|
||||
/// Get a specific message for conversation of profile by hash
|
||||
fn get_message_by_content_hash(
|
||||
&self,
|
||||
profile: &ProfileIdentity,
|
||||
conversation_id: ConversationID,
|
||||
hash: &str,
|
||||
) -> String;
|
||||
|
||||
/// Bulk get messages starting at message index and of count amoung
|
||||
fn get_messages(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_index: i32, count: u32) -> String;
|
||||
|
||||
/// Send json of a structs::Message from profile to contact. Returns computed sent message (including index and hash values)
|
||||
fn send_message_raw(&self, profile: &ProfileIdentity, conversation_id: ConversationID, msg: &str) -> String;
|
||||
|
||||
/// Send structs::Message from profile to contact. Returns computed sent message (including index and hash values) or Error
|
||||
fn send_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message: &MessageWrapper) -> Result<String, CwtchError>;
|
||||
|
||||
/// Send profile's contact an invite for/to target. Returns computed sent message (including index and hash values)
|
||||
fn send_invite_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, target_id: i32) -> String;
|
||||
|
||||
/// share a file file_path with a conersation. Returns computed sent message (including index and hash values)
|
||||
fn share_file(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str) -> String;
|
||||
|
||||
/// get list of SharedFile for a conversation
|
||||
fn get_shared_files(&self, profile: &ProfileIdentity, conversaion_id: ConversationID) -> Vec<SharedFile>;
|
||||
|
||||
/// download a file from a conversation to the file_path
|
||||
fn download_file_default_limit(
|
||||
&self,
|
||||
profile: &ProfileIdentity,
|
||||
conversation_id: ConversationID,
|
||||
file_path: &str,
|
||||
manifest_path: &str,
|
||||
file_key: &FileKey,
|
||||
);
|
||||
|
||||
/// Restart a fileshare (used when restarting app to reoffer a previously created fileshare)
|
||||
fn restart_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey);
|
||||
|
||||
/// Stop offering a fileshare
|
||||
fn stop_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey);
|
||||
|
||||
/// Query the status of a download
|
||||
fn check_download_status(&self, profile: &ProfileIdentity, file_key: &FileKey);
|
||||
|
||||
/// Verufy a download is done, and if not, resume it
|
||||
fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: &FileKey);
|
||||
/// Send profile's contact an invite for/to target
|
||||
fn send_invitation(&self, profile: &str, contact: &str, target: &str);
|
||||
|
||||
/// Ask the ACN inside the Cwtch app to restart the tor connection
|
||||
fn reset_tor(&self);
|
||||
fn reset_tor(&self, );
|
||||
|
||||
/// Cause profile to create a group on server with name
|
||||
fn start_group(&self, profile: &ProfileIdentity, name: &str, server: &str);
|
||||
|
||||
/// Queue joining a server in the out going connections queue
|
||||
fn queue_join_server(&self, profile: &ProfileIdentity, server: &ServerIdentity);
|
||||
|
||||
/// Disconnect from a specific server
|
||||
fn disconnect_from_server(&self, profile: &ProfileIdentity, server: &ServerIdentity);
|
||||
|
||||
/// Publish server status updates for a profile
|
||||
fn publish_server_update(&self, profile: &ProfileIdentity);
|
||||
|
||||
/// Get list of known servers for a profile
|
||||
fn get_server_info_list(&self, profile: &ProfileIdentity);
|
||||
|
||||
/// Delete server information from a profile, preventing future connections for all groups hosted on it
|
||||
fn delete_server_info(&self, profile: &ProfileIdentity, server: &ServerIdentity);
|
||||
fn create_group(&self, profile: &str, server: &str, name: &str);
|
||||
|
||||
/// Delete profile with encryption/password check of pass
|
||||
fn delete_profile(&self, profile: &ProfileIdentity, pass: &str);
|
||||
fn delete_profile(&self, profile: &str, pass: &str);
|
||||
|
||||
/// Cause profile to archive conversation with contact
|
||||
fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
|
||||
fn archive_conversation(&self, profile: &str, contact: &str);
|
||||
|
||||
/// Cause profile to delete contact/group identified by handle
|
||||
fn delete_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
|
||||
fn delete_contact(&self, profile: &str, handle: &str);
|
||||
|
||||
/// Cuase profile to attempt to import a contact/group/keybundle identified by bundle
|
||||
fn import_bundle(&self, profile: &ProfileIdentity, bundle: &str);
|
||||
fn import_bundle(&self, profile: &str, bundle: &str);
|
||||
|
||||
/// Set a profile attribute key to val
|
||||
fn set_profile_attribute(&self, profile: &ProfileIdentity, key: &str, val: &str);
|
||||
|
||||
/// Get a profile attribute
|
||||
fn get_profile_attribute(&self, profile: &ProfileIdentity, key: &str) -> Result<Option<String>, CwtchError>;
|
||||
fn set_profile_attribute(&self, profile: &str, key: &str, val: &str);
|
||||
|
||||
/// Set a profile's contact's attribute of key to val
|
||||
fn set_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str, val: &str);
|
||||
fn set_contact_attribute(&self, profile: &str, contact: &str, key: &str, val: &str);
|
||||
|
||||
/// Update an attribute on a message in a conversation
|
||||
fn update_message_attribute(
|
||||
&self,
|
||||
profile: &ProfileIdentity,
|
||||
conversation_id: ConversationID,
|
||||
channel_id: i32,
|
||||
message_id: i32,
|
||||
attribute_key: &str,
|
||||
attribute_value: &str,
|
||||
);
|
||||
|
||||
/// Get an attribute for a conversation
|
||||
fn get_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str) -> Result<Option<String>, CwtchError>;
|
||||
|
||||
/// Change a profile's password to new_pass if old_pass is correct
|
||||
fn change_password(&self, profile: &ProfileIdentity, old_pass: &str, new_pass: &str, new_pass_again: &str);
|
||||
|
||||
/// Export a profile to filename
|
||||
fn export_profile(&self, profile: &ProfileIdentity, filename: &str);
|
||||
|
||||
/// Import a profile from a file with supplied password. Json of a profile struct returned on success
|
||||
fn import_profile(&self, filename: &str, password: &str) -> String;
|
||||
/// Set a profile's group's attribute of key to val
|
||||
fn set_group_attribute(&self, profile: &str, group: &str, key: &str, val: &str);
|
||||
|
||||
/// Shutdown the cwtch app and associated ACN
|
||||
fn shutdown_cwtch(&self);
|
||||
|
||||
/// Server functions require server experiment to be enabled
|
||||
|
||||
/// Load all servers encrypted by password
|
||||
fn load_servers(&self, password: &str);
|
||||
|
||||
/// Create a new server, encrypted with password
|
||||
fn create_server(&self, password: &str, description: &str, autostart: bool);
|
||||
|
||||
/// Delete the specified server (if password is correct)
|
||||
fn delete_server(&self, server: ServerIdentity, current_password: &str);
|
||||
|
||||
/// Launch all loaded servers
|
||||
fn launch_servers(&self);
|
||||
|
||||
/// Launch the specified server
|
||||
fn launch_server(&self, server: ServerIdentity);
|
||||
|
||||
/// Stop the specified server
|
||||
fn stop_server(&self, server: ServerIdentity);
|
||||
|
||||
/// Stop all running servers
|
||||
fn stop_servers(&self);
|
||||
|
||||
/// Destroy all servers leaving htem un-re-runnable. call only on shutdown
|
||||
fn destroy_servers(&self);
|
||||
|
||||
/// Set the specified server's attribute of key to val
|
||||
fn set_server_attribute(&self, server: ServerIdentity, key: &str, val: &str);
|
||||
|
||||
/// Get debug info (mem, goroutine stats) from lcg in json
|
||||
fn get_debug_info(&self) -> String;
|
||||
fn shutdown_cwtch(&self, );
|
||||
}
|
||||
|
||||
/// Create a new CwtchLib that is backed by bindings to libcwtch-go
|
||||
|
|
407
src/structs.rs
407
src/structs.rs
|
@ -1,12 +1,9 @@
|
|||
use crate::structs::ConnectionState::Disconnected;
|
||||
use crate::{ConversationID, CwtchLib, ProfileIdentity};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, DefaultOnError};
|
||||
use serde_repr::*;
|
||||
use std::collections::HashMap;
|
||||
use crate::event::{ContactIdentity, FileKey};
|
||||
use crate::structs::ConnectionState::Disconnected;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// Defines the states a Cwtch connection can be in
|
||||
pub enum ConnectionState {
|
||||
/// The Cwtch connection is not conected at all
|
||||
|
@ -22,7 +19,7 @@ pub enum ConnectionState {
|
|||
/// The connection attempt failed
|
||||
Failed,
|
||||
/// The connection has been killed
|
||||
Killed,
|
||||
Killed
|
||||
}
|
||||
|
||||
impl Default for ConnectionState {
|
||||
|
@ -31,22 +28,6 @@ impl Default for ConnectionState {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ConnectionState {
|
||||
/// Creates a ConnectionState from a string sent from libcwtch-go
|
||||
fn from(name: &str) -> Self {
|
||||
match name {
|
||||
"Disconnected" => ConnectionState::Disconnected,
|
||||
"Connecting" => ConnectionState::Connecting,
|
||||
"Connected" => ConnectionState::Connected,
|
||||
"Authenticated" => ConnectionState::Authenticated,
|
||||
"Synced" => ConnectionState::Synced,
|
||||
"Failed" => ConnectionState::Failed,
|
||||
"Killed" => ConnectionState::Killed,
|
||||
_ => ConnectionState::Disconnected,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
/// Defines the various authorization modes a contact can be in
|
||||
|
@ -56,18 +37,7 @@ pub enum ContactAuthorization {
|
|||
/// The contact is approved by the user (manual action)
|
||||
Approved,
|
||||
/// The contact is blocked by the user, should be ignored
|
||||
Blocked,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
#[allow(non_snake_case)]
|
||||
/// Struct to deserialize the results of Get*Attribute requests into
|
||||
pub struct Attribute {
|
||||
/// Was the attribute value found in storage
|
||||
pub exists: bool,
|
||||
/// The value of the requested attribute
|
||||
pub value: String,
|
||||
Blocked
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -83,63 +53,26 @@ pub struct CwtchEvent {
|
|||
pub data: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
#[allow(non_snake_case)]
|
||||
/// AccessControl is a type determining client assigned authorization to a peer
|
||||
pub struct AccessControl {
|
||||
/// Any attempts from this handle to connect are blocked
|
||||
pub blocked: bool,
|
||||
/// Allows a handle to access the conversation
|
||||
pub read: bool,
|
||||
/// Allows a handle to append new messages to the conversation
|
||||
pub append: bool,
|
||||
|
||||
/// Profile should automatically try to connect with peer
|
||||
pub auto_connect: bool,
|
||||
|
||||
/// Profile should automatically exchange attributes like Name, Profile Image, etc.
|
||||
pub exchange_attributes: bool,
|
||||
|
||||
/// Allows a handle to share files to a conversation
|
||||
pub share_files: bool,
|
||||
|
||||
/// Indicates that certain filetypes should be autodownloaded and rendered when shared by this contact
|
||||
pub render_images: bool
|
||||
}
|
||||
|
||||
/// represents an access control list for a conversation. Mapping handles to conversation functions
|
||||
pub type ACL = HashMap<String, AccessControl>;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
/// Struct to serialize/deserialize conversations coming from libcwtch-go
|
||||
pub struct Conversation {
|
||||
/// onion address / id of the conversation
|
||||
#[serde(alias = "onion")]
|
||||
pub contact_id: ContactIdentity,
|
||||
/// unique identifier of the contact/conversation to be used in API access
|
||||
pub identifier: ConversationID, // TODO TEST does this work here for serde deserializtion
|
||||
/// display name of the conversation, as determined in libcwtch-go from name specified by contact
|
||||
/// Struct to serialize/deserialize contacts coming from libcwtch-go
|
||||
pub struct Contact {
|
||||
/// onion address / id of the contact
|
||||
pub onion: String,
|
||||
/// display name of the contact, as determined in libcwtch-go from name specified by contact
|
||||
pub name: String,
|
||||
#[serde_as(deserialize_as = "DefaultOnError")]
|
||||
// cwtch loads profile/conversation from storage and leaves status blank, it's filled in "soon" by events...
|
||||
#[serde_as(deserialize_as = "DefaultOnError")] // cwtch loads profile/contacts from storage and leaves status blank, it's filled in "soon" by events...
|
||||
/// contact connection status
|
||||
pub status: ConnectionState,
|
||||
/// has the conversation been manually accpted
|
||||
pub accepted: bool,
|
||||
///represents an access control list for a conversation. Mapping handles to conversation functions
|
||||
pub access_control_list: ACL,
|
||||
/// has the conversation been manually blocked
|
||||
pub blocked: bool,
|
||||
/// is this conversation a group? if so "onion" will be a group ID
|
||||
/// FIXME: deprecate
|
||||
/// contact authorization state as set by profile
|
||||
pub authorization: ContactAuthorization,
|
||||
/// is this contact a group? if so "onion" will be a group ID
|
||||
pub is_group: bool,
|
||||
//attr: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// Struct to serialize/deserialize servers coming from libcwtch-go
|
||||
pub struct Server {
|
||||
/// onion address of the server
|
||||
|
@ -148,317 +81,65 @@ pub struct Server {
|
|||
pub status: ConnectionState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
/// Struct to serialize/deserialize profiles coming from libcwtch-go
|
||||
pub struct Profile {
|
||||
/// onion address / ID of the profile
|
||||
pub profile_id: ProfileIdentity,
|
||||
pub onion: String,
|
||||
/// nick name of the onion as supplied by libcwtch-go based on "name" attribute
|
||||
pub nick: String,
|
||||
/// path to a profile image, controled by "picture" attribute
|
||||
pub image_path: String,
|
||||
/// all profile attributes
|
||||
pub attr: HashMap<String, String>,
|
||||
/// map of conversation [ onion => conversation ]
|
||||
pub conversations: HashMap<ConversationID, Conversation>,
|
||||
pub attr: HashMap<String,String>,
|
||||
/// map of contacts [ onion => contact ]
|
||||
pub contacts: HashMap<String, Contact>,
|
||||
/// map of servers [ onion => server ]
|
||||
pub servers: HashMap<String, Server>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Clone)]
|
||||
#[repr(i32)]
|
||||
/// Enum matching message types and their overlays as defined in Cwtch
|
||||
/// - https://git.openprivacy.ca/cwtch.im/cwtch/src/commit/907a7ca638fbcbaac5d652608d455d4217597fa9/model/overlay.go
|
||||
/// - https://git.openprivacy.ca/cwtch.im/cwtch-ui/src/commit/3a752b73972cbfc53b6da26116fe018ee2ac2343/lib/models/message.dart
|
||||
pub enum MessageType {
|
||||
/// A standard Cwtch message of text
|
||||
TextMessage = 1,
|
||||
/// This message is a text message but it also contains a reference to the message it is quoting
|
||||
QuotedMessage = 10,
|
||||
/// A shared contact message
|
||||
SuggestContact = 100,
|
||||
/// A group invite message
|
||||
InviteGroup = 101,
|
||||
/// a share file message
|
||||
FileShare = 200,
|
||||
/// This message is of an unsupported type so malformed
|
||||
MalformedMessage,
|
||||
}
|
||||
|
||||
impl From<i32> for MessageType {
|
||||
fn from(x: i32) -> Self {
|
||||
match x {
|
||||
1 => MessageType::TextMessage,
|
||||
10 => MessageType::QuotedMessage,
|
||||
100 => MessageType::SuggestContact,
|
||||
101 => MessageType::InviteGroup,
|
||||
200 => MessageType::FileShare,
|
||||
_ => MessageType::MalformedMessage,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// Struct to serialize/deserialize messages sent over Cwtch between profiles / conversation
|
||||
/// Overlay => data
|
||||
/// 1 TextMessage: d = plain text message
|
||||
/// 10 QuotedMessage: d = json of QuotedMessageStructure, body = plain text of message
|
||||
pub struct MessageWrapper {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
/// Struct to serialize/deserialize messages sent over Cwtch between profiles / contacts
|
||||
pub struct Message {
|
||||
/// overlay id that the message is targeting as defined in cwtch/model/overlay.go
|
||||
/// [ OverlayChat = 1, OverlayInviteContact = 100, OverlayInviteGroup = 101, OverlayFileSharing = 200 ]
|
||||
pub o: MessageType,
|
||||
/// data of the message, for OverlayChat, a
|
||||
pub d: String,
|
||||
}
|
||||
|
||||
impl MessageWrapper {
|
||||
/// parse json into a Message
|
||||
pub fn from_json(json: &str) -> Self {
|
||||
match serde_json::from_str(json) {
|
||||
Ok(m) => m,
|
||||
Err(e) => MessageWrapper {o: MessageType::MalformedMessage, d: e.to_string()}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// defined: cwtch-ui/lib/model/messages/quotedmessage.dart ~ln 15
|
||||
#[allow(non_snake_case)]
|
||||
pub struct QuotedMessageStructure {
|
||||
/// hash message id of message being quoted
|
||||
pub quotedHash: String,
|
||||
/// plain text of the reply message
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// LocallyIndexedMessage is a type wrapper around a Message and a TimeLine Index that is local to this
|
||||
/// instance of the timeline.
|
||||
/// defined in: cwtch/model/message.go ~ln 31
|
||||
#[allow(non_snake_case)]
|
||||
pub struct LocallyIndexedMessage {
|
||||
/// The message
|
||||
pub Message: LocalMessage,
|
||||
/// the local index in this timeline instance
|
||||
pub LocalIndex: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// Message is a local representation of a given message sent over a group chat channel.
|
||||
/// defined in: cwtch/model/message.go ~ln 38
|
||||
#[allow(non_snake_case)]
|
||||
pub struct LocalMessage {
|
||||
/// Timestamp of the message from sender
|
||||
pub Timestamp: String, //time.Time
|
||||
/// Timestamp message was received at
|
||||
pub Received: String, //time.Time
|
||||
/// ContactId of the sender
|
||||
pub PeerID: String,
|
||||
/// Message contents
|
||||
pub Message: MessageWrapper,
|
||||
/// author's signature verifying the message
|
||||
pub Signature: String,
|
||||
/// the signature of hte previous message in the sender's timeline
|
||||
pub PreviousMessageSig: String,
|
||||
/// was message confirmed by server
|
||||
pub ReceivedByServer: bool,
|
||||
/// was the message ack'ed by the recipient peer
|
||||
pub Acknowledged: bool, // peer to peer
|
||||
/// message if there was an error, empty if fine
|
||||
pub Error: String,
|
||||
/// Application specific flags, useful for storing small amounts of metadata
|
||||
pub Flags: u64
|
||||
}
|
||||
|
||||
// Only for internal use?
|
||||
/*
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// FilesharingOverlayMessage presents the canonical format of the File Sharing functionality Overlay Message
|
||||
/// This is the format that the UI will parse to display the message
|
||||
/// defined: cwtch/functionality/filesharing/filesharing_functionality.go ~ln 156
|
||||
pub struct FilesharingOverlayMessage {
|
||||
#[serde(alias = "f")]
|
||||
pub name: String,
|
||||
#[serde(alias = "h")]
|
||||
pub hash: String,
|
||||
#[serde(alias = "n")]
|
||||
pub nonce: String,
|
||||
#[serde(alias = "s")]
|
||||
pub size: u64,
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// SharedFile struct from cwtch defined in cwtch/functionality/filesharing/filesharing_functionality.go ~ln 464
|
||||
#[allow(non_snake_case)]
|
||||
pub struct SharedFile {
|
||||
/// The roothash.nonce identifier derived for this file share
|
||||
pub FileKey: FileKey,
|
||||
|
||||
/// Path is the OS specific location of the file
|
||||
pub Path: String,
|
||||
|
||||
/// DateShared is the original datetime the file was shared
|
||||
/// go time.Time, => DateTime<FixedOffset>
|
||||
/// DateTime::parse_from_rfc3339(cwtch_event.data["TimestampSent"].as_str()).unwrap_or( DateTime::from(Utc::now())),
|
||||
pub DateShared: String,
|
||||
|
||||
/// Active is true if the file is currently being shared, false otherwise
|
||||
pub Active: bool,
|
||||
|
||||
/// Expired is true if the file is not eligible to be shared (because e.g. it has been too long since the file was originally shared,
|
||||
/// or the file no longer exists).
|
||||
pub Expired: bool
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// Settings as defined in libcwtch-go/utils/settings.go and should be populated by handeling the UpdateGlobalSettings event emited during cwtch.start()
|
||||
#[allow(non_snake_case)]
|
||||
pub struct Settings {
|
||||
/// locale for the UI to use
|
||||
pub Locale: String,
|
||||
/// theme of the UI
|
||||
pub Theme: String,
|
||||
/// Theme mode of the ui, light or dark
|
||||
pub ThemeMode: String,
|
||||
/// previous pid of the run, managed by libcwtch-go
|
||||
pub PreviousPid: i64,
|
||||
/// controls if subsequent experiments are enabled at all
|
||||
pub ExperimentsEnabled: bool,
|
||||
/// map of experiment names and their enabled status
|
||||
pub Experiments: HashMap<String, bool>,
|
||||
/// Should the app block unknown conversations
|
||||
pub BlockUnknownConnections: bool,
|
||||
// Notification policy of a UI app
|
||||
//pub NotificationPolicy: String, //Todo: NotificationPolicy struct
|
||||
// Notification content to show for a UI app
|
||||
//pub NotificationContent: String,
|
||||
/// Should the UI hide conversation IDs
|
||||
pub StreamerMode: bool,
|
||||
/// Unused?
|
||||
pub StateRootPane: i32,
|
||||
/// is this the first run
|
||||
pub FirstTime: bool,
|
||||
/// UI column mode
|
||||
pub UIColumnModePortrait: String,
|
||||
/// UI column mode
|
||||
pub UIColumnModeLandscape: String,
|
||||
/// Path to download files to
|
||||
pub DownloadPath: String,
|
||||
// Turn on advanced tor config in the UI
|
||||
//pub AllowAdvancedTorConfig: bool,
|
||||
// Custom torrc value
|
||||
//pub CustomTorrc: String,
|
||||
// Use the value of CustomTorrc with tor
|
||||
//pub UseCustomTorrc: bool,
|
||||
// Unused? delete
|
||||
//pub UseExternalTor: bool,
|
||||
// Tor socks port, if not default
|
||||
//pub CustomSocksPort: i32,
|
||||
// Tor control port if not default
|
||||
//pub CustomControlPort: i32,
|
||||
// Use tor cache for faster start
|
||||
//pub UseTorCache: bool,
|
||||
// Tor config dir
|
||||
//pub TorCacheDir: String,
|
||||
}
|
||||
|
||||
/// Enum of experiment types that can be managed in Settings
|
||||
pub enum Experiments {
|
||||
/// experiment enabling in app management and running of Cwtch servers
|
||||
ServersExperiment,
|
||||
/// experiment enabling use of Cwtch groups
|
||||
GroupExperiment,
|
||||
/// experiment enabling filesharing
|
||||
FileSharingExperiment,
|
||||
/// experiment enabling auto downloading of image files to Settings::DownloadPath
|
||||
ImagePreviewsExperiment,
|
||||
}
|
||||
|
||||
impl Experiments {
|
||||
/// returns the experiment settings key
|
||||
pub fn to_key_string(self) -> String {
|
||||
match self {
|
||||
Experiments::ServersExperiment => "servers-experiment".to_string(),
|
||||
Experiments::GroupExperiment => "tapir-groups-experiment".to_string(),
|
||||
Experiments::FileSharingExperiment => "filesharing".to_string(),
|
||||
Experiments::ImagePreviewsExperiment => "filesharing-images".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
/// Given a CwtchLib, handles sending an event to it with updated settings represented by this struct for saving
|
||||
pub fn save(&self, cwtch: &dyn CwtchLib) -> Result<(), String> {
|
||||
cwtch.update_settings(&self);
|
||||
return Ok(());
|
||||
}
|
||||
pub o: i64,
|
||||
/// data of the message
|
||||
pub d: String
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
/// Create a new profile populated from supplied data
|
||||
/// contacts_json as supplied by libcwtch-go, a map of conversations
|
||||
/// contacts_json as supplied by libcwtch-go, a map of contacts
|
||||
/// server_list as supplied by libcwtch-go, a map of servers
|
||||
pub fn new(
|
||||
identity: ProfileIdentity,
|
||||
name: &str,
|
||||
picture: &str,
|
||||
conversations_json: &str,
|
||||
server_list: &str,
|
||||
) -> Result<Profile, String> {
|
||||
let conversations = match Profile::process_conversations(conversations_json) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
let servers = match Profile::process_servers(server_list) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
Ok(Profile {
|
||||
profile_id: identity,
|
||||
nick: name.to_string(),
|
||||
image_path: picture.to_string(),
|
||||
attr: Default::default(),
|
||||
conversations,
|
||||
servers: servers,
|
||||
})
|
||||
pub fn new(identity: &str, name: &str, picture: &str, contacts_json: &str, server_list: &str) -> Profile {
|
||||
let contacts = Profile::process_contacts(contacts_json);
|
||||
let servers = Profile::process_servers(server_list);
|
||||
Profile{ onion: identity.to_string(), nick: name.to_string(), image_path: picture.to_string(), attr: Default::default(), contacts: contacts, servers: servers }
|
||||
}
|
||||
|
||||
fn process_conversations(conversations_json: &str) -> Result<HashMap<ConversationID, Conversation>, String> {
|
||||
let mut conversations: HashMap<ConversationID, Conversation> = HashMap::new();
|
||||
if conversations_json == "null" {
|
||||
return Ok(conversations);
|
||||
fn process_contacts(constacts_json: &str) -> HashMap<String, Contact> {
|
||||
let mut contacts: HashMap<String, Contact> = HashMap::new();
|
||||
if constacts_json == "null" {
|
||||
return contacts;
|
||||
}
|
||||
let conversations_map: Vec<Conversation> = match serde_json::from_str(conversations_json) {
|
||||
Ok(cm) => cm,
|
||||
Err(e) => return Err(format!("invalid json: {:?}", e)),
|
||||
};
|
||||
for conversation in conversations_map {
|
||||
conversations.insert(conversation.identifier, conversation);
|
||||
println!("contacts_json: '{}'", constacts_json);
|
||||
let contacts_map: Vec<Contact> = serde_json::from_str(constacts_json).unwrap();
|
||||
for contact in contacts_map {
|
||||
contacts.insert(contact.onion.clone(), contact);
|
||||
}
|
||||
Ok(conversations)
|
||||
contacts
|
||||
}
|
||||
|
||||
fn process_servers(servers_json: &str) -> Result<HashMap<String, Server>, String> {
|
||||
fn process_servers(servers_json: &str) -> HashMap<String, Server> {
|
||||
let mut servers: HashMap<String, Server> = HashMap::new();
|
||||
if servers_json == "null" {
|
||||
return Ok(servers);
|
||||
return servers;
|
||||
}
|
||||
let servers_map: Vec<Server> = match serde_json::from_str(servers_json) {
|
||||
Ok(sm) => sm,
|
||||
Err(e) => return Err(format!("invalid json: {:?}", e)),
|
||||
};
|
||||
let servers_map: Vec<Server> = serde_json::from_str(servers_json).unwrap();
|
||||
for server in servers_map {
|
||||
servers.insert(server.onion.clone(), server);
|
||||
}
|
||||
Ok(servers)
|
||||
}
|
||||
|
||||
/// Find a conversation_id associated with a remote handle (used for some events with no conversation id like PeerStateChange)
|
||||
pub fn find_conversation_id_by_handle(&self, contact_id: ContactIdentity) -> Option<ConversationID> {
|
||||
match self.conversations.values().filter(|c| c.contact_id == contact_id).next() {
|
||||
Some(conversation) => Some(conversation.identifier),
|
||||
None => None
|
||||
}
|
||||
servers
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue