diff --git a/Cargo.toml b/Cargo.toml index eef3f4a..7b617db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ lazy_static = "1.4" sedregex = "0.2" rusqlite = { version = "0.26", features = ["bundled"] } hyper = { version = "0.14", features = ["server"] } +warp = "0.3" [features] tls = ["async-circe/tls"] diff --git a/src/bots/git.rs b/src/bots/git.rs new file mode 100644 index 0000000..c43389d --- /dev/null +++ b/src/bots/git.rs @@ -0,0 +1,64 @@ +use serde_json::Value::Null; +use std::net::SocketAddr; +use tokio::sync::mpsc::Sender; +use warp::Filter; + +#[derive(Clone)] +struct Tx { + tx: Sender, +} + +impl Tx { + fn new(tx: Sender) -> Self { + Tx { tx } + } +} + +async fn handle_post(json: serde_json::Value, tx: Tx) -> Result { + 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.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.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.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)) +} + +pub async fn run(tx: Sender, listen: SocketAddr) -> Result<(), tokio::io::Error> { + //let addr = SocketAddr::from((Ipv4Addr::new(192, 168, 1, 66), 51001)); + //println!("{:?}", addr); + let tx = Tx::new(tx); + let tx_filter = warp::any().map(move || tx.clone()); + + let filter = warp::post() + .and(warp::body::json()) + .and(tx_filter) + .and_then(handle_post); + + warp::serve(filter).run(listen).await; + + Ok(()) +} diff --git a/src/bots/mod.rs b/src/bots/mod.rs index 99c5cd8..6a3a58d 100644 --- a/src/bots/mod.rs +++ b/src/bots/mod.rs @@ -1,3 +1,4 @@ +pub mod git; pub mod leek; pub mod misc; pub mod sed; diff --git a/src/main.rs b/src/main.rs index 893540b..e65fb10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,10 +12,11 @@ use serde::Deserialize; use std::fmt::Write; use std::fs::File; use std::io::Read; +use std::net::SocketAddr; use std::thread; use std::{collections::HashMap, env}; -use std::net::SocketAddr; use tokio::select; +use tokio::sync::mpsc::{channel, Receiver}; use tracing_subscriber::EnvFilter; // this will be displayed when the help command is used @@ -54,6 +55,8 @@ pub struct AppState { last_eval: HashMap, titlebot: Titlebot, db: ExecutorConnection, + git_channel: String, + git_recv: Receiver, } #[derive(Deserialize)] @@ -68,7 +71,8 @@ struct ClientConf { spotify_client_secret: String, prefix: String, db_path: Option, - http_listen: Option + http_listen: Option, + git_channel: String, } #[tokio::main(flavor = "current_thread")] @@ -96,6 +100,13 @@ async fn main() -> anyhow::Result<()> { &client_config.spotify_client_secret, ); + let http_listen = client_config + .http_listen + .unwrap_or_else(|| SocketAddr::from(([127, 0, 0, 1], 5000))); + + let (git_tx, git_recv) = channel(512); + bots::git::run(git_tx, http_listen).await?; + let config = Config::runtime_config( client_config.channels, client_config.host, @@ -115,9 +126,10 @@ async fn main() -> anyhow::Result<()> { last_eval: HashMap::new(), titlebot: Titlebot::create(spotify_creds).await?, db: db_conn, + git_channel: client_config.git_channel, + git_recv, }; - let http_listen = client_config.http_listen.unwrap_or_else(|| SocketAddr::from(([127, 0, 0, 1], 5000))); if let Err(e) = executor(state, http_listen).await { tracing::error!("Error in message loop: {}", e); } @@ -153,6 +165,10 @@ async fn message_loop(state: &mut AppState) -> anyhow::Result<()> { .await?; } } + + if let Some(s) = state.git_recv.recv().await { + state.client.privmsg(&state.git_channel, &s).await?; + } } Ok(()) } diff --git a/src/web_service.rs b/src/web_service.rs index ce172ed..7a3c720 100644 --- a/src/web_service.rs +++ b/src/web_service.rs @@ -1,23 +1,29 @@ -use std::net::SocketAddr; use crate::ExecutorConnection; -use std::convert::Infallible; -use std::sync::Arc; -use hyper::{Body, Request, Response, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Request, Response, Server}; +use std::convert::Infallible; +use std::net::SocketAddr; +use std::sync::Arc; pub async fn run(db: ExecutorConnection, listen: SocketAddr) -> anyhow::Result<()> { let db = Arc::new(db); - Server::bind(&listen).serve(make_service_fn(|_| { - let db = Arc::clone(&db); - async move { - Ok::<_, Infallible>(service_fn(move |r| handle(r, Arc::clone(&db)))) - } - })).await?; + Server::bind(&listen) + .serve(make_service_fn(|_| { + let db = Arc::clone(&db); + async move { Ok::<_, Infallible>(service_fn(move |r| handle(r, Arc::clone(&db)))) } + })) + .await?; Ok(()) } -async fn handle(req: Request, db: Arc) -> Result, Infallible> { - Ok(Response::new(Body::from(format!("{:?}", db.get_quote(None).await)))) +async fn handle( + _req: Request, + db: Arc, +) -> Result, Infallible> { + Ok(Response::new(Body::from(format!( + "{:?}", + db.get_quote(None).await + )))) }