Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8fefbddffd | |||
| 7dea731cbf | |||
| ff9a46c05c | |||
| 6169e6065d | |||
| 0ae38b0e01 | |||
| b2059a76c6 | |||
| fcbe163d18 | |||
| 6a3f75af71 | |||
| a4d3146076 | |||
| eaaba5a053 | |||
| 464d7f6fab | |||
| 547a067e54 | |||
| acce38cd44 | |||
| 29fefc118b | |||
| 8feab199fe | |||
| 97f4a4374d | |||
| f27376f8eb | |||
| 9b19be2a55 | |||
| 1512018a4f |
Generated
+410
-17
@@ -2,6 +2,32 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "RhythmWorks"
|
||||
version = "0.5.1"
|
||||
dependencies = [
|
||||
"dialoguer",
|
||||
"keyring",
|
||||
"opentelemetry 0.27.1",
|
||||
"opentelemetry-otlp",
|
||||
"opentelemetry-proto",
|
||||
"opentelemetry-semantic-conventions",
|
||||
"opentelemetry_sdk",
|
||||
"reqwest",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serenity",
|
||||
"songbird",
|
||||
"symphonia",
|
||||
"tokio",
|
||||
"tonic",
|
||||
"tracing",
|
||||
"tracing-opentelemetry",
|
||||
"tracing-subscriber",
|
||||
"yt-dlp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
@@ -67,6 +93,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.2"
|
||||
@@ -85,6 +117,28 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[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 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.89"
|
||||
@@ -137,6 +191,53 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"sync_wrapper",
|
||||
"tower 0.5.2",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"sync_wrapper",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
@@ -345,6 +446,19 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"unicode-width",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
@@ -678,6 +792,18 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dialoguer"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25f104b501bf2364e78d0d3974cbc774f738f5865306ed128e1e0d7499c0ad96"
|
||||
dependencies = [
|
||||
"console",
|
||||
"shell-words",
|
||||
"tempfile",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
@@ -690,21 +816,6 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discord_music"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serenity",
|
||||
"songbird",
|
||||
"symphonia",
|
||||
"tokio",
|
||||
"yt-dlp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discortp"
|
||||
version = "0.6.0"
|
||||
@@ -747,6 +858,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.33"
|
||||
@@ -1243,6 +1360,12 @@ version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.8.1"
|
||||
@@ -1257,6 +1380,7 @@ dependencies = [
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
@@ -1275,6 +1399,7 @@ dependencies = [
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"rustls 0.23.35",
|
||||
"rustls-native-certs",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.4",
|
||||
@@ -1282,6 +1407,19 @@ dependencies = [
|
||||
"webpki-roots 1.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-timeout"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
|
||||
dependencies = [
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.6.0"
|
||||
@@ -1515,6 +1653,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.16"
|
||||
@@ -1541,6 +1688,19 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keyring"
|
||||
version = "3.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"linux-keyutils",
|
||||
"log",
|
||||
"windows-sys 0.60.2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@@ -1605,6 +1765,16 @@ dependencies = [
|
||||
"zlib-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-keyutils"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
@@ -1683,6 +1853,12 @@ dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.6"
|
||||
@@ -1937,6 +2113,108 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"js-sys",
|
||||
"pin-project-lite",
|
||||
"thiserror 1.0.69",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"js-sys",
|
||||
"pin-project-lite",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-http"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a8a7f5f6ba7c1b286c2fbca0454eaba116f63bbe69ed250b642d36fbb04d80"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"http",
|
||||
"opentelemetry 0.27.1",
|
||||
"reqwest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-otlp"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"futures-core",
|
||||
"http",
|
||||
"opentelemetry 0.27.1",
|
||||
"opentelemetry-http",
|
||||
"opentelemetry-proto",
|
||||
"opentelemetry_sdk",
|
||||
"prost",
|
||||
"reqwest",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"tonic",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-proto"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"opentelemetry 0.27.1",
|
||||
"opentelemetry_sdk",
|
||||
"prost",
|
||||
"serde",
|
||||
"tonic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-semantic-conventions"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc1b6902ff63b32ef6c489e8048c5e253e2e4a803ea3ea7e783914536eb15c52"
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry_sdk"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"futures-channel",
|
||||
"futures-executor",
|
||||
"futures-util",
|
||||
"glob",
|
||||
"opentelemetry 0.27.1",
|
||||
"percent-encoding",
|
||||
"rand 0.8.5",
|
||||
"serde_json",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
@@ -2195,6 +2473,29 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.9.6"
|
||||
@@ -2442,6 +2743,7 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls 0.23.35",
|
||||
"rustls-native-certs",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -2451,7 +2753,7 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower 0.5.2",
|
||||
"tower-http",
|
||||
"tower-service",
|
||||
"url",
|
||||
@@ -2581,6 +2883,7 @@ version = "0.23.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@@ -2601,6 +2904,15 @@ dependencies = [
|
||||
"security-framework 3.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.13.2"
|
||||
@@ -2983,6 +3295,12 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shell-words"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -3963,6 +4281,59 @@ dependencies = [
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"base64",
|
||||
"bytes",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"hyper-timeout",
|
||||
"hyper-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"prost",
|
||||
"rustls-native-certs",
|
||||
"rustls-pemfile",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-stream",
|
||||
"tower 0.4.13",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"indexmap 1.9.3",
|
||||
"pin-project",
|
||||
"pin-project-lite",
|
||||
"rand 0.8.5",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.2"
|
||||
@@ -3991,7 +4362,7 @@ dependencies = [
|
||||
"http-body",
|
||||
"iri-string",
|
||||
"pin-project-lite",
|
||||
"tower",
|
||||
"tower 0.5.2",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
@@ -4062,6 +4433,22 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-opentelemetry"
|
||||
version = "0.32.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"opentelemetry 0.31.0",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-subscriber",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.22"
|
||||
@@ -4265,6 +4652,12 @@ version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.5.1"
|
||||
|
||||
+24
-2
@@ -1,9 +1,16 @@
|
||||
[package]
|
||||
name = "discord_music"
|
||||
version = "0.1.0"
|
||||
name = "RhythmWorks"
|
||||
version = "0.5.1"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
dialoguer = "0.12.0"
|
||||
keyring = { version = "3.6.3", features = ["linux-native", "windows-native"] }
|
||||
opentelemetry = { version = "0.27.0", features = ["logs", "metrics", "trace"] }
|
||||
opentelemetry-otlp = { version = "0.27.0", features = ["trace", "metrics", "grpc-tonic", "http-proto", "tls", "reqwest-client", "reqwest-rustls"] }
|
||||
opentelemetry-proto = "0.27.0"
|
||||
opentelemetry-semantic-conventions = "0.27.0"
|
||||
opentelemetry_sdk = { version = "0.27.0", features = ["rt-tokio", "trace"] }
|
||||
reqwest = { version = "0.12.28", features = ["blocking", "json"] }
|
||||
semver = "1.0.27"
|
||||
serde = "1.0.228"
|
||||
@@ -12,4 +19,19 @@ serenity = { version = "0.12.5", features = ["client", "gateway", "voice"] }
|
||||
songbird = { version = "0.5.0", features = ["builtin-queue", "driver", "serenity"] }
|
||||
symphonia = { version = "0.5.5", features = ["aac", "alac", "isomp4", "mp3"] }
|
||||
tokio = "1.48.0"
|
||||
tonic = { version = "0.12.3", features = ["tls-roots"] }
|
||||
tracing = "0.1.41"
|
||||
tracing-opentelemetry = "0.32.0"
|
||||
tracing-subscriber = "0.3.20"
|
||||
yt-dlp = "1.4.7"
|
||||
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = "fat"
|
||||
debug = false
|
||||
codegen-units = 1
|
||||
panic = 'abort'
|
||||
strip = true
|
||||
debug-assertions = false
|
||||
overflow-checks = true
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
## Welcome to RhythmWorks
|
||||
RhythmWorks is a lightweight Discord music bot designed for simple, direct audio playback from YouTube links. It focuses on manual control, minimal complexity, and local execution, making it ideal for personal servers or small communities.
|
||||
|
||||
Unlike many modern Discord bots, RhythmWorks does not rely on hosted services or third-party dashboards. You run it yourself, connect it to your Discord server, and control playback using straightforward text commands.
|
||||
|
||||
### Features
|
||||
- Play Audio directly from YouTube
|
||||
- Basic Playback Controls
|
||||
- Runs locally on your machine
|
||||
- No external accounts or external bot hosting required
|
||||
|
||||
### How It Works
|
||||
RhythmWorks connects to Discord using a custom bot that you generate through the Discord Developer Portal
|
||||
|
||||
### Roadmap
|
||||
[Project Roadmap](https://git.racooncity.org/brotoskyj/RhythmWorks/projects/4)
|
||||
|
||||
### Getting Started
|
||||
Please follow the [Getting Started](https://git.racooncity.org/brotoskyj/RhythmWorks/wiki/Getting-Started) Documentation for details on how to get RhythmWorks up and running
|
||||
|
||||
### Discord Commands
|
||||
Please review the [Commands](https://git.racooncity.org/brotoskyj/RhythmWorks/wiki/Commands) for usage
|
||||
|
||||
### Wiki
|
||||
[RhythmWorks Wiki](https://git.racooncity.org/brotoskyj/RhythmWorks/wiki/?action=_pages) - Please review this all for all documentation
|
||||
|
||||
## License
|
||||
|
||||
[AGPLv3](https://choosealicense.com/licenses/agpl-3.0/)
|
||||
|
||||
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
cargo clean
|
||||
cargo fmt
|
||||
cargo clippy --fix --all-targets --allow-dirty
|
||||
cargo build --release
|
||||
cargo build --release --target x86_64-pc-windows-gnu
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 190 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 169 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 198 KiB |
+277
-53
@@ -1,25 +1,65 @@
|
||||
use dialoguer::Select;
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
use modules::*;
|
||||
use opentelemetry::KeyValue;
|
||||
use opentelemetry::global;
|
||||
use opentelemetry::trace::Status;
|
||||
use opentelemetry::trace::TraceContextExt;
|
||||
use opentelemetry::trace::Tracer;
|
||||
use serenity::all::ChannelId;
|
||||
use serenity::async_trait;
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::model::gateway::Ready;
|
||||
use serenity::prelude::*;
|
||||
use songbird::Event;
|
||||
use songbird::EventContext;
|
||||
use songbird::SerenityInit;
|
||||
use songbird::events::EventHandler as VoiceEventHandler;
|
||||
use songbird::get;
|
||||
use songbird::input::HlsRequest;
|
||||
use songbird::input::Input;
|
||||
use songbird::tracks::TrackHandle;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::process::Stdio;
|
||||
use std::sync::Arc;
|
||||
pub mod modules;
|
||||
|
||||
type TrackMap = Arc<Mutex<HashMap<u64, TrackHandle>>>;
|
||||
struct Handler {
|
||||
track_map: TrackMap,
|
||||
struct TrackTraceHandler {
|
||||
otel_ctx: opentelemetry::Context,
|
||||
guild_id: String,
|
||||
track_url: String,
|
||||
hls_url: String,
|
||||
event_name: &'static str,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl VoiceEventHandler for TrackTraceHandler {
|
||||
async fn act(&self, ctx: &EventContext<'_>) -> Option<Event> {
|
||||
let tracer = global::tracer("RhythmWorks");
|
||||
let track_status = if let EventContext::Track(track_list) = ctx {
|
||||
track_list.first().map(|state| format!("{:?}", state.0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
tracer.in_span(self.event_name, |cx| {
|
||||
cx.span()
|
||||
.set_attribute(KeyValue::new("Guild_ID", self.guild_id.clone()));
|
||||
cx.span()
|
||||
.set_attribute(KeyValue::new("Youtube_URL", self.track_url.clone()));
|
||||
cx.span()
|
||||
.set_attribute(KeyValue::new("Stream_URL", self.hls_url.clone()));
|
||||
cx.span().add_event(
|
||||
self.event_name,
|
||||
vec![KeyValue::new(
|
||||
"track_status",
|
||||
track_status.unwrap().to_string(),
|
||||
)],
|
||||
);
|
||||
});
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
struct Handler;
|
||||
fn get_user_voice_channel(ctx: &Context, msg: &Message) -> Option<ChannelId> {
|
||||
let guild_id = msg.guild_id?;
|
||||
let guild = ctx.cache.guild(guild_id)?;
|
||||
@@ -38,13 +78,50 @@ impl EventHandler for Handler {
|
||||
println!("Error sending message: {why:?}");
|
||||
}
|
||||
if msg.content == "!join" {
|
||||
let tracer = global::tracer("RhythmWorks");
|
||||
let span = tracer.start("Join Message Received");
|
||||
let cx = opentelemetry::Context::current_with_span(span);
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
let channel_id = match get_user_voice_channel(&ctx, &msg) {
|
||||
Some(c) => c,
|
||||
Some(g) => {
|
||||
cx.span().add_event(
|
||||
"Received Guild ID",
|
||||
vec![KeyValue::new("Server ID", g.to_string())],
|
||||
);
|
||||
cx.span().set_status(opentelemetry::trace::Status::Ok);
|
||||
cx.span()
|
||||
.set_attribute(KeyValue::new("Guild_ID", g.to_string()));
|
||||
g
|
||||
}
|
||||
None => {
|
||||
cx.span().add_event(
|
||||
"Failed to Retreive Guild ID",
|
||||
vec![KeyValue::new("Server ID", "None")],
|
||||
);
|
||||
cx.span()
|
||||
.set_status(opentelemetry::trace::Status::error("Failed"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let channel_id = match get_user_voice_channel(&ctx, &msg) {
|
||||
Some(c) => {
|
||||
cx.span().add_event(
|
||||
"Received Channel ID",
|
||||
vec![KeyValue::new("Channel ID", c.to_string())],
|
||||
);
|
||||
cx.span().set_status(Status::Ok);
|
||||
c
|
||||
}
|
||||
None => {
|
||||
cx.span().add_event(
|
||||
"Failed to Retreive Channel ID",
|
||||
vec![KeyValue::new("Channel ID", "None")],
|
||||
);
|
||||
cx.span()
|
||||
.set_status(opentelemetry::trace::Status::error(format!(
|
||||
"{} not in Voice Channel",
|
||||
msg.author
|
||||
)));
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.say(&ctx.http, "You must be in a voice channel")
|
||||
@@ -52,7 +129,6 @@ impl EventHandler for Handler {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let manager = get(&ctx).await.expect("Songbird not initialized").clone();
|
||||
|
||||
let _ = manager.join(guild_id, channel_id).await;
|
||||
@@ -61,6 +137,11 @@ impl EventHandler for Handler {
|
||||
.channel_id
|
||||
.say(&ctx.http, "Joined your voice channel!")
|
||||
.await;
|
||||
cx.span().add_event(
|
||||
"Joined Voice Channel",
|
||||
vec![KeyValue::new("Voice Channel", msg.channel_id.to_string())],
|
||||
);
|
||||
cx.span().set_status(Status::Ok);
|
||||
}
|
||||
if msg.content == "!leave" {
|
||||
let guild_id = match msg.guild_id {
|
||||
@@ -77,58 +158,168 @@ impl EventHandler for Handler {
|
||||
}
|
||||
}
|
||||
if msg.content.starts_with("!play") {
|
||||
let url = msg
|
||||
let tracer = global::tracer("RhythmWorks");
|
||||
let span = tracer.start("Play Message Received");
|
||||
let mut yt_url = msg
|
||||
.content
|
||||
.strip_prefix("!play ")
|
||||
.unwrap_or("")
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
if url.is_empty() {
|
||||
if let Some(offset) = yt_url.find('&') {
|
||||
yt_url.truncate(offset);
|
||||
}
|
||||
if yt_url.is_empty() {
|
||||
let _ = msg.reply(&ctx, "Please provide a YouTube URL.").await;
|
||||
return;
|
||||
}
|
||||
let guild_id = msg.guild_id.unwrap();
|
||||
let manager = songbird::get(&ctx)
|
||||
.await
|
||||
.expect("Songbird Voice client placed in at initialisation.")
|
||||
.clone();
|
||||
let handler_lock = if let Some(handler) = manager.get(guild_id) {
|
||||
handler
|
||||
} else {
|
||||
let channel_id = get_user_voice_channel(&ctx, &msg);
|
||||
match channel_id {
|
||||
Some(c) => manager.join(guild_id, c).await.unwrap(),
|
||||
let cx = opentelemetry::Context::current_with_span(span);
|
||||
cx.span()
|
||||
.set_attribute(KeyValue::new("Youtube_URL", yt_url.to_string()));
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => {
|
||||
cx.span().add_event(
|
||||
"Received Guild ID",
|
||||
vec![KeyValue::new("Server ID", g.to_string())],
|
||||
);
|
||||
cx.span().set_status(opentelemetry::trace::Status::Ok);
|
||||
cx.span()
|
||||
.set_attribute(KeyValue::new("Guild_ID", g.to_string()));
|
||||
g
|
||||
}
|
||||
None => {
|
||||
let _ = msg.reply(&ctx, "Join a voice channel first!").await;
|
||||
cx.span().add_event(
|
||||
"Failed to Retreive Guild ID",
|
||||
vec![KeyValue::new("Server ID", "None")],
|
||||
);
|
||||
cx.span()
|
||||
.set_status(opentelemetry::trace::Status::error("Failed"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
let manager = songbird::get(&ctx).await.unwrap().clone();
|
||||
let handler_lock = if let Some(call) = manager.get(guild_id) {
|
||||
call
|
||||
} else {
|
||||
let channel_id = match get_user_voice_channel(&ctx, &msg) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
cx.span().add_event(
|
||||
"Failed to Retreive Channel ID",
|
||||
vec![KeyValue::new("Channel ID", "None")],
|
||||
);
|
||||
cx.span()
|
||||
.set_status(opentelemetry::trace::Status::error(format!(
|
||||
"{} not in Voice Channel",
|
||||
msg.author
|
||||
)));
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.say(&ctx.http, "You must be in a voice channel")
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
let output = Command::new("yt-dlp")
|
||||
.args(["-f", "bestaudio", "-g", &url])
|
||||
manager.join(guild_id, channel_id).await.unwrap()
|
||||
};
|
||||
let output = match Command::new("./yt-dlp")
|
||||
.args(["-f", "bestaudio", "-g", "--no-playlist", &yt_url])
|
||||
.stdout(Stdio::piped())
|
||||
.output()
|
||||
.expect("Failed");
|
||||
let url_bytes = output.stdout;
|
||||
let url = String::from_utf8(url_bytes).expect("Failed");
|
||||
let mut handler = handler_lock.lock().await;
|
||||
let input = Input::from(HlsRequest::new(reqwest::Client::new(), url.to_string()));
|
||||
let track_handle = handler.play_input(input);
|
||||
let _ = track_handle.play();
|
||||
self.track_map
|
||||
.lock()
|
||||
.await
|
||||
.insert(guild_id.into(), track_handle);
|
||||
let _ = msg.channel_id.say(&ctx.http, "🎶 Playing...").await;
|
||||
{
|
||||
Ok(output) => {
|
||||
cx.span().add_event(
|
||||
"Retreiving Youtube Information",
|
||||
vec![KeyValue::new("Success", yt_url.to_string())],
|
||||
);
|
||||
output
|
||||
}
|
||||
Err(e) => {
|
||||
cx.span().add_event(
|
||||
"Retreiving Youtube Information",
|
||||
vec![KeyValue::new("Failed", e.to_string())],
|
||||
);
|
||||
cx.span().set_status(Status::error("Failed"));
|
||||
eprintln!("{}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let stream_url = String::from_utf8(output.stdout)
|
||||
.expect("Invalid UTF-8")
|
||||
.trim()
|
||||
.to_string();
|
||||
let telemetry_stream_url = stream_url.clone();
|
||||
let mut call = handler_lock.lock().await;
|
||||
let input = Input::from(HlsRequest::new(reqwest::Client::new(), stream_url));
|
||||
let track_handle = call.enqueue_input(input).await;
|
||||
let otel_ctx = opentelemetry::Context::current();
|
||||
let position = call.queue().len();
|
||||
let response = if position == 1 {
|
||||
cx.span().add_event(
|
||||
"Starting Playback",
|
||||
vec![KeyValue::new("Status", "Playing".to_string())],
|
||||
);
|
||||
"🎶 Now playing!".to_string()
|
||||
} else {
|
||||
cx.span().add_event(
|
||||
"Starting Playback",
|
||||
vec![KeyValue::new("Status", "Added to Queue".to_string())],
|
||||
);
|
||||
format!("🎶 Added Song to Queue: #{}", position)
|
||||
};
|
||||
let _ = msg.channel_id.say(&ctx.http, response).await;
|
||||
let _ = track_handle.add_event(
|
||||
Event::Track(songbird::events::TrackEvent::Play),
|
||||
TrackTraceHandler {
|
||||
otel_ctx: otel_ctx.clone(),
|
||||
guild_id: guild_id.to_string().clone(),
|
||||
track_url: yt_url.clone(),
|
||||
hls_url: telemetry_stream_url.clone(),
|
||||
event_name: "Track Started Playing",
|
||||
},
|
||||
);
|
||||
let _ = track_handle.add_event(
|
||||
Event::Track(songbird::events::TrackEvent::End),
|
||||
TrackTraceHandler {
|
||||
otel_ctx: otel_ctx.clone(),
|
||||
guild_id: guild_id.to_string().clone(),
|
||||
track_url: yt_url.clone(),
|
||||
hls_url: telemetry_stream_url.clone(),
|
||||
event_name: "Track Finished",
|
||||
},
|
||||
);
|
||||
let _ = track_handle.add_event(
|
||||
Event::Track(songbird::events::TrackEvent::Error),
|
||||
TrackTraceHandler {
|
||||
otel_ctx: otel_ctx.clone(),
|
||||
guild_id: guild_id.to_string().clone(),
|
||||
track_url: yt_url.clone(),
|
||||
hls_url: telemetry_stream_url.clone(),
|
||||
event_name: "Playback had an error",
|
||||
},
|
||||
);
|
||||
}
|
||||
if msg.content == "!skip" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
let manager = songbird::get(&ctx).await.unwrap();
|
||||
if let Some(call) = manager.get(guild_id) {
|
||||
let call = call.lock().await;
|
||||
let _ = call.queue().skip();
|
||||
let _ = msg.channel_id.say(&ctx.http, "Skipped").await;
|
||||
}
|
||||
}
|
||||
if msg.content == "!pause" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
||||
let _ = handle.pause();
|
||||
let manager = songbird::get(&ctx).await.unwrap();
|
||||
if let Some(call) = manager.get(guild_id) {
|
||||
let call = call.lock().await;
|
||||
let _ = call.queue().pause();
|
||||
}
|
||||
}
|
||||
if msg.content == "!resume" {
|
||||
@@ -136,8 +327,10 @@ impl EventHandler for Handler {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
||||
let _ = handle.play();
|
||||
let manager = songbird::get(&ctx).await.unwrap();
|
||||
if let Some(call) = manager.get(guild_id) {
|
||||
let call = call.lock().await;
|
||||
let _ = call.queue().resume();
|
||||
}
|
||||
}
|
||||
if msg.content == "!stop" {
|
||||
@@ -145,8 +338,10 @@ impl EventHandler for Handler {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
||||
let _ = handle.stop();
|
||||
let manager = songbird::get(&ctx).await.unwrap();
|
||||
if let Some(call) = manager.get(guild_id) {
|
||||
let call = call.lock().await;
|
||||
let _ = call.queue().stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,25 +349,54 @@ impl EventHandler for Handler {
|
||||
println!("{} is connected!", ready.user.name);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!("RhythmWorks Copyright (C) 2025 James Brotosky\n
|
||||
println!(
|
||||
"RhythmWorks Copyright (C) 2025 James Brotosky\n
|
||||
This program comes with ABSOLUTELY NO WARRANTY\n
|
||||
This is free software, and you are welcome to redistribute it under certain conditions.");
|
||||
updator::update().await;
|
||||
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
|
||||
This is free software, and you are welcome to redistribute it under certain conditions."
|
||||
);
|
||||
let tracer_provider = telemetry::init_telemetry();
|
||||
global::set_tracer_provider(tracer_provider.clone());
|
||||
let tracer: global::BoxedTracer = global::tracer("tracer");
|
||||
tracer
|
||||
.in_span("Checking for Updates", |_cx| updator::update())
|
||||
.await;
|
||||
let service_name = "RhythmWorks";
|
||||
let username = env::var("USER").or_else(|_| env::var("USERNAME")).unwrap();
|
||||
loop {
|
||||
let token = credentialmanager::get_token(service_name, &username);
|
||||
let options: Vec<&'static str> = vec!["- Start Bot", "- Change Token", "- Delete Token"];
|
||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt("Choose an Option")
|
||||
.default(0)
|
||||
.items(&options)
|
||||
.interact()
|
||||
.unwrap();
|
||||
match selection {
|
||||
0 => {
|
||||
let intents = GatewayIntents::GUILD_MESSAGES
|
||||
| GatewayIntents::GUILDS
|
||||
| GatewayIntents::DIRECT_MESSAGES
|
||||
| GatewayIntents::MESSAGE_CONTENT
|
||||
| GatewayIntents::GUILD_VOICE_STATES;
|
||||
let track_map: TrackMap = Arc::new(Mutex::new(HashMap::new()));
|
||||
let mut client = Client::builder(&token, intents)
|
||||
.event_handler(Handler { track_map })
|
||||
.event_handler(Handler)
|
||||
.register_songbird()
|
||||
.await
|
||||
.expect("Err creating client");
|
||||
if let Err(why) = client.start().await {
|
||||
println!("Client error: {why:?}");
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
credentialmanager::change_token(service_name, &username);
|
||||
}
|
||||
2 => {
|
||||
credentialmanager::remove_token(service_name, &username);
|
||||
}
|
||||
_ => println!("Invalid Option"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
use dialoguer::{Input, theme::ColorfulTheme};
|
||||
use keyring::Entry;
|
||||
|
||||
pub fn get_token<'a>(service: &str, username: &str) -> String {
|
||||
let entry = Entry::new(service, username).expect("Failed to get keyring entry");
|
||||
match entry.get_password() {
|
||||
Ok(token) => token,
|
||||
Err(_) => {
|
||||
let token: String = Input::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt("Enter your bot token")
|
||||
.interact_text()
|
||||
.unwrap();
|
||||
match entry.set_password(&token) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
println!("Failed to set token: {}", e);
|
||||
std::process::abort()
|
||||
}
|
||||
};
|
||||
token
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_token(service: &str, username: &str) {
|
||||
let entry = Entry::new(service, username).expect("Failed to get keyring entry");
|
||||
let new_token: String = Input::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt("New Token")
|
||||
.interact_text()
|
||||
.unwrap();
|
||||
let _ = entry.set_password(&new_token);
|
||||
}
|
||||
|
||||
pub fn remove_token(service: &str, username: &str) {
|
||||
let entry = Entry::new(service, username).expect("Failed to get keyring entry");
|
||||
let _ = entry.delete_credential();
|
||||
}
|
||||
+2
-1
@@ -1,2 +1,3 @@
|
||||
pub mod credentialmanager;
|
||||
pub mod telemetry;
|
||||
pub mod updator;
|
||||
pub mod downloadyt;
|
||||
@@ -0,0 +1,26 @@
|
||||
use opentelemetry::KeyValue;
|
||||
use opentelemetry_otlp::{WithExportConfig, WithTonicConfig};
|
||||
use opentelemetry_sdk::{Resource, runtime};
|
||||
use tonic::transport::{Channel, ClientTlsConfig};
|
||||
|
||||
pub fn init_telemetry() -> opentelemetry_sdk::trace::TracerProvider {
|
||||
let endpoint = "https://signoz.racooncity.org".to_string();
|
||||
let channel = Channel::from_shared(endpoint.clone())
|
||||
.unwrap()
|
||||
.tls_config(ClientTlsConfig::new().with_native_roots())
|
||||
.unwrap()
|
||||
.connect_lazy();
|
||||
let exporter = opentelemetry_otlp::SpanExporter::builder()
|
||||
.with_tonic()
|
||||
.with_endpoint(endpoint.clone())
|
||||
.with_channel(channel)
|
||||
.build()
|
||||
.expect("Failed to Build Exporter");
|
||||
opentelemetry_sdk::trace::TracerProvider::builder()
|
||||
.with_batch_exporter(exporter, runtime::Tokio)
|
||||
.with_resource(Resource::new(vec![KeyValue::new(
|
||||
"service.name",
|
||||
"RhythmWorks",
|
||||
)]))
|
||||
.build()
|
||||
}
|
||||
+16
-7
@@ -1,20 +1,29 @@
|
||||
use serde::Deserialize;
|
||||
use semver::Version;
|
||||
use std::thread;
|
||||
|
||||
use reqwest;
|
||||
use semver::Version;
|
||||
use serde::Deserialize;
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Release {
|
||||
tag_name: String,
|
||||
}
|
||||
|
||||
pub async fn update() {
|
||||
let body = reqwest::get("https://git.racooncity.org/api/v1/repos/brotoskyj/RhythmWorks/releases/latest").await.unwrap().text().await.unwrap();
|
||||
let body = reqwest::get(
|
||||
"https://git.racooncity.org/api/v1/repos/brotoskyj/RhythmWorks/releases/latest",
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
let release_info: Release = serde_json::from_str(&body).unwrap();
|
||||
let latest_version = Version::parse(&release_info.tag_name).unwrap();
|
||||
let current_version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
if latest_version > current_version {
|
||||
println!("Update Available")
|
||||
}
|
||||
else {
|
||||
println!("Already on current version");
|
||||
println!("Update Available! Please download the latest version");
|
||||
println!("URL: https://git.racooncity.org/brotoskyj/RhythmWorks/releases");
|
||||
thread::sleep(std::time::Duration::from_secs(10));
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user