Skip to content

0.2 update #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 8 additions & 35 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ members = [
]

[dependencies]
tokio = {version = "1.17.0", features = ["full"]}
tokio = {version = "1.18.0", features = ["full"]}
dotenv = "0.15.0"
sea-orm = {version = "0.7.1", features = ["sqlx-postgres", "runtime-tokio-rustls", "macros"], default-features = false}
poise = "0.1.0"
Expand All @@ -30,4 +30,5 @@ serde = "1.0.136"
parking_lot = "0.12.0"
dateparser = "0.1.6"
hashbrown = "0.12.0"
uuid = { version = "0.8.2", features = ["v4"]}
uuid = { version = "0.8.2", features = ["v4"]}
anyhow = "1.0.57"
2 changes: 1 addition & 1 deletion entity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ path = "src/lib.rs"

[dependencies]
sea-orm = {version = "0.7.1", features = ["sqlx-postgres", "runtime-tokio-rustls", "macros"], default-features = false}
poise = {git = "https://github.com/kangalioo/poise"} # For slash command choice parameter derive macro
poise = "0.1.0" # For slash command choice parameter derive macro
parse-display = "0.5.5"
enum-iterator = "0.7.0"
strum = {version = "0.24.0", features = ["derive"]}
62 changes: 62 additions & 0 deletions src/commands/lobby/close_lobby.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use sea_orm::DbErr;
use uuid::Uuid;

use crate::{
check::is_guild_init, commands::lobby::helper::LobbyEvent, database::get_lobby, Context, Error,
};

#[poise::command(slash_command, guild_only, check = "is_guild_init")]
pub async fn close_lobby(
ctx: Context<'_>,
#[description = "ID of the lobby"] lobby_id: String,
) -> Result<(), Error> {
let guild_id = ctx.guild_id().unwrap().0;

let lobby_id = Uuid::parse_str(&lobby_id);
if let Err(_) = lobby_id {
ctx.say("Invalid lobby ID is given").await?;
return Ok(());
}

let lobby = get_lobby(lobby_id.unwrap(), ctx.data().db).await;

match lobby {
Ok(ref lobby) => {
if lobby.guild_id.parse::<u64>().unwrap() != guild_id {
ctx.say("Lobby doesn't belong to this guild.").await?;
return Ok(());
} else if !lobby.active {
ctx.say("Lobby is not active").await?;
return Ok(());
}
}
Err(DbErr::RecordNotFound(_)) => {
ctx.say("There is no lobby with the given ID").await?;
return Ok(());
}
Err(_) => {
ctx.say("A database error has occured. Try again.").await?;
return Ok(());
}
}

let lobby = lobby.unwrap();

let active_lobbies = ctx.data().active_lobbies.write();

let channel = match active_lobbies.get(&lobby.lobby_id.to_hyphenated().to_string()) {
Some(channel) => channel,
None => {
drop(active_lobbies);
ctx.say("Lobby is not tracked.").await?;
return Ok(());
}
};

if let Err(_) = channel.send(LobbyEvent::CloseLobby(ctx.data().active_lobbies.clone())) {
ctx.say("An error occured while setting the time.").await?;
return Ok(());
}

Ok(())
}
52 changes: 43 additions & 9 deletions src/commands/lobby/command.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{commands::lobby::context::LobbyContext, info::*, check::is_guild_init};
use crate::{check::is_guild_init, commands::lobby::context::LobbyContext, info::*};
use chrono::Utc;
use helper::*;
use parking_lot::RwLock;
use poise::{
Expand Down Expand Up @@ -143,10 +144,11 @@ pub async fn create_lobby(
state: State::ContentSelection,
content: None,
content_info: None,
lobby_time,
lobby_time: (lobby_time, None),
players: vec![],
active_players: vec![],
player_list: vec![],
http_client: ctx.discord().http.clone(),
}));

while let Some(mci) = CollectComponentInteraction::new(ctx.discord())
Expand Down Expand Up @@ -376,23 +378,55 @@ pub async fn create_lobby(
// I spent too much time thinking about this and i am not proud of it.

insert_lobby(&lobby_context_locked.read(), db).await?;
let (sender, mut reciever) = unbounded_channel::<EventComponent>();
ctx.data()
.active_lobbies
.write()
.insert(lobby_context_locked.read().id_as_string.clone(), sender);
let (sender, mut reciever) = unbounded_channel::<LobbyEvent>();
ctx.data().active_lobbies.write().insert(
lobby_context_locked.read().id_as_string.clone(),
sender.clone(),
);

println!(
"Inserted lobby id: {}",
lobby_context_locked.read().id_as_string
);

// It is the first time creating a timer task so second field is always None
if let Some(time) = lobby_context_locked.read().lobby_time.0 {
lobby_context_locked.write().lobby_time.1 = Some(tokio::spawn({
let channel = sender;
let lobby_context_locked = lobby_context_locked.clone();
let db = db;
let active_lobbies = ctx.data().active_lobbies.clone();
async move{
let time_left = time - Utc::now();
// We check the time range so unwrapping is okay
let time_left = std::time::Duration::from_millis(
time_left.num_milliseconds().try_into().unwrap(),
);

// Message the users when 10 mins left
tokio::time::sleep(time_left - std::time::Duration::from_secs(600)).await;

let _ = channel.send(LobbyEvent::LobbyIsDue);

tokio::time::sleep(std::time::Duration::from_secs(600)).await;

// Make lobby inactive
let lobby = get_lobby(lobby_context_locked.read().id, db).await;
if let Ok(ref lobby) = lobby {
let _ = disable_lobby(lobby, db).await;
}

active_lobbies.write().remove(&lobby_context_locked.read().id_as_string);
}
}))
}

// End the command context here and spawn a background task
tokio::spawn({
let db = ctx.data().db.clone();
async move {
while let Some(event_c) = reciever.recv().await {
match process_lobby_event(event_c, lobby_context_locked.clone(), &db).await {
while let Some(event) = reciever.recv().await {
match process_lobby_event(event, lobby_context_locked.clone(), &db).await {
Ok(_) => {}
Err(err) => {
println!("Error processing event: {err}")
Expand Down
21 changes: 18 additions & 3 deletions src/commands/lobby/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::sync::Arc;

use chrono::{DateTime, Utc};
use poise::serenity_prelude::{self as serenity, CreateSelectMenu};
use poise::serenity_prelude::{self as serenity, CreateSelectMenu, Http};
use poise::serenity_prelude::{CreateActionRow, CreateEmbed};
use sea_orm::DatabaseConnection;
use tokio::task::JoinHandle;

use super::command::State;
use super::helper::*;
Expand All @@ -26,10 +29,16 @@ pub struct LobbyContext {
pub state: State,
pub content: Option<LobbyContent>,
pub content_info: Option<&'static ContentInfo>,
pub lobby_time: Option<DateTime<Utc>>,
pub lobby_time: ( Option<DateTime<Utc>> , Option<JoinHandle<()>>),
pub players: Vec<entity::characters::Model>,
pub active_players: Vec<entity::characters::Model>,
pub player_list: Vec<String>,
// This field is added when I was writing lobby time change command.
// I don't know why I did not thought about doing this earlier
// (probably because I thought it was not necessary)
// but since this is added there is no need to send http client through channels
// and such. I will fix those things later.
pub http_client: Arc<Http>,
}

impl LobbyContext {
Expand Down Expand Up @@ -74,7 +83,7 @@ impl LobbyContext {
self.content_info().ilvl_req
),
format!("Scheduled time: {}", {
match self.lobby_time {
match self.lobby_time.0 {
Some(time) => format!("<t:{0}:R> (<t:{0}:F>)", time.timestamp()),
None => "Not Set".to_owned() + "",
}
Expand Down Expand Up @@ -234,4 +243,10 @@ impl LobbyContext {
}
false
}

pub fn drop_timebomb(&mut self) {
if let Some(task) = &self.lobby_time.1 {
task.abort()
}
}
}
Loading