Ported randoms to the DB
+ Also added commands for adding and listing randoms + fmt, clippy failing in a library...
This commit is contained in:
parent
766dc6f171
commit
95b965a4a9
@ -13,7 +13,6 @@ use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use structopt::StructOpt;
|
||||
use tera::Tera;
|
||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
@ -29,12 +28,6 @@ pub struct AlbumConfig {
|
||||
pub album_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct RandomConfig {
|
||||
pub name: String,
|
||||
pub responses: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct MotivationConfig {
|
||||
pub album: Vec<String>,
|
||||
@ -57,9 +50,6 @@ pub struct BotConfig {
|
||||
#[serde(default)]
|
||||
pub albums: Vec<AlbumConfig>,
|
||||
|
||||
#[serde(default)]
|
||||
pub randoms: Vec<RandomConfig>,
|
||||
|
||||
pub motivation: MotivationConfig,
|
||||
|
||||
pub insults: Vec<InsultComplimentTemplate>,
|
||||
@ -88,7 +78,6 @@ impl BotConfig {
|
||||
#[derive(Debug)]
|
||||
pub struct BotState {
|
||||
pub accepted_nsfw: Option<UserId>,
|
||||
pub templates: HashMap<String, Tera>,
|
||||
pub albums: HashMap<String, Vec<Image>>,
|
||||
pub bad_apple_running: bool,
|
||||
}
|
||||
@ -96,18 +85,6 @@ pub struct BotState {
|
||||
impl BotState {
|
||||
pub async fn new(cfg: &BotConfig) -> Result<Self, Error> {
|
||||
let mut albums: HashMap<String, Vec<Image>> = HashMap::new();
|
||||
let mut templates = HashMap::new();
|
||||
|
||||
for random_config in cfg.randoms.iter() {
|
||||
let mut templates_set = Tera::default();
|
||||
for (idx, response) in random_config.responses.iter().enumerate() {
|
||||
templates_set
|
||||
.add_raw_template(&idx.to_string(), response)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
templates.insert(random_config.name.clone(), templates_set);
|
||||
}
|
||||
|
||||
for album in &cfg.albums {
|
||||
albums.insert(
|
||||
@ -118,7 +95,6 @@ impl BotState {
|
||||
|
||||
Ok(Self {
|
||||
accepted_nsfw: None,
|
||||
templates,
|
||||
albums,
|
||||
bad_apple_running: false,
|
||||
})
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
use crate::error::Error;
|
||||
use crate::models::random::RandomConfig;
|
||||
use crate::{command, group, GlobalData, BAD_APPLE};
|
||||
use rand::prelude::IteratorRandom;
|
||||
use rand::thread_rng;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serenity::client::Context;
|
||||
use serenity::constants::MESSAGE_CODE_LIMIT;
|
||||
use serenity::framework::standard::{Args, CommandResult};
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::utils::MessageBuilder;
|
||||
@ -12,7 +14,7 @@ use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
#[group]
|
||||
#[commands(dad_joke, roll, bad_apple, insult)]
|
||||
#[commands(dad_joke, roll, bad_apple, insult, add_random, list_random)]
|
||||
pub struct Joke;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
@ -49,10 +51,7 @@ struct RandomCtx {
|
||||
}
|
||||
|
||||
impl RandomCtx {
|
||||
pub async fn new(
|
||||
user: serenity::model::guild::Member,
|
||||
global_data: &GlobalData,
|
||||
) -> Result<Self, Error> {
|
||||
pub fn new(user_name: &str, global_data: &GlobalData) -> Result<Self, Error> {
|
||||
let mut random_image: HashMap<String, String> = HashMap::new();
|
||||
|
||||
for album in &global_data.cfg.albums {
|
||||
@ -64,28 +63,42 @@ impl RandomCtx {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
user: (*user.display_name()).clone(),
|
||||
user: user_name.to_string(),
|
||||
random_image,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_random(
|
||||
author_name: &str,
|
||||
global_data: &GlobalData,
|
||||
template: &str,
|
||||
) -> Result<String, Error> {
|
||||
let random_ctx = RandomCtx::new(author_name, global_data)?;
|
||||
|
||||
Ok(tera::Tera::one_off(
|
||||
template,
|
||||
&tera::Context::from_serialize(&random_ctx)?,
|
||||
false,
|
||||
)?)
|
||||
}
|
||||
|
||||
pub async fn random(ctx: &Context, msg: &Message, random_name: &str) -> CommandResult {
|
||||
let data = ctx.data.read().await;
|
||||
let global_data = data.get::<GlobalData>().unwrap();
|
||||
|
||||
let templates = global_data.bot_state.templates.get(random_name);
|
||||
|
||||
let templates = if let Some(templates) = templates {
|
||||
templates
|
||||
} else {
|
||||
return Ok(());
|
||||
let random = match RandomConfig::get_random(&global_data.db, random_name)? {
|
||||
None => return Ok(()),
|
||||
Some(r) => r,
|
||||
};
|
||||
|
||||
let template = {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
templates.get_template_names().choose(&mut rng)
|
||||
let response_template_str = match random.get_response()? {
|
||||
None => {
|
||||
msg.reply(&ctx, format!("I'm all out of material for {}", random_name))
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
Some(resp) => resp,
|
||||
};
|
||||
|
||||
let guild_member = msg
|
||||
@ -94,13 +107,11 @@ pub async fn random(ctx: &Context, msg: &Message, random_name: &str) -> CommandR
|
||||
.member(&ctx.http, msg.author.id)
|
||||
.await?;
|
||||
|
||||
let random_ctx = RandomCtx::new(guild_member, global_data).await?;
|
||||
|
||||
let reply = if let Some(template) = template {
|
||||
templates.render(template, &tera::Context::from_serialize(&random_ctx)?)?
|
||||
} else {
|
||||
"Sorry kid, all out of messages.".to_string()
|
||||
};
|
||||
let reply = render_random(
|
||||
&guild_member.display_name(),
|
||||
global_data,
|
||||
response_template_str,
|
||||
)?;
|
||||
|
||||
msg.reply(&ctx.http, reply).await?;
|
||||
|
||||
@ -108,7 +119,87 @@ pub async fn random(ctx: &Context, msg: &Message, random_name: &str) -> CommandR
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[only_in(guilds)]
|
||||
#[example("8ball Funny Response haha")]
|
||||
pub async fn add_random(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
if args.len() < 2 {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
"Look kid, you need to provide both the random name and response",
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let data = ctx.data.read().await;
|
||||
let global_data = data.get::<GlobalData>().unwrap();
|
||||
|
||||
let random_name = args.parse::<String>()?;
|
||||
args.advance();
|
||||
let random_response = args.rest();
|
||||
|
||||
if let Err(err) = render_random(&msg.author.name, global_data, random_response) {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
format!("Template failed test render, try again: {}", err),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
RandomConfig::add_random(&global_data.db, &random_name, random_response)?;
|
||||
msg.reply(&ctx.http, "New random added!").await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[example("8ball Funny Response haha")]
|
||||
pub async fn list_random(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
if args.len() < 1 {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
"Look kid, you need to provide both the random name",
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let data = ctx.data.read().await;
|
||||
let global_data = data.get::<GlobalData>().unwrap();
|
||||
|
||||
let random_name = args.parse::<String>()?;
|
||||
|
||||
let random = RandomConfig::get_random(&global_data.db, &random_name)?;
|
||||
|
||||
if let Some(random) = random {
|
||||
let mut msg_builder = MessageBuilder::new();
|
||||
msg_builder.push_line(format!("All possible responses for {}:", random_name));
|
||||
|
||||
for resp in random.responses {
|
||||
let line_msg = format!("* {}", resp);
|
||||
|
||||
if (msg_builder.0.len() + line_msg.len()) > MESSAGE_CODE_LIMIT {
|
||||
msg.channel_id.say(&ctx.http, msg_builder.build()).await?;
|
||||
msg_builder.0.clear();
|
||||
}
|
||||
|
||||
msg_builder.push_line(line_msg);
|
||||
}
|
||||
|
||||
if !msg_builder.0.is_empty() {
|
||||
msg.channel_id.say(&ctx.http, msg_builder.build()).await?;
|
||||
}
|
||||
} else {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
"*glances to the back room*, nope we ain't got that random",
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[aliases("roll")]
|
||||
#[description("Roll a die!")]
|
||||
async fn roll(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
@ -168,7 +259,6 @@ async fn bad_apple(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
||||
|
||||
#[command]
|
||||
#[aliases("compliment")]
|
||||
#[only_in(guilds)]
|
||||
async fn insult(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
let data = ctx.data.read().await;
|
||||
let global = data.get::<GlobalData>().unwrap();
|
||||
|
||||
@ -4,6 +4,7 @@ mod error;
|
||||
mod imgur;
|
||||
mod insult_compliment;
|
||||
mod inventory;
|
||||
mod models;
|
||||
mod user;
|
||||
|
||||
use crate::config::{Args, BotConfig, Channel, GlobalData};
|
||||
|
||||
1
src/models/mod.rs
Normal file
1
src/models/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod random;
|
||||
60
src/models/random.rs
Normal file
60
src/models/random.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use crate::error::Error;
|
||||
use j_db::database::Database;
|
||||
use j_db::model::JdbModel;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct RandomConfig {
|
||||
id: Option<u64>,
|
||||
pub name: String,
|
||||
pub responses: Vec<String>,
|
||||
}
|
||||
|
||||
impl JdbModel for RandomConfig {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id)
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"randoms".to_string()
|
||||
}
|
||||
|
||||
fn check_unique(&self, other: &Self) -> bool {
|
||||
!self.name.eq_ignore_ascii_case(&other.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl RandomConfig {
|
||||
pub fn add_random(db: &Database, name: &str, response: &str) -> Result<(), Error> {
|
||||
let mut random = match Self::get_random(db, name)? {
|
||||
None => db.insert::<RandomConfig>(Self {
|
||||
id: None,
|
||||
name: name.to_string(),
|
||||
responses: vec![],
|
||||
})?,
|
||||
Some(random) => random,
|
||||
};
|
||||
|
||||
random.responses.push(response.to_string());
|
||||
|
||||
db.insert::<RandomConfig>(random)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_random(db: &Database, name: &str) -> Result<Option<Self>, Error> {
|
||||
Ok(db
|
||||
.filter(|_, random: &RandomConfig| random.name.eq_ignore_ascii_case(name))?
|
||||
.next())
|
||||
}
|
||||
|
||||
pub fn get_response(&self) -> Result<Option<&String>, Error> {
|
||||
Ok(self.responses.choose(&mut thread_rng()))
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user