Port sedbot (partially)
This commit is contained in:
parent
dcbb530465
commit
324959faad
|
@ -21,10 +21,11 @@ serde = { version = "1.0", features = ["derive"] }
|
|||
arrayvec = "0.7"
|
||||
rand = "0.8"
|
||||
meval = "0.2"
|
||||
lazy_static = "1.4"
|
||||
sedregex = "0.2"
|
||||
rusqlite = { version = "0.28", features = ["bundled"] }
|
||||
futures-util = "0.3"
|
||||
irc = { version = "0.15", default-features = false, features = ["tls-rust"] }
|
||||
async-trait = "0.1"
|
||||
arg = "0.3"
|
||||
|
||||
[features]
|
||||
# debug IRC commands
|
||||
debug = []
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
use std::{error::Error, fmt::Display};
|
||||
|
||||
use arrayvec::{ArrayString, CapacityError};
|
||||
use fancy_regex::Regex;
|
||||
use lazy_static::lazy_static;
|
||||
use sedregex::find_and_replace;
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
#[derive(Debug)]
|
||||
pub enum SedError {
|
||||
Capacity(CapacityError),
|
||||
Regex(fancy_regex::Error),
|
||||
SedRegex(sedregex::ErrorKind),
|
||||
}
|
||||
|
||||
impl Display for SedError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Capacity(e) => e.fmt(f),
|
||||
Self::Regex(e) => e.fmt(f),
|
||||
Self::SedRegex(e) => e.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for SedError {}
|
||||
|
||||
impl<T> From<CapacityError<T>> for SedError {
|
||||
fn from(e: CapacityError<T>) -> Self {
|
||||
Self::Capacity(e.simplify())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<fancy_regex::Error> for SedError {
|
||||
fn from(e: fancy_regex::Error) -> Self {
|
||||
Self::Regex(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sedregex::ErrorKind> for SedError {
|
||||
fn from(e: sedregex::ErrorKind) -> Self {
|
||||
Self::SedRegex(e)
|
||||
}
|
||||
}
|
||||
|
||||
type SedResult = Result<Option<ArrayString<512>>, SedError>;
|
||||
|
||||
pub fn resolve(prev_msg: &str, cmd: &str) -> SedResult {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"^s/.*/.*").unwrap();
|
||||
}
|
||||
|
||||
if RE.is_match(cmd)? {
|
||||
return if let Some(mat) = RE.find(cmd)? {
|
||||
let slice = &cmd[mat.start()..mat.end()];
|
||||
let formatted = find_and_replace(prev_msg, [slice])?;
|
||||
Ok(Some(ArrayString::from(&formatted)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
};
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
|
@ -2,11 +2,11 @@ use crate::bot::{Message, Command};
|
|||
use async_trait::async_trait;
|
||||
|
||||
const HELP: &str = concat!(
|
||||
"=- \x1d\x02Überbot\x0f ", env!("CARGO_PKG_VERSION"), " -=\n",
|
||||
" * waifu <category>\n",
|
||||
" * owo/mock/leet [user]\n",
|
||||
" * ev <math expression>\n",
|
||||
" - This bot also provides titles of URLs and details for Spotify URIs/links. It can also resolve sed expressions.\n"
|
||||
"=- \x1d\x02Überbot\x0f ", env!("CARGO_PKG_VERSION"), " -=\r\n",
|
||||
" * waifu <category>\r\n",
|
||||
" * owo/mock/leet [user]\r\n",
|
||||
" * ev <math expression>\r\n",
|
||||
" - This bot also provides titles of URLs and details for Spotify URIs/links. It can also resolve sed expressions."
|
||||
);
|
||||
|
||||
pub struct Help;
|
||||
|
|
|
@ -44,7 +44,7 @@ fn leetify(input: &str) -> ArrayString<512> {
|
|||
let mut builder = ArrayString::<512>::new();
|
||||
|
||||
for ch in input.chars() {
|
||||
builder.push(match ch {
|
||||
builder.push(match ch.to_ascii_lowercase() {
|
||||
'a' => '4',
|
||||
'e' => '3',
|
||||
'i' => '1',
|
||||
|
@ -111,9 +111,9 @@ enum LeekCommand {
|
|||
Mock,
|
||||
}
|
||||
|
||||
fn execute_leek(cmd: LeekCommand, msg: &Message) -> anyhow::Result<String> {
|
||||
async fn execute_leek(cmd: LeekCommand, msg: &Message<'_>) -> anyhow::Result<String> {
|
||||
let nick = msg.content.unwrap_or(msg.author);
|
||||
match msg.last_msg.get(nick) {
|
||||
match msg.last_msg.read().await.get(nick) {
|
||||
Some(msg) => Ok(match cmd {
|
||||
LeekCommand::Owo => owoify(msg)?,
|
||||
LeekCommand::Leet => leetify(msg),
|
||||
|
@ -132,7 +132,7 @@ pub struct Mock;
|
|||
impl Command for Owo {
|
||||
//noinspection RsNeedlessLifetimes
|
||||
async fn execute<'a>(&mut self, msg: Message<'a>) -> anyhow::Result<String> {
|
||||
execute_leek(LeekCommand::Owo, &msg)
|
||||
execute_leek(LeekCommand::Owo, &msg).await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ impl Command for Owo {
|
|||
impl Command for Leet {
|
||||
//noinspection RsNeedlessLifetimes
|
||||
async fn execute<'a>(&mut self, msg: Message<'a>) -> anyhow::Result<String> {
|
||||
execute_leek(LeekCommand::Leet, &msg)
|
||||
execute_leek(LeekCommand::Leet, &msg).await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,6 @@ impl Command for Leet {
|
|||
impl Command for Mock {
|
||||
//noinspection RsNeedlessLifetimes
|
||||
async fn execute<'a>(&mut self, msg: Message<'a>) -> anyhow::Result<String> {
|
||||
execute_leek(LeekCommand::Mock, &msg)
|
||||
execute_leek(LeekCommand::Mock, &msg).await
|
||||
}
|
||||
}
|
||||
|
|
39
src/commands/sed.rs
Normal file
39
src/commands/sed.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use async_trait::async_trait;
|
||||
use fancy_regex::Captures;
|
||||
use crate::bot::{Message, Trigger};
|
||||
|
||||
pub struct Sed;
|
||||
|
||||
#[async_trait]
|
||||
impl Trigger for Sed {
|
||||
async fn execute<'a>(&mut self, msg: Message<'a>, matches: Captures<'a>) -> anyhow::Result<String> {
|
||||
let mut foreign_author;
|
||||
let author = if let Some(author) = matches.name("u").map(|m| m.as_str()) {
|
||||
foreign_author = true;
|
||||
author
|
||||
} else {
|
||||
foreign_author = false;
|
||||
msg.author
|
||||
};
|
||||
let lastmsg = msg.last_msg.read().await;
|
||||
let message = if let Some(msg) = lastmsg.get(author) {
|
||||
msg
|
||||
} else {
|
||||
return Ok("No previous messages found.".into());
|
||||
};
|
||||
if let (Some(find), Some(replace)) = (matches.name("r"), matches.name("w")) {
|
||||
// TODO: karx plz add flags
|
||||
//let flags = matches.name("f").map(|m| m.as_str());
|
||||
let result = message.replace(find.as_str(), replace.as_str());
|
||||
drop(lastmsg);
|
||||
if foreign_author {
|
||||
Ok(format!("(edited by {}) <{}> {}", msg.author, author, result))
|
||||
} else {
|
||||
msg.last_msg.write().await.insert(author.into(), result.to_string());
|
||||
Ok(format!("<{}> {}", author, result))
|
||||
}
|
||||
} else {
|
||||
Ok("Invalid usage.".into())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,6 +104,12 @@ async fn main() -> anyhow::Result<()> {
|
|||
bot.add_command("help".into(), Help);
|
||||
bot.add_command("waifu".into(), Waifu);
|
||||
bot.add_command("owo".into(), Owo);
|
||||
bot.add_trigger(Regex::new(r"^(?:(?<u>\S+):\s+)?s/(?<r>[^/]*)/(?<w>[^/]*)(?:/(?<f>[a-z]*))?\s*")?, Sed);
|
||||
#[cfg(feature = "debug")]
|
||||
{
|
||||
use commands::debug::*;
|
||||
bot.add_command("lastmsg".into(), LastMsg);
|
||||
}
|
||||
|
||||
let state = AppState {
|
||||
client: client.clone(),
|
||||
|
|
Loading…
Reference in a new issue