Compare commits
46 commits
#32_rotati
...
main
Author | SHA1 | Date | |
---|---|---|---|
6353d77360 | |||
|
062f826d28 | ||
d8f785b0db | |||
|
d70a037057 | ||
|
7e90f45196 | ||
7526a82bb7 | |||
3149a5f99f | |||
061b73378a | |||
a225c14b4f | |||
095ff6f2ce | |||
18fd45d39b | |||
854e946a8f | |||
d0726169ee | |||
9d409e3692 | |||
57d4947edf | |||
6d08312f48 | |||
bd9d0cd43f | |||
1af7f28a45 | |||
feff293043 | |||
227db8a741 | |||
13eb230754 | |||
eb88216740 | |||
96eb81293b | |||
5815cde38b | |||
1729ec0a54 | |||
43ef787d59 | |||
a8bed0bacc | |||
3dd81a5c54 | |||
04aa0e63d4 | |||
2b2dfc2531 | |||
e901f3ed74 | |||
3abbb8d485 | |||
b8ffd42184 | |||
764e8cd620 | |||
76f8aa2712 | |||
c4da3e9109 | |||
d27befdac6 | |||
7403f531eb | |||
1dc5c105df | |||
3a56d7bba5 | |||
327ff99b69 | |||
dedf8c3644 | |||
a6eff75e39 | |||
72226cc59b | |||
f841039c53 | |||
87dd04e12f |
29 changed files with 754 additions and 341 deletions
|
@ -1,9 +1,7 @@
|
||||||
on:
|
on:
|
||||||
- pull_request
|
|
||||||
- push
|
- push
|
||||||
- workflow_dispatch
|
- workflow_dispatch
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check_lfs:
|
check_lfs:
|
||||||
# nix/docker
|
# nix/docker
|
||||||
|
|
51
.forgejo/workflows/on_pr.yaml
Normal file
51
.forgejo/workflows/on_pr.yaml
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
on:
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_lfs:
|
||||||
|
# nix/docker
|
||||||
|
runs-on: nix
|
||||||
|
steps:
|
||||||
|
- uses: https://github.com/MPLew-is/lfs-check-action@1
|
||||||
|
|
||||||
|
# rust code must be formatted for standardisation
|
||||||
|
lint_fmt:
|
||||||
|
# build it using teh base nixos system, helps with caching
|
||||||
|
runs-on: nix
|
||||||
|
steps:
|
||||||
|
# get the repo first
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
- uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs/nix@v8
|
||||||
|
with:
|
||||||
|
server_url: ${{ gitea.server_url }}
|
||||||
|
repository: ${{ gitea.repository }}
|
||||||
|
- run: nix build .#fmt --verbose
|
||||||
|
|
||||||
|
# clippy is incredibly useful for making yer code better
|
||||||
|
lint_clippy:
|
||||||
|
# build it using teh base nixos system, helps with caching
|
||||||
|
runs-on: nix
|
||||||
|
permissions:
|
||||||
|
checks: write
|
||||||
|
steps:
|
||||||
|
# get the repo first
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
- uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs/nix@v8
|
||||||
|
with:
|
||||||
|
server_url: ${{ gitea.server_url }}
|
||||||
|
repository: ${{ gitea.repository }}
|
||||||
|
- run: nix build .#clippy --verbose
|
||||||
|
|
||||||
|
build:
|
||||||
|
# build it using teh base nixos system, helps with caching
|
||||||
|
runs-on: nix
|
||||||
|
needs: [ lint_fmt, lint_clippy ]
|
||||||
|
steps:
|
||||||
|
# get the repo first
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
- uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs/nix@v8
|
||||||
|
with:
|
||||||
|
server_url: ${{ gitea.server_url }}
|
||||||
|
repository: ${{ gitea.repository }}
|
||||||
|
- name: "Build it locally"
|
||||||
|
run: nix build --verbose
|
2
.git-blame-ignore-revs
Normal file
2
.git-blame-ignore-revs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Fix typos
|
||||||
|
7e90f451965b0edbd331765ad295a02f31d2bf24
|
|
@ -7,4 +7,4 @@ fn_params_layout = "Compressed"
|
||||||
struct_lit_width = 0
|
struct_lit_width = 0
|
||||||
tab_spaces = 2
|
tab_spaces = 2
|
||||||
use_small_heuristics = "Max"
|
use_small_heuristics = "Max"
|
||||||
#imports_granularity="Crate"
|
imports_granularity = "Crate"
|
2
.taplo.toml
Normal file
2
.taplo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[formatting]
|
||||||
|
column_width = 120
|
|
@ -4,13 +4,9 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "update_data"
|
name = "update_data"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "update_users"
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "update_committee"
|
name = "update_committee"
|
||||||
|
|
||||||
|
@ -20,6 +16,9 @@ name = "update_minecraft"
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "update_server-icon"
|
name = "update_server-icon"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "cleanup_committee"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# discord library
|
# discord library
|
||||||
serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
|
serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Skynet Discord Bot
|
# Skynet Discord Bot
|
||||||
The Skynet bot is designed to manage users on Discord.
|
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.
|
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).
|
Skynet (bot) is hosted by the Computer Society on Skynet (computer cluster).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
We have split up the documentation into different segments depending on who the user is.
|
We have split up the documentation into different segments depending on who the user is.
|
||||||
|
|
17
flake.lock
generated
17
flake.lock
generated
|
@ -32,6 +32,22 @@
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-mozilla": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1744624473,
|
||||||
|
"narHash": "sha256-S6zT/w5SyAkJ//dYdjbrXgm+6Vkd/k7qqUl4WgZ6jjk=",
|
||||||
|
"owner": "mozilla",
|
||||||
|
"repo": "nixpkgs-mozilla",
|
||||||
|
"rev": "2292d4b35aa854e312ad2e95c4bb5c293656f21a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "mozilla",
|
||||||
|
"repo": "nixpkgs-mozilla",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1722995383,
|
"lastModified": 1722995383,
|
||||||
|
@ -51,6 +67,7 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"naersk": "naersk",
|
"naersk": "naersk",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"nixpkgs-mozilla": "nixpkgs-mozilla",
|
||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
35
flake.nix
35
flake.nix
|
@ -4,6 +4,10 @@
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||||
naersk.url = "github:nix-community/naersk";
|
naersk.url = "github:nix-community/naersk";
|
||||||
|
nixpkgs-mozilla = {
|
||||||
|
url = "github:mozilla/nixpkgs-mozilla";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
utils.url = "github:numtide/flake-utils";
|
utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,12 +21,27 @@
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
utils,
|
utils,
|
||||||
naersk,
|
naersk,
|
||||||
|
nixpkgs-mozilla,
|
||||||
}:
|
}:
|
||||||
utils.lib.eachDefaultSystem (
|
utils.lib.eachDefaultSystem (
|
||||||
system: let
|
system: let
|
||||||
overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml));
|
overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml));
|
||||||
pkgs = (import nixpkgs) {inherit system;};
|
pkgs = (import nixpkgs) {
|
||||||
naersk' = pkgs.callPackage naersk {};
|
inherit system;
|
||||||
|
|
||||||
|
overlays = [
|
||||||
|
(import nixpkgs-mozilla)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
toolchain = (pkgs.rustChannelOf {
|
||||||
|
rustToolchain = ./rust-toolchain.toml;
|
||||||
|
sha256 = "sha256-KUm16pHj+cRedf8vxs/Hd2YWxpOrWZ7UOrwhILdSJBU=";
|
||||||
|
}).rust;
|
||||||
|
|
||||||
|
naersk' = pkgs.callPackage naersk {
|
||||||
|
cargo = toolchain;
|
||||||
|
rustc = toolchain;
|
||||||
|
};
|
||||||
package_name = "skynet_discord_bot";
|
package_name = "skynet_discord_bot";
|
||||||
desc = "Skynet Discord Bot";
|
desc = "Skynet Discord Bot";
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
|
@ -103,12 +122,14 @@
|
||||||
wantedBy = [];
|
wantedBy = [];
|
||||||
after = ["network-online.target"];
|
after = ["network-online.target"];
|
||||||
environment = environment_config;
|
environment = environment_config;
|
||||||
|
path = with pkgs; [ git git-lfs ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
User = "${cfg.user}";
|
User = "${cfg.user}";
|
||||||
Group = "${cfg.user}";
|
Group = "${cfg.user}";
|
||||||
ExecStart = "${self.defaultPackage."${system}"}/bin/${script}";
|
ExecStart = "${self.defaultPackage."${system}"}/bin/${script}";
|
||||||
|
# kill each service if its ran for 9 min
|
||||||
|
TimeoutStartSec=540;
|
||||||
EnvironmentFile = [
|
EnvironmentFile = [
|
||||||
"${cfg.env.discord}"
|
"${cfg.env.discord}"
|
||||||
"${cfg.env.mail}"
|
"${cfg.env.mail}"
|
||||||
|
@ -133,13 +154,14 @@
|
||||||
|
|
||||||
# modify these
|
# modify these
|
||||||
scripts = {
|
scripts = {
|
||||||
# every 20 min
|
# every 10 min
|
||||||
"update_data" = "*:0,10,20,30,40,50";
|
"update_data" = "*:0,10,20,30,40,50";
|
||||||
# groups are updated every hour, offset from teh ldap
|
# groups are updated every hour, offset from teh ldap
|
||||||
"update_users" = "*:05:00";
|
"update_users" = "*:5,15,25,35,45,55";
|
||||||
# Committee server has its own timer
|
# Committee server has its own timer
|
||||||
"update_committee" = "*:15:00";
|
"update_committee" = "*:5,15,25,35,45,55";
|
||||||
# minecraft stuff is updated at 5am
|
# minecraft stuff is updated at 5am
|
||||||
|
# this service does not depend on teh discord cache
|
||||||
"update_minecraft" = "5:10:00";
|
"update_minecraft" = "5:10:00";
|
||||||
# server icon gets updated daily at midnight
|
# server icon gets updated daily at midnight
|
||||||
"update_server-icon" = "0:01:00";
|
"update_server-icon" = "0:01:00";
|
||||||
|
@ -202,6 +224,7 @@
|
||||||
after = ["network-online.target"];
|
after = ["network-online.target"];
|
||||||
wants = [];
|
wants = [];
|
||||||
environment = environment_config;
|
environment = environment_config;
|
||||||
|
path = with pkgs; [ git git-lfs ];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
User = "${cfg.user}";
|
User = "${cfg.user}";
|
||||||
|
|
137
src/bin/cleanup_committee.rs
Normal file
137
src/bin/cleanup_committee.rs
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
use serenity::{
|
||||||
|
all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent},
|
||||||
|
async_trait,
|
||||||
|
client::{Context, EventHandler},
|
||||||
|
model::gateway::GatewayIntents,
|
||||||
|
Client,
|
||||||
|
};
|
||||||
|
use skynet_discord_bot::{
|
||||||
|
common::{
|
||||||
|
database::{db_init, DataBase},
|
||||||
|
set_roles::committee::db_roles_get,
|
||||||
|
},
|
||||||
|
get_config, Config,
|
||||||
|
};
|
||||||
|
use sqlx::{Pool, Sqlite};
|
||||||
|
use std::{process, sync::Arc};
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
/// Cleanup teh Committee server
|
||||||
|
///
|
||||||
|
/// This removes any invalid roles/channels which have been set up accidentally
|
||||||
|
/// DO NOT run this locally unless you have a fresh copy of the live database handy.
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let config = get_config();
|
||||||
|
let db = match db_init(&config).await {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Intents are a bitflag, bitwise operations can be used to dictate which intents to use
|
||||||
|
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
||||||
|
// Build our client.
|
||||||
|
let mut client = Client::builder(&config.discord_token, intents)
|
||||||
|
.event_handler(Handler {})
|
||||||
|
.cache_settings(serenity::cache::Settings::default())
|
||||||
|
.await
|
||||||
|
.expect("Error creating client");
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
|
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||||
|
data.insert::<DataBase>(Arc::new(db));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(why) = client.start().await {
|
||||||
|
println!("Client error: {why:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Handler;
|
||||||
|
#[async_trait]
|
||||||
|
impl EventHandler for Handler {
|
||||||
|
async fn cache_ready(&self, ctx: Context, _guilds: Vec<GuildId>) {
|
||||||
|
let config_lock = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
let config_global = config_lock.read().await;
|
||||||
|
|
||||||
|
let server = config_global.committee_server;
|
||||||
|
|
||||||
|
ctx.shard.chunk_guild(server, Some(2000), false, ChunkGuildFilter::None, None);
|
||||||
|
|
||||||
|
println!("Cache loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) {
|
||||||
|
if (chunk.chunk_index + 1) == chunk.chunk_count {
|
||||||
|
println!("Cache built successfully!");
|
||||||
|
let db = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let config_lock = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
let config = config_lock.read().await;
|
||||||
|
|
||||||
|
cleanup(&db, &ctx, &config).await;
|
||||||
|
// finish up
|
||||||
|
process::exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cleanup(db: &Pool<Sqlite>, ctx: &Context, config: &Config) {
|
||||||
|
let server = config.committee_server;
|
||||||
|
let committees = db_roles_get(db).await;
|
||||||
|
|
||||||
|
if let Ok(channels) = server.channels(ctx).await {
|
||||||
|
for (id, channel) in &channels {
|
||||||
|
let name = &channel.name;
|
||||||
|
let committee_tmp = committees.iter().filter(|x| &x.name_channel == name).collect::<Vec<_>>();
|
||||||
|
let committee = match committee_tmp.first() {
|
||||||
|
// if there are no committees which match then this is not a channel we care about
|
||||||
|
None => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(x) => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
// if the id of the channel does not match then remove it
|
||||||
|
if id != &committee.id_channel {
|
||||||
|
println!("Deleting Channel - ID: {} Name: {}", id, &channel.name);
|
||||||
|
if let Err(e) = channel.delete(ctx).await {
|
||||||
|
dbg!(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(mut roles) = server.roles(ctx).await {
|
||||||
|
for (id, role) in &mut roles {
|
||||||
|
let name = &role.name;
|
||||||
|
let committee_tmp = committees.iter().filter(|x| &x.name_role == name).collect::<Vec<_>>();
|
||||||
|
let committee = match committee_tmp.first() {
|
||||||
|
// if there are no committees which match then this is not a channel we care about
|
||||||
|
None => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(x) => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
// if the id of the role does not match then remove it
|
||||||
|
if id != &committee.id_role {
|
||||||
|
println!("Deleting Role - ID: {} Name: {}", id, &role.name);
|
||||||
|
if let Err(e) = role.delete(ctx).await {
|
||||||
|
dbg!(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,17 @@
|
||||||
use serenity::{
|
use serenity::{
|
||||||
|
all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent},
|
||||||
async_trait,
|
async_trait,
|
||||||
client::{Context, EventHandler},
|
client::{Context, EventHandler},
|
||||||
model::gateway::{GatewayIntents, Ready},
|
model::gateway::GatewayIntents,
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::database::{db_init, DataBase};
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::set_roles::committee;
|
common::{
|
||||||
use skynet_discord_bot::{get_config, Config};
|
database::{db_init, DataBase},
|
||||||
|
set_roles::committee,
|
||||||
|
},
|
||||||
|
get_config, Config,
|
||||||
|
};
|
||||||
use std::{process, sync::Arc};
|
use std::{process, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
@ -23,6 +28,7 @@ async fn main() {
|
||||||
// Build our client.
|
// Build our client.
|
||||||
let mut client = Client::builder(&config.discord_token, intents)
|
let mut client = Client::builder(&config.discord_token, intents)
|
||||||
.event_handler(Handler {})
|
.event_handler(Handler {})
|
||||||
|
.cache_settings(serenity::cache::Settings::default())
|
||||||
.await
|
.await
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
|
|
||||||
|
@ -30,25 +36,39 @@ async fn main() {
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||||
data.insert::<DataBase>(Arc::new(RwLock::new(db)));
|
data.insert::<DataBase>(Arc::new(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(why) = client.start().await {
|
if let Err(why) = client.start().await {
|
||||||
println!("Client error: {:?}", why);
|
println!("Client error: {why:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Handler;
|
struct Handler;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
async fn cache_ready(&self, ctx: Context, _guilds: Vec<GuildId>) {
|
||||||
let ctx = Arc::new(ctx);
|
let config_lock = {
|
||||||
println!("{} is connected!", ready.user.name);
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
let config_global = config_lock.read().await;
|
||||||
|
|
||||||
|
let server = config_global.committee_server;
|
||||||
|
|
||||||
|
ctx.shard.chunk_guild(server, Some(2000), false, ChunkGuildFilter::None, None);
|
||||||
|
|
||||||
|
println!("Cache loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) {
|
||||||
|
if (chunk.chunk_index + 1) == chunk.chunk_count {
|
||||||
|
println!("Cache built successfully!");
|
||||||
// u[date committee server
|
// u[date committee server
|
||||||
committee::check_committee(Arc::clone(&ctx)).await;
|
committee::check_committee(&ctx).await;
|
||||||
|
|
||||||
// finish up
|
// finish up
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,10 +4,13 @@ use serenity::{
|
||||||
model::gateway::{GatewayIntents, Ready},
|
model::gateway::{GatewayIntents, Ready},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::database::{db_init, DataBase};
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::wolves::cns::get_wolves;
|
common::{
|
||||||
use skynet_discord_bot::common::wolves::committees::get_cns;
|
database::{db_init, DataBase},
|
||||||
use skynet_discord_bot::{get_config, Config};
|
wolves::{cns::get_wolves, committees::get_cns},
|
||||||
|
},
|
||||||
|
get_config, Config,
|
||||||
|
};
|
||||||
use std::{process, sync::Arc};
|
use std::{process, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
@ -27,6 +30,7 @@ async fn main() {
|
||||||
// Build our client.
|
// Build our client.
|
||||||
let mut client = Client::builder(&config.discord_token, intents)
|
let mut client = Client::builder(&config.discord_token, intents)
|
||||||
.event_handler(Handler {})
|
.event_handler(Handler {})
|
||||||
|
.cache_settings(serenity::cache::Settings::default())
|
||||||
.await
|
.await
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
|
|
||||||
|
@ -34,11 +38,11 @@ async fn main() {
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||||
data.insert::<DataBase>(Arc::new(RwLock::new(db)));
|
data.insert::<DataBase>(Arc::new(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(why) = client.start().await {
|
if let Err(why) = client.start().await {
|
||||||
println!("Client error: {:?}", why);
|
println!("Client error: {why:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use skynet_discord_bot::common::database::db_init;
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::minecraft::{get_minecraft_config, update_server, whitelist_wipe};
|
common::{
|
||||||
use skynet_discord_bot::get_config;
|
database::db_init,
|
||||||
|
minecraft::{get_minecraft_config, update_server, whitelist_wipe},
|
||||||
|
},
|
||||||
|
get_config,
|
||||||
|
};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
|
@ -4,9 +4,11 @@ use serenity::{
|
||||||
model::gateway::{GatewayIntents, Ready},
|
model::gateway::{GatewayIntents, Ready},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon};
|
|
||||||
use skynet_discord_bot::{
|
use skynet_discord_bot::{
|
||||||
common::database::{db_init, DataBase},
|
common::{
|
||||||
|
database::{db_init, DataBase},
|
||||||
|
server_icon::{get_config_icons, update_icon},
|
||||||
|
},
|
||||||
get_config, Config,
|
get_config, Config,
|
||||||
};
|
};
|
||||||
use std::{process, sync::Arc};
|
use std::{process, sync::Arc};
|
||||||
|
@ -25,6 +27,7 @@ async fn main() {
|
||||||
// Build our client.
|
// Build our client.
|
||||||
let mut client = Client::builder(&config.discord_token, intents)
|
let mut client = Client::builder(&config.discord_token, intents)
|
||||||
.event_handler(Handler {})
|
.event_handler(Handler {})
|
||||||
|
.cache_settings(serenity::cache::Settings::default())
|
||||||
.await
|
.await
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
|
|
||||||
|
@ -32,11 +35,11 @@ async fn main() {
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||||
data.insert::<DataBase>(Arc::new(RwLock::new(db)));
|
data.insert::<DataBase>(Arc::new(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(why) = client.start().await {
|
if let Err(why) = client.start().await {
|
||||||
println!("Client error: {:?}", why);
|
println!("Client error: {why:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +50,10 @@ impl EventHandler for Handler {
|
||||||
let ctx = Arc::new(ctx);
|
let ctx = Arc::new(ctx);
|
||||||
println!("{} is connected!", ready.user.name);
|
println!("{} is connected!", ready.user.name);
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
use serenity::{
|
use serenity::{
|
||||||
|
all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent},
|
||||||
async_trait,
|
async_trait,
|
||||||
client::{Context, EventHandler},
|
client::{Context, EventHandler},
|
||||||
model::gateway::{GatewayIntents, Ready},
|
model::gateway::GatewayIntents,
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::database::{db_init, get_server_config_bulk, DataBase};
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::set_roles::normal;
|
common::{
|
||||||
use skynet_discord_bot::{get_config, Config};
|
database::{db_init, get_server_config_bulk, DataBase},
|
||||||
use std::{process, sync::Arc};
|
set_roles::normal,
|
||||||
|
},
|
||||||
|
get_config, Config,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
process,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -22,7 +33,11 @@ async fn main() {
|
||||||
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
||||||
// Build our client.
|
// Build our client.
|
||||||
let mut client = Client::builder(&config.discord_token, intents)
|
let mut client = Client::builder(&config.discord_token, intents)
|
||||||
.event_handler(Handler {})
|
.event_handler(Handler {
|
||||||
|
server_count: Default::default(),
|
||||||
|
server_cached: Default::default(),
|
||||||
|
})
|
||||||
|
.cache_settings(serenity::cache::Settings::default())
|
||||||
.await
|
.await
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
|
|
||||||
|
@ -30,38 +45,51 @@ async fn main() {
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||||
data.insert::<DataBase>(Arc::new(RwLock::new(db)));
|
data.insert::<DataBase>(Arc::new(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(why) = client.start().await {
|
if let Err(why) = client.start().await {
|
||||||
println!("Client error: {:?}", why);
|
println!("Client error: {why:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Handler;
|
struct Handler {
|
||||||
|
server_count: AtomicUsize,
|
||||||
|
server_cached: AtomicUsize,
|
||||||
|
}
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
async fn cache_ready(&self, ctx: Context, guilds: Vec<GuildId>) {
|
||||||
let ctx = Arc::new(ctx);
|
self.server_count.swap(guilds.len(), Ordering::SeqCst);
|
||||||
println!("{} is connected!", ready.user.name);
|
for guild in guilds {
|
||||||
|
ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None);
|
||||||
|
}
|
||||||
|
println!("Cache loaded {}", &self.server_count.load(Ordering::SeqCst));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) {
|
||||||
|
if (chunk.chunk_index + 1) == chunk.chunk_count {
|
||||||
|
self.server_cached.fetch_add(1, Ordering::SeqCst);
|
||||||
|
if (self.server_cached.load(Ordering::SeqCst) + 1) == self.server_count.load(Ordering::SeqCst) {
|
||||||
|
println!("Cache built successfully!");
|
||||||
|
|
||||||
// this goes into each server and sets roles for each wolves member
|
// this goes into each server and sets roles for each wolves member
|
||||||
check_bulk(Arc::clone(&ctx)).await;
|
check_bulk(&ctx).await;
|
||||||
|
|
||||||
// finish up
|
// finish up
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn check_bulk(ctx: Arc<Context>) {
|
async fn check_bulk(ctx: &Context) {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
for server_config in get_server_config_bulk(&db).await {
|
for server_config in get_server_config_bulk(&db).await {
|
||||||
normal::update_server(&ctx, &server_config, &[], &[]).await;
|
normal::update_server(ctx, &server_config, &[], &[]).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction};
|
use serenity::{
|
||||||
use serenity::client::Context;
|
all::{CommandDataOption, CommandDataOptionValue, CommandInteraction},
|
||||||
use skynet_discord_bot::common::database::{get_server_config, DataBase, Servers};
|
client::Context,
|
||||||
use skynet_discord_bot::common::set_roles::normal::update_server;
|
};
|
||||||
use skynet_discord_bot::common::wolves::cns::get_wolves;
|
use skynet_discord_bot::common::{
|
||||||
|
database::{get_server_config, DataBase, Servers},
|
||||||
|
set_roles::normal::update_server,
|
||||||
|
wolves::cns::get_wolves,
|
||||||
|
};
|
||||||
use sqlx::{Error, Pool, Sqlite};
|
use sqlx::{Error, Pool, Sqlite};
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
|
@ -52,11 +56,10 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
return "Please provide a valid channel for ``Bot Channel``".to_string();
|
return "Please provide a valid channel for ``Bot Channel``".to_string();
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let server_data = Servers {
|
let server_data = Servers {
|
||||||
server: command.guild_id.unwrap_or_default(),
|
server: command.guild_id.unwrap_or_default(),
|
||||||
|
@ -72,8 +75,8 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
match add_server(&db, ctx, &server_data).await {
|
match add_server(&db, ctx, &server_data).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
return format!("Failure to insert into Servers {:?}", server_data);
|
return format!("Failure to insert into Servers {server_data:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Resul
|
||||||
.fetch_optional(db)
|
.fetch_optional(db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// if the entry does not exist already tehn do a user update
|
// if the entry does not exist already then do a user update
|
||||||
let (update, current_remove, current_role, past_remove, past_role) = match &existing {
|
let (update, current_remove, current_role, past_remove, past_role) = match &existing {
|
||||||
None => (true, false, None, false, None),
|
None => (true, false, None, false, None),
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
|
|
|
@ -5,8 +5,7 @@ pub mod committee {
|
||||||
use serenity::all::{
|
use serenity::all::{
|
||||||
CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption,
|
CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::database::DataBase;
|
use skynet_discord_bot::common::{database::DataBase, set_roles::committee::db_roles_get};
|
||||||
use skynet_discord_bot::common::set_roles::committee::db_roles_get;
|
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let sub_options = if let Some(CommandDataOption {
|
let sub_options = if let Some(CommandDataOption {
|
||||||
|
@ -28,11 +27,10 @@ pub mod committee {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let mut cs = vec![];
|
let mut cs = vec![];
|
||||||
// pull it from a DB
|
// pull it from a DB
|
||||||
|
@ -53,7 +51,7 @@ pub mod committee {
|
||||||
for (count, name) in cs {
|
for (count, name) in cs {
|
||||||
let leading = if count < 10 { " " } else { "" };
|
let leading = if count < 10 { " " } else { "" };
|
||||||
|
|
||||||
let line = format!("{}{} {}", leading, count, name);
|
let line = format!("{leading}{count} {name}");
|
||||||
|
|
||||||
let length = line.len() + 1;
|
let length = line.len() + 1;
|
||||||
|
|
||||||
|
@ -85,23 +83,28 @@ pub mod servers {
|
||||||
// get the list of all the current clubs/socs
|
// get the list of all the current clubs/socs
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::all::{CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption};
|
use serenity::all::{CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption};
|
||||||
use skynet_discord_bot::common::database::{get_server_config_bulk, DataBase};
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::set_roles::committee::get_committees;
|
common::{
|
||||||
use skynet_discord_bot::get_now_iso;
|
database::{get_server_config_bulk, DataBase},
|
||||||
|
set_roles::committee::get_committees,
|
||||||
|
},
|
||||||
|
get_now_iso,
|
||||||
|
};
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let mut committees = HashMap::new();
|
let mut committees = HashMap::new();
|
||||||
for committee in get_committees(&db).await {
|
if let Some(x) = get_committees(&db).await {
|
||||||
|
for committee in x {
|
||||||
committees.insert(committee.id, committee.to_owned());
|
committees.insert(committee.id, committee.to_owned());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut cs = vec![];
|
let mut cs = vec![];
|
||||||
// pull it from a DB
|
// pull it from a DB
|
||||||
|
@ -143,11 +146,11 @@ pub mod servers {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
let line = format!("{}{} {}{} {}", current_leading, current, past_leading, past, name);
|
let line = format!("{current_leading}{current} {past_leading}{past} {name}");
|
||||||
|
|
||||||
let length = line.len() + 1;
|
let length = line.len() + 1;
|
||||||
|
|
||||||
// +3 is to account for the closing fense
|
// +3 is to account for the closing fence
|
||||||
if length < (limit + 3) {
|
if length < (limit + 3) {
|
||||||
response.push(line);
|
response.push(line);
|
||||||
limit -= length;
|
limit -= length;
|
||||||
|
|
|
@ -9,19 +9,24 @@ pub(crate) mod user {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::commands::wolves::link::get_server_member_discord;
|
use crate::commands::wolves::link::get_server_member_discord;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction};
|
use serenity::{
|
||||||
use serenity::model::id::UserId;
|
all::{CommandDataOption, CommandDataOptionValue, CommandInteraction},
|
||||||
use skynet_discord_bot::common::database::Wolves;
|
model::id::UserId,
|
||||||
use skynet_discord_bot::common::minecraft::{whitelist_update, Minecraft};
|
};
|
||||||
use skynet_discord_bot::Config;
|
use skynet_discord_bot::{
|
||||||
|
common::{
|
||||||
|
database::Wolves,
|
||||||
|
minecraft::{whitelist_update, Minecraft},
|
||||||
|
},
|
||||||
|
Config,
|
||||||
|
};
|
||||||
use sqlx::Error;
|
use sqlx::Error;
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
|
@ -69,14 +74,14 @@ pub(crate) mod user {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
dbg!("{:?}", e);
|
dbg!("{:?}", e);
|
||||||
return format!("Failure to minecraft username {:?}", username);
|
return format!("Failure to minecraft username {username:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
username_mc = username.to_string();
|
username_mc = username.to_string();
|
||||||
} else {
|
} else {
|
||||||
match get_minecraft_bedrock(username, &config.minecraft_mcprofile).await {
|
match get_minecraft_bedrock(username, &config.minecraft_mcprofile).await {
|
||||||
None => {
|
None => {
|
||||||
return format!("No UID found for {:?}", username);
|
return format!("No UID found for {username:?}");
|
||||||
}
|
}
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
match add_minecraft_bedrock(&db, &command.user.id, &x.floodgateuid).await {
|
match add_minecraft_bedrock(&db, &command.user.id, &x.floodgateuid).await {
|
||||||
|
@ -185,14 +190,17 @@ pub(crate) mod server {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub(crate) mod add {
|
pub(crate) mod add {
|
||||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommand, CreateCommandOption};
|
use serenity::{
|
||||||
use serenity::model::id::GuildId;
|
all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommand, CreateCommandOption},
|
||||||
|
model::id::GuildId,
|
||||||
|
};
|
||||||
use sqlx::Error;
|
use sqlx::Error;
|
||||||
// this is to managfe the server side of commands related to minecraft
|
// this is to manage the server side of commands related to minecraft
|
||||||
use super::*;
|
use super::*;
|
||||||
use skynet_discord_bot::common::minecraft::update_server;
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::minecraft::Minecraft;
|
common::minecraft::{update_server, Minecraft},
|
||||||
use skynet_discord_bot::Config;
|
Config,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn register() -> CreateCommand {
|
pub fn register() -> CreateCommand {
|
||||||
CreateCommand::new("minecraft_add")
|
CreateCommand::new("minecraft_add")
|
||||||
|
@ -220,16 +228,15 @@ pub(crate) mod server {
|
||||||
return String::from("Expected Server ID");
|
return String::from("Expected Server ID");
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
match add_server(&db, &g_id, &server_minecraft).await {
|
match add_server(&db, &g_id, &server_minecraft).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
return format!("Failure to insert into Minecraft {} {}", &g_id, &server_minecraft);
|
return format!("Failure to insert into Minecraft {} {}", &g_id, &server_minecraft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,12 +267,14 @@ pub(crate) mod server {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod list {
|
pub(crate) mod list {
|
||||||
use serenity::all::CommandInteraction;
|
use serenity::{all::CommandInteraction, builder::CreateCommand, client::Context};
|
||||||
use serenity::builder::CreateCommand;
|
use skynet_discord_bot::{
|
||||||
use serenity::client::Context;
|
common::{
|
||||||
use skynet_discord_bot::common::database::DataBase;
|
database::DataBase,
|
||||||
use skynet_discord_bot::common::minecraft::{get_minecraft_config_server, server_information};
|
minecraft::{get_minecraft_config_server, server_information},
|
||||||
use skynet_discord_bot::Config;
|
},
|
||||||
|
Config,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn register() -> CreateCommand {
|
pub fn register() -> CreateCommand {
|
||||||
CreateCommand::new("minecraft_list")
|
CreateCommand::new("minecraft_list")
|
||||||
|
@ -279,11 +288,10 @@ pub(crate) mod server {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let servers = get_minecraft_config_server(&db, g_id).await;
|
let servers = get_minecraft_config_server(&db, g_id).await;
|
||||||
|
|
||||||
|
@ -320,12 +328,13 @@ pub(crate) mod server {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod delete {
|
pub(crate) mod delete {
|
||||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommandOption};
|
use serenity::{
|
||||||
use serenity::builder::CreateCommand;
|
all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommandOption},
|
||||||
use serenity::client::Context;
|
builder::CreateCommand,
|
||||||
use serenity::model::id::GuildId;
|
client::Context,
|
||||||
use skynet_discord_bot::common::database::DataBase;
|
model::id::GuildId,
|
||||||
use skynet_discord_bot::common::minecraft::Minecraft;
|
};
|
||||||
|
use skynet_discord_bot::common::{database::DataBase, minecraft::Minecraft};
|
||||||
use sqlx::{Error, Pool, Sqlite};
|
use sqlx::{Error, Pool, Sqlite};
|
||||||
|
|
||||||
pub fn register() -> CreateCommand {
|
pub fn register() -> CreateCommand {
|
||||||
|
@ -354,16 +363,15 @@ pub(crate) mod server {
|
||||||
return String::from("Expected Server ID");
|
return String::from("Expected Server ID");
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
match server_remove(&db, &g_id, &server_minecraft).await {
|
match server_remove(&db, &g_id, &server_minecraft).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
return format!("Failure to insert into Minecraft {} {}", &g_id, &server_minecraft);
|
return format!("Failure to insert into Minecraft {} {}", &g_id, &server_minecraft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,11 +62,10 @@ pub mod edit {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
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 = command.guild_id.unwrap_or_default();
|
||||||
let server_data = RoleAdder {
|
let server_data = RoleAdder {
|
||||||
|
@ -79,8 +78,8 @@ pub mod edit {
|
||||||
match add_server(&db, &server_data, delete).await {
|
match add_server(&db, &server_data, delete).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
return format!("Failure to insert into Servers {:?}", server_data);
|
return format!("Failure to insert into Servers {server_data:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +100,9 @@ pub mod edit {
|
||||||
}
|
}
|
||||||
|
|
||||||
if delete {
|
if delete {
|
||||||
format!("Removed {} + {} = {}", role_a_name, role_b_name, role_c_name)
|
format!("Removed {role_a_name} + {role_b_name} = {role_c_name}")
|
||||||
} else {
|
} else {
|
||||||
format!("Added {} + {} = {}", role_a_name, role_b_name, role_c_name)
|
format!("Added {role_a_name} + {role_b_name} = {role_c_name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,13 +141,12 @@ pub mod edit {
|
||||||
pub mod list {}
|
pub mod list {}
|
||||||
|
|
||||||
pub mod tools {
|
pub mod tools {
|
||||||
use serenity::client::Context;
|
use serenity::{client::Context, model::guild::Member};
|
||||||
use serenity::model::guild::Member;
|
|
||||||
use skynet_discord_bot::common::database::RoleAdder;
|
use skynet_discord_bot::common::database::RoleAdder;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
pub async fn on_role_change(db: &Pool<Sqlite>, ctx: &Context, new_data: Member) {
|
pub async fn on_role_change(db: &Pool<Sqlite>, ctx: &Context, new_data: Member) {
|
||||||
// check if the role changed is part of the oens for this server
|
// check if the role changed is part of the ones for this server
|
||||||
if let Ok(role_adders) = sqlx::query_as::<_, RoleAdder>(
|
if let Ok(role_adders) = sqlx::query_as::<_, RoleAdder>(
|
||||||
r#"
|
r#"
|
||||||
SELECT *
|
SELECT *
|
||||||
|
@ -164,7 +162,7 @@ pub mod tools {
|
||||||
let mut roles_remove = vec![];
|
let mut roles_remove = vec![];
|
||||||
|
|
||||||
for role_adder in role_adders {
|
for role_adder in role_adders {
|
||||||
// if the user has both A dnd B give them C
|
// if the user has both A and 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)
|
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);
|
roles_add.push(role_adder.role_c);
|
||||||
|
@ -180,13 +178,13 @@ pub mod tools {
|
||||||
|
|
||||||
if !roles_add.is_empty() {
|
if !roles_add.is_empty() {
|
||||||
if let Err(e) = new_data.add_roles(&ctx, &roles_add).await {
|
if let Err(e) = new_data.add_roles(&ctx, &roles_add).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !roles_remove.is_empty() {
|
if !roles_remove.is_empty() {
|
||||||
if let Err(e) = new_data.remove_roles(&ctx, &roles_remove).await {
|
if let Err(e) = new_data.remove_roles(&ctx, &roles_remove).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,10 @@ pub(crate) mod admin {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
|
@ -69,11 +68,10 @@ pub(crate) mod user {
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_toml = get_config_icons::minimal();
|
let config_toml = get_config_icons::minimal();
|
||||||
|
|
||||||
|
@ -93,7 +91,7 @@ pub(crate) mod user {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_current_icon(db: &Pool<Sqlite>) -> Option<ServerIcons> {
|
pub async fn get_current_icon(db: &Pool<Sqlite>) -> Option<ServerIcons> {
|
||||||
match sqlx::query_as::<_, ServerIcons>(
|
match sqlx::query_as::<_, ServerIcons>(
|
||||||
"
|
"
|
||||||
SELECT * from server_icons ORDER BY id DESC LIMIT 1
|
SELECT * from server_icons ORDER BY id DESC LIMIT 1
|
||||||
|
@ -113,8 +111,10 @@ pub(crate) mod user {
|
||||||
|
|
||||||
pub(crate) mod festival {
|
pub(crate) mod festival {
|
||||||
use serenity::all::{CommandInteraction, Context};
|
use serenity::all::{CommandInteraction, Context};
|
||||||
use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon::get_festival};
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::Config;
|
common::server_icon::{get_config_icons, update_icon::get_festival},
|
||||||
|
Config,
|
||||||
|
};
|
||||||
|
|
||||||
// use this to return what current festivals are active?
|
// use this to return what current festivals are active?
|
||||||
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
|
@ -143,11 +143,10 @@ pub(crate) mod user {
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_toml = get_config_icons::minimal();
|
let config_toml = get_config_icons::minimal();
|
||||||
|
|
||||||
|
@ -205,11 +204,11 @@ pub(crate) mod user {
|
||||||
|
|
||||||
// the `` is so that the numbers will be rendered in monospaced font
|
// the `` is so that the numbers will be rendered in monospaced font
|
||||||
// the <> is to suppress the URL embed
|
// the <> is to suppress the URL embed
|
||||||
let line = format!("``{}{}`` [{}](<{}>)", current_leading, times, name, url);
|
let line = format!("``{current_leading}{times}`` [{name}](<{url}>)");
|
||||||
|
|
||||||
let length = line.len() + 1;
|
let length = line.len() + 1;
|
||||||
|
|
||||||
// +3 is to account for the closing fense
|
// +3 is to account for the closing fence
|
||||||
if length < (limit + 3) {
|
if length < (limit + 3) {
|
||||||
response.push(line);
|
response.push(line);
|
||||||
limit -= length;
|
limit -= length;
|
||||||
|
|
|
@ -4,11 +4,16 @@ use lettre::{
|
||||||
Message, SmtpTransport, Transport,
|
Message, SmtpTransport, Transport,
|
||||||
};
|
};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use serenity::all::CommandOptionType;
|
use serenity::{
|
||||||
use serenity::builder::CreateCommandOption;
|
all::CommandOptionType,
|
||||||
use serenity::{builder::CreateCommand, client::Context, model::id::UserId};
|
builder::{CreateCommand, CreateCommandOption},
|
||||||
use skynet_discord_bot::common::database::{DataBase, Wolves, WolvesVerify};
|
client::Context,
|
||||||
use skynet_discord_bot::{get_now_iso, random_string, Config};
|
model::id::UserId,
|
||||||
|
};
|
||||||
|
use skynet_discord_bot::{
|
||||||
|
common::database::{DataBase, Wolves, WolvesVerify},
|
||||||
|
get_now_iso, random_string, Config,
|
||||||
|
};
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
pub mod link {
|
pub mod link {
|
||||||
|
@ -16,11 +21,10 @@ pub mod link {
|
||||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction};
|
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction};
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
|
@ -96,7 +100,7 @@ pub mod link {
|
||||||
return "Email already verified".to_string();
|
return "Email already verified".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a auth key
|
// generate an auth key
|
||||||
let auth = random_string(20);
|
let auth = random_string(20);
|
||||||
match send_mail(&config, &details.email, &auth, &command.user.name) {
|
match send_mail(&config, &details.email, &auth, &command.user.name) {
|
||||||
Ok(_) => match save_to_db(&db, &details, &auth, &command.user.id).await {
|
Ok(_) => match save_to_db(&db, &details, &auth, &command.user.id).await {
|
||||||
|
@ -110,7 +114,7 @@ pub mod link {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
format!("Verification email sent to {}, it may take up to 15 min for it to arrive. If it takes longer check the Junk folder.", email)
|
format!("Verification email sent to {email}, it may take up to 15 min for it to arrive. If it takes longer check the Junk folder.")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_server_member_discord(db: &Pool<Sqlite>, user: &UserId) -> Option<Wolves> {
|
pub async fn get_server_member_discord(db: &Pool<Sqlite>, user: &UserId) -> Option<Wolves> {
|
||||||
|
@ -205,7 +209,7 @@ pub mod link {
|
||||||
.subject("Skynet: Link Discord to Wolves.")
|
.subject("Skynet: Link Discord to Wolves.")
|
||||||
.multipart(
|
.multipart(
|
||||||
// This is composed of two parts.
|
// This is composed of two parts.
|
||||||
// also helps not trip spam settings (uneven number of url's
|
// also helps not trip spam settings (uneven number of urls)
|
||||||
MultiPart::alternative()
|
MultiPart::alternative()
|
||||||
.singlepart(SinglePart::builder().header(header::ContentType::TEXT_PLAIN).body(body_text))
|
.singlepart(SinglePart::builder().header(header::ContentType::TEXT_PLAIN).body(body_text))
|
||||||
.singlepart(SinglePart::builder().header(header::ContentType::TEXT_HTML).body(html.into_string())),
|
.singlepart(SinglePart::builder().header(header::ContentType::TEXT_HTML).body(html.into_string())),
|
||||||
|
@ -279,22 +283,40 @@ pub mod link {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod link_docs {
|
||||||
|
use super::*;
|
||||||
|
pub mod users {
|
||||||
|
use super::*;
|
||||||
|
use serenity::all::CommandInteraction;
|
||||||
|
|
||||||
|
pub async fn run(_command: &CommandInteraction, _ctx: &Context) -> String {
|
||||||
|
"https://forgejo.skynet.ie/Skynet/discord-bot/src/branch/main/doc/User.md".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub mod committee {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
pub mod verify {
|
pub mod verify {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::commands::wolves::link::{db_pending_clear_expired, get_server_member_discord, get_verify_from_db};
|
use crate::commands::wolves::link::{db_pending_clear_expired, get_server_member_discord, get_verify_from_db};
|
||||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, GuildId, RoleId};
|
use serenity::{
|
||||||
use serenity::model::user::User;
|
all::{CommandDataOption, CommandDataOptionValue, CommandInteraction},
|
||||||
use skynet_discord_bot::common::database::get_server_config;
|
model::user::User,
|
||||||
use skynet_discord_bot::common::database::{ServerMembersWolves, Servers};
|
};
|
||||||
use skynet_discord_bot::common::wolves::committees::Committees;
|
use skynet_discord_bot::common::{
|
||||||
|
database::{get_server_config, ServerMembersWolves, Servers},
|
||||||
|
wolves::committees::Committees,
|
||||||
|
};
|
||||||
use sqlx::Error;
|
use sqlx::Error;
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
// check if user has used /link_wolves
|
// check if user has used /link_wolves
|
||||||
let details = if let Some(x) = get_verify_from_db(&db, &command.user.id).await {
|
let details = if let Some(x) = get_verify_from_db(&db, &command.user.id).await {
|
||||||
|
@ -341,12 +363,12 @@ pub mod verify {
|
||||||
"Discord username linked to Wolves".to_string()
|
"Discord username linked to Wolves".to_string()
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
"Failed to save, please try /link_wolves again".to_string()
|
"Failed to save, please try /link_wolves again".to_string()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Err(e) => println!("{:?}", e),
|
Err(e) => println!("{e:?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
"Failed to verify".to_string()
|
"Failed to verify".to_string()
|
||||||
|
@ -403,7 +425,7 @@ pub mod verify {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = member.add_roles(&ctx, &roles).await {
|
if let Err(e) = member.add_roles(&ctx, &roles).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,7 +441,7 @@ pub mod verify {
|
||||||
WHERE committee LIKE ?1
|
WHERE committee LIKE ?1
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(format!("%{}%", wolves_id))
|
.bind(format!("%{wolves_id}%"))
|
||||||
.fetch_all(db)
|
.fetch_all(db)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
|
@ -429,12 +451,18 @@ pub mod verify {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_server_roles_committee(db: &Pool<Sqlite>, discord: &User, ctx: &Context) {
|
async fn set_server_roles_committee(db: &Pool<Sqlite>, discord: &User, ctx: &Context) {
|
||||||
|
let config_lock = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
let config = config_lock.read().await;
|
||||||
|
|
||||||
if let Some(x) = get_server_member_discord(db, &discord.id).await {
|
if let Some(x) = get_server_member_discord(db, &discord.id).await {
|
||||||
// if they are a member of one or more committees, and in teh committee server then give the teh general committee role
|
// if they are a member of one or more committees, and in teh committee server then give them the general committee role
|
||||||
// they will get teh more specific vanity role later
|
// they will get teh more specific vanity role later
|
||||||
if !get_committees_id(db, x.id_wolves).await.is_empty() {
|
if !get_committees_id(db, x.id_wolves).await.is_empty() {
|
||||||
let server = GuildId::new(1220150752656363520);
|
let server = config.committee_server;
|
||||||
let committee_member = RoleId::new(1226602779968274573);
|
let committee_member = config.committee_role;
|
||||||
|
|
||||||
if let Ok(member) = server.member(ctx, &discord.id).await {
|
if let Ok(member) = server.member(ctx, &discord.id).await {
|
||||||
member.add_roles(&ctx, &[committee_member]).await.unwrap_or_default();
|
member.add_roles(&ctx, &[committee_member]).await.unwrap_or_default();
|
||||||
|
@ -464,13 +492,12 @@ pub mod unlink {
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
// dosent matter if there is one or not, it will be removed regardless
|
// doesn't matter if there is one or not, it will be removed regardless
|
||||||
delete_link(&db, &command.user.id).await;
|
delete_link(&db, &command.user.id).await;
|
||||||
|
|
||||||
"Discord link removed".to_string()
|
"Discord link removed".to_string()
|
||||||
|
@ -516,4 +543,5 @@ pub fn register() -> CreateCommand {
|
||||||
.add_sub_option(CreateCommandOption::new(CommandOptionType::String, "minecraft_username", "Your Minecraft username").required(true))
|
.add_sub_option(CreateCommandOption::new(CommandOptionType::String, "minecraft_username", "Your Minecraft username").required(true))
|
||||||
.add_sub_option(CreateCommandOption::new(CommandOptionType::Boolean, "bedrock_account", "Is this a Bedrock account?").required(false)),
|
.add_sub_option(CreateCommandOption::new(CommandOptionType::Boolean, "bedrock_account", "Is this a Bedrock account?").required(false)),
|
||||||
)
|
)
|
||||||
|
.add_option(CreateCommandOption::new(CommandOptionType::SubCommand, "docs", "Link to where the documentation can be found."))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::model::guild;
|
use serenity::{
|
||||||
use serenity::model::id::{ChannelId, GuildId, RoleId, UserId};
|
model::{
|
||||||
use serenity::prelude::TypeMapKey;
|
guild,
|
||||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow};
|
id::{ChannelId, GuildId, RoleId, UserId},
|
||||||
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
},
|
||||||
use std::str::FromStr;
|
prelude::TypeMapKey,
|
||||||
use std::sync::Arc;
|
};
|
||||||
use tokio::sync::RwLock;
|
use sqlx::{
|
||||||
|
sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow},
|
||||||
|
Error, FromRow, Pool, Row, Sqlite,
|
||||||
|
};
|
||||||
|
use std::{str::FromStr, sync::Arc};
|
||||||
|
|
||||||
pub struct DataBase;
|
pub struct DataBase;
|
||||||
impl TypeMapKey for DataBase {
|
impl TypeMapKey for DataBase {
|
||||||
type Value = Arc<RwLock<Pool<Sqlite>>>;
|
type Value = Arc<Pool<Sqlite>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
@ -220,7 +224,7 @@ pub async fn db_init(config: &Config) -> Result<Pool<Sqlite>, Error> {
|
||||||
let pool = SqlitePoolOptions::new()
|
let pool = SqlitePoolOptions::new()
|
||||||
.max_connections(5)
|
.max_connections(5)
|
||||||
.connect_with(
|
.connect_with(
|
||||||
SqliteConnectOptions::from_str(&format!("sqlite://{}", database))?
|
SqliteConnectOptions::from_str(&format!("sqlite://{database}"))?
|
||||||
.foreign_keys(true)
|
.foreign_keys(true)
|
||||||
.create_if_missing(true),
|
.create_if_missing(true),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use crate::common::set_roles::normal::get_server_member_bulk;
|
use crate::{common::set_roles::normal::get_server_member_bulk, Config};
|
||||||
use crate::Config;
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serenity::model::id::GuildId;
|
use serenity::model::id::GuildId;
|
||||||
use sqlx::sqlite::SqliteRow;
|
use sqlx::{sqlite::SqliteRow, Error, FromRow, Pool, Row, Sqlite};
|
||||||
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct Minecraft {
|
pub struct Minecraft {
|
||||||
|
@ -27,7 +24,7 @@ impl<'r> FromRow<'r, SqliteRow> for Minecraft {
|
||||||
/**
|
/**
|
||||||
loop through all members of server
|
loop through all members of server
|
||||||
get a list of folks with mc accounts that are members
|
get a list of folks with mc accounts that are members
|
||||||
and a list that arent members
|
and a list that aren't members
|
||||||
*/
|
*/
|
||||||
pub async fn update_server(server_id: &str, db: &Pool<Sqlite>, g_id: &GuildId, config: &Config) {
|
pub async fn update_server(server_id: &str, db: &Pool<Sqlite>, g_id: &GuildId, config: &Config) {
|
||||||
let mut usernames = vec![];
|
let mut usernames = vec![];
|
||||||
|
@ -112,7 +109,7 @@ pub async fn whitelist_wipe(server: &str, token: &str) {
|
||||||
};
|
};
|
||||||
post(&format!("{url_base}/files/delete"), &bearer, &deletion).await;
|
post(&format!("{url_base}/files/delete"), &bearer, &deletion).await;
|
||||||
|
|
||||||
// recreate teh file, passing in the type here so the compiler knows what type of vec it is
|
// recreate the file, passing in the type here so the compiler knows what type of Vec it is
|
||||||
post::<Vec<&str>>(&format!("{url_base}/files/write?file=%2Fwhitelist.json"), &bearer, &vec![]).await;
|
post::<Vec<&str>>(&format!("{url_base}/files/write?file=%2Fwhitelist.json"), &bearer, &vec![]).await;
|
||||||
|
|
||||||
// reload the whitelist
|
// reload the whitelist
|
||||||
|
@ -155,7 +152,7 @@ pub async fn get_minecraft_config_server(db: &Pool<Sqlite>, g_id: GuildId) -> Ve
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn whitelist_update(add: &Vec<(String, bool)>, server: &str, token: &str) {
|
pub async fn whitelist_update(add: &Vec<(String, bool)>, server: &str, token: &str) {
|
||||||
println!("Update whitelist for {}", server);
|
println!("Update whitelist for {server}");
|
||||||
let url_base = format!("https://panel.games.skynet.ie/api/client/servers/{server}");
|
let url_base = format!("https://panel.games.skynet.ie/api/client/servers/{server}");
|
||||||
let bearer = format!("Bearer {token}");
|
let bearer = format!("Bearer {token}");
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// this code is taken from https://github.com/MCorange99/svg2colored-png/tree/main
|
// this code is taken from https://github.com/MCorange99/svg2colored-png/tree/main
|
||||||
// I was unable to figure out how to use usvg myself so younked it from here.
|
// I was unable to figure out how to use usvg myself so yoinked it from here.
|
||||||
|
|
||||||
use std::ffi::OsStr;
|
use std::{
|
||||||
use std::path::{Path, PathBuf};
|
ffi::OsStr,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
// use clap::builder::OsStr;
|
|
||||||
use color_eyre::{eyre::bail, Result};
|
use color_eyre::{eyre::bail, Result};
|
||||||
use usvg_text_layout::TreeTextToPath;
|
use usvg_text_layout::TreeTextToPath;
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ pub struct Args {
|
||||||
/// Output folder where the PNG's will be placed
|
/// Output folder where the PNG's will be placed
|
||||||
pub output: PathBuf,
|
pub output: PathBuf,
|
||||||
|
|
||||||
/// Comma seperated colors that will be used in HEX Eg. 000000,ffffff
|
/// Comma separated colors that will be used in HEX Eg. 000000,ffffff
|
||||||
/// Can be like an object: black:000000,white:ffffff
|
/// Can be like an object: black:000000,white:ffffff
|
||||||
pub colors: String,
|
pub colors: String,
|
||||||
|
|
||||||
|
@ -177,7 +178,7 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_color(&self, svg: &str, color: &String) -> String {
|
fn set_color(&self, svg: &str, color: &String) -> String {
|
||||||
svg.replace("fill=\"currentColor\"", &format!("fill=\"#{}\"", color))
|
svg.replace("fill=\"currentColor\"", &format!("fill=\"#{color}\""))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_svg_data(&self, fi: &Path) -> Result<String> {
|
fn get_svg_data(&self, fi: &Path) -> Result<String> {
|
||||||
|
|
|
@ -114,7 +114,7 @@ pub mod update_icon {
|
||||||
|
|
||||||
/// Update the server icon, pulling from open governance.
|
/// Update the server icon, pulling from open governance.
|
||||||
pub async fn update_icon_main(ctx: &Context, db: &Pool<Sqlite>, config_global: &Config, config_toml_local: &ConfigTomlLocal) {
|
pub async fn update_icon_main(ctx: &Context, db: &Pool<Sqlite>, config_global: &Config, config_toml_local: &ConfigTomlLocal) {
|
||||||
let server = GuildId::new(689189992417067052);
|
let server = config_global.compsoc_server;
|
||||||
|
|
||||||
// clone repo into local folder
|
// clone repo into local folder
|
||||||
clone_repo(config_global, config_toml_local);
|
clone_repo(config_global, config_toml_local);
|
||||||
|
@ -191,6 +191,28 @@ pub mod update_icon {
|
||||||
{
|
{
|
||||||
dbg!(e);
|
dbg!(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Err(e) = Command::new("git")
|
||||||
|
// Install LFS for the repo
|
||||||
|
.arg("lfs")
|
||||||
|
.arg("install")
|
||||||
|
.current_dir(&folder)
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
dbg!(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = Command::new("git")
|
||||||
|
// clone the repo, gracefully "fails"
|
||||||
|
.arg("lfs")
|
||||||
|
.arg("pull")
|
||||||
|
.arg("origin")
|
||||||
|
.arg("main")
|
||||||
|
.current_dir(&folder)
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
dbg!(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_logos(config: &Config, config_toml: &ConfigToml) -> Vec<LogoData> {
|
fn get_logos(config: &Config, config_toml: &ConfigToml) -> Vec<LogoData> {
|
||||||
|
@ -259,7 +281,7 @@ pub mod update_icon {
|
||||||
|
|
||||||
// check if exists
|
// check if exists
|
||||||
if !path_new.exists() {
|
if !path_new.exists() {
|
||||||
// convert if it hasnt been converted already
|
// convert if it hasn't been converted already
|
||||||
match r.render(&path_local, &args) {
|
match r.render(&path_local, &args) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
|
@ -286,9 +308,19 @@ pub mod update_icon {
|
||||||
fn logos_filter(festival_data: &FestivalData, existing: Vec<LogoData>) -> Vec<LogoData> {
|
fn logos_filter(festival_data: &FestivalData, existing: Vec<LogoData>) -> Vec<LogoData> {
|
||||||
let mut filtered: Vec<LogoData> = vec![];
|
let mut filtered: Vec<LogoData> = vec![];
|
||||||
|
|
||||||
|
let allowed_files = vec![".png", ".jpeg", ".gif", ".svg"];
|
||||||
'outer: for logo in existing {
|
'outer: for logo in existing {
|
||||||
let name_lowercase0 = logo.name.to_ascii_lowercase();
|
let name_lowercase0 = logo.name.to_ascii_lowercase();
|
||||||
let name_lowercase = name_lowercase0.to_str().unwrap_or_default();
|
let name_lowercase = name_lowercase0.to_str().unwrap_or_default();
|
||||||
|
let mut allowed = false;
|
||||||
|
for allowed_type in &allowed_files {
|
||||||
|
if name_lowercase.ends_with(allowed_type) {
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if !festival_data.current.is_empty() {
|
if !festival_data.current.is_empty() {
|
||||||
// if its a current festival filter based on it
|
// if its a current festival filter based on it
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
pub mod normal {
|
pub mod normal {
|
||||||
use crate::common::database::{DataBase, ServerMembersWolves, Servers, Wolves};
|
use crate::{
|
||||||
use crate::get_now_iso;
|
common::database::{DataBase, ServerMembersWolves, Servers, Wolves},
|
||||||
use serenity::client::Context;
|
get_now_iso,
|
||||||
use serenity::model::id::{GuildId, RoleId, UserId};
|
};
|
||||||
|
use serenity::{
|
||||||
|
client::Context,
|
||||||
|
model::id::{GuildId, RoleId, UserId},
|
||||||
|
};
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
|
struct RolesChange {
|
||||||
|
total: i32,
|
||||||
|
new: i32,
|
||||||
|
current_add: i32,
|
||||||
|
current_rem: i32,
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &[UserId]) {
|
pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &[UserId]) {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let Servers {
|
let Servers {
|
||||||
server,
|
server,
|
||||||
role_past,
|
role_past,
|
||||||
|
@ -20,7 +29,12 @@ pub mod normal {
|
||||||
..
|
..
|
||||||
} = server;
|
} = server;
|
||||||
|
|
||||||
let mut roles_set = [0, 0, 0];
|
let mut roles_set = RolesChange {
|
||||||
|
total: 0,
|
||||||
|
new: 0,
|
||||||
|
current_add: 0,
|
||||||
|
current_rem: 0,
|
||||||
|
};
|
||||||
let mut members = vec![];
|
let mut members = vec![];
|
||||||
|
|
||||||
for member in get_server_member_bulk(&db, server).await {
|
for member in get_server_member_bulk(&db, server).await {
|
||||||
|
@ -32,28 +46,30 @@ pub mod normal {
|
||||||
|
|
||||||
if let Ok(x) = server.members(ctx, None, None).await {
|
if let Ok(x) = server.members(ctx, None, None).await {
|
||||||
for member in x {
|
for member in x {
|
||||||
// members_changed acts as an override to only deal with teh users in it
|
// members_changed acts as an override to only deal with the users in it
|
||||||
if !members_changed.is_empty() && !members_changed.contains(&member.user.id) {
|
if !members_changed.is_empty() && !members_changed.contains(&member.user.id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if members.contains(&member.user.id) {
|
if members.contains(&member.user.id) {
|
||||||
|
roles_set.total += 1;
|
||||||
|
|
||||||
let mut roles = vec![];
|
let mut roles = vec![];
|
||||||
|
|
||||||
if let Some(role) = &role_past {
|
if let Some(role) = &role_past {
|
||||||
if !member.roles.contains(role) {
|
if !member.roles.contains(role) {
|
||||||
roles_set[0] += 1;
|
roles_set.new += 1;
|
||||||
roles.push(role.to_owned());
|
roles.push(role.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !member.roles.contains(role_current) {
|
if !member.roles.contains(role_current) {
|
||||||
roles_set[1] += 1;
|
roles_set.current_add += 1;
|
||||||
roles.push(role_current.to_owned());
|
roles.push(role_current.to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = member.add_roles(ctx, &roles).await {
|
if let Err(e) = member.add_roles(ctx, &roles).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// old and never
|
// old and never
|
||||||
|
@ -65,16 +81,16 @@ pub mod normal {
|
||||||
}
|
}
|
||||||
|
|
||||||
if member.roles.contains(role_current) {
|
if member.roles.contains(role_current) {
|
||||||
roles_set[2] += 1;
|
roles_set.current_rem += 1;
|
||||||
// if theya re not a current member and have the role then remove it
|
// if they're not a current member and have the role then remove it
|
||||||
if let Err(e) = member.remove_role(ctx, role_current).await {
|
if let Err(e) = member.remove_role(ctx, role_current).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for role in remove_roles.iter().flatten() {
|
for role in remove_roles.iter().flatten() {
|
||||||
if let Err(e) = member.remove_role(ctx, role).await {
|
if let Err(e) = member.remove_role(ctx, role).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +99,14 @@ pub mod normal {
|
||||||
set_server_numbers(&db, server, members_all as i64, members.len() as i64).await;
|
set_server_numbers(&db, server, members_all as i64, members.len() as i64).await;
|
||||||
|
|
||||||
// small bit of logging to note changes over time
|
// small bit of logging to note changes over time
|
||||||
println!("{:?} Changes: New: +{}, Current: +{}/-{}", server.get(), roles_set[0], roles_set[1], roles_set[2]);
|
println!(
|
||||||
|
"{:?} Total: {} Changes: New: +{}, Current: +{}/-{}",
|
||||||
|
server.get(),
|
||||||
|
roles_set.total,
|
||||||
|
roles_set.new,
|
||||||
|
roles_set.current_add,
|
||||||
|
roles_set.current_rem
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_server_member_bulk(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
pub async fn get_server_member_bulk(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
||||||
|
@ -123,7 +146,7 @@ pub mod normal {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failure to insert into {}", server.get());
|
println!("Failure to insert into {}", server.get());
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,58 +154,56 @@ pub mod normal {
|
||||||
|
|
||||||
// for updating committee members
|
// for updating committee members
|
||||||
pub mod committee {
|
pub mod committee {
|
||||||
use crate::common::database::{get_channel_from_row, get_role_from_row, DataBase, Wolves};
|
use crate::{
|
||||||
use crate::common::wolves::committees::Committees;
|
common::{
|
||||||
use crate::Config;
|
database::{get_channel_from_row, get_role_from_row, DataBase, Wolves},
|
||||||
|
wolves::committees::Committees,
|
||||||
|
},
|
||||||
|
Config,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::all::{EditRole, GuildId};
|
use serenity::{
|
||||||
use serenity::builder::CreateChannel;
|
all::EditRole,
|
||||||
use serenity::client::Context;
|
builder::CreateChannel,
|
||||||
use serenity::model::channel::ChannelType;
|
client::Context,
|
||||||
use serenity::model::guild::Member;
|
model::{channel::ChannelType, guild::Member, id::ChannelId, prelude::RoleId},
|
||||||
use serenity::model::id::ChannelId;
|
};
|
||||||
use serenity::model::prelude::RoleId;
|
use sqlx::{sqlite::SqliteRow, Error, FromRow, Pool, Row, Sqlite};
|
||||||
use sqlx::sqlite::SqliteRow;
|
|
||||||
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub async fn check_committee(ctx: Arc<Context>) {
|
pub async fn check_committee(ctx: &Context) {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let config_global = config_lock.read().await;
|
let config_global = config_lock.read().await;
|
||||||
|
|
||||||
let server = GuildId::new(1220150752656363520);
|
let server = config_global.committee_server;
|
||||||
|
|
||||||
// because to use it to update a single user we need to pre-get the members of teh server
|
// because to use it to update a single user we need to pre-get the members of teh server
|
||||||
let mut members = server.members(&ctx, None, None).await.unwrap_or_default();
|
let mut members = server.members(&ctx, None, None).await.unwrap_or_default();
|
||||||
|
|
||||||
update_committees(&db, &ctx, &config_global, &mut members).await;
|
update_committees(&db, ctx, &config_global, &mut members).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function can take a vec of members (or just one) and gives tehm the appropiate roles on teh committee server
|
This function can take a Vec of members (or just one) and gives them the appropriate roles on teh committee server
|
||||||
*/
|
*/
|
||||||
pub async fn update_committees(db: &Pool<Sqlite>, ctx: &Context, _config: &Config, members: &mut Vec<Member>) {
|
pub async fn update_committees(db: &Pool<Sqlite>, ctx: &Context, config: &Config, members: &mut Vec<Member>) {
|
||||||
let server = GuildId::new(1220150752656363520);
|
let server = config.committee_server;
|
||||||
let committee_member = RoleId::new(1226602779968274573);
|
let committee_member = config.committee_role;
|
||||||
let committees = get_committees(db).await;
|
let committees = match get_committees(db).await {
|
||||||
let categories = [
|
None => {
|
||||||
ChannelId::new(1226606560973815839),
|
return;
|
||||||
// C&S Chats 2
|
}
|
||||||
ChannelId::new(1341457244973305927),
|
Some(x) => x,
|
||||||
// C&S Chats 3
|
};
|
||||||
ChannelId::new(1341457509717639279),
|
let categories = config.committee_category.clone();
|
||||||
];
|
|
||||||
|
|
||||||
// information about the server
|
// information about the server
|
||||||
let mut roles_db = HashMap::new();
|
let mut roles_db = HashMap::new();
|
||||||
|
@ -203,11 +224,11 @@ pub mod committee {
|
||||||
|
|
||||||
let mut channels = server.channels(&ctx).await.unwrap_or_default();
|
let mut channels = server.channels(&ctx).await.unwrap_or_default();
|
||||||
|
|
||||||
// a map of users and the roles they are goign to be getting
|
// a map of users and the roles they are going to be getting
|
||||||
let mut users_roles = HashMap::new();
|
let mut users_roles = HashMap::new();
|
||||||
|
|
||||||
let mut re_order = false;
|
let mut re_order = false;
|
||||||
// we need to create roles and channels if tehy dont already exist
|
// we need to create roles and channels if they don't already exist
|
||||||
let mut category_index = 0;
|
let mut category_index = 0;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
|
@ -308,21 +329,21 @@ pub mod committee {
|
||||||
|
|
||||||
// now we have a map of all users that should get roles time to go through all the folks on teh server
|
// now we have a map of all users that should get roles time to go through all the folks on teh server
|
||||||
for member in members {
|
for member in members {
|
||||||
|
// if member.user.id != 136522490632601600 {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
let roles_current = member.roles(ctx).unwrap_or_default();
|
let roles_current = member.roles(ctx).unwrap_or_default();
|
||||||
|
|
||||||
let roles_required = match users_roles.get(&member.user.id) {
|
let roles_required = match users_roles.get(&member.user.id) {
|
||||||
None => {
|
None => {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
Some(x) => {
|
Some(x) => x.to_owned(),
|
||||||
let mut tmp = x.to_owned();
|
|
||||||
if !tmp.is_empty() {
|
|
||||||
tmp.push(committee_member);
|
|
||||||
}
|
|
||||||
tmp
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let on_committee = !roles_required.is_empty();
|
||||||
|
|
||||||
let mut roles_rem = vec![];
|
let mut roles_rem = vec![];
|
||||||
let mut roles_add = vec![];
|
let mut roles_add = vec![];
|
||||||
// get a list of all the roles to remove from someone
|
// get a list of all the roles to remove from someone
|
||||||
|
@ -331,14 +352,25 @@ pub mod committee {
|
||||||
for role in &roles_current {
|
for role in &roles_current {
|
||||||
roles_current_id.push(role.id.to_owned());
|
roles_current_id.push(role.id.to_owned());
|
||||||
if !roles_required.contains(&role.id) {
|
if !roles_required.contains(&role.id) {
|
||||||
|
if role.id == committee_member && on_committee {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
roles_rem.push(role.id.to_owned());
|
roles_rem.push(role.id.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !roles_required.is_empty() {
|
let has_committee_role = roles_current_id.contains(&committee_member);
|
||||||
// if there are committee roles then give the general purporse role
|
|
||||||
roles_add.push(committee_member);
|
|
||||||
|
|
||||||
|
if on_committee && !has_committee_role {
|
||||||
|
// if there are committee roles then give the general purpose role
|
||||||
|
roles_add.push(committee_member);
|
||||||
|
}
|
||||||
|
if !on_committee && has_committee_role {
|
||||||
|
roles_rem.push(committee_member);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !roles_required.is_empty() {
|
||||||
if let Some(x) = roles_db.get_mut(&0) {
|
if let Some(x) = roles_db.get_mut(&0) {
|
||||||
x.count += 1;
|
x.count += 1;
|
||||||
}
|
}
|
||||||
|
@ -357,8 +389,6 @@ pub mod committee {
|
||||||
if !roles_add.is_empty() {
|
if !roles_add.is_empty() {
|
||||||
// these roles are flavor roles, only there to make folks mentionable
|
// these roles are flavor roles, only there to make folks mentionable
|
||||||
member.add_roles(&ctx, &roles_add).await.unwrap_or_default();
|
member.add_roles(&ctx, &roles_add).await.unwrap_or_default();
|
||||||
} else {
|
|
||||||
member.remove_roles(&ctx, &[committee_member]).await.unwrap_or_default();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,10 +436,10 @@ pub mod committee {
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct CommitteeRoles {
|
pub struct CommitteeRoles {
|
||||||
id_wolves: i64,
|
id_wolves: i64,
|
||||||
id_role: RoleId,
|
pub id_role: RoleId,
|
||||||
id_channel: ChannelId,
|
pub id_channel: ChannelId,
|
||||||
pub name_role: String,
|
pub name_role: String,
|
||||||
name_channel: String,
|
pub name_channel: String,
|
||||||
pub count: i64,
|
pub count: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,8 +476,8 @@ pub mod committee {
|
||||||
{
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failure to insert into Wolves {:?}", role);
|
println!("Failure to insert into Wolves {role:?}");
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,13 +494,13 @@ pub mod committee {
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
println!("Failure to get Roles from committee_roles");
|
println!("Failure to get Roles from committee_roles");
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
vec![]
|
vec![]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_committees(db: &Pool<Sqlite>) -> Vec<Committees> {
|
pub async fn get_committees(db: &Pool<Sqlite>) -> Option<Vec<Committees>> {
|
||||||
sqlx::query_as::<_, Committees>(
|
match sqlx::query_as::<_, Committees>(
|
||||||
r#"
|
r#"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM committees
|
FROM committees
|
||||||
|
@ -478,10 +508,13 @@ pub mod committee {
|
||||||
)
|
)
|
||||||
.fetch_all(db)
|
.fetch_all(db)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| {
|
{
|
||||||
|
Ok(x) => Some(x),
|
||||||
|
Err(e) => {
|
||||||
dbg!(e);
|
dbg!(e);
|
||||||
vec![]
|
None
|
||||||
})
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_server_member_discord(db: &Pool<Sqlite>, user: &i64) -> Option<Wolves> {
|
async fn get_server_member_discord(db: &Pool<Sqlite>, user: &i64) -> Option<Wolves> {
|
||||||
|
|
|
@ -38,8 +38,8 @@ async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesResultUserMin) {
|
||||||
{
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failure to insert into Wolves {:?}", user);
|
println!("Failure to insert into Wolves {user:?}");
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,12 +48,14 @@ async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesResultUserMin) {
|
||||||
This is getting data for Clubs and Socs
|
This is getting data for Clubs and Socs
|
||||||
*/
|
*/
|
||||||
pub mod cns {
|
pub mod cns {
|
||||||
use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers};
|
use crate::{
|
||||||
use crate::common::set_roles::normal::update_server;
|
common::{
|
||||||
use crate::common::wolves::{add_users_wolves, WolvesResultUserMin};
|
database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers},
|
||||||
use crate::Config;
|
wolves::{add_users_wolves, WolvesResultUserMin},
|
||||||
use serenity::client::Context;
|
},
|
||||||
use serenity::model::id::GuildId;
|
Config,
|
||||||
|
};
|
||||||
|
use serenity::{client::Context, model::id::GuildId};
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
@ -67,11 +69,10 @@ pub mod cns {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_wolves(ctx: &Context) {
|
pub async fn get_wolves(ctx: &Context) {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
|
@ -96,7 +97,6 @@ pub mod cns {
|
||||||
let existing = existing_tmp.iter().map(|data| (data.id_wolves, data)).collect::<BTreeMap<_, _>>();
|
let existing = existing_tmp.iter().map(|data| (data.id_wolves, data)).collect::<BTreeMap<_, _>>();
|
||||||
|
|
||||||
// list of users that need to be updated for this server
|
// list of users that need to be updated for this server
|
||||||
let mut user_to_update = vec![];
|
|
||||||
let mut server_name_tmp = None;
|
let mut server_name_tmp = None;
|
||||||
for user in wolves.get_members(wolves_api).await {
|
for user in wolves.get_members(wolves_api).await {
|
||||||
// dbg!(&user.committee);
|
// dbg!(&user.committee);
|
||||||
|
@ -115,10 +115,6 @@ pub mod cns {
|
||||||
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
||||||
if old.expiry != user.expiry {
|
if old.expiry != user.expiry {
|
||||||
add_users_server_members(&db, server, &user).await;
|
add_users_server_members(&db, server, &user).await;
|
||||||
|
|
||||||
if let Some(discord_id) = old.discord {
|
|
||||||
user_to_update.push(discord_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,9 +125,6 @@ pub mod cns {
|
||||||
set_server_member(&db, server, cs_id).await;
|
set_server_member(&db, server, cs_id).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !user_to_update.is_empty() {
|
|
||||||
update_server(ctx, &server_config, &[], &user_to_update).await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +144,7 @@ pub mod cns {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failure to set server name {}", server.get());
|
println!("Failure to set server name {}", server.get());
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +183,7 @@ pub mod cns {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failure to insert into ServerMembers {} {:?}", server.get(), user);
|
println!("Failure to insert into ServerMembers {} {:?}", server.get(), user);
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,8 +193,7 @@ pub mod cns {
|
||||||
Get and store the data on C&S committees
|
Get and store the data on C&S committees
|
||||||
*/
|
*/
|
||||||
pub mod committees {
|
pub mod committees {
|
||||||
use crate::common::database::DataBase;
|
use crate::{common::database::DataBase, Config};
|
||||||
use crate::Config;
|
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
|
@ -231,11 +223,10 @@ pub mod committees {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_cns(ctx: &Context) {
|
pub async fn get_cns(ctx: &Context) {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
|
@ -270,8 +261,8 @@ pub mod committees {
|
||||||
{
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failure to insert into Committees {:?}", committee);
|
println!("Failure to insert into Committees {committee:?}");
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/lib.rs
26
src/lib.rs
|
@ -3,8 +3,10 @@ pub mod common;
|
||||||
use chrono::{Datelike, SecondsFormat, Utc};
|
use chrono::{Datelike, SecondsFormat, Utc};
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use rand::{distr::Alphanumeric, rng, Rng};
|
use rand::{distr::Alphanumeric, rng, Rng};
|
||||||
use serenity::model::id::{ChannelId, GuildId, RoleId};
|
use serenity::{
|
||||||
use serenity::prelude::TypeMapKey;
|
model::id::{ChannelId, GuildId, RoleId},
|
||||||
|
prelude::TypeMapKey,
|
||||||
|
};
|
||||||
use std::{env, sync::Arc};
|
use std::{env, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
@ -32,7 +34,10 @@ pub struct Config {
|
||||||
// discord server for committee
|
// discord server for committee
|
||||||
pub committee_server: GuildId,
|
pub committee_server: GuildId,
|
||||||
pub committee_role: RoleId,
|
pub committee_role: RoleId,
|
||||||
pub committee_category: ChannelId,
|
pub committee_category: Vec<ChannelId>,
|
||||||
|
|
||||||
|
// items pertaining to CompSoc only
|
||||||
|
pub compsoc_server: GuildId,
|
||||||
}
|
}
|
||||||
impl TypeMapKey for Config {
|
impl TypeMapKey for Config {
|
||||||
type Value = Arc<RwLock<Config>>;
|
type Value = Arc<RwLock<Config>>;
|
||||||
|
@ -57,7 +62,8 @@ pub fn get_config() -> Config {
|
||||||
wolves_api: "".to_string(),
|
wolves_api: "".to_string(),
|
||||||
committee_server: GuildId::new(1),
|
committee_server: GuildId::new(1),
|
||||||
committee_role: RoleId::new(1),
|
committee_role: RoleId::new(1),
|
||||||
committee_category: ChannelId::new(1),
|
committee_category: vec![],
|
||||||
|
compsoc_server: GuildId::new(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(x) = env::var("DATABASE_HOME") {
|
if let Ok(x) = env::var("DATABASE_HOME") {
|
||||||
|
@ -99,14 +105,22 @@ pub fn get_config() -> Config {
|
||||||
config.committee_server = GuildId::new(x);
|
config.committee_server = GuildId::new(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(x) = env::var("COMMITTEE_DISCORD") {
|
if let Ok(x) = env::var("COMMITTEE_ROLE") {
|
||||||
if let Ok(x) = x.trim().parse::<u64>() {
|
if let Ok(x) = x.trim().parse::<u64>() {
|
||||||
config.committee_role = RoleId::new(x);
|
config.committee_role = RoleId::new(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(x) = env::var("COMMITTEE_CATEGORY") {
|
if let Ok(x) = env::var("COMMITTEE_CATEGORY") {
|
||||||
|
for part in x.split(',') {
|
||||||
|
if let Ok(x) = part.trim().parse::<u64>() {
|
||||||
|
config.committee_category.push(ChannelId::new(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(x) = env::var("COMPSOC_DISCORD") {
|
||||||
if let Ok(x) = x.trim().parse::<u64>() {
|
if let Ok(x) = x.trim().parse::<u64>() {
|
||||||
config.committee_category = ChannelId::new(x);
|
config.compsoc_server = GuildId::new(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
77
src/main.rs
77
src/main.rs
|
@ -1,23 +1,28 @@
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
|
||||||
use crate::commands::role_adder::tools::on_role_change;
|
use crate::commands::role_adder::tools::on_role_change;
|
||||||
use serenity::all::{
|
|
||||||
ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, Interaction,
|
|
||||||
};
|
|
||||||
use serenity::model::guild::Member;
|
|
||||||
use serenity::{
|
use serenity::{
|
||||||
|
all::{Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, Interaction},
|
||||||
async_trait,
|
async_trait,
|
||||||
client::{Context, EventHandler},
|
client::{Context, EventHandler},
|
||||||
|
gateway::{ActivityData, ChunkGuildFilter},
|
||||||
model::{
|
model::{
|
||||||
|
event::GuildMemberUpdateEvent,
|
||||||
gateway::{GatewayIntents, Ready},
|
gateway::{GatewayIntents, Ready},
|
||||||
|
guild::Member,
|
||||||
|
id::GuildId,
|
||||||
user::OnlineStatus,
|
user::OnlineStatus,
|
||||||
},
|
},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_member, DataBase};
|
use skynet_discord_bot::{
|
||||||
use skynet_discord_bot::common::set_roles::committee::update_committees;
|
common::{
|
||||||
use skynet_discord_bot::common::wolves::committees::Committees;
|
database::{db_init, get_server_config, get_server_member, DataBase},
|
||||||
use skynet_discord_bot::{get_config, Config};
|
set_roles::committee::update_committees,
|
||||||
|
wolves::committees::Committees,
|
||||||
|
},
|
||||||
|
get_config, Config,
|
||||||
|
};
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
@ -26,15 +31,21 @@ struct Handler;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
|
// this caches members of all servers teh bot is in
|
||||||
|
async fn cache_ready(&self, ctx: Context, guilds: Vec<GuildId>) {
|
||||||
|
for guild in guilds {
|
||||||
|
ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None);
|
||||||
|
}
|
||||||
|
println!("Cache built successfully!");
|
||||||
|
}
|
||||||
|
|
||||||
// handles previously linked accounts joining the server
|
// handles previously linked accounts joining the server
|
||||||
async fn guild_member_addition(&self, ctx: Context, new_member: Member) {
|
async fn guild_member_addition(&self, ctx: Context, new_member: Member) {
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = db_lock.read().await;
|
|
||||||
|
|
||||||
let config_lock = {
|
let config_lock = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
@ -42,7 +53,7 @@ impl EventHandler for Handler {
|
||||||
let config_global = config_lock.read().await;
|
let config_global = config_lock.read().await;
|
||||||
|
|
||||||
// committee server takes priority
|
// committee server takes priority
|
||||||
let committee_server = GuildId::new(1220150752656363520);
|
let committee_server = config_global.committee_server;
|
||||||
if new_member.guild_id.get() == committee_server.get() {
|
if new_member.guild_id.get() == committee_server.get() {
|
||||||
let mut member = vec![new_member.clone()];
|
let mut member = vec![new_member.clone()];
|
||||||
update_committees(&db, &ctx, &config_global, &mut member).await;
|
update_committees(&db, &ctx, &config_global, &mut member).await;
|
||||||
|
@ -68,7 +79,7 @@ impl EventHandler for Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = new_member.add_roles(&ctx, &roles).await {
|
if let Err(e) = new_member.add_roles(&ctx, &roles).await {
|
||||||
println!("{:?}", e);
|
println!("{e:?}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let tmp = get_committee(&db, config_server.wolves_id).await;
|
let tmp = get_committee(&db, config_server.wolves_id).await;
|
||||||
|
@ -96,14 +107,12 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
|
||||||
// handles role updates
|
// handles role updates
|
||||||
async fn guild_member_update(&self, ctx: Context, _old_data: Option<Member>, new_data: Option<Member>, _: GuildMemberUpdateEvent) {
|
async fn guild_member_update(&self, ctx: Context, _old_data: Option<Member>, new_data: Option<Member>, _: GuildMemberUpdateEvent) {
|
||||||
// get config/db
|
// get config/db
|
||||||
let db_lock = {
|
let db = {
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
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 ones for this server
|
||||||
|
|
||||||
// check if the role changed is part of the oens for this server
|
|
||||||
if let Some(x) = new_data {
|
if let Some(x) = new_data {
|
||||||
on_role_change(&db, &ctx, x).await;
|
on_role_change(&db, &ctx, x).await;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +122,12 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
|
||||||
println!("[Main] {} is connected!", ready.user.name);
|
println!("[Main] {} is connected!", ready.user.name);
|
||||||
ctx.set_presence(Some(ActivityData::playing("with humanity's fate")), OnlineStatus::Online);
|
ctx.set_presence(Some(ActivityData::playing("with humanity's fate")), OnlineStatus::Online);
|
||||||
|
|
||||||
|
let config_lock = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
let config = config_lock.read().await;
|
||||||
|
|
||||||
match Command::set_global_commands(
|
match Command::set_global_commands(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
vec and go to https://discord.com/channels/{}/{} and use
|
||||||
{
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e)
|
println!("{e:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inter-Committee server
|
// Inter-Committee server
|
||||||
match GuildId::new(1220150752656363520)
|
match config.committee_server.set_commands(&ctx.http, vec![commands::count::committee::register()]).await {
|
||||||
.set_commands(&ctx.http, vec![commands::count::committee::register()])
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e)
|
println!("{e:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compsoc Server
|
// CompSoc Server
|
||||||
match GuildId::new(689189992417067052)
|
match config
|
||||||
|
.compsoc_server
|
||||||
.set_commands(
|
.set_commands(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
vec![
|
vec![
|
||||||
// commands just for the compsoc server
|
// commands just for the CompSoc server
|
||||||
commands::count::servers::register(),
|
commands::count::servers::register(),
|
||||||
commands::server_icon::user::register(),
|
commands::server_icon::user::register(),
|
||||||
],
|
],
|
||||||
|
@ -156,7 +169,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
|
||||||
{
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e)
|
println!("{e:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,6 +188,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
|
||||||
"verify" => commands::wolves::verify::run(&command, &ctx).await,
|
"verify" => commands::wolves::verify::run(&command, &ctx).await,
|
||||||
"unlink" => commands::wolves::unlink::run(&command, &ctx).await,
|
"unlink" => commands::wolves::unlink::run(&command, &ctx).await,
|
||||||
"link_minecraft" => commands::minecraft::user::add::run(&command, &ctx).await,
|
"link_minecraft" => commands::minecraft::user::add::run(&command, &ctx).await,
|
||||||
|
"docs" => commands::wolves::link_docs::users::run(&command, &ctx).await,
|
||||||
// "link" => commands::count::servers::run(&command, &ctx).await,
|
// "link" => commands::count::servers::run(&command, &ctx).await,
|
||||||
&_ => format!("not implemented :( wolves {}", x.name.as_str()),
|
&_ => format!("not implemented :( wolves {}", x.name.as_str()),
|
||||||
},
|
},
|
||||||
|
@ -242,7 +256,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(why) = command.edit_response(&ctx.http, EditInteractionResponse::new().content(content)).await {
|
if let Err(why) = command.edit_response(&ctx.http, EditInteractionResponse::new().content(content)).await {
|
||||||
println!("Cannot respond to slash command: {}", why);
|
println!("Cannot respond to slash command: {why}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +291,8 @@ async fn main() {
|
||||||
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
||||||
// Build our client.
|
// Build our client.
|
||||||
let mut client = Client::builder(&config.discord_token, intents)
|
let mut client = Client::builder(&config.discord_token, intents)
|
||||||
.event_handler(Handler {})
|
.event_handler(Handler)
|
||||||
|
.cache_settings(serenity::cache::Settings::default())
|
||||||
.await
|
.await
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
|
|
||||||
|
@ -285,7 +300,7 @@ async fn main() {
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||||
data.insert::<DataBase>(Arc::new(RwLock::new(db)));
|
data.insert::<DataBase>(Arc::new(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, start a single shard, and start listening to events.
|
// Finally, start a single shard, and start listening to events.
|
||||||
|
@ -293,6 +308,6 @@ async fn main() {
|
||||||
// Shards will automatically attempt to reconnect, and will perform
|
// Shards will automatically attempt to reconnect, and will perform
|
||||||
// exponential backoff until it reconnects.
|
// exponential backoff until it reconnects.
|
||||||
if let Err(why) = client.start().await {
|
if let Err(why) = client.start().await {
|
||||||
println!("Client error: {:?}", why);
|
println!("Client error: {why:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue