Skip to content
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

Add giveaway command; #15

Open
wants to merge 3 commits into
base: main
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ sqlx = { version = "0.7.2", features = [
"json",
# "bigint",
] }
redis = "0.23.3"
11 changes: 11 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,18 @@ services:
- "5431:5432"
volumes:
- ./postgres_data:/var/lib/postgresql/data
redis:
image: "redis:latest"
container_name: redis
command: redis-server --requirepass mypassword
environment:
REDIS_PASSWORD: mypassword
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
networks:
backend:
7 changes: 7 additions & 0 deletions docs/00.docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Docs
this folder should be used for requirements, documentation and so on.
The convention used in this folder will be:
- `[0-9][0-9].[feature]-req.md` in case of requirement
- `[0-9][0-9].[document]-doc.md` in case of documentation

A bit overkill? Maybe, but I like the order
7 changes: 7 additions & 0 deletions docs/01.giveaway-req.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Giveaway
The giveaway command should be implemented with crons which should be set by the user through the command
`/giveaway n day`.
Crons will be saved into the database and at application startup should be retrieved
and resumed.
Eventually, all crons in the time of downtime of the bot should be delayed at the bot startup.
The crons should be saved on redis
57 changes: 57 additions & 0 deletions src/commands/giveaway.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::time::Duration;

use redis::Commands;
use serenity::{
client::Context,
framework::standard::{macros::command, Args, CommandResult},
model::channel::Message,
};
use sqlx::types::chrono::Local;

use crate::{commands::send_message, GlobalState};

#[command]
async fn giveaway(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let mut cloned_args = args.clone();
let message_content = cloned_args.quoted().message();
let vec_args = message_content.split_whitespace().collect::<Vec<&str>>();
let (number_str, unit) = vec_args.split_at(1);

let number: u64 = number_str[0].parse::<u64>().unwrap();
let now = Local::now();

let duration: u64 = match unit[0] {
"day" | "days" => Duration::as_secs(&Duration::new(number * 24 * 60 * 60, 0)),
"week" | "weeks" => Duration::as_secs(&Duration::new(number * 7 * 24 * 60 * 60, 0)),
_ => 0,
};

let schedule = now + Duration::new(duration, 0);
let data_read: tokio::sync::RwLockReadGuard<'_, serenity::prelude::TypeMap> =
ctx.data.read().await;
let timestamp_seconds =
schedule.timestamp() + (schedule.timestamp_subsec_nanos() as f64 / 1_000_000_000.0) as i64;

if let Some(global_state) = data_read.get::<GlobalState>() {
let mut redis_state = global_state.redis.lock().await;
let key = msg.guild_id.unwrap().0.to_string();
let _ = redis_state
.set::<String, String, String>(key.clone(), "OK".to_string())
.unwrap();
{
let redis_res: redis::RedisResult<i32> =
redis_state.expire_at(key, timestamp_seconds as usize);
match redis_res {
Ok(_) => println!("Key set and expired successfully"),
Err(e) => eprintln!("Error expiring key: {}", e),
}
}
}
let outgoing_msg = format!(
"event created with following schedule: {:?}",
schedule.to_string(),
);
send_message(ctx, msg, outgoing_msg).await;

Ok(())
}
1 change: 1 addition & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use serenity::{model::prelude::Message, prelude::Context};

pub mod giveaway;
pub mod help;
pub mod leaderboard;
pub mod multipliers;
Expand Down
3 changes: 2 additions & 1 deletion src/commands/set_text_multiplier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ async fn set_text_multiplier(ctx: &Context, msg: &Message, args: Args) -> Comman
.unwrap_or_default()
.parse::<i64>()
.unwrap();
let data_read = ctx.data.read().await;
let mut outgoing_msg: String =
"You don't have permissions to change text multiplier!".to_string();

let data_read: tokio::sync::RwLockReadGuard<'_, serenity::prelude::TypeMap> =
ctx.data.read().await;
if let Some(global_state) = data_read.get::<GlobalState>() {
let guild_state = global_state.guilds.lock().await;

Expand Down
11 changes: 9 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{collections::HashSet, env, sync::Arc};

use crate::commands::giveaway::GIVEAWAY_COMMAND;
use crate::commands::leaderboard::LEADERBOARD_COMMAND;
use crate::commands::multipliers::MULTIPLIERS_COMMAND;
use crate::commands::reset_scores::RESET_SCORES_COMMAND;
Expand Down Expand Up @@ -39,14 +40,16 @@ mod services;
reset_scores,
set_voice_multiplier,
set_text_multiplier,
multipliers
multipliers,
giveaway
)]
pub struct Bot;

pub struct GlobalStateInner {
guilds: Arc<Mutex<Arc<Guilds>>>,
users: Arc<Mutex<Arc<Users>>>,
pub active_users: Arc<Mutex<HashSet<i64>>>,
pub redis: Arc<Mutex<redis::Connection>>,
}

pub struct GlobalState {}
Expand Down Expand Up @@ -89,7 +92,6 @@ impl EventHandler for Handler {
for id in guild_ids {
let g = ctx.http.get_guild(id as u64).await;
match g {
// let http_ctx =
Ok(_) => {
if let Ok(channels) = g.unwrap().channels(&ctx.http).await {
for c in channels {
Expand Down Expand Up @@ -132,6 +134,10 @@ async fn main() {
.await
.unwrap();

// Redis settings
let redis_client = redis::Client::open("redis://:[email protected]:6379");
let con: redis::Connection = redis_client.unwrap().get_connection().unwrap();

// Discord settings
let token = env::var("DISCORD_TOKEN").expect("Expected a token for discord in the environment");
let intents = GatewayIntents::GUILD_MESSAGES
Expand Down Expand Up @@ -187,6 +193,7 @@ async fn main() {
guilds: guilds_pool,
users: users_pool,
active_users: Arc::new(Mutex::new(HashSet::new())),
redis: Arc::new(Mutex::new(con)),
})
.await
.expect("Error creating client");
Expand Down