forked from Skynet/discord-bot
Compare commits
60 commits
Author | SHA1 | Date | |
---|---|---|---|
b7d36de976 | |||
68ffa55dc5 | |||
9b3c71e321 | |||
0478f634fa | |||
ee0c8f0987 | |||
b55650b221 | |||
4691869ae9 | |||
68d7b53905 | |||
bf55dfe31e | |||
ad94b197ae | |||
1f3c33458e | |||
bab6e4fdec | |||
f00db7ef5d | |||
37ea38f516 | |||
93359698f0 | |||
dda05d7ca1 | |||
5dee9acbaa | |||
96a61e6fc8 | |||
94292fa388 | |||
2daa010d25 | |||
da4d006bc0 | |||
80c9191eee | |||
1c3ccbecf5 | |||
d1af8a7c1f | |||
0d9ce2de7f | |||
5e7964ae26 | |||
32292a3c0b | |||
ffce78a10d | |||
7980739627 | |||
2aad895bb3 | |||
ec74dc0aa7 | |||
42f301455a | |||
5b21bc47bd | |||
2db136a736 | |||
72c4b1e794 | |||
5e17a98bff | |||
0ab290a876 | |||
a62f893a98 | |||
43c5cd2eff | |||
d9211dca9a | |||
c71dbe7214 | |||
bf08aa650c | |||
f3ef03a418 | |||
11240914ac | |||
e9aed40f41 | |||
0df7c8a29f | |||
4998dba225 | |||
8d1c6b1bd1 | |||
d3a975a1d1 | |||
|
5f4e46bb51 | ||
28b911c468 | |||
e7caf148dd | |||
befced76f8 | |||
421864e151 | |||
557dcb9f8c | |||
b75fa39bcf | |||
986d2f19c9 | |||
cfb5d95be4 | |||
7ed20108fb | |||
c63945bb86 |
25 changed files with 1197 additions and 254 deletions
|
@ -19,6 +19,10 @@ jobs:
|
|||
steps:
|
||||
# get the repo first
|
||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||
- uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs@v3
|
||||
with:
|
||||
repository: ${{ gitea.repository }}
|
||||
ref_name: ${{ gitea.ref_name }}
|
||||
- run: nix build .#fmt --verbose
|
||||
|
||||
# clippy is incredibly useful for making yer code better
|
||||
|
@ -30,6 +34,10 @@ jobs:
|
|||
steps:
|
||||
# get the repo first
|
||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||
- uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs@v3
|
||||
with:
|
||||
repository: ${{ gitea.repository }}
|
||||
ref_name: ${{ gitea.ref_name }}
|
||||
- run: nix build .#clippy --verbose
|
||||
|
||||
build:
|
||||
|
@ -39,6 +47,10 @@ jobs:
|
|||
steps:
|
||||
# get the repo first
|
||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||
- uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs@v3
|
||||
with:
|
||||
repository: ${{ gitea.repository }}
|
||||
ref_name: ${{ gitea.ref_name }}
|
||||
- name: "Build it locally"
|
||||
run: nix build --verbose
|
||||
|
||||
|
@ -49,7 +61,7 @@ jobs:
|
|||
needs: [ build ]
|
||||
steps:
|
||||
- name: "Deploy to Skynet"
|
||||
uses: https://forgejo.skynet.ie/Skynet/actions-deploy-to-skynet@v2
|
||||
uses: https://forgejo.skynet.ie/Skynet/actions/deploy@v3
|
||||
with:
|
||||
input: 'skynet_discord_bot'
|
||||
token: ${{ secrets.API_TOKEN_FORGEJO }}
|
37
.gitattributes
vendored
Normal file
37
.gitattributes
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Git config here
|
||||
* text eol=lf
|
||||
|
||||
#############################################
|
||||
# Git lfs stuff
|
||||
# Documents
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.doc filter=lfs diff=lfs merge=lfs -text
|
||||
*.docx filter=lfs diff=lfs merge=lfs -text
|
||||
# Excel
|
||||
*.xls filter=lfs diff=lfs merge=lfs -text
|
||||
*.xlsx filter=lfs diff=lfs merge=lfs -text
|
||||
*.xlsm filter=lfs diff=lfs merge=lfs -text
|
||||
# Powerpoints
|
||||
*.ppt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pptx filter=lfs diff=lfs merge=lfs -text
|
||||
*.ppsx filter=lfs diff=lfs merge=lfs -text
|
||||
# Images
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
# Video
|
||||
*.mkv filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.wmv filter=lfs diff=lfs merge=lfs -text
|
||||
# Misc
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
# ET4011
|
||||
*.cbe filter=lfs diff=lfs merge=lfs -text
|
||||
*.pbs filter=lfs diff=lfs merge=lfs -text
|
||||
# Open/Libre office
|
||||
# from https://www.libreoffice.org/discover/what-is-opendocument/
|
||||
*.odt filter=lfs diff=lfs merge=lfs -text
|
||||
*.ods filter=lfs diff=lfs merge=lfs -text
|
||||
*.odp filter=lfs diff=lfs merge=lfs -text
|
||||
*.odg filter=lfs diff=lfs merge=lfs -text
|
||||
# QT
|
||||
*.ui filter=lfs diff=lfs merge=lfs -text
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,11 +2,13 @@
|
|||
/.idea
|
||||
|
||||
.env
|
||||
*.env
|
||||
|
||||
result
|
||||
/result
|
||||
|
||||
*.db
|
||||
*.db.*
|
||||
|
||||
tmp/
|
||||
tmp.*
|
||||
|
|
459
Cargo.lock
generated
459
Cargo.lock
generated
|
@ -107,9 +107,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.89"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
||||
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
|
@ -143,7 +143,7 @@ dependencies = [
|
|||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand 2.1.1",
|
||||
"futures-lite 2.3.0",
|
||||
"futures-lite 2.5.0",
|
||||
"slab",
|
||||
]
|
||||
|
||||
|
@ -158,21 +158,21 @@ dependencies = [
|
|||
"async-io",
|
||||
"async-lock",
|
||||
"blocking",
|
||||
"futures-lite 2.3.0",
|
||||
"futures-lite 2.5.0",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "2.3.4"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8"
|
||||
checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-io",
|
||||
"futures-lite 2.3.0",
|
||||
"futures-lite 2.5.0",
|
||||
"parking",
|
||||
"polling",
|
||||
"rustix",
|
||||
|
@ -206,7 +206,7 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-lite 2.3.0",
|
||||
"futures-lite 2.5.0",
|
||||
"gloo-timers",
|
||||
"kv-log-macro",
|
||||
"log",
|
||||
|
@ -218,6 +218,28 @@ dependencies = [
|
|||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[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.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.7.1"
|
||||
|
@ -232,7 +254,7 @@ checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -359,7 +381,7 @@ dependencies = [
|
|||
"async-channel 2.3.1",
|
||||
"async-task",
|
||||
"futures-io",
|
||||
"futures-lite 2.3.0",
|
||||
"futures-lite 2.5.0",
|
||||
"piper",
|
||||
]
|
||||
|
||||
|
@ -564,9 +586,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.46"
|
||||
version = "0.4.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6"
|
||||
checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265"
|
||||
dependencies = [
|
||||
"curl-sys",
|
||||
"libc",
|
||||
|
@ -579,9 +601,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "curl-sys"
|
||||
version = "0.4.75+curl-8.10.0"
|
||||
version = "0.4.78+curl-8.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a4fd752d337342e4314717c0d9b6586b059a120c80029ebe4d49b11fec7875e"
|
||||
checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
@ -901,9 +923,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "2.3.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
|
||||
checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1"
|
||||
dependencies = [
|
||||
"fastrand 2.1.1",
|
||||
"futures-core",
|
||||
|
@ -920,7 +942,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1024,7 +1046,26 @@ dependencies = [
|
|||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http 0.2.12",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes 1.7.1",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"http 1.1.0",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
|
@ -1147,6 +1188,17 @@ dependencies = [
|
|||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.6"
|
||||
|
@ -1154,7 +1206,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"http",
|
||||
"http 0.2.12",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"http 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body-util"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.1",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
|
@ -1216,9 +1291,9 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"h2 0.3.26",
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
|
@ -1230,6 +1305,26 @@ dependencies = [
|
|||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"h2 0.4.7",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.1",
|
||||
"httparse",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.24.2"
|
||||
|
@ -1237,13 +1332,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http",
|
||||
"hyper",
|
||||
"http 0.2.12",
|
||||
"hyper 0.14.30",
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"hyper 1.5.1",
|
||||
"hyper-util",
|
||||
"rustls 0.23.18",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.0",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper-util",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
|
||||
dependencies = [
|
||||
"bytes 1.7.1",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.1",
|
||||
"hyper 1.5.1",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.7",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.61"
|
||||
|
@ -1330,7 +1477,7 @@ dependencies = [
|
|||
"curl-sys",
|
||||
"flume 0.9.2",
|
||||
"futures-lite 1.13.0",
|
||||
"http",
|
||||
"http 0.2.12",
|
||||
"log",
|
||||
"once_cell",
|
||||
"slab",
|
||||
|
@ -1678,7 +1825,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1760,22 +1907,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
|||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.5"
|
||||
version = "1.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
|
||||
checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.5"
|
||||
version = "1.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||
checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1830,9 +1977,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
|||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.7.3"
|
||||
version = "3.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511"
|
||||
checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
|
@ -1901,9 +2048,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -2014,11 +2161,11 @@ dependencies = [
|
|||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"h2 0.3.26",
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.30",
|
||||
"hyper-rustls 0.24.2",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
|
@ -2028,12 +2175,12 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls 0.21.12",
|
||||
"rustls-pemfile",
|
||||
"rustls-pemfile 1.0.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper",
|
||||
"system-configuration",
|
||||
"sync_wrapper 0.1.2",
|
||||
"system-configuration 0.5.1",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
"tokio-util",
|
||||
|
@ -2047,6 +2194,49 @@ dependencies = [
|
|||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes 1.7.1",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.4.7",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper-rustls 0.27.3",
|
||||
"hyper-tls",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls-pemfile 2.2.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.2",
|
||||
"system-configuration 0.6.1",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
|
@ -2145,10 +2335,23 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
|
|||
dependencies = [
|
||||
"log",
|
||||
"ring 0.17.8",
|
||||
"rustls-webpki",
|
||||
"rustls-webpki 0.101.7",
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki 0.102.8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "1.0.4"
|
||||
|
@ -2158,6 +2361,21 @@ dependencies = [
|
|||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[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.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.7"
|
||||
|
@ -2168,6 +2386,17 @@ dependencies = [
|
|||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
|
||||
dependencies = [
|
||||
"ring 0.17.8",
|
||||
"rustls-pki-types",
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
|
@ -2239,9 +2468,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -2258,13 +2487,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2321,7 +2550,7 @@ dependencies = [
|
|||
"mime_guess",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"reqwest",
|
||||
"reqwest 0.11.27",
|
||||
"serde",
|
||||
"serde-value",
|
||||
"serde_json",
|
||||
|
@ -2423,6 +2652,7 @@ dependencies = [
|
|||
"sqlx",
|
||||
"surf",
|
||||
"tokio",
|
||||
"wolves_oxidised",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2819,9 +3049,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.77"
|
||||
version = "2.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2834,6 +3064,15 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
|
@ -2842,7 +3081,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
|||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
"system-configuration-sys 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation",
|
||||
"system-configuration-sys 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2855,6 +3105,16 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.12.0"
|
||||
|
@ -2885,7 +3145,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2996,7 +3256,17 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3020,6 +3290,17 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||
dependencies = [
|
||||
"rustls 0.23.18",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.16"
|
||||
|
@ -3031,6 +3312,19 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-test"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"bytes 1.7.1",
|
||||
"futures-core",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.12"
|
||||
|
@ -3070,7 +3364,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3107,7 +3401,7 @@ dependencies = [
|
|||
"base64 0.13.1",
|
||||
"byteorder",
|
||||
"bytes 1.7.1",
|
||||
"http",
|
||||
"http 0.2.12",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
|
@ -3227,9 +3521,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
|||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101"
|
||||
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
|
@ -3298,7 +3592,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -3332,7 +3626,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -3432,6 +3726,36 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
@ -3590,6 +3914,17 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wolves_oxidised"
|
||||
version = "0.1.0"
|
||||
source = "git+https://forgejo.skynet.ie/Skynet/wolves-oxidised.git#867778128c1ef580ebfded7808bbd4e86f22903b"
|
||||
dependencies = [
|
||||
"reqwest 0.12.9",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
|
@ -3608,7 +3943,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.89",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -19,6 +19,9 @@ name = "update_minecraft"
|
|||
serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
|
||||
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
|
||||
|
||||
# wolves api
|
||||
wolves_oxidised = { git = "https://forgejo.skynet.ie/Skynet/wolves-oxidised.git" }
|
||||
|
||||
# to make the http requests
|
||||
surf = "2.3.2"
|
||||
|
||||
|
@ -37,4 +40,4 @@ chrono = "0.4.26"
|
|||
lettre = "0.10.4"
|
||||
maud = "0.25.0"
|
||||
|
||||
serde = "1.0.188"
|
||||
serde = "1.0"
|
9
LICENSE
Normal file
9
LICENSE
Normal file
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Skynet
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
74
README.md
74
README.md
|
@ -1,70 +1,10 @@
|
|||
# Skynet Discord Bot
|
||||
This bots core purpose is to give members roles based on their status on <ulwolves.ie>.
|
||||
It uses an api key provided by wolves to get member lists.
|
||||
The Skynet bot is designed to manage users on Discord.
|
||||
It allows users to link their UL Wolves account with Wolves in a GDPR compliant manner.
|
||||
Skynet (bot) is hosted is hosted by the Computer Society on Skynet (computer cluster).
|
||||
|
||||
Users are able to link their wolves account to the bot and that works across discord servers.
|
||||
For example is a user links on the CompSoc Discord then they will also get their roles (automagically) on Games Dev if they are a member there.
|
||||
## Documentation
|
||||
We have split up the documentation into different segments depending on who the user is.
|
||||
|
||||
## Commands - Admin
|
||||
|
||||
You need admin access to run any of the commands in this section.
|
||||
Either the server owner or a suer with the ``Administrator`` permission
|
||||
|
||||
### Getting the Skynet Discord bot
|
||||
1. Email ``keith@assurememberships.com`` from committee email and say ye want an api key for ``193.1.99.74``
|
||||
2. Create a role for current members (maybe call it ``current-member`` ?)
|
||||
3. (Optional) create a role for all past and current members (ye can use the existing ``member`` role for this, )
|
||||
4. Invite the bot https://discord.com/api/oauth2/authorize?client_id=1145761669256069270&permissions=139855185984&scope=bot
|
||||
5. Make sure the bot role ``@skynet`` is above these two roles (so it can manage them)
|
||||
6. Make sure that you have a role that gives ye administrator powers
|
||||
7. Use the command ``/add`` and insert the api key, role current and role all (desktop recommended)
|
||||
|
||||
The reason for both roles is ye have one for active members while the second is for all current and past members.
|
||||
|
||||
### Minecraft
|
||||
The bot is able to manage the whitelist of a Minecraft server managed by the Computer Society.
|
||||
Talk to us to get a server.
|
||||
|
||||
#### Add
|
||||
This links a minecraft server with your club/society.
|
||||
|
||||
``/minecraft_add SERVER_ID``
|
||||
|
||||
|
||||
#### List
|
||||
List the servers linked to your club/society.
|
||||
It is possible to have more than one minecraft server
|
||||
|
||||
``/minecraft_list``
|
||||
|
||||
#### Delete
|
||||
This unlinks a minecraft server from your club/society.
|
||||
|
||||
``/minecraft_delete SERVER_ID``
|
||||
|
||||
## Commands - User
|
||||
|
||||
### Setup
|
||||
* Start the process using ``/link_wolves WOLVES_EMAIL``
|
||||
* The email that is in the Contact Email here: <https://ulwolves.ie/memberships/profile>
|
||||
* An email will be sent to them that they need to verify using ``/verify CODE``
|
||||
* This will only have to be done once.
|
||||
|
||||
* If the user is an active member on wolves
|
||||
* If they are in any servers with teh Skynet Bot
|
||||
* They will get relevant roles.
|
||||
* If they Join a server with teh bot enabled.
|
||||
* They will be granted the roles automatically
|
||||
* If the user is **not** an active member on wolves.
|
||||
* If they have no Roles
|
||||
* No change
|
||||
* If they have Past Member Role
|
||||
* No change
|
||||
* If they have both Roles
|
||||
* The current-member role will be removed from them
|
||||
* Past Member role will remain unchanged
|
||||
|
||||
### Minecraft
|
||||
Users can link their Minecraft username to grant them access to any servers where teh whitelist is managed by teh bot.
|
||||
|
||||
``/link_minecraft MINECRAFT_USERNAME``
|
||||
* [Committees](./doc/Committee.md)
|
||||
* [Member](./doc/User.md)
|
5
db/migrations/5_welcome-message.sql
Normal file
5
db/migrations/5_welcome-message.sql
Normal file
|
@ -0,0 +1,5 @@
|
|||
-- temp table to allow folks to verify by committee email.
|
||||
-- delete the col in teh server table
|
||||
ALTER TABLE servers ADD COLUMN bot_channel_id integer DEFAULT 0;
|
||||
ALTER TABLE servers ADD COLUMN server_name text NOT NULL DEFAULT "";
|
||||
ALTER TABLE servers ADD COLUMN wolves_link text NOT NULL DEFAULT "";
|
11
db/migrations/6_role-adder.sql
Normal file
11
db/migrations/6_role-adder.sql
Normal file
|
@ -0,0 +1,11 @@
|
|||
CREATE TABLE IF NOT EXISTS roles_adder (
|
||||
server integer not null,
|
||||
role_a integer not null,
|
||||
role_b integer not null,
|
||||
role_c integer not null,
|
||||
PRIMARY KEY(server,role_a,role_b,role_c)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_roles_adder_server ON roles_adder (server);
|
||||
CREATE INDEX IF NOT EXISTS index_roles_adder_from ON roles_adder (role_a,role_b);
|
||||
CREATE INDEX IF NOT EXISTS index_roles_adder_to ON roles_adder (role_c);
|
||||
CREATE INDEX IF NOT EXISTS index_roles_adder_search ON roles_adder (server,role_a,role_b);
|
3
db/migrations/7_minecraft-bedrock.sql
Normal file
3
db/migrations/7_minecraft-bedrock.sql
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
-- Using this col we will be able to see if someone has a bedrock account (as well as a java one)
|
||||
ALTER TABLE wolves ADD COLUMN minecraft_uid TEXT;
|
75
doc/Committee.md
Normal file
75
doc/Committee.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Skynet Discord Bot
|
||||
This bots core purpose is to give members roles based on their status on <https://ulwolves.ie>.
|
||||
It uses an api key provided by wolves to get member lists.
|
||||
|
||||
Users are able to link their wolves account to the bot and that works across discord servers.
|
||||
For example is a user links on the CompSoc Discord then they will also get their roles (automagically) on Games Dev if they are a member there.
|
||||
|
||||
## Setup - Committee
|
||||
You need admin access to run any of the commands in this section.
|
||||
Either the server owner or a user with the ``Administrator`` permission.
|
||||
|
||||
### Get the API Key
|
||||
The ``api_key`` is used by the Bot in order to request information, it will be used later in the process.
|
||||
|
||||
1. Email ``keith@assurememberships.com`` from committee email and say you want an ``api_key`` for ``193.1.99.74``
|
||||
* The committee email is the one here: <https://cp.ulwolves.ie/mailbox/>
|
||||
* This may take up to a week to get the key.
|
||||
|
||||
### Setup Server
|
||||
The Bot reason for existing is being able to give members Roles.
|
||||
So we have to create those.
|
||||
|
||||
1. Create a role for Current Members.
|
||||
* You can call it whatever you want.
|
||||
* ``member-current`` is a good choice.
|
||||
* This should be a new role
|
||||
2. **Optional**: you can create a role that is given to folks who were but no longer a member.
|
||||
* ``member`` would be a good choice for this
|
||||
* If you have an existing member role this is also a good fit.
|
||||
|
||||
The reason for both roles is ye have one for active members while the second is for all current and past members.
|
||||
|
||||
### Invite Bot
|
||||
1. Invite the bot https://discord.com/api/oauth2/authorize?client_id=1145761669256069270&permissions=139855185984&scope=bot
|
||||
2. Make sure the bot role ``@skynet`` is above these two roles created in the previous step
|
||||
* This is so it can manage the roles (give and remove them from users)
|
||||
|
||||
### Setup Bot
|
||||
This is where the bot is configured.
|
||||
You will need the ``api_key`` from the start of the process.
|
||||
You (personally) will need a role with ``Administrator`` permission to be able to do this.
|
||||
|
||||
1. Use the command ``/add`` and a list of options will pop up.
|
||||
2. ``api_key`` is the key you got from Keith earlier.
|
||||
3. ``role_current`` is the ``member-current`` that you created earlier.
|
||||
4. ``role_past`` (optional) is the role for all current and past members.
|
||||
5. ``bot_channel`` is a channel that folks are recommended to use the bot.
|
||||
* You can have it so folks cannot see message history
|
||||
6. ``server_name`` For example ``UL Computer Society``
|
||||
* Will be removed in the future
|
||||
7. ``wolves_link`` for example <https://ulwolves.ie/society/computer>
|
||||
* Will be removed in the future
|
||||
|
||||
At this point the bot is set up and no further action is required.
|
||||
|
||||
### Minecraft
|
||||
The bot is able to manage the whitelist of a Minecraft server managed by the Computer Society.
|
||||
Talk to us to get a server.
|
||||
|
||||
#### Add
|
||||
This links a minecraft server with your club/society.
|
||||
|
||||
``/minecraft_add SERVER_ID``
|
||||
|
||||
|
||||
#### List
|
||||
List the servers linked to your club/society.
|
||||
It is possible to have more than one minecraft server
|
||||
|
||||
``/minecraft_list``
|
||||
|
||||
#### Delete
|
||||
This unlinks a minecraft server from your club/society.
|
||||
|
||||
``/minecraft_delete SERVER_ID``
|
26
doc/User.md
Normal file
26
doc/User.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Skynet Discord Bot
|
||||
The Skynet bot is designed to make it easy to verify that you are a member of a Club/Society.
|
||||
The bot will be able to give you member roles for any partnered servers.
|
||||
It also provides secondary manifests such as granting access to minecraft servers managed by teh Computer Society.
|
||||
|
||||
## Setup
|
||||
This is to link your Discord account with your UL Wolves account.
|
||||
**You will only need to do this once**.
|
||||
|
||||
### Setup
|
||||
1. In a Discord server with the Skynet Bot enter ``/link_wolves YOUR_WOLVES_CONTACT_EMAIL``
|
||||
<img src="../media/setup_user_01.png" alt="link process start" width="50%" height="50%">
|
||||
* Your ``YOUR_WOLVES_CONTACT_EMAIL`` is the email in the Contact Email here: <https://ulwolves.ie/memberships/profile>
|
||||
* This is most likely your student mail
|
||||
2. An email will be sent to you with a verification code.
|
||||
<img src="../media/setup_user_02.png" alt="signup email" width="50%" height="50%">
|
||||
3. Verify the code using ``/verify CODE_FROM_EMAIL`` in Discord.
|
||||
<img src="../media/setup_user_03.png" alt="verify in discord" width="50%" height="50%">
|
||||
4. Once complete your Wolves and Discord accounts will be linked.
|
||||
|
||||
You will get member roles on any Discord that is using the bot that you are a member of.
|
||||
|
||||
### Minecraft
|
||||
You can link your Minecraft username to grant you access to any Minecraft server run by UL Computer Society.
|
||||
|
||||
``/link_minecraft MINECRAFT_USERNAME``
|
|
@ -75,7 +75,7 @@
|
|||
cfg = config.services."${package_name}";
|
||||
# secret options are in the env file(s) loaded separately
|
||||
environment_config = {
|
||||
HOME = cfg.home;
|
||||
DATABASE_HOME = cfg.home;
|
||||
DATABASE = "database.db";
|
||||
};
|
||||
|
||||
|
|
BIN
media/setup_user_01.png
(Stored with Git LFS)
Normal file
BIN
media/setup_user_01.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
media/setup_user_02.png
(Stored with Git LFS)
Normal file
BIN
media/setup_user_02.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
media/setup_user_03.png
(Stored with Git LFS)
Normal file
BIN
media/setup_user_03.png
(Stored with Git LFS)
Normal file
Binary file not shown.
|
@ -1,2 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "1.80"
|
||||
channel = "1.80"
|
||||
|
|
|
@ -39,18 +39,60 @@ pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> Stri
|
|||
.as_ref()
|
||||
.expect("Expected role object")
|
||||
{
|
||||
Some(role.id.to_owned())
|
||||
role.id.to_owned()
|
||||
} else {
|
||||
return "Please provide a valid role for ``Role Current``".to_string();
|
||||
};
|
||||
|
||||
let mut role_past = None;
|
||||
if let Some(x) = command.data.options.get(2) {
|
||||
if let Some(x) = command.data.options.get(5) {
|
||||
if let Some(CommandDataOptionValue::Role(role)) = &x.resolved {
|
||||
role_past = Some(role.id.to_owned());
|
||||
}
|
||||
};
|
||||
|
||||
let bot_channel_id = if let CommandDataOptionValue::Channel(channel) = command
|
||||
.data
|
||||
.options
|
||||
.get(2)
|
||||
.expect("Expected channel option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Expected channel object")
|
||||
{
|
||||
channel.id.to_owned()
|
||||
} else {
|
||||
return "Please provide a valid channel for ``Bot Channel``".to_string();
|
||||
};
|
||||
|
||||
let server_name = if let CommandDataOptionValue::String(name) = command
|
||||
.data
|
||||
.options
|
||||
.get(3)
|
||||
.expect("Expected Server Name option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Expected Server Name object")
|
||||
{
|
||||
name
|
||||
} else {
|
||||
&"UL Computer Society".to_string()
|
||||
};
|
||||
|
||||
let wolves_link = if let CommandDataOptionValue::String(wolves) = command
|
||||
.data
|
||||
.options
|
||||
.get(4)
|
||||
.expect("Expected Wolves Link option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Expected Server Name object")
|
||||
{
|
||||
wolves
|
||||
} else {
|
||||
&"https://ulwolves.ie/society/computer".to_string()
|
||||
};
|
||||
|
||||
let db_lock = {
|
||||
let data_read = ctx.data.read().await;
|
||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||
|
@ -64,6 +106,9 @@ pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> Stri
|
|||
role_current,
|
||||
member_past: 0,
|
||||
member_current: 0,
|
||||
bot_channel_id,
|
||||
server_name: server_name.to_owned(),
|
||||
wolves_link: wolves_link.to_string(),
|
||||
};
|
||||
|
||||
match add_server(&db, ctx, &server_data).await {
|
||||
|
@ -95,6 +140,27 @@ pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicatio
|
|||
.kind(CommandOptionType::Role)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("bot_channel")
|
||||
.description("Safe space for folks to use the bot commands.")
|
||||
.kind(CommandOptionType::Channel)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("server_name")
|
||||
.description("Name of the Discord Server.")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("wolves_link")
|
||||
.description("Link to the Club/Society on UL Wolves.")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("role_past")
|
||||
|
@ -107,18 +173,20 @@ pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicatio
|
|||
async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Result<Option<Servers>, Error> {
|
||||
let existing = get_server_config(db, &server.server).await;
|
||||
let role_past = server.role_past.map(|x| *x.as_u64() as i64);
|
||||
let role_current = server.role_current.map(|x| *x.as_u64() as i64);
|
||||
|
||||
let insert = sqlx::query_as::<_, Servers>(
|
||||
"
|
||||
INSERT OR REPLACE INTO servers (server, wolves_api, role_past, role_current)
|
||||
VALUES (?1, ?2, ?3, ?4)
|
||||
INSERT OR REPLACE INTO servers (server, wolves_api, role_past, role_current, bot_channel_id, server_name, wolves_link)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
|
||||
",
|
||||
)
|
||||
.bind(*server.server.as_u64() as i64)
|
||||
.bind(&server.wolves_api)
|
||||
.bind(role_past)
|
||||
.bind(role_current)
|
||||
.bind(*server.role_current.as_u64() as i64)
|
||||
.bind(*server.bot_channel_id.as_u64() as i64)
|
||||
.bind(&server.server_name)
|
||||
.bind(&server.wolves_link)
|
||||
.fetch_optional(db)
|
||||
.await;
|
||||
|
||||
|
@ -133,7 +201,7 @@ async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Resul
|
|||
if x.role_current != server.role_current {
|
||||
result.0 = true;
|
||||
result.1 = true;
|
||||
result.2 = x.role_current;
|
||||
result.2 = Some(x.role_current);
|
||||
}
|
||||
if x.role_past != server.role_past {
|
||||
result.0 = true;
|
||||
|
|
|
@ -172,7 +172,7 @@ pub mod link {
|
|||
let creds = Credentials::new(config.mail_user.clone(), config.mail_pass.clone());
|
||||
|
||||
// Open a remote connection to gmail using STARTTLS
|
||||
let mailer = SmtpTransport::starttls_relay(&config.mail_smtp).unwrap().credentials(creds).build();
|
||||
let mailer = SmtpTransport::starttls_relay(&config.mail_smtp)?.credentials(creds).build();
|
||||
|
||||
// Send the email
|
||||
mailer.send(&email)
|
||||
|
|
|
@ -59,7 +59,34 @@ pub mod link {
|
|||
// check if email exists
|
||||
let details = match get_server_member_email(&db, email).await {
|
||||
None => {
|
||||
return "Please check it is your preferred contact on https://ulwolves.ie/memberships/profile and that you are fully paid up.".to_string()
|
||||
let invalid_user = "Please check it matches (including case) your preferred contact on https://ulwolves.ie/memberships/profile and that you are fully paid up.".to_string();
|
||||
|
||||
let wolves = wolves_oxidised::Client::new(&config.wolves_url, Some(&config.wolves_api));
|
||||
|
||||
// see if the user actually exists
|
||||
let id = match wolves.get_member(email).await {
|
||||
None => {
|
||||
return invalid_user;
|
||||
}
|
||||
Some(x) => x,
|
||||
};
|
||||
|
||||
// save teh user id and email to teh db
|
||||
match save_to_db_user(&db, id, email).await {
|
||||
Ok(x) => x,
|
||||
Err(x) => {
|
||||
dbg!(x);
|
||||
return "Error: unable to save user to teh database, contact Computer Society".to_string();
|
||||
}
|
||||
};
|
||||
|
||||
// pull it back out (technically could do it in previous step but more explicit)
|
||||
match get_server_member_email(&db, email).await {
|
||||
None => {
|
||||
return "Error: failed to read user from database.".to_string();
|
||||
}
|
||||
Some(x) => x,
|
||||
}
|
||||
}
|
||||
Some(x) => x,
|
||||
};
|
||||
|
@ -133,7 +160,7 @@ pub mod link {
|
|||
"h2, h4 { font-family: Arial, Helvetica, sans-serif; }"
|
||||
}
|
||||
}
|
||||
div style="display: flex; flex-direction: column; align-items: center;" {
|
||||
div {
|
||||
h2 { "Hello from Skynet!" }
|
||||
// Substitute in the name of our recipient.
|
||||
p { "Hi " (user) "," }
|
||||
|
@ -184,7 +211,7 @@ pub mod link {
|
|||
let creds = Credentials::new(config.mail_user.clone(), config.mail_pass.clone());
|
||||
|
||||
// Open a remote connection to gmail using STARTTLS
|
||||
let mailer = SmtpTransport::starttls_relay(&config.mail_smtp).unwrap().credentials(creds).build();
|
||||
let mailer = SmtpTransport::starttls_relay(&config.mail_smtp)?.credentials(creds).build();
|
||||
|
||||
// Send the email
|
||||
mailer.send(&email)
|
||||
|
@ -232,6 +259,20 @@ pub mod link {
|
|||
.fetch_optional(db)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn save_to_db_user(db: &Pool<Sqlite>, id_wolves: i64, email: &str) -> Result<Option<Wolves>, sqlx::Error> {
|
||||
sqlx::query_as::<_, Wolves>(
|
||||
"
|
||||
INSERT INTO wolves (id_wolves, email)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT(id_wolves) DO UPDATE SET email = $2
|
||||
",
|
||||
)
|
||||
.bind(id_wolves)
|
||||
.bind(email)
|
||||
.fetch_optional(db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub mod verify {
|
||||
|
@ -352,10 +393,8 @@ pub mod verify {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(role) = &role_current {
|
||||
if !member.roles.contains(role) {
|
||||
roles.push(role.to_owned());
|
||||
}
|
||||
if !member.roles.contains(&role_current) {
|
||||
roles.push(role_current.to_owned());
|
||||
}
|
||||
|
||||
if let Err(e) = member.add_roles(&ctx, &roles).await {
|
||||
|
|
|
@ -15,18 +15,29 @@ pub(crate) mod user {
|
|||
pub(crate) mod add {
|
||||
use super::*;
|
||||
use crate::commands::link_email::link::get_server_member_discord;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serenity::model::id::UserId;
|
||||
use skynet_discord_bot::{whitelist_update, Config, Minecraft, Wolves};
|
||||
use sqlx::Error;
|
||||
|
||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command.name("link_minecraft").description("Link your minecraft account").create_option(|option| {
|
||||
option
|
||||
.name("minecraft-username")
|
||||
.description("Your Minecraft username")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
command
|
||||
.name("link_minecraft")
|
||||
.description("Link your minecraft account")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("minecraft_username")
|
||||
.description("Your Minecraft username")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("bedrock_account")
|
||||
.description("Is this a Bedrock account?")
|
||||
.kind(CommandOptionType::Boolean)
|
||||
.required(false)
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
||||
|
@ -61,19 +72,48 @@ pub(crate) mod user {
|
|||
return "Please provide a valid username".to_string();
|
||||
};
|
||||
|
||||
// insert the username into the database
|
||||
match add_minecraft(&db, &command.user.id, username).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
dbg!("{:?}", e);
|
||||
return format!("Failure to minecraft username {:?}", username);
|
||||
// this is always true unless they state its not
|
||||
let mut java = true;
|
||||
if let Some(x) = command.data.options.get(1) {
|
||||
if let Some(CommandDataOptionValue::Boolean(z)) = x.to_owned().resolved {
|
||||
java = !z;
|
||||
}
|
||||
}
|
||||
|
||||
let username_mc;
|
||||
if java {
|
||||
// insert the username into the database
|
||||
match add_minecraft(&db, &command.user.id, username).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
dbg!("{:?}", e);
|
||||
return format!("Failure to minecraft username {:?}", username);
|
||||
}
|
||||
}
|
||||
username_mc = username.to_string();
|
||||
} else {
|
||||
match get_minecraft_bedrock(username, &config.minecraft_mcprofile).await {
|
||||
None => {
|
||||
return format!("No UID found for {:?}", username);
|
||||
}
|
||||
Some(x) => {
|
||||
match add_minecraft_bedrock(&db, &command.user.id, &x.floodgateuid).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
dbg!("{:?}", e);
|
||||
return format!("Failure to minecraft UID {:?}", &x.floodgateuid);
|
||||
}
|
||||
}
|
||||
|
||||
username_mc = x.floodgateuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get a list of servers that the user is a member of
|
||||
if let Ok(servers) = get_servers(&db, &command.user.id).await {
|
||||
for server in servers {
|
||||
whitelist_update(&vec![username.to_string()], &server.minecraft, &config.discord_token_minecraft).await;
|
||||
whitelist_update(&vec![(username_mc.to_owned(), java)], &server.minecraft, &config.discord_token_minecraft).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,6 +134,51 @@ pub(crate) mod user {
|
|||
.await
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct BedrockDetails {
|
||||
pub gamertag: String,
|
||||
pub xuid: String,
|
||||
pub floodgateuid: String,
|
||||
pub icon: String,
|
||||
pub gamescore: String,
|
||||
pub accounttier: String,
|
||||
pub textureid: String,
|
||||
pub skin: String,
|
||||
pub linked: bool,
|
||||
pub java_uuid: String,
|
||||
pub java_name: String,
|
||||
}
|
||||
|
||||
async fn get_minecraft_bedrock(username: &str, api_key: &str) -> Option<BedrockDetails> {
|
||||
let url = format!("https://mcprofile.io/api/v1/bedrock/gamertag/{username}/");
|
||||
match surf::get(url)
|
||||
.header("x-api-key", api_key)
|
||||
.header("User-Agent", "UL Computer Society")
|
||||
.recv_json()
|
||||
.await
|
||||
{
|
||||
Ok(res) => Some(res),
|
||||
Err(e) => {
|
||||
dbg!(e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_minecraft_bedrock(db: &Pool<Sqlite>, user: &UserId, minecraft: &str) -> Result<Option<Wolves>, Error> {
|
||||
sqlx::query_as::<_, Wolves>(
|
||||
"
|
||||
UPDATE wolves
|
||||
SET minecraft_uid = ?2
|
||||
WHERE discord = ?1;
|
||||
",
|
||||
)
|
||||
.bind(*user.as_u64() as i64)
|
||||
.bind(minecraft)
|
||||
.fetch_optional(db)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_servers(db: &Pool<Sqlite>, discord: &UserId) -> Result<Vec<Minecraft>, Error> {
|
||||
sqlx::query_as::<_, Minecraft>(
|
||||
"
|
||||
|
|
|
@ -2,3 +2,4 @@ pub mod add_server;
|
|||
pub mod committee;
|
||||
pub mod link_email;
|
||||
pub mod minecraft;
|
||||
pub mod role_adder;
|
||||
|
|
238
src/commands/role_adder.rs
Normal file
238
src/commands/role_adder.rs
Normal file
|
@ -0,0 +1,238 @@
|
|||
use serenity::{
|
||||
builder::CreateApplicationCommand,
|
||||
client::Context,
|
||||
model::{
|
||||
application::interaction::application_command::ApplicationCommandInteraction,
|
||||
prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue},
|
||||
},
|
||||
};
|
||||
|
||||
use skynet_discord_bot::{is_admin, DataBase, RoleAdder};
|
||||
use sqlx::{Error, Pool, Sqlite};
|
||||
|
||||
pub mod edit {
|
||||
use super::*;
|
||||
|
||||
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
||||
// check if user has high enough permisssions
|
||||
if let Some(msg) = is_admin(command, ctx).await {
|
||||
return msg;
|
||||
}
|
||||
|
||||
let role_a = if let CommandDataOptionValue::Role(role) = command
|
||||
.data
|
||||
.options
|
||||
.first()
|
||||
.expect("Expected role option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Expected role object")
|
||||
{
|
||||
role.id.to_owned()
|
||||
} else {
|
||||
return "Please provide a valid role for ``Role Current``".to_string();
|
||||
};
|
||||
|
||||
let role_b = if let CommandDataOptionValue::Role(role) = command
|
||||
.data
|
||||
.options
|
||||
.get(1)
|
||||
.expect("Expected role option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Expected role object")
|
||||
{
|
||||
role.id.to_owned()
|
||||
} else {
|
||||
return "Please provide a valid role for ``Role Current``".to_string();
|
||||
};
|
||||
|
||||
let role_c = if let CommandDataOptionValue::Role(role) = command
|
||||
.data
|
||||
.options
|
||||
.get(2)
|
||||
.expect("Expected role option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Expected role object")
|
||||
{
|
||||
role.id.to_owned()
|
||||
} else {
|
||||
return "Please provide a valid role for ``Role Current``".to_string();
|
||||
};
|
||||
|
||||
if role_a == role_b {
|
||||
return "Roles A and B must be different".to_string();
|
||||
}
|
||||
|
||||
if (role_c == role_a) || (role_c == role_b) {
|
||||
return "Role C cannot be same as A or B".to_string();
|
||||
}
|
||||
|
||||
let mut delete = false;
|
||||
|
||||
if let Some(x) = command.data.options.get(3) {
|
||||
let tmp = x.to_owned();
|
||||
if let Some(CommandDataOptionValue::Boolean(z)) = tmp.resolved {
|
||||
delete = z;
|
||||
}
|
||||
}
|
||||
|
||||
let db_lock = {
|
||||
let data_read = ctx.data.read().await;
|
||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||
};
|
||||
let db = db_lock.read().await;
|
||||
|
||||
let server = command.guild_id.unwrap_or_default();
|
||||
let server_data = RoleAdder {
|
||||
server,
|
||||
role_a,
|
||||
role_b,
|
||||
role_c,
|
||||
};
|
||||
|
||||
match add_server(&db, &server_data, delete).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
return format!("Failure to insert into Servers {:?}", server_data);
|
||||
}
|
||||
}
|
||||
|
||||
let mut role_a_name = String::new();
|
||||
let mut role_b_name = String::new();
|
||||
let mut role_c_name = String::new();
|
||||
|
||||
if let Ok(x) = server.roles(&ctx).await {
|
||||
if let Some(y) = x.get(&role_a) {
|
||||
role_a_name = y.to_owned().name;
|
||||
}
|
||||
if let Some(y) = x.get(&role_b) {
|
||||
role_b_name = y.to_owned().name;
|
||||
}
|
||||
if let Some(y) = x.get(&role_b) {
|
||||
role_c_name = y.to_owned().name;
|
||||
}
|
||||
}
|
||||
|
||||
if delete {
|
||||
format!("Removed {} + {} = {}", role_a_name, role_b_name, role_c_name)
|
||||
} else {
|
||||
format!("Added {} + {} = {}", role_a_name, role_b_name, role_c_name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command
|
||||
.name("roles_adder")
|
||||
.description("Combine roles together to an new one")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("role_a")
|
||||
.description("A role you want to add to Role B")
|
||||
.kind(CommandOptionType::Role)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("role_b")
|
||||
.description("A role you want to add to Role A")
|
||||
.kind(CommandOptionType::Role)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| option.name("role_c").description("Sum of A and B").kind(CommandOptionType::Role).required(true))
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("delete")
|
||||
.description("Delete this entry.")
|
||||
.kind(CommandOptionType::Boolean)
|
||||
.required(false)
|
||||
})
|
||||
}
|
||||
|
||||
async fn add_server(db: &Pool<Sqlite>, server: &RoleAdder, delete: bool) -> Result<Option<RoleAdder>, Error> {
|
||||
if delete {
|
||||
sqlx::query_as::<_, RoleAdder>(
|
||||
"
|
||||
DELETE FROM roles_adder
|
||||
WHERE server = ?1 AND role_a = ?2 AND role_b = ?3 AND role_c = ?4
|
||||
",
|
||||
)
|
||||
.bind(*server.server.as_u64() as i64)
|
||||
.bind(*server.role_a.as_u64() as i64)
|
||||
.bind(*server.role_b.as_u64() as i64)
|
||||
.bind(*server.role_c.as_u64() as i64)
|
||||
.fetch_optional(db)
|
||||
.await
|
||||
} else {
|
||||
sqlx::query_as::<_, RoleAdder>(
|
||||
"
|
||||
INSERT OR REPLACE INTO roles_adder (server, role_a, role_b, role_c)
|
||||
VALUES (?1, ?2, ?3, ?4)
|
||||
",
|
||||
)
|
||||
.bind(*server.server.as_u64() as i64)
|
||||
.bind(*server.role_a.as_u64() as i64)
|
||||
.bind(*server.role_b.as_u64() as i64)
|
||||
.bind(*server.role_c.as_u64() as i64)
|
||||
.fetch_optional(db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
pub mod list {}
|
||||
|
||||
pub mod tools {
|
||||
use serenity::client::Context;
|
||||
use serenity::model::guild::Member;
|
||||
use skynet_discord_bot::RoleAdder;
|
||||
use sqlx::{Pool, Sqlite};
|
||||
|
||||
pub async fn on_role_change(db: &Pool<Sqlite>, ctx: &Context, mut new_data: Member) {
|
||||
// check if the role changed is part of the oens for this server
|
||||
if let Ok(role_adders) = sqlx::query_as::<_, RoleAdder>(
|
||||
r#"
|
||||
SELECT *
|
||||
FROM roles_adder
|
||||
WHERE server = ?
|
||||
"#,
|
||||
)
|
||||
.bind(*new_data.guild_id.as_u64() as i64)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
{
|
||||
let mut roles_add = vec![];
|
||||
let mut roles_remove = vec![];
|
||||
|
||||
for role_adder in role_adders {
|
||||
// if the user has both A dnd B give them C
|
||||
if new_data.roles.contains(&role_adder.role_a) && new_data.roles.contains(&role_adder.role_b) && !new_data.roles.contains(&role_adder.role_c)
|
||||
{
|
||||
roles_add.push(role_adder.role_c);
|
||||
}
|
||||
|
||||
// If the suer has C but not A or B remove C
|
||||
if new_data.roles.contains(&role_adder.role_c)
|
||||
&& (!new_data.roles.contains(&role_adder.role_a) || !new_data.roles.contains(&role_adder.role_b))
|
||||
{
|
||||
roles_remove.push(role_adder.role_c);
|
||||
}
|
||||
}
|
||||
|
||||
if !roles_add.is_empty() {
|
||||
if let Err(e) = new_data.add_roles(&ctx, &roles_add).await {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
if !roles_remove.is_empty() {
|
||||
if let Err(e) = new_data.remove_roles(&ctx, &roles_remove).await {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
174
src/lib.rs
174
src/lib.rs
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serenity::{
|
||||
model::{
|
||||
guild,
|
||||
id::{GuildId, RoleId},
|
||||
id::{ChannelId, GuildId, RoleId},
|
||||
},
|
||||
prelude::TypeMapKey,
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ use sqlx::{
|
|||
use std::{env, str::FromStr, sync::Arc};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
// manages where teh database is stored
|
||||
pub home: String,
|
||||
|
@ -30,6 +31,7 @@ pub struct Config {
|
|||
// tokens for discord and other API's
|
||||
pub discord_token: String,
|
||||
pub discord_token_minecraft: String,
|
||||
pub minecraft_mcprofile: String,
|
||||
|
||||
// email settings
|
||||
pub mail_smtp: String,
|
||||
|
@ -38,6 +40,8 @@ pub struct Config {
|
|||
|
||||
// wolves API base for clubs/socs
|
||||
pub wolves_url: String,
|
||||
// API key for accessing more general resources
|
||||
pub wolves_api: String,
|
||||
}
|
||||
impl TypeMapKey for Config {
|
||||
type Value = Arc<RwLock<Config>>;
|
||||
|
@ -55,6 +59,7 @@ pub fn get_config() -> Config {
|
|||
let mut config = Config {
|
||||
discord_token: "".to_string(),
|
||||
discord_token_minecraft: "".to_string(),
|
||||
minecraft_mcprofile: "".to_string(),
|
||||
|
||||
home: ".".to_string(),
|
||||
database: "database.db".to_string(),
|
||||
|
@ -63,9 +68,10 @@ pub fn get_config() -> Config {
|
|||
mail_user: "".to_string(),
|
||||
mail_pass: "".to_string(),
|
||||
wolves_url: "".to_string(),
|
||||
wolves_api: "".to_string(),
|
||||
};
|
||||
|
||||
if let Ok(x) = env::var("HOME") {
|
||||
if let Ok(x) = env::var("DATABASE_HOME") {
|
||||
config.home = x.trim().to_string();
|
||||
}
|
||||
if let Ok(x) = env::var("DATABASE") {
|
||||
|
@ -78,6 +84,9 @@ pub fn get_config() -> Config {
|
|||
if let Ok(x) = env::var("DISCORD_TOKEN_MINECRAFT") {
|
||||
config.discord_token_minecraft = x.trim().to_string();
|
||||
}
|
||||
if let Ok(x) = env::var("MINECRAFT_MCPROFILE_KEY") {
|
||||
config.minecraft_mcprofile = x.trim().to_string();
|
||||
}
|
||||
|
||||
if let Ok(x) = env::var("EMAIL_SMTP") {
|
||||
config.mail_smtp = x.trim().to_string();
|
||||
|
@ -89,9 +98,12 @@ pub fn get_config() -> Config {
|
|||
config.mail_pass = x.trim().to_string();
|
||||
}
|
||||
|
||||
if let Ok(x) = env::var("WOLVES_URL") {
|
||||
if let Ok(x) = env::var("WOLVES_URL_BASE") {
|
||||
config.wolves_url = x.trim().to_string();
|
||||
}
|
||||
if let Ok(x) = env::var("WOLVES_API") {
|
||||
config.wolves_api = x.trim().to_string();
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
@ -123,6 +135,7 @@ pub struct ServerMembersWolves {
|
|||
pub email: String,
|
||||
pub discord: Option<UserId>,
|
||||
pub minecraft: Option<String>,
|
||||
pub minecraft_uid: Option<String>,
|
||||
}
|
||||
impl<'r> FromRow<'r, SqliteRow> for ServerMembersWolves {
|
||||
fn from_row(row: &'r SqliteRow) -> Result<Self, Error> {
|
||||
|
@ -147,6 +160,7 @@ impl<'r> FromRow<'r, SqliteRow> for ServerMembersWolves {
|
|||
email: row.try_get("email")?,
|
||||
discord,
|
||||
minecraft: row.try_get("minecraft")?,
|
||||
minecraft_uid: row.try_get("minecraft_uid")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -228,9 +242,13 @@ pub struct Servers {
|
|||
pub server: GuildId,
|
||||
pub wolves_api: String,
|
||||
pub role_past: Option<RoleId>,
|
||||
pub role_current: Option<RoleId>,
|
||||
pub role_current: RoleId,
|
||||
pub member_past: i64,
|
||||
pub member_current: i64,
|
||||
pub bot_channel_id: ChannelId,
|
||||
// these can be removed in teh future with an API update
|
||||
pub server_name: String,
|
||||
pub wolves_link: String,
|
||||
}
|
||||
impl<'r> FromRow<'r, SqliteRow> for Servers {
|
||||
fn from_row(row: &'r SqliteRow) -> Result<Self, Error> {
|
||||
|
@ -250,15 +268,14 @@ impl<'r> FromRow<'r, SqliteRow> for Servers {
|
|||
let role_current = match row.try_get("role_current") {
|
||||
Ok(x) => {
|
||||
let tmp: i64 = x;
|
||||
if tmp == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(RoleId::from(tmp as u64))
|
||||
}
|
||||
RoleId::from(tmp as u64)
|
||||
}
|
||||
_ => None,
|
||||
_ => RoleId::from(0u64),
|
||||
};
|
||||
|
||||
let bot_channel_tmp: i64 = row.try_get("bot_channel_id")?;
|
||||
let bot_channel_id = ChannelId::from(bot_channel_tmp as u64);
|
||||
|
||||
Ok(Self {
|
||||
server,
|
||||
wolves_api: row.try_get("wolves_api")?,
|
||||
|
@ -266,6 +283,9 @@ impl<'r> FromRow<'r, SqliteRow> for Servers {
|
|||
role_current,
|
||||
member_past: row.try_get("member_past")?,
|
||||
member_current: row.try_get("member_current")?,
|
||||
bot_channel_id,
|
||||
server_name: row.try_get("server_name")?,
|
||||
wolves_link: row.try_get("wolves_link")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -287,6 +307,37 @@ impl<'r> FromRow<'r, SqliteRow> for Minecraft {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct RoleAdder {
|
||||
pub server: GuildId,
|
||||
pub role_a: RoleId,
|
||||
pub role_b: RoleId,
|
||||
pub role_c: RoleId,
|
||||
}
|
||||
impl<'r> FromRow<'r, SqliteRow> for RoleAdder {
|
||||
fn from_row(row: &'r SqliteRow) -> Result<Self, Error> {
|
||||
let server_tmp: i64 = row.try_get("server")?;
|
||||
let server = GuildId::from(server_tmp as u64);
|
||||
|
||||
Ok(Self {
|
||||
server,
|
||||
role_a: get_role_from_row(row, "role_a"),
|
||||
role_b: get_role_from_row(row, "role_b"),
|
||||
role_c: get_role_from_row(row, "role_c"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_role_from_row(row: &SqliteRow, col: &str) -> RoleId {
|
||||
match row.try_get(col) {
|
||||
Ok(x) => {
|
||||
let tmp: i64 = x;
|
||||
RoleId(tmp as u64)
|
||||
}
|
||||
_ => RoleId::from(0u64),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, Error> {
|
||||
let database = format!("{}/{}", &config.home, &config.database);
|
||||
|
||||
|
@ -300,7 +351,7 @@ pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, Error> {
|
|||
.await?;
|
||||
|
||||
// migrations are amazing!
|
||||
sqlx::migrate!("./db/migrations").run(&pool).await.unwrap();
|
||||
sqlx::migrate!("./db/migrations").run(&pool).await?;
|
||||
|
||||
Ok(pool)
|
||||
}
|
||||
|
@ -403,11 +454,9 @@ pub mod set_roles {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(role) = &role_current {
|
||||
if !member.roles.contains(role) {
|
||||
roles_set[1] += 1;
|
||||
roles.push(role.to_owned());
|
||||
}
|
||||
if !member.roles.contains(role_current) {
|
||||
roles_set[1] += 1;
|
||||
roles.push(role_current.to_owned());
|
||||
}
|
||||
|
||||
if let Err(e) = member.add_roles(ctx, &roles).await {
|
||||
|
@ -422,13 +471,11 @@ pub mod set_roles {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(role) = &role_current {
|
||||
if member.roles.contains(role) {
|
||||
roles_set[2] += 1;
|
||||
// if theya re not a current member and have the role then remove it
|
||||
if let Err(e) = member.remove_role(ctx, role).await {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
if member.roles.contains(role_current) {
|
||||
roles_set[2] += 1;
|
||||
// if theya re not a current member and have the role then remove it
|
||||
if let Err(e) = member.remove_role(ctx, role_current).await {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -493,36 +540,8 @@ pub mod get_data {
|
|||
use super::*;
|
||||
use crate::set_roles::update_server;
|
||||
use std::collections::BTreeMap;
|
||||
use wolves_oxidised::WolvesUser;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct WolvesResultUser {
|
||||
committee: String,
|
||||
member_id: String,
|
||||
first_name: String,
|
||||
last_name: String,
|
||||
contact_email: String,
|
||||
opt_in_email: String,
|
||||
student_id: Option<String>,
|
||||
note: Option<String>,
|
||||
expiry: String,
|
||||
requested: String,
|
||||
approved: String,
|
||||
sitename: String,
|
||||
domain: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct WolvesResult {
|
||||
success: i8,
|
||||
result: Vec<WolvesResultUser>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct WolvesResultLocal {
|
||||
pub id_wolves: String,
|
||||
pub email: String,
|
||||
pub expiry: String,
|
||||
}
|
||||
pub async fn get_wolves(ctx: &Context) {
|
||||
let db_lock = {
|
||||
let data_read = ctx.data.read().await;
|
||||
|
@ -536,6 +555,9 @@ pub mod get_data {
|
|||
};
|
||||
let config = config_lock.read().await;
|
||||
|
||||
// set up teh client
|
||||
let wolves = wolves_oxidised::Client::new(&config.wolves_url, Some(&config.wolves_api));
|
||||
|
||||
for server_config in get_server_config_bulk(&db).await {
|
||||
let Servers {
|
||||
server,
|
||||
|
@ -548,7 +570,7 @@ pub mod get_data {
|
|||
|
||||
// list of users that need to be updated for this server
|
||||
let mut user_to_update = vec![];
|
||||
for user in get_wolves_sub(&config, wolves_api).await {
|
||||
for user in wolves.get_members(wolves_api).await {
|
||||
let id = user.member_id.parse::<u64>().unwrap_or_default();
|
||||
match existing.get(&(id as i64)) {
|
||||
None => {
|
||||
|
@ -594,30 +616,7 @@ pub mod get_data {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
async fn get_wolves_sub(config: &Config, wolves_api: &str) -> Vec<WolvesResultUser> {
|
||||
if config.wolves_url.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
// get wolves data
|
||||
if let Ok(mut res) = surf::post(&config.wolves_url).header("X-AM-Identity", wolves_api).await {
|
||||
if let Ok(WolvesResult {
|
||||
success,
|
||||
result,
|
||||
}) = res.body_json().await
|
||||
{
|
||||
if success != 1 {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
vec![]
|
||||
}
|
||||
|
||||
async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesResultUser) {
|
||||
async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesUser) {
|
||||
// expiry
|
||||
match sqlx::query_as::<_, Wolves>(
|
||||
"
|
||||
|
@ -638,7 +637,7 @@ pub mod get_data {
|
|||
}
|
||||
}
|
||||
}
|
||||
async fn add_users_server_members(db: &Pool<Sqlite>, server: &GuildId, user: &WolvesResultUser) {
|
||||
async fn add_users_server_members(db: &Pool<Sqlite>, server: &GuildId, user: &WolvesUser) {
|
||||
match sqlx::query_as::<_, ServerMembers>(
|
||||
"
|
||||
INSERT OR REPLACE INTO server_members (server, id_wolves, expiry)
|
||||
|
@ -707,7 +706,10 @@ pub async fn update_server(server_id: &str, db: &Pool<Sqlite>, g_id: &GuildId, c
|
|||
let mut usernames = vec![];
|
||||
for member in get_server_member_bulk(db, g_id).await {
|
||||
if let Some(x) = member.minecraft {
|
||||
usernames.push(x);
|
||||
usernames.push((x, true));
|
||||
}
|
||||
if let Some(x) = member.minecraft_uid {
|
||||
usernames.push((x, true));
|
||||
}
|
||||
}
|
||||
if !usernames.is_empty() {
|
||||
|
@ -771,13 +773,19 @@ struct BodyDelete {
|
|||
files: Vec<String>,
|
||||
}
|
||||
|
||||
pub async fn whitelist_update(add: &Vec<String>, server: &str, token: &str) {
|
||||
pub async fn whitelist_update(add: &Vec<(String, bool)>, server: &str, token: &str) {
|
||||
let url_base = format!("http://panel.games.skynet.ie/api/client/servers/{server}");
|
||||
let bearer = format!("Bearer {token}");
|
||||
|
||||
for name in add {
|
||||
let data = BodyCommand {
|
||||
command: format!("whitelist add {name}"),
|
||||
for (name, java) in add {
|
||||
let data = if *java {
|
||||
BodyCommand {
|
||||
command: format!("whitelist add {name}"),
|
||||
}
|
||||
} else {
|
||||
BodyCommand {
|
||||
command: format!("fwhitelist add {name}"),
|
||||
}
|
||||
};
|
||||
post(&format!("{url_base}/command"), &bearer, &data).await;
|
||||
}
|
||||
|
|
55
src/main.rs
55
src/main.rs
|
@ -1,25 +1,28 @@
|
|||
pub mod commands;
|
||||
|
||||
use crate::commands::role_adder::tools::on_role_change;
|
||||
use serenity::model::guild::Member;
|
||||
use serenity::{
|
||||
async_trait,
|
||||
client::{Context, EventHandler},
|
||||
model::{
|
||||
application::{command::Command, interaction::Interaction},
|
||||
gateway::{GatewayIntents, Ready},
|
||||
guild,
|
||||
prelude::Activity,
|
||||
user::OnlineStatus,
|
||||
},
|
||||
Client,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use skynet_discord_bot::{db_init, get_config, get_server_config, get_server_member, Config, DataBase};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
struct Handler;
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn guild_member_addition(&self, ctx: Context, mut new_member: guild::Member) {
|
||||
// handles previously linked accounts joining the server
|
||||
async fn guild_member_addition(&self, ctx: Context, mut new_member: Member) {
|
||||
let db_lock = {
|
||||
let data_read = ctx.data.read().await;
|
||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||
|
@ -40,24 +43,40 @@ impl EventHandler for Handler {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(role) = &config.role_current {
|
||||
if !new_member.roles.contains(role) {
|
||||
roles.push(role.to_owned());
|
||||
}
|
||||
if !new_member.roles.contains(&config.role_current) {
|
||||
roles.push(config.role_current.to_owned());
|
||||
}
|
||||
|
||||
if let Err(e) = new_member.add_roles(&ctx, &roles).await {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
} else {
|
||||
let msg = format!(
|
||||
r#"
|
||||
Welcome {} to the {} server!
|
||||
Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use ``/link_wolves`` to get full access.
|
||||
"#,
|
||||
new_member.display_name(),
|
||||
&config.server_name,
|
||||
&config.wolves_link,
|
||||
&config.server,
|
||||
&config.bot_channel_id
|
||||
);
|
||||
|
||||
if let Err(err) = new_member.user.direct_message(&ctx, |m| m.content(&msg)).await {
|
||||
dbg!(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||
println!("[Main] {} is connected!", ready.user.name);
|
||||
ctx.set_presence(Some(Activity::playing("with humanity's fate")), OnlineStatus::Online).await;
|
||||
|
||||
match Command::set_global_application_commands(&ctx.http, |commands| {
|
||||
commands
|
||||
.create_application_command(|command| commands::add_server::register(command))
|
||||
.create_application_command(|command| commands::role_adder::edit::register(command))
|
||||
.create_application_command(|command| commands::link_email::link::register(command))
|
||||
.create_application_command(|command| commands::link_email::verify::register(command))
|
||||
.create_application_command(|command| commands::minecraft::server::add::register(command))
|
||||
|
@ -89,6 +108,7 @@ impl EventHandler for Handler {
|
|||
"link_minecraft" => commands::minecraft::user::add::run(&command, &ctx).await,
|
||||
// admin commands
|
||||
"add" => commands::add_server::run(&command, &ctx).await,
|
||||
"roles_adder" => commands::role_adder::edit::run(&command, &ctx).await,
|
||||
"minecraft_add" => commands::minecraft::server::add::run(&command, &ctx).await,
|
||||
"minecraft_list" => commands::minecraft::server::list::run(&command, &ctx).await,
|
||||
"minecraft_delete" => commands::minecraft::server::delete::run(&command, &ctx).await,
|
||||
|
@ -103,6 +123,20 @@ impl EventHandler for Handler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handles role updates
|
||||
async fn guild_member_update(&self, ctx: Context, _old_data: Option<Member>, new_data: Member) {
|
||||
// get config/db
|
||||
let db_lock = {
|
||||
let data_read = ctx.data.read().await;
|
||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||
};
|
||||
|
||||
let db = db_lock.read().await;
|
||||
|
||||
// check if the role changed is part of the oens for this server
|
||||
on_role_change(&db, &ctx, new_data).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
@ -110,7 +144,10 @@ async fn main() {
|
|||
let config = get_config();
|
||||
let db = match db_init(&config).await {
|
||||
Ok(x) => x,
|
||||
Err(_) => return,
|
||||
Err(err) => {
|
||||
dbg!(err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Intents are a bitflag, bitwise operations can be used to dictate which intents to use
|
||||
|
|
Loading…
Reference in a new issue