descriptions and pings, new yaml crate
This commit is contained in:
parent
bc9b9959c5
commit
bebc021a37
6 changed files with 179 additions and 106 deletions
99
Cargo.lock
generated
99
Cargo.lock
generated
|
|
@ -8,15 +8,6 @@ version = "2.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
|
|
@ -26,6 +17,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arraydeque"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
|
|
@ -85,9 +82,9 @@ version = "4.0.0-snapshot"
|
|||
dependencies = [
|
||||
"rand 0.9.2",
|
||||
"rusqlite",
|
||||
"rust-yaml",
|
||||
"serenity",
|
||||
"tokio",
|
||||
"yaml-rust2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -280,10 +277,13 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
|
|
@ -724,18 +724,6 @@ dependencies = [
|
|||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.1",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
|
|
@ -824,15 +812,6 @@ version = "2.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
|
|
@ -1135,35 +1114,6 @@ dependencies = [
|
|||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.28"
|
||||
|
|
@ -1235,18 +1185,6 @@ dependencies = [
|
|||
"sqlite-wasm-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-yaml"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22075c416a33b2fc18e6502b3836023436ca39b67cff4ae8300dffa12bc05dfc"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"indexmap",
|
||||
"memmap2",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
|
|
@ -2362,6 +2300,17 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust2"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "631a50d867fafb7093e709d75aaee9e0e0d5deb934021fcea25ac2fe09edc51e"
|
||||
dependencies = [
|
||||
"arraydeque",
|
||||
"encoding_rs",
|
||||
"hashlink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.1"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ version = "4.0.0-snapshot"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
rust-yaml = "0.0.5"
|
||||
yaml-rust2 = "0.11.0"
|
||||
rand = "0.9.2"
|
||||
rusqlite = { version = "0.38.0", features = [ "bundled" ] }
|
||||
tokio = { version = "1.49.0", features = [ "rt-multi-thread" ] }
|
||||
|
|
|
|||
|
|
@ -2,24 +2,19 @@ use rand::seq::SliceRandom;
|
|||
|
||||
fn parse_yaml(yaml: &String) -> Option<bracket_bot_v4::CreateBracketInfo> {
|
||||
|
||||
let content = rust_yaml::Yaml::new().load_str(&yaml).ok()?;
|
||||
let content = &yaml_rust2::YamlLoader::load_from_str(yaml).ok()?[0];
|
||||
|
||||
let bracket_name = String::from(content.get_str("name")?.as_str()?);
|
||||
let channel_id: u64 = content.get_str("channel_id")?.as_str()?.parse().ok()?;
|
||||
let role_id: u64 = content.get_str("role_id")?.as_str()?.parse().ok()?;
|
||||
let entries = content.get_str("entries")?.as_sequence()?;
|
||||
let bracket_name = String::from(content["name"].as_str()?);
|
||||
let channel_id: u64 = content["channel_id"].as_str()?.parse::<u64>().ok()?;
|
||||
let role_id: u64 = content["role_id"].as_str()?.parse::<u64>().ok()?;
|
||||
let entries = content["entries"].as_vec()?;
|
||||
|
||||
let mut entry_infos = Vec::new();
|
||||
for entry in entries {
|
||||
|
||||
let name = String::from(entry.get_str("name")?.as_str()?);
|
||||
let description = match entry.get_str("description") {
|
||||
None => None, Some(v) => Some(String::from(v.as_str()?)) };
|
||||
let emoji = match entry.get_str("emoji") {
|
||||
None => None, Some(v) => Some(String::from(v.as_str()?)) };
|
||||
|
||||
let name = String::from(entry["name"].as_str()?);
|
||||
let description = entry["description"].as_str().and_then(|s| Some(String::from(s)));
|
||||
let emoji= entry["emoji"].as_str().and_then(|s| Some(String::from(s)));
|
||||
entry_infos.push(bracket_bot_v4::CreateBracketEntryInfo { name, description, emoji });
|
||||
|
||||
}
|
||||
|
||||
entry_infos.shuffle(&mut rand::rng());
|
||||
|
|
|
|||
4
src/bin/gateway.rs
Normal file
4
src/bin/gateway.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#[tokio::main]
|
||||
async fn main() {
|
||||
bracket_bot_v4::run_gateway().await;
|
||||
}
|
||||
|
|
@ -40,4 +40,6 @@ async fn main() {
|
|||
bracket_bot_v4::post_poll(&mut dbc, &dc, bracket_id, channel_id, &poll).await;
|
||||
}
|
||||
|
||||
bracket_bot_v4::ping_bracket_role(&dbc, &dc, bracket_id, channel_id).await;
|
||||
|
||||
}
|
||||
|
|
|
|||
159
src/lib.rs
159
src/lib.rs
|
|
@ -21,7 +21,7 @@ pub struct CreateBracketInfo {
|
|||
pub bracket_name: String,
|
||||
pub channel_id: u64,
|
||||
pub role_id: u64,
|
||||
pub entries: Vec<CreateBracketEntryInfo>
|
||||
pub entries: Vec<CreateBracketEntryInfo>
|
||||
}
|
||||
|
||||
pub struct UnprocessedPoll {
|
||||
|
|
@ -127,19 +127,75 @@ async fn create_discord_conn_core(bot_token: &String)
|
|||
Ok(DiscordConn { client })
|
||||
}
|
||||
|
||||
pub async fn create_discord_conn() -> DiscordConn {
|
||||
fn get_token() -> String {
|
||||
let token = std::env::var("BOT_TOKEN");
|
||||
match token {
|
||||
Err(e) => {
|
||||
eprintln!("Could not get BOT_TOKEN variable: {e}");
|
||||
std::process::exit(1);
|
||||
},
|
||||
Ok(t) => {
|
||||
match create_discord_conn_core(&t).await {
|
||||
Ok(t) => t
|
||||
}
|
||||
}
|
||||
|
||||
struct GatewayHandler;
|
||||
|
||||
#[serenity::async_trait]
|
||||
impl serenity::client::EventHandler for GatewayHandler {
|
||||
|
||||
async fn interaction_create(
|
||||
&self, ctx: serenity::client::Context, interaction: serenity::model::application::Interaction) {
|
||||
|
||||
if let serenity::model::application::Interaction::Component(cpt) = interaction {
|
||||
let id = &cpt.data.custom_id;
|
||||
|
||||
if id.starts_with("toggle ") {
|
||||
|
||||
let role_id = serenity::model::id::RoleId::new(id[7..].parse::<u64>().unwrap());
|
||||
let guild_id = cpt.guild_id.unwrap();
|
||||
let member = guild_id.member(&ctx, cpt.user.id).await.unwrap();
|
||||
let removing = cpt.user.has_role(&ctx, guild_id, role_id).await.unwrap();
|
||||
|
||||
let result =
|
||||
if removing {
|
||||
member.remove_role(&ctx, role_id).await
|
||||
}
|
||||
else {
|
||||
member.add_role(&ctx, role_id).await
|
||||
};
|
||||
match result {
|
||||
Ok(()) => {}, Err(e) => {
|
||||
eprintln!("error toggling role {}: {}", role_id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut msg =
|
||||
serenity::builder::CreateInteractionResponseMessage::default();
|
||||
msg = msg.content(if removing { "Removed role." } else { "Added role." });
|
||||
msg = msg.ephemeral(true);
|
||||
let resp= serenity::builder::CreateInteractionResponse::Message(msg);
|
||||
cpt.create_response(&ctx, resp).await.unwrap();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn create_gateway_client() -> Result<serenity::Client, serenity::Error> {
|
||||
let intents = serenity::model::gateway::GatewayIntents::empty();
|
||||
let mut builder = serenity::Client::builder(get_token(), intents);
|
||||
builder = builder.event_handler(GatewayHandler);
|
||||
builder.await
|
||||
}
|
||||
|
||||
pub async fn create_discord_conn() -> DiscordConn {
|
||||
match create_discord_conn_core(&get_token()).await {
|
||||
Ok(dc) => dc, Err(e) => discord_error(&e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_bracket_core_discord(dc: &DiscordConn, info: &CreateBracketInfo) -> Result<(), serenity::Error> {
|
||||
|
|
@ -149,14 +205,14 @@ async fn create_bracket_core_discord(dc: &DiscordConn, info: &CreateBracketInfo)
|
|||
let mut message = serenity::builder::CreateMessage::new();
|
||||
message = message.content(format!("# Bracket: {}", info.bracket_name));
|
||||
|
||||
let mut button = serenity::builder::CreateButton::new(info.role_id.to_string());
|
||||
button = button.label("toggle pings");
|
||||
let button_id = String::from("toggle ") + &info.role_id.to_string();
|
||||
let mut button = serenity::builder::CreateButton::new(button_id);
|
||||
button = button.label("Toggle pings");
|
||||
|
||||
//message = message.button(button);
|
||||
message = message.button(button);
|
||||
|
||||
let sent = channel.send_message(&dc.client.http, message).await?;
|
||||
//sent.pin(&dc.client.http).await
|
||||
Ok(())
|
||||
sent.pin(&dc.client.http).await
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -405,7 +461,7 @@ pub fn get_channel_id(dbc: &mut DbConn, bracket_id: i32) -> u64 {
|
|||
}
|
||||
|
||||
fn go_to_next_round_core_db(dbc: &mut DbConn, bracket_id: i32)
|
||||
-> Result<(i32, Vec<String>), rusqlite::Error> {
|
||||
-> Result<(i32, Vec<String>, Option<String>), rusqlite::Error> {
|
||||
|
||||
let trans = dbc.conn.transaction()?;
|
||||
|
||||
|
|
@ -436,12 +492,23 @@ fn go_to_next_round_core_db(dbc: &mut DbConn, bracket_id: i32)
|
|||
last_entry_id = Some(row.get(0)?);
|
||||
}
|
||||
|
||||
let winner_description: Option<String> =
|
||||
if all_entries.len() == 1 {
|
||||
trans.query_one(
|
||||
"SELECT description FROM entries WHERE rowid = ?",
|
||||
(last_entry_id,),
|
||||
|r| r.get(0))?
|
||||
}
|
||||
else {
|
||||
None
|
||||
};
|
||||
|
||||
drop(rows);
|
||||
drop(statement);
|
||||
|
||||
if all_entries.len() == 1 {
|
||||
trans.commit()?;
|
||||
return Ok((next_round, all_entries));
|
||||
return Ok((next_round, all_entries, winner_description));
|
||||
}
|
||||
|
||||
if all_entries.len() % 2 == 1 {
|
||||
|
|
@ -451,13 +518,14 @@ fn go_to_next_round_core_db(dbc: &mut DbConn, bracket_id: i32)
|
|||
}
|
||||
|
||||
trans.commit()?;
|
||||
Ok((next_round, all_entries))
|
||||
Ok((next_round, all_entries, winner_description))
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async fn go_to_next_round_core_discord(dc: &DiscordConn, new_round: i32, channel_id: u64, names: &Vec<String>)
|
||||
async fn go_to_next_round_core_discord(
|
||||
dc: &DiscordConn, new_round: i32, channel_id: u64, names: &Vec<String>, winner_description: &Option<String>)
|
||||
-> Result<(), serenity::Error> {
|
||||
|
||||
if names.len() == 0 {
|
||||
|
|
@ -470,6 +538,11 @@ async fn go_to_next_round_core_discord(dc: &DiscordConn, new_round: i32, channel
|
|||
channel.say(
|
||||
&dc.client.http,
|
||||
format!("# WINNER: {}", names[0])).await?;
|
||||
if let Some(wd) = winner_description.as_ref() {
|
||||
channel.say(
|
||||
&dc.client.http,
|
||||
wd).await?;
|
||||
}
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -489,11 +562,11 @@ async fn go_to_next_round_core_discord(dc: &DiscordConn, new_round: i32, channel
|
|||
}
|
||||
|
||||
pub async fn go_to_next_round(dbc: &mut DbConn, dc: &DiscordConn, bracket_id: i32, channel_id: u64) {
|
||||
let (new_round, names) =
|
||||
let (new_round, names, winner_description) =
|
||||
match go_to_next_round_core_db(dbc, bracket_id) {
|
||||
Ok(t) => t, Err(e) => db_error(&e)
|
||||
};
|
||||
match go_to_next_round_core_discord(&dc, new_round, channel_id, &names).await {
|
||||
match go_to_next_round_core_discord(&dc, new_round, channel_id, &names, &winner_description).await {
|
||||
Ok(()) => {}, Err(e) => discord_error(&e)
|
||||
}
|
||||
}
|
||||
|
|
@ -539,7 +612,16 @@ fn create_poll_answer(entry: &EntryForPoll) -> serenity::builder::CreatePollAnsw
|
|||
|
||||
}
|
||||
|
||||
pub async fn post_poll_core_discord(
|
||||
async fn maybe_post_description(dc: &DiscordConn, channel_id: u64, description: &Option<String>)
|
||||
-> Result<(), serenity::Error> {
|
||||
if let Some(s) = description {
|
||||
let channel = serenity::model::id::ChannelId::new(channel_id);
|
||||
channel.say(&dc.client.http, s).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn post_poll_core_discord(
|
||||
dc: &DiscordConn, channel_id: u64, entry_1: &EntryForPoll, entry_2: &EntryForPoll)
|
||||
-> Result<PostedPoll, serenity::Error> {
|
||||
|
||||
|
|
@ -560,6 +642,8 @@ pub async fn post_poll_core_discord(
|
|||
message = message.poll(pollr);
|
||||
|
||||
let posted = channel.send_message(&dc.client.http, message).await?;
|
||||
maybe_post_description(dc, channel_id, &entry_1.description).await?;
|
||||
maybe_post_description(dc, channel_id, &entry_2.description).await?;
|
||||
|
||||
let mut answer_id_1: Option<i32> = None;
|
||||
let mut answer_id_2: Option<i32> = None;
|
||||
|
|
@ -617,3 +701,42 @@ pub async fn post_poll(dbc: &mut DbConn, dc: &DiscordConn, bracket_id: i32, chan
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
fn get_bracket_role(dbc: &DbConn, bracket_id: i32) -> Result<String, rusqlite::Error> {
|
||||
Ok(
|
||||
dbc.conn.query_one(
|
||||
"SELECT role_id FROM brackets WHERE rowid = ?",
|
||||
(bracket_id,),
|
||||
|r| r.get::<usize, String>(0))?)
|
||||
}
|
||||
|
||||
pub async fn ping_bracket_role(dbc: &DbConn, dc: &DiscordConn, bracket_id: i32, channel_id: u64) {
|
||||
|
||||
let role_id =
|
||||
match get_bracket_role(&dbc, bracket_id) {
|
||||
Ok(r) => r, Err(e) => db_error(&e)
|
||||
};
|
||||
|
||||
let mut m = serenity::builder::CreateAllowedMentions::new();
|
||||
m = m.all_roles(true);
|
||||
let mut msg = serenity::builder::CreateMessage::new();
|
||||
msg = msg.allowed_mentions(m);
|
||||
msg = msg.content(format!("<@&{}>", role_id));
|
||||
|
||||
let channel = serenity::model::id::ChannelId::new(channel_id);
|
||||
match channel.send_message(&dc.client.http, msg).await {
|
||||
Ok(_) => {}, Err(e) => discord_error(&e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn run_gateway_core() -> Result<(), serenity::Error> {
|
||||
let mut client = create_gateway_client().await?;
|
||||
client.start().await
|
||||
}
|
||||
|
||||
pub async fn run_gateway() {
|
||||
match run_gateway_core().await {
|
||||
Ok(()) => {}, Err(e) => discord_error(&e)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue