lol what are good commits
This commit is contained in:
parent
d543802181
commit
4b7a981a88
13 changed files with 189 additions and 112 deletions
49
Cargo.lock
generated
49
Cargo.lock
generated
|
@ -304,7 +304,10 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"clap",
|
||||
"dotenv",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rand",
|
||||
"regex",
|
||||
"serenity",
|
||||
|
@ -334,6 +337,19 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
|
@ -561,6 +577,15 @@ version = "1.3.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||
dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.13.5"
|
||||
|
@ -967,6 +992,12 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.3"
|
||||
|
@ -1401,6 +1432,15 @@ dependencies = [
|
|||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
|
@ -1799,6 +1839,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
|
@ -15,4 +15,7 @@ futures = "0.3"
|
|||
tokio = { version = "0.2", features = ["full"] }
|
||||
dotenv = "0.15"
|
||||
rand = "0.7"
|
||||
unicode-segmentation = "1.6.0"
|
||||
unicode-segmentation = "1.6"
|
||||
log = "0.4"
|
||||
env_logger = "0.7"
|
||||
lazy_static = "1.4"
|
|
@ -1,3 +1,4 @@
|
|||
use log::error;
|
||||
use serenity::framework::standard::{macros::command, Args, CommandResult};
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::prelude::Context;
|
||||
|
@ -6,7 +7,16 @@ use serenity::prelude::Context;
|
|||
async fn clap(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
let resp = match args
|
||||
.iter()
|
||||
.map(|e: Result<String, _>| e.unwrap())
|
||||
.map(|arg: Result<String, _>| match arg {
|
||||
Ok(arg) => arg,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to cast clap arg to String; returning empty string instead: {:?}",
|
||||
e
|
||||
);
|
||||
String::default()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice()
|
||||
{
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// This was directly ported from the Java version. I make no quality assurances.
|
||||
use serenity::framework::standard::{macros::command, Args, CommandResult};
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::prelude::Context;
|
||||
|
|
|
@ -7,10 +7,15 @@ use serenity::prelude::Context;
|
|||
async fn heck(ctx: &mut Context, msg: &Message) -> CommandResult {
|
||||
let db_pool = ctx.data.clone();
|
||||
let mut db_pool = db_pool.write().await;
|
||||
let db_pool = db_pool.get_mut::<DbConnPool>().unwrap();
|
||||
let db_pool = db_pool
|
||||
.get_mut::<DbConnPool>()
|
||||
.expect("No db pool in context?!");
|
||||
let value = db_pool.get_heck().await;
|
||||
msg.channel_id
|
||||
.say(ctx, format!("This command has been hecked {} times", value))
|
||||
.say(
|
||||
ctx,
|
||||
format!("This command has been hecked {} times", value?),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
|
47
src/main.rs
47
src/main.rs
|
@ -1,9 +1,12 @@
|
|||
use crate::commands::GENERAL_GROUP;
|
||||
use crate::passive::Handler;
|
||||
use serenity::client::Client;
|
||||
use env_logger;
|
||||
use log::error;
|
||||
use serenity::client::{validate_token, Client};
|
||||
use serenity::framework::standard::StandardFramework;
|
||||
use std::env;
|
||||
use util::db::DbConnPool;
|
||||
use util::error::KuranteError;
|
||||
|
||||
mod commands;
|
||||
mod passive;
|
||||
|
@ -12,28 +15,48 @@ mod util;
|
|||
pub(crate) const COMMAND_PREFIX: &str = "~";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
async fn main() {
|
||||
std::process::exit(match run().await {
|
||||
Ok(_) => 0,
|
||||
Err(_) => 1,
|
||||
});
|
||||
}
|
||||
|
||||
async fn run() -> Result<(), KuranteError> {
|
||||
// Init dotenv vars before the env logger
|
||||
dotenv::dotenv().ok();
|
||||
env_logger::init();
|
||||
|
||||
let framework = StandardFramework::new()
|
||||
.configure(|c| c.prefix(COMMAND_PREFIX))
|
||||
.group(&GENERAL_GROUP);
|
||||
|
||||
let mut client =
|
||||
Client::new_with_extras(&env::var("DISCORD_TOKEN").expect("token"), |extras| {
|
||||
extras
|
||||
.event_handler(Handler::default())
|
||||
.framework(framework)
|
||||
})
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
let token = match env::var("DISCORD_TOKEN") {
|
||||
Ok(token) => match validate_token(&token) {
|
||||
Ok(_) => token,
|
||||
Err(_) => {
|
||||
error!("Provided token was invalid.");
|
||||
return Err(KuranteError::InvalidToken);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("`DISCORD_TOKEN` environment variable was not set. Unable to start bot!");
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
|
||||
let mut client = Client::new_with_extras(token, |extras| {
|
||||
extras
|
||||
.event_handler(Handler::default())
|
||||
.framework(framework)
|
||||
})
|
||||
.await?;
|
||||
|
||||
{
|
||||
let mut data = client.data.write().await;
|
||||
data.insert::<DbConnPool>(DbConnPool::new().await);
|
||||
data.insert::<DbConnPool>(DbConnPool::new().await?);
|
||||
}
|
||||
|
||||
// start listening for events by starting a single shard
|
||||
if let Err(why) = client.start().await {
|
||||
println!("An error occurred while running the client: {:?}", why);
|
||||
}
|
||||
|
|
|
@ -1,30 +1,12 @@
|
|||
use crate::simple_responder;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use serenity::async_trait;
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::prelude::{Context, EventHandler};
|
||||
|
||||
pub(crate) struct YellResponder {
|
||||
regex: Regex,
|
||||
}
|
||||
|
||||
impl Default for YellResponder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
regex: Regex::new(r"A+H{5,}").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for YellResponder {
|
||||
async fn message(&self, ctx: Context, message: Message) {
|
||||
let content = &message.content_safe(ctx.clone()).await;
|
||||
if self.regex.is_match(content) {
|
||||
message
|
||||
.channel_id
|
||||
.say(ctx, "its ok ur gonna get a 6* someday")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
simple_responder!(
|
||||
YellResponder,
|
||||
r"A+H{5,}",
|
||||
"its ok ur gonna get a 6* someday"
|
||||
);
|
||||
|
|
|
@ -1,30 +1,12 @@
|
|||
use crate::simple_responder;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use serenity::async_trait;
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::prelude::{Context, EventHandler};
|
||||
|
||||
pub(crate) struct BestDoctorResponder {
|
||||
regex: Regex,
|
||||
}
|
||||
|
||||
impl Default for BestDoctorResponder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
regex: Regex::new(r"[iI].*(?:best|genius) doc").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for BestDoctorResponder {
|
||||
async fn message(&self, ctx: Context, message: Message) {
|
||||
let content = &message.content_safe(ctx.clone()).await;
|
||||
if self.regex.is_match(content) {
|
||||
message
|
||||
.channel_id
|
||||
.say(ctx, "smol brain doctor..")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
simple_responder!(
|
||||
BestDoctorResponder,
|
||||
r"[iI].*(?:best|genius) doc",
|
||||
"smol brain doctor..."
|
||||
);
|
||||
|
|
|
@ -1,29 +1,11 @@
|
|||
use crate::simple_responder;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use serenity::async_trait;
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::prelude::{Context, EventHandler};
|
||||
|
||||
pub(crate) struct FufufuResponder {
|
||||
regex: Regex,
|
||||
}
|
||||
|
||||
impl Default for FufufuResponder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
regex: Regex::new(r"(?:[fF][uU]){3,}").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for FufufuResponder {
|
||||
async fn message(&self, ctx: Context, message: Message) {
|
||||
let content = &message.content_safe(ctx.clone()).await;
|
||||
if self.regex.is_match(content) {
|
||||
message.channel_id.say(ctx, get_desu()).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
simple_responder!(FufufuResponder, r"(?:[fF][uU]){3,}", (get_desu()));
|
||||
|
||||
const DESU_STRINGS: &[&str] = &[
|
||||
"です。",
|
||||
|
|
|
@ -17,9 +17,9 @@ impl Default for Handler {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
responders: vec![
|
||||
Box::new(BestDoctorResponder::default()),
|
||||
Box::new(FufufuResponder::default()),
|
||||
Box::new(YellResponder::default()),
|
||||
Box::new(BestDoctorResponder),
|
||||
Box::new(FufufuResponder),
|
||||
Box::new(YellResponder),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -33,3 +33,25 @@ impl EventHandler for Handler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! simple_responder {
|
||||
// $phrase should be `expr`, see https://github.com/dtolnay/async-trait/issues/46
|
||||
// above issue is blocked on rustc bug, see https://github.com/rust-lang/rust/issues/43081
|
||||
($name:tt, $regex:expr, $phrase:tt) => {
|
||||
lazy_static! {
|
||||
static ref REGEX: Regex = Regex::new($regex).unwrap();
|
||||
}
|
||||
|
||||
pub(crate) struct $name;
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for $name {
|
||||
async fn message(&self, ctx: Context, message: Message) {
|
||||
if REGEX.is_match(&message.content_safe(ctx.clone()).await) {
|
||||
message.channel_id.say(ctx, $phrase).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use serenity::prelude::TypeMapKey;
|
||||
use sqlx::{
|
||||
sqlite::{SqliteConnection, SqlitePool},
|
||||
Pool,
|
||||
Error, Pool,
|
||||
};
|
||||
use std::env;
|
||||
|
||||
|
@ -12,22 +12,21 @@ pub(crate) struct DbConnPool {
|
|||
}
|
||||
|
||||
impl DbConnPool {
|
||||
pub async fn new() -> Self {
|
||||
Self {
|
||||
pool: init_pool().await,
|
||||
}
|
||||
pub async fn new() -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
pool: init_pool().await?,
|
||||
})
|
||||
}
|
||||
pub async fn get_heck(&self) -> i32 {
|
||||
|
||||
pub async fn get_heck(&self) -> Result<i32, Error> {
|
||||
sqlx::query!("UPDATE Heck SET count = count + 1")
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
sqlx::query!("SELECT count FROM Heck")
|
||||
Ok(sqlx::query!("SELECT count FROM Heck")
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
.unwrap()
|
||||
.count
|
||||
.await?
|
||||
.count)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,30 +34,26 @@ impl TypeMapKey for DbConnPool {
|
|||
type Value = Self;
|
||||
}
|
||||
|
||||
async fn init_pool() -> DbPool {
|
||||
async fn init_pool() -> Result<DbPool, Error> {
|
||||
let pool = SqlitePool::builder()
|
||||
.build(&env::var("DATABASE_URL").unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"CREATE TABLE IF NOT EXISTS Heck (id INTEGER PRIMARY KEY NOT NULL, count INTEGER NOT NULL)"
|
||||
)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
if sqlx::query!("SELECT count FROM Heck")
|
||||
.fetch_all(&pool)
|
||||
.await
|
||||
.unwrap()
|
||||
.await?
|
||||
.is_empty()
|
||||
{
|
||||
sqlx::query!("INSERT INTO Heck VALUES (1, 0)")
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
}
|
||||
|
||||
pool
|
||||
Ok(pool)
|
||||
}
|
||||
|
|
22
src/util/error.rs
Normal file
22
src/util/error.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
pub enum KuranteError {
|
||||
MissingEnvVar(std::env::VarError),
|
||||
Bot(serenity::Error),
|
||||
InvalidToken,
|
||||
Database(sqlx::Error),
|
||||
}
|
||||
|
||||
/// Generates a from implementation from the specified type to the provided
|
||||
/// bunbun error.
|
||||
macro_rules! from_error {
|
||||
($from:ty, $to:ident) => {
|
||||
impl From<$from> for KuranteError {
|
||||
fn from(e: $from) -> Self {
|
||||
Self::$to(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
from_error!(std::env::VarError, MissingEnvVar);
|
||||
from_error!(serenity::Error, Bot);
|
||||
from_error!(sqlx::Error, Database);
|
|
@ -1 +1,2 @@
|
|||
pub mod db;
|
||||
pub mod error;
|
||||
|
|
Loading…
Reference in a new issue