Make it work, still messy as hell
This commit is contained in:
parent
307918c108
commit
4e197fc4c0
|
@ -1,2 +1,2 @@
|
||||||
[target.x86_64-unknown-linux-musl]
|
[target.x86_64-unknown-linux-musl]
|
||||||
rustflags=["-Ctarget-feature=-crt-static"]
|
rustflags = ["-Ctarget-feature=-crt-static"]
|
||||||
|
|
|
@ -11,6 +11,7 @@ tokio = { version = "1.15", features = ["rt", "macros", "signal"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
tracing-log = "0.1"
|
||||||
reqwest = "0.11"
|
reqwest = "0.11"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
fancy-regex = "0.7"
|
fancy-regex = "0.7"
|
||||||
|
@ -21,11 +22,12 @@ serde = "1.0"
|
||||||
arrayvec = "0.7"
|
arrayvec = "0.7"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
meval = "0.2"
|
meval = "0.2"
|
||||||
async-circe = { git = "https://git.karx.xyz/circe/async-circe" }
|
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
sedregex = "0.2"
|
sedregex = "0.2"
|
||||||
rusqlite = { version = "0.26", features = ["bundled"] }
|
rusqlite = { version = "0.26", features = ["bundled"] }
|
||||||
warp = "0.3"
|
warp = "0.3"
|
||||||
|
futures-util = "0.3"
|
||||||
|
irc = { version = "0.15", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
tls = ["async-circe/tls"]
|
tls = ["irc/tls-rust"]
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
use serde_json::Value::Null;
|
|
||||||
use tokio::sync::mpsc::Sender;
|
|
||||||
|
|
||||||
pub async fn handle_post(
|
|
||||||
json: serde_json::Value,
|
|
||||||
tx: Sender<String>,
|
|
||||||
) -> Result<impl warp::Reply, warp::Rejection> {
|
|
||||||
if json["commits"] != Null {
|
|
||||||
let commits = json["commits"].as_array().unwrap();
|
|
||||||
let repo = &json["repository"]["full_name"].as_str().unwrap().trim();
|
|
||||||
if commits.len() != 1 {
|
|
||||||
tx.send(format!("{} new commits on {}:", commits.len(), repo))
|
|
||||||
.await
|
|
||||||
.expect("Failed to send string to main thread");
|
|
||||||
for commit in commits {
|
|
||||||
let author = &commit["author"]["name"].as_str().unwrap().trim();
|
|
||||||
let message = &commit["message"].as_str().unwrap().trim();
|
|
||||||
tx.send(format!("{} - {}", author, message))
|
|
||||||
.await
|
|
||||||
.expect("Failed to send string to main thread");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let author = &json["commits"][0]["author"]["name"]
|
|
||||||
.as_str()
|
|
||||||
.unwrap()
|
|
||||||
.trim();
|
|
||||||
let message = &json["commits"][0]["message"].as_str().unwrap().trim();
|
|
||||||
tx.send(format!("New commit on {}: {} - {}", repo, message, author))
|
|
||||||
.await
|
|
||||||
.expect("Failed to send string to main thread");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(warp::reply::with_status("Ok", warp::http::StatusCode::OK))
|
|
||||||
}
|
|
|
@ -24,7 +24,7 @@ impl<T> From<CapacityError<T>> for LeekCapacityError {
|
||||||
|
|
||||||
type LeekResult = Result<ArrayString<512>, LeekCapacityError>;
|
type LeekResult = Result<ArrayString<512>, LeekCapacityError>;
|
||||||
|
|
||||||
pub fn mock(input: &str) -> LeekResult {
|
fn mock(input: &str) -> LeekResult {
|
||||||
let mut builder = ArrayString::<512>::new();
|
let mut builder = ArrayString::<512>::new();
|
||||||
|
|
||||||
for ch in input.chars() {
|
for ch in input.chars() {
|
||||||
|
@ -38,7 +38,7 @@ pub fn mock(input: &str) -> LeekResult {
|
||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leetify(input: &str) -> LeekResult {
|
fn leetify(input: &str) -> LeekResult {
|
||||||
let mut builder = ArrayString::<512>::new();
|
let mut builder = ArrayString::<512>::new();
|
||||||
|
|
||||||
for ch in input.chars() {
|
for ch in input.chars() {
|
||||||
|
@ -58,7 +58,7 @@ pub fn leetify(input: &str) -> LeekResult {
|
||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn owoify(input: &str) -> LeekResult {
|
fn owoify(input: &str) -> LeekResult {
|
||||||
let mut builder: ArrayString<512> = ArrayString::from("\x1d")?;
|
let mut builder: ArrayString<512> = ArrayString::from("\x1d")?;
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut last_char = '\0';
|
let mut last_char = '\0';
|
||||||
|
@ -101,3 +101,35 @@ pub fn owoify(input: &str) -> LeekResult {
|
||||||
builder.try_push_str("~~")?;
|
builder.try_push_str("~~")?;
|
||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LeekCommand {
|
||||||
|
Owo,
|
||||||
|
Leet,
|
||||||
|
Mock,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_leek(
|
||||||
|
state: &mut crate::AppState,
|
||||||
|
cmd: LeekCommand,
|
||||||
|
target: &str,
|
||||||
|
nick: &str,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
match state.last_msgs.get(nick) {
|
||||||
|
Some(msg) => {
|
||||||
|
tracing::debug!("Executing {:?} on {:?}", cmd, msg);
|
||||||
|
let output = match cmd {
|
||||||
|
LeekCommand::Owo => super::leek::owoify(msg)?,
|
||||||
|
LeekCommand::Leet => super::leek::leetify(msg)?,
|
||||||
|
LeekCommand::Mock => super::leek::mock(msg)?,
|
||||||
|
};
|
||||||
|
state.client.send_privmsg(target, &output)?;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
state
|
||||||
|
.client
|
||||||
|
.send_privmsg(target, "No last messages found.")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -4,13 +4,6 @@ use serde_json::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum LeekCommand {
|
|
||||||
Owo,
|
|
||||||
Leet,
|
|
||||||
Mock,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_waifu_pic(category: &str) -> anyhow::Result<Option<String>> {
|
pub async fn get_waifu_pic(category: &str) -> anyhow::Result<Option<String>> {
|
||||||
let api_resp = reqwest::get(format!("https://api.waifu.pics/sfw/{}", category))
|
let api_resp = reqwest::get(format!("https://api.waifu.pics/sfw/{}", category))
|
||||||
.await?
|
.await?
|
||||||
|
@ -40,29 +33,3 @@ pub fn mathbot(
|
||||||
Ok(ArrayString::from("No expression to evaluate")?)
|
Ok(ArrayString::from("No expression to evaluate")?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_leek(
|
|
||||||
state: &mut crate::AppState,
|
|
||||||
cmd: LeekCommand,
|
|
||||||
channel: &str,
|
|
||||||
nick: &str,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
match state.last_msgs.get(nick) {
|
|
||||||
Some(msg) => {
|
|
||||||
tracing::debug!("Executing {:?} on {:?}", cmd, msg);
|
|
||||||
let output = match cmd {
|
|
||||||
LeekCommand::Owo => super::leek::owoify(msg)?,
|
|
||||||
LeekCommand::Leet => super::leek::leetify(msg)?,
|
|
||||||
LeekCommand::Mock => super::leek::mock(msg)?,
|
|
||||||
};
|
|
||||||
state.client.privmsg(channel, &output).await?;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
state
|
|
||||||
.client
|
|
||||||
.privmsg(channel, "No last messages found.")
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
pub mod git;
|
|
||||||
pub mod leek;
|
pub mod leek;
|
||||||
pub mod misc;
|
pub mod misc;
|
||||||
pub mod sed;
|
pub mod sed;
|
||||||
|
|
|
@ -46,7 +46,7 @@ type SedResult = Result<Option<ArrayString<512>>, SedError>;
|
||||||
|
|
||||||
pub fn resolve(prev_msg: &str, cmd: &str) -> SedResult {
|
pub fn resolve(prev_msg: &str, cmd: &str) -> SedResult {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref RE: Regex = Regex::new(r"^s/.*/.*").unwrap(); // yes this regex is valid, don't worry about it
|
static ref RE: Regex = Regex::new(r"^s/.*/.*").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if RE.is_match(cmd)? {
|
if RE.is_match(cmd)? {
|
||||||
|
|
176
src/main.rs
176
src/main.rs
|
@ -1,24 +1,29 @@
|
||||||
mod bots;
|
|
||||||
mod database;
|
|
||||||
mod web_service;
|
|
||||||
|
|
||||||
use crate::database::{DbExecutor, ExecutorConnection};
|
|
||||||
use arrayvec::ArrayString;
|
|
||||||
use async_circe::{commands::Command, Client, Config};
|
|
||||||
use bots::title::Titlebot;
|
|
||||||
use bots::{misc, misc::LeekCommand, sed};
|
|
||||||
use rspotify::Credentials;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::{collections::HashMap, env};
|
use std::{collections::HashMap, env};
|
||||||
|
|
||||||
|
use arrayvec::ArrayString;
|
||||||
|
use futures_util::stream::StreamExt;
|
||||||
|
use irc::client::prelude::Config;
|
||||||
|
use irc::client::Client;
|
||||||
|
use irc::proto::{ChannelExt, Command, Prefix};
|
||||||
|
use rspotify::Credentials;
|
||||||
|
use serde::Deserialize;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||||
|
use tracing_log::LogTracer;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
|
use crate::bots::{leek, misc, sed, title};
|
||||||
|
use crate::database::{DbExecutor, ExecutorConnection};
|
||||||
|
|
||||||
|
mod bots;
|
||||||
|
mod database;
|
||||||
|
mod web_service;
|
||||||
|
|
||||||
// this will be displayed when the help command is used
|
// this will be displayed when the help command is used
|
||||||
const HELP: &[&str] = &[
|
const HELP: &[&str] = &[
|
||||||
concat!("=- \x1d\x02Ü\x02berbot\x0f ", env!("CARGO_PKG_VERSION"), " -="),
|
concat!("=- \x1d\x02Ü\x02berbot\x0f ", env!("CARGO_PKG_VERSION"), " -="),
|
||||||
|
@ -53,7 +58,7 @@ pub struct AppState {
|
||||||
client: Client,
|
client: Client,
|
||||||
last_msgs: HashMap<String, String>,
|
last_msgs: HashMap<String, String>,
|
||||||
last_eval: HashMap<String, f64>,
|
last_eval: HashMap<String, f64>,
|
||||||
titlebot: Titlebot,
|
titlebot: title::Titlebot,
|
||||||
db: ExecutorConnection,
|
db: ExecutorConnection,
|
||||||
git_channel: String,
|
git_channel: String,
|
||||||
}
|
}
|
||||||
|
@ -62,6 +67,7 @@ pub struct AppState {
|
||||||
struct ClientConf {
|
struct ClientConf {
|
||||||
channels: Vec<String>,
|
channels: Vec<String>,
|
||||||
host: String,
|
host: String,
|
||||||
|
tls: bool,
|
||||||
mode: Option<String>,
|
mode: Option<String>,
|
||||||
nickname: Option<String>,
|
nickname: Option<String>,
|
||||||
port: u16,
|
port: u16,
|
||||||
|
@ -76,6 +82,7 @@ struct ClientConf {
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
LogTracer::init()?;
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
.with_env_filter(EnvFilter::from_env("UBERBOT_LOG"))
|
.with_env_filter(EnvFilter::from_env("UBERBOT_LOG"))
|
||||||
.init();
|
.init();
|
||||||
|
@ -103,24 +110,29 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.http_listen
|
.http_listen
|
||||||
.unwrap_or_else(|| SocketAddr::from(([127, 0, 0, 1], 5000)));
|
.unwrap_or_else(|| SocketAddr::from(([127, 0, 0, 1], 5000)));
|
||||||
|
|
||||||
let config = Config::runtime_config(
|
let uber_ver = concat!("Überbot ", env!("CARGO_PKG_VERSION"));
|
||||||
client_config.channels,
|
let irc_config = Config {
|
||||||
client_config.host,
|
nickname: client_config.nickname,
|
||||||
client_config.mode,
|
username: Some(client_config.username.clone()),
|
||||||
client_config.nickname,
|
realname: Some(client_config.username),
|
||||||
client_config.port,
|
server: Some(client_config.host),
|
||||||
client_config.username,
|
port: Some(client_config.port),
|
||||||
);
|
use_tls: Some(client_config.tls),
|
||||||
|
channels: client_config.channels,
|
||||||
let mut client = Client::new(config).await?;
|
umodes: client_config.mode,
|
||||||
client.identify().await?;
|
user_info: Some(uber_ver.into()),
|
||||||
|
version: Some(uber_ver.into()),
|
||||||
|
..Config::default()
|
||||||
|
};
|
||||||
|
let client = Client::from_config(irc_config).await?;
|
||||||
|
client.identify()?;
|
||||||
|
|
||||||
let state = AppState {
|
let state = AppState {
|
||||||
prefix: client_config.prefix,
|
prefix: client_config.prefix,
|
||||||
client,
|
client,
|
||||||
last_msgs: HashMap::new(),
|
last_msgs: HashMap::new(),
|
||||||
last_eval: HashMap::new(),
|
last_eval: HashMap::new(),
|
||||||
titlebot: Titlebot::create(spotify_creds).await?,
|
titlebot: title::Titlebot::create(spotify_creds).await?,
|
||||||
db: db_conn,
|
db: db_conn,
|
||||||
git_channel: client_config.git_channel,
|
git_channel: client_config.git_channel,
|
||||||
};
|
};
|
||||||
|
@ -146,31 +158,39 @@ async fn executor(
|
||||||
http_listen: SocketAddr,
|
http_listen: SocketAddr,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let web_db = state.db.clone();
|
let web_db = state.db.clone();
|
||||||
let git_channel = state.git_channel.clone();
|
|
||||||
select! {
|
select! {
|
||||||
r = web_service::run(web_db, git_tx, http_listen) => r?,
|
r = web_service::run(web_db, git_tx, http_listen) => r?,
|
||||||
r = message_loop(&mut state) => r?,
|
r = message_loop(&mut state) => r?,
|
||||||
r = git_recv.recv() => {
|
r = git_recv.recv() => {
|
||||||
if let Some(message) = r {
|
if let Some(message) = r {
|
||||||
state.client.privmsg(&git_channel, &message).await?;
|
state.client.send_privmsg(&state.git_channel, &message)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = terminate_signal() => {
|
_ = terminate_signal() => {
|
||||||
tracing::info!("Sending QUIT message");
|
tracing::info!("Sending QUIT message");
|
||||||
state.client.quit(Some("überbot shutting down")).await?;
|
state.client.send_quit("überbot shutting down")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn message_loop(state: &mut AppState) -> anyhow::Result<()> {
|
async fn message_loop(state: &mut AppState) -> anyhow::Result<()> {
|
||||||
while let Some(cmd) = state.client.read().await? {
|
let mut stream = state.client.stream()?;
|
||||||
if let Command::PRIVMSG(nick, channel, message) = cmd {
|
while let Some(message) = stream.next().await.transpose()? {
|
||||||
if let Err(e) = handle_privmsg(state, nick, &channel, message).await {
|
if let Command::PRIVMSG(ref origin, content) = message.command {
|
||||||
state
|
if origin.is_channel_name() {
|
||||||
.client
|
if let Some(author) = message.prefix.as_ref().and_then(|p| match p {
|
||||||
.privmsg(&channel, &format!("Error: {}", e))
|
Prefix::Nickname(name, _, _) => Some(&name[..]),
|
||||||
.await?;
|
_ => None,
|
||||||
|
}) {
|
||||||
|
if let Err(e) = handle_privmsg(state, author, origin, content).await {
|
||||||
|
state
|
||||||
|
.client
|
||||||
|
.send_privmsg(origin, &format!("Error: {}", e))?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tracing::warn!("Couldn't get the author for a message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,35 +207,35 @@ fn separate_to_space(str: &str, prefix_len: usize) -> (&str, Option<&str>) {
|
||||||
|
|
||||||
async fn handle_privmsg(
|
async fn handle_privmsg(
|
||||||
state: &mut AppState,
|
state: &mut AppState,
|
||||||
nick: String,
|
author: &str,
|
||||||
channel: &str,
|
origin: &str,
|
||||||
message: String,
|
content: String,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !message.starts_with(state.prefix.as_str()) {
|
if !content.starts_with(state.prefix.as_str()) {
|
||||||
if let Some(titlebot_msg) = state.titlebot.resolve(&message).await? {
|
if let Some(titlebot_msg) = state.titlebot.resolve(&content).await? {
|
||||||
state.client.privmsg(&channel, &titlebot_msg).await?;
|
state.client.send_privmsg(origin, &titlebot_msg)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prev_msg) = state.last_msgs.get(&nick) {
|
if let Some(prev_msg) = state.last_msgs.get(author) {
|
||||||
if let Some(formatted) = sed::resolve(prev_msg, &message)? {
|
if let Some(formatted) = sed::resolve(prev_msg, &content)? {
|
||||||
let mut result = ArrayString::<512>::new();
|
let mut result = ArrayString::<512>::new();
|
||||||
write!(result, "<{}> {}", nick, formatted)?;
|
write!(result, "<{}> {}", author, formatted)?;
|
||||||
state.client.privmsg(&channel, &result).await?;
|
state.client.send_privmsg(origin, &result)?;
|
||||||
state.last_msgs.insert(nick, formatted.to_string());
|
state.last_msgs.insert(author.into(), formatted.to_string());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.last_msgs.insert(nick, message);
|
state.last_msgs.insert(author.into(), content);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let (command, remainder) = separate_to_space(&message, state.prefix.len());
|
let (command, remainder) = separate_to_space(&content, state.prefix.len());
|
||||||
tracing::debug!("Command received ({:?}; {:?})", command, remainder);
|
tracing::debug!("Command received ({:?}; {:?})", command, remainder);
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
"help" => {
|
"help" => {
|
||||||
for help_line in HELP {
|
for help_line in HELP {
|
||||||
state.client.privmsg(&channel, help_line).await?;
|
state.client.send_privmsg(origin, help_line)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"waifu" => {
|
"waifu" => {
|
||||||
|
@ -225,76 +245,72 @@ async fn handle_privmsg(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.as_str())
|
.map(|v| v.as_str())
|
||||||
.unwrap_or("Invalid category. Valid categories: https://waifu.pics/docs");
|
.unwrap_or("Invalid category. Valid categories: https://waifu.pics/docs");
|
||||||
state.client.privmsg(&channel, response).await?;
|
state.client.send_privmsg(origin, response)?;
|
||||||
}
|
}
|
||||||
"mock" => {
|
"mock" => {
|
||||||
misc::execute_leek(
|
leek::execute_leek(
|
||||||
state,
|
state,
|
||||||
LeekCommand::Mock,
|
leek::LeekCommand::Mock,
|
||||||
channel,
|
origin,
|
||||||
remainder.unwrap_or(&nick),
|
remainder.unwrap_or(author),
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"leet" => {
|
"leet" => {
|
||||||
misc::execute_leek(
|
leek::execute_leek(
|
||||||
state,
|
state,
|
||||||
LeekCommand::Leet,
|
leek::LeekCommand::Leet,
|
||||||
channel,
|
origin,
|
||||||
remainder.unwrap_or(&nick),
|
remainder.unwrap_or(author),
|
||||||
)
|
)?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"owo" => {
|
"owo" => {
|
||||||
misc::execute_leek(state, LeekCommand::Owo, channel, remainder.unwrap_or(&nick))
|
leek::execute_leek(
|
||||||
.await?;
|
state,
|
||||||
|
leek::LeekCommand::Owo,
|
||||||
|
origin,
|
||||||
|
remainder.unwrap_or(author),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
"ev" => {
|
"ev" => {
|
||||||
let result = misc::mathbot(nick, remainder, &mut state.last_eval)?;
|
let result = misc::mathbot(author.into(), remainder, &mut state.last_eval)?;
|
||||||
state.client.privmsg(&channel, &result).await?;
|
state.client.send_privmsg(origin, &result)?;
|
||||||
}
|
}
|
||||||
"grab" => {
|
"grab" => {
|
||||||
if let Some(target) = remainder {
|
if let Some(target) = remainder {
|
||||||
if target == nick {
|
if target == author {
|
||||||
state
|
state
|
||||||
.client
|
.client
|
||||||
.privmsg(&channel, "You can't grab yourself")
|
.send_privmsg(target, "You can't grab yourself")?;
|
||||||
.await?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Some(prev_msg) = state.last_msgs.get(target) {
|
if let Some(prev_msg) = state.last_msgs.get(target) {
|
||||||
if state.db.add_quote(prev_msg.clone(), target.into()).await {
|
if state.db.add_quote(prev_msg.clone(), target.into()).await {
|
||||||
state.client.privmsg(&channel, "Quote added").await?;
|
state.client.send_privmsg(target, "Quote added")?;
|
||||||
} else {
|
} else {
|
||||||
state
|
state
|
||||||
.client
|
.client
|
||||||
.privmsg(&channel, "A database error has occurred")
|
.send_privmsg(target, "A database error has occurred")?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state
|
state
|
||||||
.client
|
.client
|
||||||
.privmsg(&channel, "No previous messages to grab")
|
.send_privmsg(target, "No previous messages to grab")?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state
|
state.client.send_privmsg(origin, "No nickname to grab")?;
|
||||||
.client
|
|
||||||
.privmsg(&channel, "No nickname to grab")
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"quot" => {
|
"quot" => {
|
||||||
if let Some(quote) = state.db.get_quote(remainder.map(|v| v.to_string())).await {
|
if let Some(quote) = state.db.get_quote(remainder.map(|v| v.to_string())).await {
|
||||||
let mut resp = ArrayString::<512>::new();
|
let mut resp = ArrayString::<512>::new();
|
||||||
write!(resp, "\"{}\" ~{}", quote.0, quote.1)?;
|
write!(resp, "\"{}\" ~{}", quote.0, quote.1)?;
|
||||||
state.client.privmsg(&channel, &resp).await?;
|
state.client.send_privmsg(origin, &resp)?;
|
||||||
} else {
|
} else {
|
||||||
state.client.privmsg(&channel, "No quotes found").await?;
|
state.client.send_privmsg(origin, "No quotes found")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
state.client.privmsg(&channel, "Unknown command").await?;
|
state.client.send_privmsg(origin, "Unknown command")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ExecutorConnection;
|
use crate::ExecutorConnection;
|
||||||
|
use serde_json::Value::Null;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
@ -16,7 +17,7 @@ pub async fn run(
|
||||||
.and(warp::post())
|
.and(warp::post())
|
||||||
.and(warp::body::json())
|
.and(warp::body::json())
|
||||||
.and(tx_filter)
|
.and(tx_filter)
|
||||||
.and_then(crate::bots::git::handle_post);
|
.and_then(handle_webhook);
|
||||||
|
|
||||||
let filter = db_filter.or(tx_filter);
|
let filter = db_filter.or(tx_filter);
|
||||||
warp::serve(filter).run(listen).await;
|
warp::serve(filter).run(listen).await;
|
||||||
|
@ -36,3 +37,36 @@ async fn handle(db: ExecutorConnection) -> Result<impl warp::Reply, warp::Reject
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_webhook(
|
||||||
|
json: serde_json::Value,
|
||||||
|
tx: Sender<String>,
|
||||||
|
) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
if json["commits"] != Null {
|
||||||
|
let commits = json["commits"].as_array().unwrap();
|
||||||
|
let repo = &json["repository"]["full_name"].as_str().unwrap().trim();
|
||||||
|
if commits.len() != 1 {
|
||||||
|
tx.send(format!("{} new commits on {}:", commits.len(), repo))
|
||||||
|
.await
|
||||||
|
.expect("Failed to send string to main thread");
|
||||||
|
for commit in commits {
|
||||||
|
let author = &commit["author"]["name"].as_str().unwrap().trim();
|
||||||
|
let message = &commit["message"].as_str().unwrap().trim();
|
||||||
|
tx.send(format!("{} - {}", author, message))
|
||||||
|
.await
|
||||||
|
.expect("Failed to send string to main thread");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let author = &json["commits"][0]["author"]["name"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
.trim();
|
||||||
|
let message = &json["commits"][0]["message"].as_str().unwrap().trim();
|
||||||
|
tx.send(format!("New commit on {}: {} - {}", repo, message, author))
|
||||||
|
.await
|
||||||
|
.expect("Failed to send string to main thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(warp::reply::with_status("Ok", warp::http::StatusCode::OK))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue