aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2021-06-24 15:06:43 -0700
committerFuwn <[email protected]>2021-06-24 15:06:43 -0700
commit2bccd50b7a11dda0ae239ce13efcdac118bfee92 (patch)
tree28f665461bb9746d70878071b11537d784a59842 /src
downloaddos-bot-2bccd50b7a11dda0ae239ce13efcdac118bfee92.tar.xz
dos-bot-2bccd50b7a11dda0ae239ce13efcdac118bfee92.zip
feat(dos-bot): :star:
Diffstat (limited to 'src')
-rw-r--r--src/commands.rs40
-rw-r--r--src/config.rs32
-rw-r--r--src/main.rs156
3 files changed, 228 insertions, 0 deletions
diff --git a/src/commands.rs b/src/commands.rs
new file mode 100644
index 0000000..086b6c3
--- /dev/null
+++ b/src/commands.rs
@@ -0,0 +1,40 @@
+// Copyright (C) 2021-2021 Fuwn
+// SPDX-License-Identifier: GPL-3.0-only
+
+use serenity::{
+ framework::standard::{macros::command, CommandResult},
+ model::prelude::*,
+ prelude::*,
+};
+
+#[command]
+pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
+ msg.channel_id.say(&ctx.http, "Pong!").await?;
+
+ Ok(())
+}
+
+#[command]
+pub async fn help(ctx: &Context, msg: &Message) -> CommandResult {
+ msg
+ .channel_id
+ .say(
+ &ctx.http,
+ r#"```
+ commands
+ ========
+
+help - you are here
+ping - pong!
+
+ information
+ ===========
+
+- https://github.com/fuwn/dos-bot
+- https://discord.io/assembly
+```"#,
+ )
+ .await?;
+
+ Ok(())
+}
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..afdba2d
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,32 @@
+// Copyright (C) 2021-2021 Fuwn
+// SPDX-License-Identifier: GPL-3.0-only
+
+use config::ConfigError;
+use serde_derive::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct RolesRole {
+ pub message: u64,
+ pub role: u64,
+}
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Config {
+ pub token: String,
+ pub roles: Vec<RolesRole>,
+}
+impl Config {
+ #[allow(future_prelude_collision)]
+ fn new() -> Result<Self, ConfigError> {
+ let mut c = config::Config::default();
+
+ c.merge(config::File::with_name(".dos-bot/config.json"))
+ .expect("unable to access configuration file");
+
+ c.try_into()
+ }
+
+ /// # Panics
+ /// if the configuration file is unable to be accessed.
+ #[must_use]
+ pub fn get() -> Self { Self::new().unwrap() }
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..333f9f9
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,156 @@
+// Copyright (C) 2021-2021 Fuwn
+// SPDX-License-Identifier: GPL-3.0-only
+
+#![feature(
+ type_ascription,
+ hash_set_entry,
+ type_name_of_val,
+ decl_macro,
+ proc_macro_hygiene
+)]
+#![deny(
+ warnings,
+ nonstandard_style,
+ unused,
+ future_incompatible,
+ rust_2018_idioms,
+ unsafe_code
+)]
+#![deny(clippy::all, clippy::nursery, clippy::pedantic)]
+#![recursion_limit = "128"]
+#![doc(
+ html_logo_url = "https://cdn.discordapp.com/icons/854071194453671976/bc8c80e4bcfa66ecd55da8ceaa80\
+ f5a8.webp?size=128",
+ html_favicon_url = "https://cdn.discordapp.com/icons/854071194453671976/bc8c80e4bcfa66ecd55da8cea\
+ a80f5a8.webp?size=128"
+)]
+
+pub mod commands;
+pub mod config;
+
+#[macro_use]
+extern crate log;
+
+use std::{collections::HashSet, sync::Arc};
+
+#[allow(clippy::wildcard_imports)]
+use commands::*;
+use serenity::{
+ async_trait,
+ client::bridge::gateway::{GatewayIntents, ShardManager},
+ framework::{standard::macros::group, StandardFramework},
+ http::Http,
+ model::{
+ channel::Reaction,
+ gateway::{Activity, Ready},
+ },
+ prelude::*,
+};
+
+use crate::config::Config;
+
+pub struct ShardManagerContainer;
+impl TypeMapKey for ShardManagerContainer {
+ type Value = Arc<Mutex<ShardManager>>;
+}
+
+struct Handler;
+#[async_trait]
+impl EventHandler for Handler {
+ async fn reaction_add(&self, ctx: Context, reaction: Reaction) {
+ if let Some(guild) = reaction.guild_id {
+ if let Some(c) = config::Config::get()
+ .roles
+ .iter()
+ .find(|x| x.message == reaction.message_id.0)
+ {
+ guild
+ .member(&ctx, reaction.user_id.expect("unable to locate user id"))
+ .await
+ .expect("unable to locate member")
+ .add_role(&ctx, c.role)
+ .await
+ .expect("unable to add role to member");
+ }
+ }
+ }
+
+ async fn reaction_remove(&self, ctx: Context, reaction: Reaction) {
+ if let Some(guild) = reaction.guild_id {
+ if let Some(c) = config::Config::get()
+ .roles
+ .iter()
+ .find(|x| x.message == reaction.message_id.0)
+ {
+ guild
+ .member(&ctx, reaction.user_id.expect("unable to locate user id"))
+ .await
+ .expect("unable to locate member")
+ .remove_role(&ctx, c.role)
+ .await
+ .expect("unable to add role to member");
+ }
+ }
+ }
+
+ async fn ready(&self, ctx: Context, ready: Ready) {
+ info!("connected to discord gateway as {}", ready.user.name);
+
+ ctx
+ .set_activity(Activity::watching(">help - discord.io/assembly"))
+ .await;
+ }
+}
+
+#[group]
+#[commands(ping, help)]
+struct General;
+
+#[tokio::main]
+async fn main() {
+ dotenv::dotenv().ok();
+
+ std::env::set_var("RUST_LOG", "dos_bot=info");
+ pretty_env_logger::init();
+
+ let http = Http::new_with_token(Config::get().token.as_str());
+
+ let (owners, _bot_id) = match http.get_current_application_info().await {
+ Ok(info) => {
+ let mut owners = HashSet::new();
+ owners.insert(info.owner.id);
+
+ (owners, info.id)
+ }
+ Err(why) => panic!("could not access application info: {:?}", why),
+ };
+
+ let framework = StandardFramework::new()
+ .configure(|c| c.owners(owners).prefix(">"))
+ .group(&GENERAL_GROUP);
+
+ let mut client = Client::builder(Config::get().token.as_str())
+ .framework(framework)
+ .event_handler(Handler)
+ .intents(GatewayIntents::all())
+ .await
+ .expect("error creating dos-bot");
+
+ {
+ let mut data = client.data.write().await;
+ data.insert::<ShardManagerContainer>(client.shard_manager.clone());
+ }
+
+ let shard_manager = client.shard_manager.clone();
+
+ tokio::spawn(async move {
+ tokio::signal::ctrl_c()
+ .await
+ .expect("could not register ctrl+c handler");
+ shard_manager.lock().await.shutdown_all().await;
+ });
+
+ if let Err(why) = client.start().await {
+ error!("client error: {:?}", why);
+ }
+}