Add cli parsing logic and logging to rotom_discord_bot

This commit is contained in:
2025-01-29 20:03:19 +00:00
parent 42108ea8e7
commit d2de03fde1
8 changed files with 616 additions and 13 deletions

20
.env.example Normal file
View File

@@ -0,0 +1,20 @@
# Logging (env_logger) -----------------------------------------------------------------------------------
RUST_LOG="rotom_discord_bot=debug"
# Discord ------------------------------------------------------------------------------------------------
BOT_TOKEN="my_bot_token"
# Database -----------------------------------------------------------------------------------------------
# DATABASE_DIALECT="mysql"
# DATABASE_URL="mysql://username:password@host/database"
# DATABASE_DIALECT="postgres"
# DATABASE_URL="postgres://username:password@host/database"
DATABASE_DIALECT="sqlite"
DATABASE_URL="/path/to/sqlite/database.db"
# --------------------------------------------------------------------------------------------------------

325
Cargo.lock generated
View File

@@ -32,6 +32,56 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
"once_cell",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.85" version = "0.1.85"
@@ -43,6 +93,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.4.0" version = "1.4.0"
@@ -94,7 +155,7 @@ version = "0.71.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.8.0",
"cexpr", "cexpr",
"clang-sys", "clang-sys",
"itertools", "itertools",
@@ -106,6 +167,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.8.0" version = "2.8.0"
@@ -185,6 +252,70 @@ dependencies = [
"libloading", "libloading",
] ]
[[package]]
name = "clap"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags 1.3.2",
"clap_lex 0.2.4",
"indexmap 1.9.3",
"strsim 0.10.0",
"termcolor",
"textwrap",
]
[[package]]
name = "clap"
version = "4.5.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
dependencies = [
"anstream",
"anstyle",
"clap_lex 0.7.4",
"strsim 0.11.1",
]
[[package]]
name = "clap_derive"
version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]] [[package]]
name = "cmake" name = "cmake"
version = "0.1.52" version = "0.1.52"
@@ -194,6 +325,12 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.16" version = "0.2.16"
@@ -298,7 +435,7 @@ dependencies = [
"ident_case", "ident_case",
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim 0.11.1",
"syn", "syn",
] ]
@@ -328,7 +465,7 @@ version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf1bedf64cdb9643204a36dd15b19a6ce8e7aa7f7b105868e9f1fad5ffa7d12" checksum = "ccf1bedf64cdb9643204a36dd15b19a6ce8e7aa7f7b105868e9f1fad5ffa7d12"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.8.0",
"byteorder", "byteorder",
"diesel_derives", "diesel_derives",
"itoa", "itoa",
@@ -413,6 +550,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
dependencies = [
"clap 3.2.25",
]
[[package]] [[package]]
name = "dsl_auto_type" name = "dsl_auto_type"
version = "0.1.2" version = "0.1.2"
@@ -433,6 +579,29 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@@ -563,6 +732,12 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.2" version = "0.15.2"
@@ -580,6 +755,15 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hmac" name = "hmac"
version = "0.12.1" version = "0.12.1"
@@ -589,6 +773,12 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]] [[package]]
name = "icu_collections" name = "icu_collections"
version = "1.5.0" version = "1.5.0"
@@ -734,6 +924,16 @@ dependencies = [
"icu_properties", "icu_properties",
] ]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.7.1" version = "2.7.1"
@@ -741,9 +941,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown 0.15.2",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.13.0" version = "0.13.0"
@@ -784,7 +990,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee7893dab2e44ae5f9d0173f26ff4aa327c10b01b06a72b52dd9405b628640d" checksum = "4ee7893dab2e44ae5f9d0173f26ff4aa327c10b01b06a72b52dd9405b628640d"
dependencies = [ dependencies = [
"indexmap", "indexmap 2.7.1",
] ]
[[package]] [[package]]
@@ -847,7 +1053,7 @@ version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [ dependencies = [
"hashbrown", "hashbrown 0.15.2",
] ]
[[package]] [[package]]
@@ -910,7 +1116,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi",
"windows-sys", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -950,7 +1156,7 @@ checksum = "478b0ff3f7d67b79da2b96f56f334431aef65e15ba4b29dd74a4236e29582bdc"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"bindgen", "bindgen",
"bitflags", "bitflags 2.8.0",
"btoi", "btoi",
"byteorder", "byteorder",
"bytes", "bytes",
@@ -1044,6 +1250,12 @@ version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "os_str_bytes"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.3" version = "0.12.3"
@@ -1246,7 +1458,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.8.0",
] ]
[[package]] [[package]]
@@ -1301,8 +1513,15 @@ dependencies = [
name = "rotom_discord_bot" name = "rotom_discord_bot"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap 4.5.27",
"dotenvy",
"env_logger",
"log",
"rotom_core", "rotom_core",
"rotom_database", "rotom_database",
"secrecy",
"thiserror 2.0.11",
"tokio",
] ]
[[package]] [[package]]
@@ -1344,6 +1563,15 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "secrecy"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
dependencies = [
"zeroize",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.217" version = "1.0.217"
@@ -1413,6 +1641,15 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "1.0.1" version = "1.0.1"
@@ -1441,7 +1678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -1467,6 +1704,12 @@ dependencies = [
"unicode-properties", "unicode-properties",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@@ -1511,6 +1754,21 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.69" version = "1.0.69"
@@ -1619,8 +1877,21 @@ dependencies = [
"mio", "mio",
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry",
"socket2", "socket2",
"windows-sys", "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]] [[package]]
@@ -1689,7 +1960,7 @@ version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [ dependencies = [
"indexmap", "indexmap 2.7.1",
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
@@ -1763,6 +2034,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.12.0" version = "1.12.0"
@@ -1887,6 +2164,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
@@ -1902,6 +2188,15 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"
@@ -2053,6 +2348,12 @@ dependencies = [
"synstructure", "synstructure",
] ]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]] [[package]]
name = "zerovec" name = "zerovec"
version = "0.10.4" version = "0.10.4"

View File

@@ -4,8 +4,15 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.5.27", features = ["derive", "env"] }
dotenvy = { version = "0.15.7", features = ["clap"] }
env_logger = "0.11.6"
log = "0.4.25"
rotom_core = { path = "../rotom_core" } rotom_core = { path = "../rotom_core" }
rotom_database = { path = "../rotom_database", default-features = false } rotom_database = { path = "../rotom_database", default-features = false }
secrecy = "0.10.3"
thiserror = "2.0.11"
tokio = { version = "1.43.0", features = ["full"] }
[features] [features]
default = ["mysql", "postgres", "sqlite"] default = ["mysql", "postgres", "sqlite"]

View File

@@ -0,0 +1,17 @@
use rotom_core::repository::RepositoryProvider;
use crate::cli::DiscordCredentials;
#[derive(Debug, thiserror::Error)]
pub enum AppError {
}
pub async fn start<R>(_credentials: DiscordCredentials, _repository_provider: R) -> Result<(), AppError>
where
R: RepositoryProvider + Send + Sync + 'static,
R::BackendError: Send + Sync,
for<'a> R::Repository<'a>: Send + Sync,
{
todo!()
}

View File

@@ -0,0 +1,29 @@
use clap::Parser;
/// Subcommand of the CLI application.
#[derive(Debug, Clone, Parser)]
pub enum Command {
/// Start the main discord bot application.
#[command(
name = "start",
about,
long_about = None,
)]
Start(super::start::Start),
}
#[derive(Debug, thiserror::Error)]
pub enum CommandError {
#[error(transparent)]
StartError(#[from] super::start::StartError),
}
impl Command {
pub async fn execute(self) -> Result<(), CommandError> {
match self {
Command::Start(start) => start.execute().await?,
}
Ok(())
}
}

View File

@@ -0,0 +1,148 @@
use std::fmt::Debug;
use std::path::PathBuf;
use clap::Parser;
use clap::ValueEnum;
use command::Command;
use secrecy::SecretString;
pub mod command;
pub mod start;
#[derive(Debug, thiserror::Error)]
pub enum CliError {
#[error(transparent)]
Dotenvy(#[from] dotenvy::Error),
}
/// Parses command line arguments.
pub fn parse() -> Result<Cli, CliError> {
// First phase: If a dotenv file is specified, load values from it.
// This allows values in the dotenv file to be used when parsing other arguments.
let dotenv = Dotenv::parse();
if let Some(dotenv_path) = &dotenv.path {
dotenvy::from_path_override(dotenv_path)?;
}
// Second phase: Parse CLI options using the `Cli` parser.
let mut cli = Cli::parse();
// The `Cli` parser contains the `Dotenv` parser and it may parse different results in different phases.
// It is replaced here to ensure the `Cli` instance reflects the original dotenv configuration.
cli.dotenv = dotenv;
return Ok(cli);
}
/// Main command line interface for the librarian application.
///
/// This struct combines the dotenv configuration with the subcommands
/// that the CLI application supports.
///
/// The help and version flags and subcommands are explicitly enabled
/// because `Dotenv` disables them and `Cli` requires them to be enabled.
#[derive(Debug, Parser)]
#[command(
name = "rotom",
about,
version,
long_about = None,
ignore_errors = false,
disable_help_flag = false,
disable_help_subcommand = false,
disable_version_flag = false,
)]
pub struct Cli {
/// Configuration for loading environment variables from a dotenv file.
#[command(flatten)]
pub dotenv: Dotenv,
/// The command to be executed as part of the CLI application.
#[command(subcommand)]
pub command: Command,
}
/// Configuration for loading environment variables from a dotenv file.
///
/// This struct is used to specify the path to a dotenv file from which
/// environment variables can be loaded. The default value is `.env`.
///
/// The help and version flags and subcommands are disabled because
/// they are handled by `Cli` which is parsed after `Dotenv`.
#[derive(Debug, Clone, Parser)]
#[command(
ignore_errors = true,
disable_help_flag = true,
disable_help_subcommand = true,
disable_version_flag = true
)]
pub struct Dotenv {
/// The path to the dotenv file.
#[arg(
name = "path",
short = None,
long = "dotenv",
env = "DOTENV",
)]
pub path: Option<PathBuf>,
}
#[derive(Clone, Copy, Debug, ValueEnum)]
pub enum DatabaseDialect {
#[cfg(feature = "mysql")]
Mysql,
#[cfg(feature = "postgres")]
Postgres,
#[cfg(feature = "sqlite")]
Sqlite,
}
impl From<DatabaseDialect> for rotom_database::DatabaseDialect {
fn from(value: DatabaseDialect) -> Self {
use rotom_database::DatabaseDialect as Dialect;
match value {
#[cfg(feature = "mysql")]
DatabaseDialect::Mysql => Dialect::Mysql,
#[cfg(feature = "postgres")]
DatabaseDialect::Postgres => Dialect::Postgres,
#[cfg(feature = "sqlite")]
DatabaseDialect::Sqlite => Dialect::Sqlite,
}
}
}
/// Credentials required to establish a database connection.
#[derive(Clone, Debug, Parser)]
pub struct DatabaseCredentials {
/// The dialect of the database to connect to.
#[arg(
short = None,
long = "database-dialect",
env = "DATABASE_DIALECT",
)]
pub dialect: DatabaseDialect,
/// The URL of the database to connect to. This should include the
/// necessary credentials (username and password) and the database
/// name, following the format: `dialect://username:password@host:port/database`.
#[arg(
short = None,
long = "database-url",
env = "DATABASE_URL",
hide_env_values(true),
)]
pub url: SecretString,
}
/// Credentials required to authenticate a bot with Discord.
#[derive(Clone, Debug, Parser)]
pub struct DiscordCredentials {
/// The token used to authenticate the bot with Discord.
#[arg(
short = None,
long = "bot-token",
env = "BOT_TOKEN",
hide_env_values(true),
)]
pub bot_token: SecretString,
}

View File

@@ -0,0 +1,62 @@
use clap::Parser;
use secrecy::ExposeSecret;
use super::DatabaseCredentials;
use super::DiscordCredentials;
/// Start the main discord bot application.
#[derive(Debug, Clone, Parser)]
pub struct Start {
/// Credentials required to establish a database connection.
#[command(flatten)]
pub database: DatabaseCredentials,
/// Credentials required to authenticate a bot with Discord.
#[command(flatten)]
pub discord: DiscordCredentials,
}
#[derive(Debug, thiserror::Error)]
pub enum StartError {
#[error(transparent)]
RepositoryBackendError(#[from] rotom_database::BackendError),
#[error(transparent)]
AppError(#[from] crate::app::AppError),
}
impl Start {
pub async fn execute(self) -> Result<(), StartError> {
log::debug!("{:#?}", self);
let database_url = self.database.url.expose_secret();
match self.database.dialect {
#[cfg(feature = "mysql")]
crate::cli::DatabaseDialect::Mysql => {
log::info!("Running any pending database migrations.");
rotom_database::mysql::run_pending_migrations(database_url)?;
let repository_provider = rotom_database::mysql::repository_provider(database_url).await?;
log::info!("Starting discord application.");
crate::app::start(self.discord, repository_provider).await?;
},
#[cfg(feature = "postgres")]
crate::cli::DatabaseDialect::Postgres => {
log::info!("Running any pending database migrations.");
rotom_database::postgres::run_pending_migrations(database_url)?;
let repository_provider = rotom_database::postgres::repository_provider(database_url).await?;
log::info!("Starting discord application.");
crate::app::start(self.discord, repository_provider).await?;
},
#[cfg(feature = "sqlite")]
crate::cli::DatabaseDialect::Sqlite => {
log::info!("Running any pending database migrations.");
rotom_database::sqlite::run_pending_migrations(database_url)?;
let repository_provider = rotom_database::sqlite::repository_provider(database_url).await?;
log::info!("Starting discord application.");
crate::app::start(self.discord, repository_provider).await?;
},
}
Ok(())
}
}

View File

@@ -1 +1,20 @@
fn main() {} mod app;
mod cli;
#[derive(Debug, thiserror::Error)]
enum MainError {
#[error(transparent)]
CliError(#[from] cli::CliError),
#[error(transparent)]
CommandError(#[from] cli::command::CommandError)
}
#[tokio::main]
async fn main() -> Result<(), MainError> {
let c = cli::parse()?;
env_logger::init();
c.command.execute().await?;
Ok(())
}