feat: first fully working version
This commit is contained in:
parent
9c9287c5ff
commit
43dab27968
5 changed files with 300 additions and 431 deletions
389
Cargo.lock
generated
389
Cargo.lock
generated
|
@ -2,34 +2,6 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
|
@ -75,7 +47,7 @@ version = "1.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -86,7 +58,7 @@ checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
|
|||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -95,61 +67,6 @@ version = "1.0.98"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
|
||||
dependencies = [
|
||||
"async-stream-impl",
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream-impl"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.1"
|
||||
|
@ -162,27 +79,6 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
|
||||
dependencies = [
|
||||
"derive_more-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more-impl"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discord-rich-presence"
|
||||
version = "0.2.5"
|
||||
|
@ -197,12 +93,6 @@ dependencies = [
|
|||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.3"
|
||||
|
@ -226,22 +116,6 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
|
@ -253,12 +127,6 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "hl-zed-dc-rpc"
|
||||
version = "0.1.0"
|
||||
|
@ -266,52 +134,10 @@ dependencies = [
|
|||
"anyhow",
|
||||
"discord-rich-presence",
|
||||
"env_logger",
|
||||
"hyprland",
|
||||
"log",
|
||||
"regex",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyprland"
|
||||
version = "0.4.0-beta.2"
|
||||
source = "git+https://github.com/hyprland-community/hyprland-rs#fce63060619422f52563514b474398e380e5fc51"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"async-stream",
|
||||
"derive_more",
|
||||
"either",
|
||||
"futures-lite",
|
||||
"hyprland-macros",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"paste",
|
||||
"phf",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyprland-macros"
|
||||
version = "0.4.0-beta.2"
|
||||
source = "git+https://github.com/hyprland-community/hyprland-rs#fce63060619422f52563514b474398e380e5fc51"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -368,110 +194,12 @@ version = "2.7.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_macros",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
|
@ -505,21 +233,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
|
@ -549,12 +262,6 @@ version = "0.8.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
|
@ -604,28 +311,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
|
@ -657,47 +342,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.46.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
@ -713,27 +363,12 @@ dependencies = [
|
|||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
|
@ -806,23 +441,3 @@ name = "windows_x86_64_msvc"
|
|||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
|
|
@ -5,9 +5,12 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1.0.98"
|
||||
discord-rich-presence = { git = "https://github.com/vionya/discord-rich-presence" } # git cause errors
|
||||
env_logger = "0.11.8"
|
||||
hyprland = { git = "https://github.com/hyprland-community/hyprland-rs" }
|
||||
log = "0.4.27"
|
||||
|
||||
regex = "1.11.1"
|
||||
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
|
||||
discord-rich-presence = { git = "https://github.com/vionya/discord-rich-presence" } # git cause errors
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* This file WAS ONCE is part of discord-presence. Extension for Zed that adds support for Discord Rich Presence using LSP. It is heavily modified to be used here.
|
||||
* This file WAS ONCE is part of discord-presence. Extension for Zed that
|
||||
* adds support for Discord Rich Presence using LSP. It is heavily modified
|
||||
* to be used here.
|
||||
*
|
||||
* Copyright (c) 2025 Steinhübl, Virt
|
||||
*/
|
||||
|
@ -16,15 +18,11 @@ use log::{debug, error, info};
|
|||
#[derive(Debug)]
|
||||
pub struct Discord {
|
||||
client: DiscordIpcClient,
|
||||
start_timestamp: Duration,
|
||||
}
|
||||
|
||||
impl Discord {
|
||||
pub fn new(id: &str) -> Result<Self> {
|
||||
let since_epoch =
|
||||
SystemTime::now().duration_since(UNIX_EPOCH).expect("we are after 1970 right??");
|
||||
|
||||
Ok(Self { client: DiscordIpcClient::new(id), start_timestamp: since_epoch })
|
||||
Ok(Self { client: DiscordIpcClient::new(id) })
|
||||
}
|
||||
|
||||
pub fn connect(&mut self) -> Result<()> {
|
||||
|
@ -58,9 +56,15 @@ impl Discord {
|
|||
small_image: Option<String>,
|
||||
small_text: Option<String>,
|
||||
git_remote_url: Option<String>,
|
||||
timestamp: SystemTime,
|
||||
) -> Result<()> {
|
||||
let activity = Activity::new()
|
||||
.timestamps(Timestamps::new().start(self.start_timestamp.as_millis() as i64))
|
||||
let activity =
|
||||
Activity::new()
|
||||
.timestamps(
|
||||
Timestamps::new()
|
||||
.start(timestamp.duration_since(UNIX_EPOCH).expect("1970!!").as_millis()
|
||||
as i64),
|
||||
)
|
||||
.buttons(
|
||||
git_remote_url
|
||||
.as_ref()
|
||||
|
|
130
src/hyprland.rs
Normal file
130
src/hyprland.rs
Normal file
|
@ -0,0 +1,130 @@
|
|||
use std::{
|
||||
io::{self, Read, Write},
|
||||
os::unix::net::UnixStream,
|
||||
path::PathBuf,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use log::debug;
|
||||
use serde::Deserialize;
|
||||
|
||||
pub type Address = String;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct HyprlandClient {
|
||||
pub address: Address,
|
||||
pub class: String,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HyprlandEvent {
|
||||
Open { address: Address, workspace: String, title: String, class: String },
|
||||
Active { address: Address },
|
||||
Close { address: Address },
|
||||
Title { address: Address, title: String },
|
||||
}
|
||||
|
||||
pub struct Hyprland {
|
||||
path: PathBuf,
|
||||
stream: Option<UnixStream>,
|
||||
}
|
||||
|
||||
impl Hyprland {
|
||||
/// creates a new instance based on the environment variables
|
||||
pub fn env() -> Result<Self> {
|
||||
let instance = std::env::var("HYPRLAND_INSTANCE_SIGNATURE")
|
||||
.context("unable to read HYPRLAND_INSTANCE_SIGNATURE env")?;
|
||||
|
||||
let runtime_dir =
|
||||
std::env::var("XDG_RUNTIME_DIR").context("unable to read XDG_RUNTIME_DIR env")?;
|
||||
|
||||
Ok(Self { path: PathBuf::from(format!("{runtime_dir}/hypr/{instance}")), stream: None })
|
||||
}
|
||||
|
||||
pub fn connect(&mut self, timeout: Duration) -> Result<()> {
|
||||
debug!("connecting to hyprland socket 2");
|
||||
|
||||
let stream = UnixStream::connect(self.path.join(".socket2.sock"))
|
||||
.context("failed to connect to hyprland ipc")?;
|
||||
stream.set_read_timeout(Some(timeout)).context("failed to set socket timeout")?;
|
||||
|
||||
self.stream = Some(stream);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_events(&mut self) -> Result<Option<Vec<HyprlandEvent>>> {
|
||||
let Some(stream) = self.stream.as_mut() else {
|
||||
return Err(anyhow!("not yet connected to the ipc"));
|
||||
};
|
||||
|
||||
let mut buf = [0; 4096];
|
||||
let len = match stream.read(&mut buf) {
|
||||
Ok(len) => len,
|
||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => return Ok(None),
|
||||
Err(e) => return Err(e).context("failed to read from hyprland socket"),
|
||||
};
|
||||
|
||||
let string =
|
||||
String::from_utf8(buf[..len].to_vec()).context("read data from stream is not utf8")?;
|
||||
|
||||
Ok(Some(
|
||||
string
|
||||
.split('\n')
|
||||
.filter_map(|split| {
|
||||
let things = split.split(">>").collect::<Vec<_>>();
|
||||
if things.len() != 2 {
|
||||
return None;
|
||||
};
|
||||
|
||||
let event = things[0];
|
||||
let args = things[1].split(',').collect::<Vec<_>>();
|
||||
|
||||
match event {
|
||||
"activewindowv2" if args.len() == 1 => {
|
||||
Some(HyprlandEvent::Active { address: args[0].to_string() })
|
||||
}
|
||||
"openwindow" if args.len() == 4 => Some(HyprlandEvent::Open {
|
||||
address: args[0].to_string(),
|
||||
workspace: args[1].to_string(),
|
||||
class: args[2].to_string(),
|
||||
title: args[3].to_string(),
|
||||
}),
|
||||
"closewindow" if args.len() == 1 => {
|
||||
Some(HyprlandEvent::Close { address: args[0].to_string() })
|
||||
}
|
||||
"windowtitlev2" if args.len() == 2 => Some(HyprlandEvent::Title {
|
||||
address: args[0].to_string(),
|
||||
title: args[1].to_string(),
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
/// dispatches a command over hyprland's socket 1 and reads the result
|
||||
fn dispatch_command(&self, command: &str) -> Result<String> {
|
||||
let mut stream = UnixStream::connect(self.path.join(".socket.sock"))
|
||||
.context("failed to connect to hl's socket 1")?;
|
||||
|
||||
stream
|
||||
.write_all(format!("j/{command}").as_bytes())
|
||||
.context("failed to write to hl's socket 1")?;
|
||||
|
||||
let mut buf = String::new();
|
||||
stream.read_to_string(&mut buf).context("failed to read from hl's socket 1")?;
|
||||
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// gets the workspace state from socket 1
|
||||
pub fn get_all_clients(&self) -> Result<Vec<HyprlandClient>> {
|
||||
serde_json::from_str(
|
||||
&self.dispatch_command("clients").context("failed to run `clients` hyprctl command")?,
|
||||
)
|
||||
.context("failed to deserialize output of `clients` hyprctl command")
|
||||
}
|
||||
}
|
169
src/main.rs
169
src/main.rs
|
@ -1,52 +1,168 @@
|
|||
use std::{thread::sleep, time::Duration};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant, SystemTime},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use discord::Discord;
|
||||
use hyprland::{
|
||||
data::{Client, Clients},
|
||||
event_listener::EventListener,
|
||||
shared::HyprData,
|
||||
};
|
||||
use hyprland::{Address, Hyprland};
|
||||
use language::get_language;
|
||||
use log::{debug, info};
|
||||
|
||||
pub mod discord;
|
||||
pub mod hyprland;
|
||||
pub mod language;
|
||||
|
||||
const APP_ID: &str = "1263505205522337886";
|
||||
const ICONS_URL: &str =
|
||||
"https://raw.githubusercontent.com/xhyrom/zed-discord-presence/main/assets/icons";
|
||||
const ZED_CLASS: &str = "dev.zed.Zed";
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut discord = Discord::new(APP_ID)?;
|
||||
discord.connect()?;
|
||||
#[derive(Debug)]
|
||||
struct ZedInstance {
|
||||
workspace: String,
|
||||
file: Option<String>,
|
||||
started: SystemTime,
|
||||
|
||||
update_discord(&mut discord)?;
|
||||
//set_activity(&mut discord, "main.rs", "a secret new rust project")?;
|
||||
|
||||
sleep(Duration::from_secs(10));
|
||||
|
||||
Ok(())
|
||||
// last time it was focused
|
||||
focused: SystemTime,
|
||||
}
|
||||
|
||||
pub fn update_discord(discord: &mut Discord) -> Result<()> {
|
||||
let mut clients =
|
||||
Clients::get()?.into_iter().filter(|c| c.class == "dev.zed.Zed").collect::<Vec<_>>();
|
||||
clients.sort_by(|c, d| c.focus_history_id.cmp(&d.focus_history_id));
|
||||
impl ZedInstance {
|
||||
pub fn new(title: &str) -> Self {
|
||||
let mut s = Self {
|
||||
workspace: String::new(),
|
||||
file: None,
|
||||
started: SystemTime::now(),
|
||||
focused: SystemTime::now(),
|
||||
};
|
||||
|
||||
if let Some(client) = clients.first() {
|
||||
let split = client.title.split('—').collect::<Vec<_>>();
|
||||
s.set_title(title);
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let split = title.split('—').collect::<Vec<_>>();
|
||||
|
||||
if split.len() == 1 {
|
||||
set_activity(discord, "not-doing-anything-atm", split[0].trim())?;
|
||||
self.file = None;
|
||||
self.workspace = split[0].trim().to_string();
|
||||
} else if split.len() == 2 {
|
||||
set_activity(discord, split[1].trim(), split[0].trim())?;
|
||||
self.workspace = split[0].trim().to_string();
|
||||
self.file = Some(split[1].trim().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_activity(discord: &mut Discord, file: &str, workspace: &str) -> Result<()> {
|
||||
fn main() -> Result<()> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let idle = Duration::from_secs(10 * 60);
|
||||
|
||||
let mut discord = Discord::new(APP_ID)?;
|
||||
let mut hyprland = Hyprland::env()?;
|
||||
|
||||
let mut instances = HashMap::new();
|
||||
let mut active = Address::new();
|
||||
|
||||
for client in hyprland.get_all_clients()? {
|
||||
if client.class != "dev.zed.Zed" {
|
||||
continue;
|
||||
}
|
||||
|
||||
instances.insert(
|
||||
// we strip the 0x as this only appears in this request
|
||||
client.address.strip_prefix("0x").unwrap_or("unknown").to_string(),
|
||||
ZedInstance::new(&client.title),
|
||||
);
|
||||
}
|
||||
|
||||
info!("connecting to discord ipc");
|
||||
discord.connect()?;
|
||||
info!("connecting to hyprland ipc");
|
||||
hyprland.connect(Duration::from_secs(60))?;
|
||||
|
||||
let mut first = true;
|
||||
loop {
|
||||
let events = hyprland.read_events()?;
|
||||
debug!("received new hyprland events");
|
||||
|
||||
// only check on timeout if not active
|
||||
let mut changed = first || events.is_none() && !instances.contains_key(&active);
|
||||
first = false;
|
||||
|
||||
if let Some(events) = events {
|
||||
for event in events {
|
||||
changed |= match event {
|
||||
hyprland::HyprlandEvent::Open { address, title, class, .. }
|
||||
if class == ZED_CLASS =>
|
||||
{
|
||||
instances.insert(address, ZedInstance::new(&title));
|
||||
true
|
||||
}
|
||||
hyprland::HyprlandEvent::Active { address } => {
|
||||
let changed = if let Some(instance) = instances.get_mut(&active) {
|
||||
instance.focused = SystemTime::now();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
active = address;
|
||||
|
||||
changed || instances.contains_key(&active)
|
||||
}
|
||||
hyprland::HyprlandEvent::Close { address } => {
|
||||
instances.remove(&address).is_some()
|
||||
}
|
||||
hyprland::HyprlandEvent::Title { address, title } => {
|
||||
if let Some(instance) = instances.get_mut(&address) {
|
||||
instance.set_title(&title);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if let Some(instance) = instances.get(&active).or_else(|| {
|
||||
instances.values().max_by(|a, b| a.focused.cmp(&b.focused)).filter(|instance| {
|
||||
SystemTime::now().duration_since(instance.focused).expect("compare times wtf")
|
||||
< idle
|
||||
})
|
||||
}) {
|
||||
info!(
|
||||
"setting discord activity to {} in workspace {}",
|
||||
instance.file.as_ref().map(|s| s.as_str()).unwrap_or("<none>"),
|
||||
instance.workspace
|
||||
);
|
||||
|
||||
set_activity(
|
||||
&mut discord,
|
||||
instance.file.as_ref().map(|s| s.as_str()).unwrap_or("nothing"),
|
||||
&instance.workspace,
|
||||
instance.started,
|
||||
)?
|
||||
} else {
|
||||
info!("removing discord activity");
|
||||
discord.clear()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_activity(
|
||||
discord: &mut Discord,
|
||||
file: &str,
|
||||
workspace: &str,
|
||||
started: SystemTime,
|
||||
) -> Result<()> {
|
||||
let language = get_language(file);
|
||||
let language_upper: String = language.chars().take(1).chain(language.chars().skip(1)).collect();
|
||||
|
||||
|
@ -58,5 +174,6 @@ pub fn set_activity(discord: &mut Discord, file: &str, workspace: &str) -> Resul
|
|||
Some(format!("{ICONS_URL}/zed.png")),
|
||||
Some("Zed".to_string()),
|
||||
None,
|
||||
started,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue