initial commit

This commit is contained in:
ultrablob 2025-05-15 15:19:37 -04:00
commit 4bb3879443
5 changed files with 2538 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
.env

2374
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

11
Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "gork"
version = "0.1.0"
edition = "2024"
[dependencies]
dotenvy = "0.15.7"
rand = "0.9.1"
serenity = "0.12"
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
yaml-rust2 = "0.10.1"

26
config.yaml Normal file
View file

@ -0,0 +1,26 @@
questions:
- "?"
- should
- will
- is
- gonna
- going to
- do
- are
default_responses:
- no
- don't think so
- nah
- definitely
- nope
question_responses:
- yes
- idk
- maybe
- for sure
- i hope so
- hopefully not
- probably not
- probably
- yep
- certainly

125
src/main.rs Normal file
View file

@ -0,0 +1,125 @@
use std::env;
use std::fs::read_to_string;
use std::time::Duration;
use dotenvy::dotenv;
use rand::random_range;
use rand::seq::IndexedRandom;
use serenity::all::Typing;
use serenity::async_trait;
use serenity::model::channel::Message;
use serenity::prelude::*;
use tokio::time::sleep;
use yaml_rust2::{Yaml, YamlLoader};
fn is_question(message: &str) -> bool {
get_keywords()
.questions
.iter()
.any(|keyword| message.contains(keyword))
}
struct Keywords {
questions: Vec<String>,
default_responses: Vec<String>,
question_responses: Vec<String>,
}
fn get_keywords() -> Keywords {
let mut docs: Vec<Yaml> =
YamlLoader::load_from_str(&read_to_string("config.yaml").expect("Need a config.yaml"))
.expect("Invalid yaml! Could not parse.");
let config: &mut Yaml = docs
.get_mut(0) // This returns Option<&mut Yaml>
.expect("Invalid yaml! No documents found in YAML file.");
// Your closure now works because `config` is `&mut Yaml`
let mut load_array = |key: &str| {
config[key] // This will use IndexMut if config is &mut Yaml, giving &mut Yaml
.as_mut_vec() // Requires &mut self on the Yaml item
.expect(&format!("Invalid or missing array for key: '{}'", key))
.into_iter() // Iterates over &mut Yaml items in the inner vec
.map(|x| {
x.as_str()
.expect(&format!(
"Non-string value found in array for key: '{}'",
key
))
.to_string() // Convert &str to owned String
})
.collect()
};
Keywords {
questions: load_array("questions"),
default_responses: load_array("default_responses"),
question_responses: load_array("question_responses"),
}
}
struct Handler;
#[async_trait]
impl EventHandler for Handler {
async fn message(&self, ctx: Context, msg: Message) {
let mut responses = get_keywords().default_responses;
if is_question(&msg.content) {
responses.extend(get_keywords().question_responses);
}
let current_user_id = match ctx.http.get_current_user().await {
Ok(user) => user.id,
Err(why) => {
eprintln!("Could not get current user: {:?}", why);
return;
}
};
if !msg.mentions.iter().any(|user| user.id == current_user_id)
|| msg.referenced_message.is_some()
{
return;
}
let typing = Typing::start(ctx.http.clone(), msg.channel_id);
sleep(Duration::from_millis(random_range(600..2200))).await;
let selected_response = {
let mut rng_instance = rand::rng();
responses
.choose(&mut rng_instance)
.expect("Responses array should not be empty")
};
if let Err(why) = msg.channel_id.say(&ctx.http, selected_response).await {
eprintln!("Error sending message: {:?}", why);
}
typing.stop();
}
}
#[tokio::main]
async fn main() {
dotenv().expect("Need a .env file!");
// Login with a bot token from the environment
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
// Set gateway intents, which decides what events the bot will be notified about
let intents = GatewayIntents::GUILD_MESSAGES
| GatewayIntents::DIRECT_MESSAGES
| GatewayIntents::MESSAGE_CONTENT;
// Create a new instance of the Client, logging in as a bot.
let mut client = Client::builder(&token, intents)
.event_handler(Handler)
.await
.expect("Err creating client");
// Start listening for events by starting a single shard
if let Err(why) = client.start().await {
println!("Client error: {why:?}");
}
}