lol what are good commits

This commit is contained in:
Edward Shen 2020-05-02 01:04:51 -04:00
parent d543802181
commit 4b7a981a88
Signed by: edward
GPG key ID: 19182661E818369F
13 changed files with 189 additions and 112 deletions

49
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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()
{

View file

@ -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;

View file

@ -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(())

View file

@ -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);
}

View file

@ -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"
);

View file

@ -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..."
);

View file

@ -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] = &[
"です。",

View file

@ -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();
}
}
}
};
}

View file

@ -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
View 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);

View file

@ -1 +1,2 @@
pub mod db;
pub mod error;