diff --git a/db/migrations/5_welcome-message.sql b/db/migrations/5_welcome-message.sql new file mode 100644 index 0000000..15a139c --- /dev/null +++ b/db/migrations/5_welcome-message.sql @@ -0,0 +1,5 @@ +-- temp table to allow folks to verify by committee email. +-- delete the col in teh server table +ALTER TABLE servers ADD COLUMN bot_channel_id integer DEFAULT 0; +ALTER TABLE servers ADD COLUMN server_name text NOT NULL; +ALTER TABLE servers ADD COLUMN wolves_link text NOT NULL; \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4e5db89..8cca5be 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.80" \ No newline at end of file +channel = "1.80" diff --git a/src/commands/add_server.rs b/src/commands/add_server.rs index e1e7ca4..e140283 100644 --- a/src/commands/add_server.rs +++ b/src/commands/add_server.rs @@ -39,18 +39,60 @@ pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> Stri .as_ref() .expect("Expected role object") { - Some(role.id.to_owned()) + role.id.to_owned() } else { return "Please provide a valid role for ``Role Current``".to_string(); }; let mut role_past = None; - if let Some(x) = command.data.options.get(2) { + if let Some(x) = command.data.options.get(5) { if let Some(CommandDataOptionValue::Role(role)) = &x.resolved { role_past = Some(role.id.to_owned()); } }; + let bot_channel_id = if let CommandDataOptionValue::Channel(channel) = command + .data + .options + .get(2) + .expect("Expected channel option") + .resolved + .as_ref() + .expect("Expected channel object") + { + channel.id.to_owned() + } else { + return "Please provide a valid channel for ``Bot Channel``".to_string(); + }; + + let server_name = if let CommandDataOptionValue::String(name) = command + .data + .options + .get(3) + .expect("Expected Server Name option") + .resolved + .as_ref() + .expect("Expected Server Name object") + { + name + } else { + &"UL Computer Society".to_string() + }; + + let wolves_link = if let CommandDataOptionValue::String(wolves) = command + .data + .options + .get(4) + .expect("Expected Wolves Link option") + .resolved + .as_ref() + .expect("Expected Server Name object") + { + wolves + } else { + &"https://ulwolves.ie/society/computer".to_string() + }; + let db_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() @@ -64,6 +106,9 @@ pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> Stri role_current, member_past: 0, member_current: 0, + bot_channel_id, + server_name: server_name.to_owned(), + wolves_link: wolves_link.to_string(), }; match add_server(&db, ctx, &server_data).await { @@ -95,6 +140,27 @@ pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicatio .kind(CommandOptionType::Role) .required(true) }) + .create_option(|option| { + option + .name("bot_channel") + .description("Safe space for folks to use the bot commands.") + .kind(CommandOptionType::Channel) + .required(true) + }) + .create_option(|option| { + option + .name("server_name") + .description("Name of the Discord Server.") + .kind(CommandOptionType::String) + .required(true) + }) + .create_option(|option| { + option + .name("wolves_link") + .description("Link to the Club/Society on UL Wolves.") + .kind(CommandOptionType::String) + .required(true) + }) .create_option(|option| { option .name("role_past") @@ -107,18 +173,20 @@ pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicatio async fn add_server(db: &Pool, ctx: &Context, server: &Servers) -> Result, Error> { let existing = get_server_config(db, &server.server).await; let role_past = server.role_past.map(|x| *x.as_u64() as i64); - let role_current = server.role_current.map(|x| *x.as_u64() as i64); let insert = sqlx::query_as::<_, Servers>( " - INSERT OR REPLACE INTO servers (server, wolves_api, role_past, role_current) - VALUES (?1, ?2, ?3, ?4) + INSERT OR REPLACE INTO servers (server, wolves_api, role_past, role_current, bot_channel_id, server_name, wolves_link) + VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7) ", ) .bind(*server.server.as_u64() as i64) .bind(&server.wolves_api) .bind(role_past) - .bind(role_current) + .bind(*server.role_current.as_u64() as i64) + .bind(*server.bot_channel_id.as_u64() as i64) + .bind(&server.server_name) + .bind(&server.wolves_link) .fetch_optional(db) .await; @@ -133,7 +201,7 @@ async fn add_server(db: &Pool, ctx: &Context, server: &Servers) -> Resul if x.role_current != server.role_current { result.0 = true; result.1 = true; - result.2 = x.role_current; + result.2 = Some(x.role_current); } if x.role_past != server.role_past { result.0 = true; diff --git a/src/commands/committee.rs b/src/commands/committee.rs index 3de0ec9..487171b 100644 --- a/src/commands/committee.rs +++ b/src/commands/committee.rs @@ -172,7 +172,7 @@ pub mod link { let creds = Credentials::new(config.mail_user.clone(), config.mail_pass.clone()); // Open a remote connection to gmail using STARTTLS - let mailer = SmtpTransport::starttls_relay(&config.mail_smtp).unwrap().credentials(creds).build(); + let mailer = SmtpTransport::starttls_relay(&config.mail_smtp)?.credentials(creds).build(); // Send the email mailer.send(&email) diff --git a/src/commands/link_email.rs b/src/commands/link_email.rs index 5a0fd26..e597ea3 100644 --- a/src/commands/link_email.rs +++ b/src/commands/link_email.rs @@ -184,7 +184,7 @@ pub mod link { let creds = Credentials::new(config.mail_user.clone(), config.mail_pass.clone()); // Open a remote connection to gmail using STARTTLS - let mailer = SmtpTransport::starttls_relay(&config.mail_smtp).unwrap().credentials(creds).build(); + let mailer = SmtpTransport::starttls_relay(&config.mail_smtp)?.credentials(creds).build(); // Send the email mailer.send(&email) @@ -352,10 +352,8 @@ pub mod verify { } } - if let Some(role) = &role_current { - if !member.roles.contains(role) { - roles.push(role.to_owned()); - } + if !member.roles.contains(&role_current) { + roles.push(role_current.to_owned()); } if let Err(e) = member.add_roles(&ctx, &roles).await { diff --git a/src/lib.rs b/src/lib.rs index c0d980a..abfc829 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use serenity::{ model::{ guild, - id::{GuildId, RoleId}, + id::{ChannelId, GuildId, RoleId}, }, prelude::TypeMapKey, }; @@ -228,9 +228,13 @@ pub struct Servers { pub server: GuildId, pub wolves_api: String, pub role_past: Option, - pub role_current: Option, + pub role_current: RoleId, pub member_past: i64, pub member_current: i64, + pub bot_channel_id: ChannelId, + // these can be removed in teh future with an API update + pub server_name: String, + pub wolves_link: String, } impl<'r> FromRow<'r, SqliteRow> for Servers { fn from_row(row: &'r SqliteRow) -> Result { @@ -250,15 +254,14 @@ impl<'r> FromRow<'r, SqliteRow> for Servers { let role_current = match row.try_get("role_current") { Ok(x) => { let tmp: i64 = x; - if tmp == 0 { - None - } else { - Some(RoleId::from(tmp as u64)) - } + RoleId::from(tmp as u64) } - _ => None, + _ => RoleId::from(0u64), }; + let bot_channel_tmp: i64 = row.try_get("bot_channel_id")?; + let bot_channel_id = ChannelId::from(bot_channel_tmp as u64); + Ok(Self { server, wolves_api: row.try_get("wolves_api")?, @@ -266,6 +269,9 @@ impl<'r> FromRow<'r, SqliteRow> for Servers { role_current, member_past: row.try_get("member_past")?, member_current: row.try_get("member_current")?, + bot_channel_id, + server_name: row.try_get("server_name")?, + wolves_link: row.try_get("wolves_link")?, }) } } @@ -300,7 +306,7 @@ pub async fn db_init(config: &Config) -> Result, Error> { .await?; // migrations are amazing! - sqlx::migrate!("./db/migrations").run(&pool).await.unwrap(); + sqlx::migrate!("./db/migrations").run(&pool).await?; Ok(pool) } @@ -403,11 +409,9 @@ pub mod set_roles { } } - if let Some(role) = &role_current { - if !member.roles.contains(role) { - roles_set[1] += 1; - roles.push(role.to_owned()); - } + if !member.roles.contains(role_current) { + roles_set[1] += 1; + roles.push(role_current.to_owned()); } if let Err(e) = member.add_roles(ctx, &roles).await { @@ -422,13 +426,11 @@ pub mod set_roles { } } - if let Some(role) = &role_current { - if member.roles.contains(role) { - roles_set[2] += 1; - // if theya re not a current member and have the role then remove it - if let Err(e) = member.remove_role(ctx, role).await { - println!("{:?}", e); - } + if member.roles.contains(role_current) { + roles_set[2] += 1; + // if theya re not a current member and have the role then remove it + if let Err(e) = member.remove_role(ctx, role_current).await { + println!("{:?}", e); } } } diff --git a/src/main.rs b/src/main.rs index cbe8d5d..316f31e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,8 @@ use serenity::{ application::{command::Command, interaction::Interaction}, gateway::{GatewayIntents, Ready}, guild, + prelude::Activity, + user::OnlineStatus, }, Client, }; @@ -40,20 +42,44 @@ impl EventHandler for Handler { } } - if let Some(role) = &config.role_current { - if !new_member.roles.contains(role) { - roles.push(role.to_owned()); - } + if !new_member.roles.contains(&config.role_current) { + roles.push(config.role_current.to_owned()); } if let Err(e) = new_member.add_roles(&ctx, &roles).await { println!("{:?}", e); } + } else { + let msg = format!( + r#" + Welcome {} to the {} server! + Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use ``/link_wolves`` to get full access. + "#, + new_member.display_name(), + &config.server_name, + &config.wolves_link, + &config.server, + &config.bot_channel_id + ); + // let msg = format!( + // "Welcome {} to the {} server! \n\ + // Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use ``/link_wolves`` to get full access.", + // new_member.display_name(), + // &config.server_name, + // &config.wolves_link, + // &config.server, + // &config.bot_channel_id + // ); + + if let Err(err) = new_member.user.direct_message(&ctx, |m| m.content(&msg)).await { + dbg!(err); + } } } async fn ready(&self, ctx: Context, ready: Ready) { println!("[Main] {} is connected!", ready.user.name); + ctx.set_presence(Some(Activity::playing("with humanity's fate")), OnlineStatus::Online).await; match Command::set_global_application_commands(&ctx.http, |commands| { commands