uberbot/src/bots/leek.rs

136 lines
3.3 KiB
Rust
Raw Normal View History

use arrayvec::{ArrayString};
2021-12-30 17:02:12 -06:00
use rand::Rng;
2022-01-02 14:58:54 -06:00
use std::{
error::Error,
fmt::{Debug, Display},
};
2021-12-29 14:08:49 -06:00
2021-12-30 17:02:12 -06:00
#[derive(Debug)]
pub struct CapacityError(arrayvec::CapacityError);
2021-12-30 17:02:12 -06:00
impl Display for CapacityError {
2021-12-30 17:02:12 -06:00
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.0, f)
}
}
impl Error for CapacityError {}
2021-12-30 17:02:12 -06:00
impl<T> From<arrayvec::CapacityError<T>> for CapacityError {
fn from(e: arrayvec::CapacityError<T>) -> Self {
Self(e.simplify())
2021-12-30 17:02:12 -06:00
}
}
type LeekResult = Result<ArrayString<512>, CapacityError>;
2021-12-30 17:02:12 -06:00
fn mock(input: &str) -> ArrayString<512> {
2021-12-29 14:56:29 -06:00
let mut builder = ArrayString::<512>::new();
2021-12-29 14:25:22 -06:00
2021-12-30 17:02:12 -06:00
for ch in input.chars() {
2021-12-29 14:25:22 -06:00
if rand::random() {
2021-12-31 17:51:54 -06:00
builder.push(ch.to_ascii_uppercase());
2021-12-29 14:25:22 -06:00
} else {
2021-12-31 17:51:54 -06:00
builder.push(ch.to_ascii_lowercase());
2021-12-29 14:25:22 -06:00
}
}
builder
2021-12-29 14:25:22 -06:00
}
2021-12-29 14:08:49 -06:00
fn leetify(input: &str) -> ArrayString<512> {
2021-12-29 14:56:29 -06:00
let mut builder = ArrayString::<512>::new();
2021-12-29 14:08:49 -06:00
2021-12-30 17:02:12 -06:00
for ch in input.chars() {
2021-12-31 17:51:54 -06:00
builder.push(match ch {
2021-12-29 14:56:29 -06:00
'a' => '4',
'e' => '3',
'i' => '1',
'o' => '0',
'g' => '6',
's' => '5',
't' => '7',
'b' => '8',
2021-12-30 17:02:12 -06:00
_ => ch,
2021-12-31 17:51:54 -06:00
});
2021-12-29 14:08:49 -06:00
}
builder
2021-12-30 17:02:12 -06:00
}
2022-01-26 05:58:49 -06:00
fn owoify(input: &str) -> LeekResult {
2021-12-31 17:51:54 -06:00
let mut builder: ArrayString<512> = ArrayString::from("\x1d")?;
2021-12-30 17:02:12 -06:00
let mut rng = rand::thread_rng();
let mut last_char = '\0';
for byte in input.bytes() {
let mut ch = char::from(byte);
if !ch.is_ascii() {
continue;
}
// owoify character
ch = match ch.to_ascii_lowercase() {
'r' | 'l' => 'w',
_ => ch,
};
// stutter (e.g. "o-ohayou gozaimasu!")
if last_char == ' ' && rng.gen_bool(0.2) {
builder.try_push(ch)?;
builder.try_push('-')?;
}
match ch {
// nya-ify
'a' | 'e' | 'i' | 'o' | 'u' if last_char == 'n' => {
builder.try_push('y')?;
}
// textmoji
'.' => {
builder.try_push_str(match rng.gen_range(0..6) {
1 => " OwO",
2021-12-31 17:51:54 -06:00
2 => " (◕ᴗ◕✿)",
2021-12-30 17:02:12 -06:00
3 => " >w<",
4 => " >_<",
5 => " ^•ﻌ•^",
_ => " ^^",
})?;
}
_ => {}
}
builder.try_push(ch)?;
last_char = ch;
}
2021-12-31 17:51:54 -06:00
builder.try_push_str("~~")?;
2021-12-30 17:02:12 -06:00
Ok(builder)
2021-12-29 14:25:49 -06:00
}
2022-01-26 05:58:49 -06:00
#[derive(Debug, Clone, Copy)]
pub enum Command {
2022-01-26 05:58:49 -06:00
Owo,
Leet,
Mock,
}
pub fn execute(
2022-01-26 05:58:49 -06:00
state: &mut crate::AppState,
cmd: Command,
2022-01-26 05:58:49 -06:00
target: &str,
nick: &str,
) -> anyhow::Result<()> {
match state.last_msgs.get(nick) {
Some(msg) => {
tracing::debug!("Executing {:?} on {:?}", cmd, msg);
let output = match cmd {
Command::Owo => super::leek::owoify(msg)?,
Command::Leet => super::leek::leetify(msg),
Command::Mock => super::leek::mock(msg),
2022-01-26 05:58:49 -06:00
};
state.client.send_privmsg(target, &output)?;
}
None => {
state
.client
.send_privmsg(target, "No last messages found.")?;
}
}
Ok(())
}