initial commit
This commit is contained in:
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Intellij Idea
|
||||||
|
.idea
|
||||||
|
mixer_discord_bot.iml
|
||||||
|
|
||||||
|
# Rust
|
||||||
|
Cargo.lock
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Database
|
||||||
|
data.db
|
||||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "mixer_discord_bot"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio = { version = "*", features = ["full"] }
|
||||||
|
serenity = { version = "*", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
|
||||||
|
sqlx = { version = "*", features = ["runtime-tokio-rustls", "sqlite"] }
|
||||||
|
sea-orm = { version = "*", features = ["sqlx-sqlite", "runtime-tokio-rustls", "macros"] }
|
||||||
|
ctrlc = "*"
|
||||||
13
src/bot/commands/mod.rs
Normal file
13
src/bot/commands/mod.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
pub mod ping;
|
||||||
|
|
||||||
|
use serenity::builder::CreateApplicationCommand;
|
||||||
|
use serenity::client::Context;
|
||||||
|
use serenity::model::application::interaction::application_command::ApplicationCommandInteraction;
|
||||||
|
use serenity::async_trait;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait MixerCommand: Sync + Send {
|
||||||
|
fn name(&self) -> String;
|
||||||
|
fn create(&self, command: &mut CreateApplicationCommand);
|
||||||
|
async fn execute(&self, ctx: &Context, interaction: ApplicationCommandInteraction) -> serenity::Result<()>;
|
||||||
|
}
|
||||||
38
src/bot/commands/ping.rs
Normal file
38
src/bot/commands/ping.rs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
use serenity::builder::CreateApplicationCommand;
|
||||||
|
use serenity::client::Context;
|
||||||
|
use serenity::model::application::interaction::{
|
||||||
|
application_command::ApplicationCommandInteraction,
|
||||||
|
InteractionResponseType
|
||||||
|
};
|
||||||
|
use serenity::async_trait;
|
||||||
|
use crate::bot::commands::MixerCommand;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Ping;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl MixerCommand for Ping {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"ping".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, command: &mut CreateApplicationCommand) {
|
||||||
|
command.name(self.name()).description("Hello world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn execute(&self, ctx: &Context, interaction: ApplicationCommandInteraction) -> serenity::Result<()> {
|
||||||
|
let content = "Pong!";
|
||||||
|
interaction.create_interaction_response(&ctx.http, |response| {
|
||||||
|
response.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||||
|
.interaction_response_data(|message| {
|
||||||
|
message.content(content)
|
||||||
|
})
|
||||||
|
}).await?;
|
||||||
|
|
||||||
|
println!("{:#?}", interaction.get_interaction_response(&ctx.http).await?);
|
||||||
|
|
||||||
|
println!("Interacted");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/bot/handler.rs
Normal file
41
src/bot/handler.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use serenity::client::{Context, EventHandler};
|
||||||
|
use serenity::model::gateway::Ready;
|
||||||
|
use serenity::async_trait;
|
||||||
|
use serenity::model::application::command::Command;
|
||||||
|
use serenity::model::application::interaction::Interaction;
|
||||||
|
use crate::bot::MixerBotContainer;
|
||||||
|
|
||||||
|
pub struct Handler;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl EventHandler for Handler {
|
||||||
|
async fn ready(&self, ctx: Context, data_about_bot: Ready) {
|
||||||
|
println!("{} is connected!", data_about_bot.user.name);
|
||||||
|
|
||||||
|
let data = ctx.data.read().await;
|
||||||
|
let bot_commands = &data.get::<MixerBotContainer>().unwrap().read().await.commands;
|
||||||
|
Command::set_global_application_commands(&ctx.http, |commands| {
|
||||||
|
for cmd in bot_commands.values() {
|
||||||
|
commands.create_application_command(|command| {
|
||||||
|
cmd.create(command);
|
||||||
|
command
|
||||||
|
});
|
||||||
|
println!("Registered command \"{}\"", cmd.name())
|
||||||
|
}
|
||||||
|
commands
|
||||||
|
}).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||||
|
let data = ctx.data.read().await;
|
||||||
|
let bot_commands = &data.get::<MixerBotContainer>().unwrap().read().await.commands;
|
||||||
|
|
||||||
|
match interaction {
|
||||||
|
Interaction::ApplicationCommand(command) =>
|
||||||
|
if let Some(mixer_command) = bot_commands.get(&command.data.name) {
|
||||||
|
mixer_command.execute(&ctx, command).await.unwrap()
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/bot/mod.rs
Normal file
76
src/bot/mod.rs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
pub mod commands;
|
||||||
|
mod handler;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use serenity::{CacheAndHttp, Client};
|
||||||
|
use serenity::client::bridge::gateway::ShardManager;
|
||||||
|
use serenity::prelude::{GatewayIntents, TypeMap, TypeMapKey};
|
||||||
|
use tokio::sync::{Mutex, RwLock};
|
||||||
|
use crate::bot::commands::MixerCommand;
|
||||||
|
use crate::bot::handler::Handler;
|
||||||
|
|
||||||
|
pub struct MixerBot {
|
||||||
|
token: String,
|
||||||
|
commands: HashMap<String, Box<dyn MixerCommand>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ShardManagerContainer;
|
||||||
|
struct MixerBotContainer;
|
||||||
|
|
||||||
|
|
||||||
|
impl TypeMapKey for ShardManagerContainer {
|
||||||
|
type Value = Arc<Mutex<ShardManager>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeMapKey for MixerBotContainer {
|
||||||
|
type Value = Arc<RwLock<MixerBot>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl MixerBot {
|
||||||
|
pub fn new(token: String) -> Self {
|
||||||
|
Self {
|
||||||
|
token,
|
||||||
|
commands: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(self) -> serenity::Result<()> {
|
||||||
|
let mut client = Client::builder(&self.token, GatewayIntents::empty()).event_handler(Handler).await?;
|
||||||
|
|
||||||
|
let bot;
|
||||||
|
{
|
||||||
|
let mut data = client.data.write().await;
|
||||||
|
data.insert::<ShardManagerContainer>(client.shard_manager.clone());
|
||||||
|
data.insert::<MixerBotContainer>(Arc::new(RwLock::new(self)));
|
||||||
|
bot = data.get::<MixerBotContainer>().unwrap().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
let shard_manager = client.shard_manager.clone();
|
||||||
|
let cache_and_http = client.cache_and_http.clone();
|
||||||
|
let data = client.data.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
tokio::signal::ctrl_c().await.expect("Could not register ctrl+c handler");
|
||||||
|
|
||||||
|
bot.write().await.shutdown(data, cache_and_http).await;
|
||||||
|
|
||||||
|
shard_manager.lock().await.shutdown_all().await;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
client.start().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_command(&mut self, command: Box<dyn MixerCommand>) -> &mut Self {
|
||||||
|
self.commands.insert(command.name(), command);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn shutdown(&self, data: Arc<RwLock<TypeMap>>, cache_and_http: Arc<CacheAndHttp>) {
|
||||||
|
println!("{:#?}", cache_and_http.http);
|
||||||
|
println!("Bot has been shutdown.");
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main.rs
Normal file
17
src/main.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
mod bot;
|
||||||
|
|
||||||
|
use crate::bot::commands::ping::Ping;
|
||||||
|
use crate::bot::MixerBot;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> serenity::Result<()> {
|
||||||
|
let mut bot = MixerBot::new(
|
||||||
|
"NTE2MzMyMzM2NzQ5NzQwMDUz.GiLPzQ.j5gIUGqx6vF6CFhJv8yizksDi-dOBqCvxR32EE".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
bot.add_command(Box::new(Ping));
|
||||||
|
|
||||||
|
bot.start().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user