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"
|
arrayvec = "0.7"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
meval = "0.2"
|
meval = "0.2"
|
||||||
lazy_static = "1.4"
|
|
||||||
sedregex = "0.2"
|
|
||||||
rusqlite = { version = "0.28", features = ["bundled"] }
|
rusqlite = { version = "0.28", features = ["bundled"] }
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
irc = { version = "0.15", default-features = false, features = ["tls-rust"] }
|
irc = { version = "0.15", default-features = false, features = ["tls-rust"] }
|
||||||
async-trait = "0.1"
|
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;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
const HELP: &str = concat!(
|
const HELP: &str = concat!(
|
||||||
"=- \x1d\x02Überbot\x0f ", env!("CARGO_PKG_VERSION"), " -=\n",
|
"=- \x1d\x02Überbot\x0f ", env!("CARGO_PKG_VERSION"), " -=\r\n",
|
||||||
" * waifu <category>\n",
|
" * waifu <category>\r\n",
|
||||||
" * owo/mock/leet [user]\n",
|
" * owo/mock/leet [user]\r\n",
|
||||||
" * ev <math expression>\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.\n"
|
" - This bot also provides titles of URLs and details for Spotify URIs/links. It can also resolve sed expressions."
|
||||||
);
|
);
|
||||||
|
|
||||||
pub struct Help;
|
pub struct Help;
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn leetify(input: &str) -> ArrayString<512> {
|
||||||
let mut builder = ArrayString::<512>::new();
|
let mut builder = ArrayString::<512>::new();
|
||||||
|
|
||||||
for ch in input.chars() {
|
for ch in input.chars() {
|
||||||
builder.push(match ch {
|
builder.push(match ch.to_ascii_lowercase() {
|
||||||
'a' => '4',
|
'a' => '4',
|
||||||
'e' => '3',
|
'e' => '3',
|
||||||
'i' => '1',
|
'i' => '1',
|
||||||
|
@ -111,9 +111,9 @@ enum LeekCommand {
|
||||||
Mock,
|
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);
|
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 {
|
Some(msg) => Ok(match cmd {
|
||||||
LeekCommand::Owo => owoify(msg)?,
|
LeekCommand::Owo => owoify(msg)?,
|
||||||
LeekCommand::Leet => leetify(msg),
|
LeekCommand::Leet => leetify(msg),
|
||||||
|
@ -132,7 +132,7 @@ pub struct Mock;
|
||||||
impl Command for Owo {
|
impl Command for Owo {
|
||||||
//noinspection RsNeedlessLifetimes
|
//noinspection RsNeedlessLifetimes
|
||||||
async fn execute<'a>(&mut self, msg: Message<'a>) -> anyhow::Result<String> {
|
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 {
|
impl Command for Leet {
|
||||||
//noinspection RsNeedlessLifetimes
|
//noinspection RsNeedlessLifetimes
|
||||||
async fn execute<'a>(&mut self, msg: Message<'a>) -> anyhow::Result<String> {
|
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 {
|
impl Command for Mock {
|
||||||
//noinspection RsNeedlessLifetimes
|
//noinspection RsNeedlessLifetimes
|
||||||
async fn execute<'a>(&mut self, msg: Message<'a>) -> anyhow::Result<String> {
|
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("help".into(), Help);
|
||||||
bot.add_command("waifu".into(), Waifu);
|
bot.add_command("waifu".into(), Waifu);
|
||||||
bot.add_command("owo".into(), Owo);
|
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 {
|
let state = AppState {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
|
|
Loading…
Reference in a new issue