diff --git a/Cargo.lock b/Cargo.lock index d472ec7..c0ae122 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1685,6 +1685,7 @@ dependencies = [ name = "mixer-discord-bot" version = "0.1.0" dependencies = [ + "entity", "image", "imageproc", "itertools 0.11.0", diff --git a/Cargo.toml b/Cargo.toml index 6f01547..16ebac0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,6 @@ members = [ "mixer-discord-bot", "migration", + "entity" ] default-members = ["mixer-discord-bot"] \ No newline at end of file diff --git a/entity/Cargo.toml b/entity/Cargo.toml new file mode 100644 index 0000000..991d9e3 --- /dev/null +++ b/entity/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "entity" +version = "0.1.0" +edition = "2021" + +[lib] +name = "entity" +path = "src/lib.rs" + +[dependencies] +sea-orm = "0.11.3" diff --git a/mixer-discord-bot/src/database/models/guild.rs b/entity/src/guilds.rs similarity index 56% rename from mixer-discord-bot/src/database/models/guild.rs rename to entity/src/guilds.rs index 2fb9f08..348a46b 100644 --- a/mixer-discord-bot/src/database/models/guild.rs +++ b/entity/src/guilds.rs @@ -1,17 +1,16 @@ use sea_orm::entity::prelude::*; -#[derive(Debug, Clone, Copy, Eq, PartialEq, DeriveEntityModel)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "guilds")] pub struct Model { - #[sea_orm(primary_key, auto_increment)] + #[sea_orm(primary_key)] pub id: i32, #[sea_orm(unique)] pub guild_id: i64, - #[sea_orm(default_value = false)] pub verified: bool, } -#[derive(Debug, EnumIter, DeriveRelation)] +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/lib.rs b/entity/src/lib.rs new file mode 100644 index 0000000..41769c3 --- /dev/null +++ b/entity/src/lib.rs @@ -0,0 +1,6 @@ +pub mod prelude; + +pub mod guilds; +pub mod lobbies; +pub mod players; +pub mod sea_orm_active_enums; diff --git a/mixer-discord-bot/src/database/models/lobby.rs b/entity/src/lobbies.rs similarity index 65% rename from mixer-discord-bot/src/database/models/lobby.rs rename to entity/src/lobbies.rs index a5d0a0d..50b5803 100644 --- a/mixer-discord-bot/src/database/models/lobby.rs +++ b/entity/src/lobbies.rs @@ -1,18 +1,17 @@ use sea_orm::entity::prelude::*; -#[derive(Debug, Clone, Copy, Eq, PartialEq, DeriveEntityModel)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "lobbies")] pub struct Model { - #[sea_orm(primary_key, auto_increment)] + #[sea_orm(primary_key)] pub id: i32, - pub guild_id: i64, pub main_voice_id: i64, pub red_team_voice_id: i64, pub blue_team_voice_id: i64, } -#[derive(Debug, EnumIter, DeriveRelation)] +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} diff --git a/mixer-discord-bot/src/database/models/player.rs b/entity/src/players.rs similarity index 59% rename from mixer-discord-bot/src/database/models/player.rs rename to entity/src/players.rs index 6e7abdc..bb9a1f1 100644 --- a/mixer-discord-bot/src/database/models/player.rs +++ b/entity/src/players.rs @@ -1,42 +1,34 @@ +use super::sea_orm_active_enums::Role; use sea_orm::entity::prelude::*; -use super::role::Role; - -#[derive(Debug, Clone, PartialEq, DeriveEntityModel)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] #[sea_orm(table_name = "players")] pub struct Model { - #[sea_orm(primary_key, auto_increment)] + #[sea_orm(primary_key)] pub id: i32, - #[sea_orm(unique)] pub discord_id: i64, pub bn_name: Option, pub bn_tag: Option, - pub last_played: Option, - - #[sea_orm(default_value = 2500.0)] + #[sea_orm(column_type = "Float")] pub tank_rating: f32, - #[sea_orm(default_value = 300.0)] + #[sea_orm(column_type = "Float")] pub tank_rd: f32, - #[sea_orm(default_value = 0.06)] + #[sea_orm(column_type = "Float")] pub tank_volatility: f32, - - #[sea_orm(default_value = 2500.0)] + #[sea_orm(column_type = "Float")] pub dps_rating: f32, - #[sea_orm(default_value = 300.0)] + #[sea_orm(column_type = "Float")] pub dps_rd: f32, - #[sea_orm(default_value = 0.06)] + #[sea_orm(column_type = "Float")] pub dps_volatility: f32, - - #[sea_orm(default_value = 2500.0)] + #[sea_orm(column_type = "Float")] pub support_rating: f32, - #[sea_orm(default_value = 300.0)] + #[sea_orm(column_type = "Float")] pub support_rd: f32, - #[sea_orm(default_value = 0.06)] + #[sea_orm(column_type = "Float")] pub support_volatility: f32, - - #[sea_orm(default_value = true)] pub flex: bool, pub primary_role: Option, pub secondary_role: Option, diff --git a/entity/src/prelude.rs b/entity/src/prelude.rs new file mode 100644 index 0000000..6fefefe --- /dev/null +++ b/entity/src/prelude.rs @@ -0,0 +1,4 @@ +pub use super::guilds::Entity as Guilds; +pub use super::lobbies::Entity as Lobbies; +pub use super::players::Entity as Players; +pub use super::sea_orm_active_enums::Role; diff --git a/entity/src/sea_orm_active_enums.rs b/entity/src/sea_orm_active_enums.rs new file mode 100644 index 0000000..d949d4a --- /dev/null +++ b/entity/src/sea_orm_active_enums.rs @@ -0,0 +1,35 @@ +use sea_orm::entity::prelude::*; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "role")] +pub enum Role { + #[sea_orm(string_value = "tank")] + Tank, + #[sea_orm(string_value = "dps")] + Dps, + #[sea_orm(string_value = "support")] + Support, +} + +impl TryFrom<&str> for Role { + type Error = String; + + fn try_from(val: &str) -> Result { + match val { + "tank" => Ok(Role::Tank), + "dps" => Ok(Role::Dps), + "support" => Ok(Role::Support), + _ => Err(format!("Unknown enum variant '{}'", val)), + } + } +} + +impl From<&Role> for i32 { + fn from(val: &Role) -> Self { + match val { + Role::Tank => 0, + Role::Dps => 1, + Role::Support => 2, + } + } +} diff --git a/mixer-discord-bot/Cargo.toml b/mixer-discord-bot/Cargo.toml index 6a061ef..a544b4a 100644 --- a/mixer-discord-bot/Cargo.toml +++ b/mixer-discord-bot/Cargo.toml @@ -5,12 +5,14 @@ edition = "2021" [dependencies] migration = { path = "../migration" } +entity = { path = "../entity" } +tokio = { version = "1.29.1", features = ["full"] } tracing = "0.1.37" -serenity = {version = "0.11.5", default-features = false, features = ["rustls_backend", "client", "gateway", "model", "cache", "collector", "utils"] } +serenity = {version = "0.11.6", default-features = false, features = ["rustls_backend", "client", "gateway", "model", "cache", "collector", "utils"] } sqlx = { version = "0.6.3", features = ["runtime-tokio-rustls", "postgres"] } sea-orm = { version = "0.11.3", features = ["sqlx-postgres", "runtime-tokio-rustls", "macros"] } -itertools = "0.10.5" +itertools = "0.11.0" shuttle-secrets = "0.20.0" shuttle-serenity = "0.20.0" shuttle-runtime = "0.20.0" diff --git a/mixer-discord-bot/src/bot/commands/lobby.rs b/mixer-discord-bot/src/bot/commands/lobby.rs index 9792262..254a555 100644 --- a/mixer-discord-bot/src/bot/commands/lobby.rs +++ b/mixer-discord-bot/src/bot/commands/lobby.rs @@ -18,14 +18,14 @@ use std::borrow::Cow; use std::time::Duration; use crate::bot::commands::MixerCommand; -use crate::database::models::lobby::Model; -use crate::database::models::role::Role; use crate::database::queries::prelude::*; use crate::database::DatabaseContainer; use crate::image_manipulation::ImageGeneratorContainer; use crate::mixer::mixer; use crate::mixer::player::Player; use crate::mixer::team::Team; +use entity::lobbies; +use entity::prelude::Role; #[derive(Clone)] pub struct LobbyCommand; @@ -296,7 +296,7 @@ impl LobbyCommand { &self, ctx: &Context, interaction: ApplicationCommandInteraction, - lobby: Model, + lobby: lobbies::Model, teams: (Team, Team), players: Vec, ) -> serenity::Result<()> { @@ -305,7 +305,7 @@ impl LobbyCommand { let team1_names = team1 .players .iter() - .sorted_by(|((a, _), _), ((b, _), _)| i32::from(*a).cmp(&i32::from(*b))) + .sorted_by(|((a, _), _), ((b, _), _)| i32::from(a).cmp(&i32::from(b))) .map(|(_, i)| async { if let Ok(user) = players[i.unwrap()].discord_id.to_user(ctx).await { user.name @@ -320,7 +320,7 @@ impl LobbyCommand { let team2_names = team2 .players .iter() - .sorted_by(|((a, _), _), ((b, _), _)| i32::from(*a).cmp(&i32::from(*b))) + .sorted_by(|((a, _), _), ((b, _), _)| i32::from(a).cmp(&i32::from(b))) .map(|(_, i)| async { if let Ok(user) = players[i.unwrap()].discord_id.to_user(ctx).await { user.name @@ -472,7 +472,7 @@ impl LobbyCommand { async fn process_valid_teams_start( &self, ctx: &Context, - lobby: Model, + lobby: lobbies::Model, team1: &Team, team2: &Team, players: Vec, diff --git a/mixer-discord-bot/src/bot/commands/preference.rs b/mixer-discord-bot/src/bot/commands/preference.rs index 4ee8f1d..339d277 100644 --- a/mixer-discord-bot/src/bot/commands/preference.rs +++ b/mixer-discord-bot/src/bot/commands/preference.rs @@ -9,9 +9,9 @@ use serenity::model::prelude::interaction::application_command::CommandDataOptio use serenity::model::Permissions; use crate::bot::commands::MixerCommand; -use crate::database::models::role::Role; use crate::database::queries::prelude::*; use crate::database::DatabaseContainer; +use entity::prelude::Role; #[derive(Clone)] pub struct PreferenceCommand; diff --git a/mixer-discord-bot/src/bot/commands/rating.rs b/mixer-discord-bot/src/bot/commands/rating.rs index 86c1f4c..dd0a2f1 100644 --- a/mixer-discord-bot/src/bot/commands/rating.rs +++ b/mixer-discord-bot/src/bot/commands/rating.rs @@ -9,10 +9,10 @@ use serenity::model::prelude::command::CommandOptionType; use serenity::model::Permissions; use crate::bot::commands::MixerCommand; -use crate::database::models::role::Role; use crate::database::queries::prelude::*; use crate::database::DatabaseContainer; use crate::mixer::rating::Rating; +use entity::prelude::Role; #[derive(Clone)] pub struct RatingCommand; @@ -163,7 +163,7 @@ impl MixerCommand for RatingCommand { .content(format!( "Setting rank for user <@{}> to {} {}", user.id, - String::from(role), + role, rating )) .allowed_mentions(|mentions| mentions.empty_users()) diff --git a/mixer-discord-bot/src/bot/commands/settings.rs b/mixer-discord-bot/src/bot/commands/settings.rs index e484b0e..1233395 100644 --- a/mixer-discord-bot/src/bot/commands/settings.rs +++ b/mixer-discord-bot/src/bot/commands/settings.rs @@ -11,7 +11,7 @@ use std::collections::hash_map::RandomState; use std::collections::HashMap; use crate::bot::commands::MixerCommand; -use crate::database::models::role::Role; +use entity::prelude::Role; pub struct SettingsCommand; diff --git a/mixer-discord-bot/src/database/mod.rs b/mixer-discord-bot/src/database/mod.rs index 1f7136d..cbb37da 100644 --- a/mixer-discord-bot/src/database/mod.rs +++ b/mixer-discord-bot/src/database/mod.rs @@ -1,4 +1,3 @@ -pub mod models; pub mod queries; use sea_orm::{DatabaseConnection, SqlxPostgresConnector}; diff --git a/mixer-discord-bot/src/database/models/mod.rs b/mixer-discord-bot/src/database/models/mod.rs deleted file mode 100644 index eb77d40..0000000 --- a/mixer-discord-bot/src/database/models/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub(super) mod prelude; - -pub mod guild; -pub mod lobby; -pub mod player; -pub mod role; diff --git a/mixer-discord-bot/src/database/models/prelude.rs b/mixer-discord-bot/src/database/models/prelude.rs deleted file mode 100644 index 3a304e6..0000000 --- a/mixer-discord-bot/src/database/models/prelude.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub use super::guild::Entity as Guilds; -pub use super::lobby::Entity as Lobbies; -pub use super::player::Entity as Players; diff --git a/mixer-discord-bot/src/database/models/role.rs b/mixer-discord-bot/src/database/models/role.rs deleted file mode 100644 index ba2c043..0000000 --- a/mixer-discord-bot/src/database/models/role.rs +++ /dev/null @@ -1,45 +0,0 @@ -use sea_orm::{DeriveActiveEnum, EnumIter}; - -#[derive(EnumIter, DeriveActiveEnum, Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "role")] -pub enum Role { - #[sea_orm(string_value = "tank")] - Tank, - #[sea_orm(string_value = "dps")] - Dps, - #[sea_orm(string_value = "support")] - Support, -} - -impl From for String { - fn from(role: Role) -> Self { - match role { - Role::Tank => "tank".to_string(), - Role::Dps => "dps".to_string(), - Role::Support => "support".to_string(), - } - } -} - -impl TryFrom<&str> for Role { - type Error = (); - - fn try_from(role: &str) -> Result { - match role { - "tank" => Ok(Role::Tank), - "dps" => Ok(Role::Dps), - "support" => Ok(Role::Support), - _ => Err(()), - } - } -} - -impl From for i32 { - fn from(role: Role) -> Self { - match role { - Role::Tank => 0, - Role::Dps => 1, - Role::Support => 2, - } - } -} diff --git a/mixer-discord-bot/src/database/queries/guild.rs b/mixer-discord-bot/src/database/queries/guild.rs index 93a6140..528be55 100644 --- a/mixer-discord-bot/src/database/queries/guild.rs +++ b/mixer-discord-bot/src/database/queries/guild.rs @@ -2,7 +2,8 @@ use sea_orm::prelude::*; use sea_orm::{DatabaseConnection, IntoActiveModel, Set}; use serenity::model::prelude::GuildId; -use crate::database::models::*; +use entity::guilds; +use entity::prelude::*; pub struct Query; @@ -10,14 +11,14 @@ impl Query { pub async fn create( connection: &DatabaseConnection, guild_id: GuildId, - ) -> Option { - let guild = guild::ActiveModel { + ) -> Option { + let guild = guilds::ActiveModel { guild_id: Set(guild_id.0 as i64), verified: Set(false), ..Default::default() }; - guild::Entity::insert(guild).exec(connection).await.ok()?; + Guilds::insert(guild).exec(connection).await.ok()?; Self::guild_by_guild_id(connection, guild_id).await } @@ -25,7 +26,7 @@ impl Query { pub async fn create_if_not_exists( connection: &DatabaseConnection, guild_id: GuildId, - ) -> Option { + ) -> Option { if let Some(guild) = Self::guild_by_guild_id(connection, guild_id).await { Some(guild) } else { @@ -36,9 +37,9 @@ impl Query { pub async fn guild_by_guild_id( connection: &DatabaseConnection, guild_id: GuildId, - ) -> Option { - guild::Entity::find() - .filter(guild::Column::GuildId.eq(guild_id.0 as i64)) + ) -> Option { + Guilds::find() + .filter(guilds::Column::GuildId.eq(guild_id.0 as i64)) .one(connection) .await .ok()? @@ -48,13 +49,13 @@ impl Query { connection: &DatabaseConnection, guild_id: GuildId, verified: bool, - ) -> Option { + ) -> Option { let mut guild = Query::guild_by_guild_id(connection, guild_id) .await? .into_active_model(); guild.verified = Set(verified); - guild::Entity::update(guild).exec(connection).await.ok() + Guilds::update(guild).exec(connection).await.ok() } } diff --git a/mixer-discord-bot/src/database/queries/lobby.rs b/mixer-discord-bot/src/database/queries/lobby.rs index eb738d2..f2394be 100644 --- a/mixer-discord-bot/src/database/queries/lobby.rs +++ b/mixer-discord-bot/src/database/queries/lobby.rs @@ -3,8 +3,8 @@ use sea_orm::ActiveValue::Set; use sea_orm::DatabaseConnection; use serenity::model::prelude::*; -use crate::database::models::prelude::*; -use crate::database::models::{self, lobby}; +use entity::lobbies; +use entity::prelude::*; pub struct Query; @@ -15,8 +15,8 @@ impl Query { main_voice_id: ChannelId, red_team_voice_id: ChannelId, blue_team_voice_id: ChannelId, - ) -> Option { - let lobby = models::lobby::ActiveModel { + ) -> Option { + let lobby = lobbies::ActiveModel { guild_id: Set(guild_id.0 as i64), main_voice_id: Set(main_voice_id.0 as i64), red_team_voice_id: Set(red_team_voice_id.0 as i64), @@ -33,14 +33,14 @@ impl Query { connection: &DatabaseConnection, guild_id: GuildId, channel_id: ChannelId, - ) -> Option { + ) -> Option { Lobbies::find() .filter( - lobby::Column::GuildId.eq(guild_id.0 as i64).and( - lobby::Column::MainVoiceId + lobbies::Column::GuildId.eq(guild_id.0 as i64).and( + lobbies::Column::MainVoiceId .eq(channel_id.0 as i64) - .or(lobby::Column::RedTeamVoiceId.eq(channel_id.0 as i64)) - .or(lobby::Column::BlueTeamVoiceId.eq(channel_id.0 as i64)), + .or(lobbies::Column::RedTeamVoiceId.eq(channel_id.0 as i64)) + .or(lobbies::Column::BlueTeamVoiceId.eq(channel_id.0 as i64)), ), ) .one(connection) diff --git a/mixer-discord-bot/src/database/queries/player.rs b/mixer-discord-bot/src/database/queries/player.rs index 7460779..f60ce18 100644 --- a/mixer-discord-bot/src/database/queries/player.rs +++ b/mixer-discord-bot/src/database/queries/player.rs @@ -3,20 +3,23 @@ use sea_orm::prelude::*; use sea_orm::{DatabaseConnection, IntoActiveModel, Set}; use serenity::model::prelude::UserId; -use crate::database::models::player; -use crate::database::models::role::Role; use crate::mixer::rating::Rating; +use entity::players; +use entity::prelude::*; pub struct Query; impl Query { - pub async fn create(connection: &DatabaseConnection, user_id: UserId) -> Option { - let player = player::ActiveModel { + pub async fn create( + connection: &DatabaseConnection, + user_id: UserId, + ) -> Option { + let player = players::ActiveModel { discord_id: Set(user_id.0 as i64), ..Default::default() }; - player::Entity::insert(player).exec(connection).await.ok()?; + Players::insert(player).exec(connection).await.ok()?; Self::player_by_user_id(connection, user_id).await } @@ -24,7 +27,7 @@ impl Query { pub async fn create_if_not_exists( connection: &DatabaseConnection, user_id: UserId, - ) -> Option { + ) -> Option { if let Some(player) = Self::player_by_user_id(connection, user_id).await { Some(player) } else { @@ -35,9 +38,9 @@ impl Query { pub async fn player_by_user_id( connection: &DatabaseConnection, user_id: UserId, - ) -> Option { - player::Entity::find() - .filter(player::Column::DiscordId.eq(user_id.0 as i64)) + ) -> Option { + Players::find() + .filter(players::Column::DiscordId.eq(user_id.0 as i64)) .one(connection) .await .ok()? @@ -46,10 +49,10 @@ impl Query { pub async fn players_by_user_ids( connection: &DatabaseConnection, user_ids: Vec, - ) -> Option> { - player::Entity::find() + ) -> Option> { + Players::find() .filter( - player::Column::DiscordId + players::Column::DiscordId .is_in(user_ids.iter().map(|id| id.0 as i64).collect_vec()), ) .all(connection) @@ -62,7 +65,7 @@ impl Query { user_id: UserId, role: Role, rating: Rating, - ) -> Option { + ) -> Option { let mut player = Self::player_by_user_id(connection, user_id) .await? .into_active_model(); @@ -85,7 +88,7 @@ impl Query { } } - player::Entity::update(player).exec(connection).await.ok() + Players::update(player).exec(connection).await.ok() } pub async fn update_preference( @@ -95,7 +98,7 @@ impl Query { primary: Option, secondary: Option, tertiary: Option, - ) -> Option { + ) -> Option { let mut player = Self::player_by_user_id(connection, user_id) .await? .into_active_model(); @@ -105,20 +108,20 @@ impl Query { player.secondary_role = Set(secondary); player.tertiary_role = Set(tertiary); - player::Entity::update(player).exec(connection).await.ok() + Players::update(player).exec(connection).await.ok() } pub async fn update_last_played( connection: &DatabaseConnection, user_id: UserId, last_played: DateTime, - ) -> Option { + ) -> Option { let mut player = Self::player_by_user_id(connection, user_id) .await? .into_active_model(); player.last_played = Set(Some(last_played)); - player::Entity::update(player).exec(connection).await.ok() + Players::update(player).exec(connection).await.ok() } } diff --git a/mixer-discord-bot/src/mixer/mixer.rs b/mixer-discord-bot/src/mixer/mixer.rs index 9feb36b..eb7d1e7 100644 --- a/mixer-discord-bot/src/mixer/mixer.rs +++ b/mixer-discord-bot/src/mixer/mixer.rs @@ -1,9 +1,9 @@ use itertools::Itertools; use std::cmp::Ordering; -use crate::database::models::role::Role; use crate::mixer::player::Player; use crate::mixer::team::Team; +use entity::prelude::Role; #[derive(Debug)] struct PlayerRoleEntry { diff --git a/mixer-discord-bot/src/mixer/player.rs b/mixer-discord-bot/src/mixer/player.rs index 8a6d1fd..23aa3a8 100644 --- a/mixer-discord-bot/src/mixer/player.rs +++ b/mixer-discord-bot/src/mixer/player.rs @@ -4,9 +4,9 @@ use serenity::model::id::UserId; use sqlx::types::chrono::Utc; use std::collections::HashMap; -use crate::database::models::player::Model; -use crate::database::models::role::Role; use crate::mixer::rating::Rating; +use entity::players; +use entity::prelude::Role; #[derive(Debug, Clone, PartialEq)] pub struct Player { @@ -22,7 +22,7 @@ pub struct Player { } impl Player { - pub fn new(model: Model) -> Self { + pub fn new(model: players::Model) -> Self { Self { id: model.id, discord_id: UserId::from(model.discord_id as u64), diff --git a/mixer-discord-bot/src/mixer/team.rs b/mixer-discord-bot/src/mixer/team.rs index 07bb10d..5c65865 100644 --- a/mixer-discord-bot/src/mixer/team.rs +++ b/mixer-discord-bot/src/mixer/team.rs @@ -1,9 +1,9 @@ use sea_orm::Iterable; use std::collections::HashMap; -use crate::database::models::role::Role; use crate::mixer::player::Player; use crate::mixer::rating::Rating; +use entity::prelude::Role; #[derive(Debug, Clone)] pub struct Team {