diff options
| author | Jokler <jokler@protonmail.com> | 2020-02-22 22:46:06 +0100 |
|---|---|---|
| committer | Jokler <jokler@protonmail.com> | 2020-02-22 23:20:10 +0100 |
| commit | 84804836f5c1e782c77f1bbf676177151558e008 (patch) | |
| tree | 55f0ee9664018f6ed0cc41d2cfcf13ca3e0ffe60 /src/web_server.rs | |
| parent | 5eea11a03c11551091b2c72f48590aec7f5410f0 (diff) | |
| download | pokebot-84804836f5c1e782c77f1bbf676177151558e008.tar.gz pokebot-84804836f5c1e782c77f1bbf676177151558e008.zip | |
Add tmtu mode as a front-end
Diffstat (limited to 'src/web_server.rs')
| -rw-r--r-- | src/web_server.rs | 104 |
1 files changed, 101 insertions, 3 deletions
diff --git a/src/web_server.rs b/src/web_server.rs index 02c57e7..80c914c 100644 --- a/src/web_server.rs +++ b/src/web_server.rs @@ -1,17 +1,22 @@ use std::sync::Arc; +use std::time::Duration; use actix::{Actor, Addr, Handler, Message, SyncArbiter, SyncContext}; use actix_web::{ - get, middleware::Logger, web, App, HttpResponse, HttpServer, Responder, ResponseError, + get, http::header, middleware::Logger, post, web, App, Error, HttpResponse, HttpServer, + Responder, ResponseError, }; use askama::actix_web::TemplateIntoResponse; use askama::Template; use derive_more::Display; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use crate::bot::MasterBot; use crate::youtube_dl::AudioMetadata; +mod front_end_cookie; +use front_end_cookie::FrontEnd; + pub struct WebServerArgs { pub domain: String, pub bind_address: String, @@ -28,6 +33,8 @@ pub async fn start(args: WebServerArgs) -> std::io::Result<()> { .data(bot_addr.clone()) .wrap(Logger::default()) .service(index) + .service(tmtu_bot) + .service(post_front_end) .service(web::scope("/api").service(get_bot_list).service(get_bot)) .service(actix_files::Files::new("/static", "static/")) }) @@ -46,6 +53,34 @@ impl Actor for BotExecutor { type Context = SyncContext<Self>; } +#[derive(Deserialize)] +#[serde(rename_all = "kebab-case")] +struct FrontEndForm { + front_end: FrontEnd, +} + +#[post("/front-end")] +async fn post_front_end(form: web::Form<FrontEndForm>) -> Result<HttpResponse, Error> { + front_end_cookie::set_front_end(form.into_inner().front_end).await +} + +struct BotNameListRequest; + +impl Message for BotNameListRequest { + // A plain Vec does not work for some reason + type Result = Result<Vec<String>, ()>; +} + +impl Handler<BotNameListRequest> for BotExecutor { + type Result = Result<Vec<String>, ()>; + + fn handle(&mut self, _: BotNameListRequest, _: &mut Self::Context) -> Self::Result { + let bot = &self.0; + + Ok(bot.bot_names()) + } +} + struct BotDataListRequest; impl Message for BotDataListRequest { @@ -86,17 +121,32 @@ struct OverviewTemplate<'a> { bots: &'a [BotData], } +#[derive(Template)] +#[template(path = "tmtu/index.htm")] +struct TmtuTemplate { + bot_names: Vec<String>, + bot: Option<BotData>, +} + #[derive(Debug, Serialize)] pub struct BotData { pub name: String, pub state: crate::bot::State, pub volume: f64, + pub position: Option<Duration>, pub currently_playing: Option<AudioMetadata>, pub playlist: Vec<AudioMetadata>, } #[get("/")] -async fn index(bot: web::Data<Addr<BotExecutor>>) -> impl Responder { +async fn index(bot: web::Data<Addr<BotExecutor>>, front: FrontEnd) -> Result<HttpResponse, Error> { + match front { + FrontEnd::Lazy => lazy_index(bot).await, + FrontEnd::Tmtu => tmtu_index(bot).await, + } +} + +async fn lazy_index(bot: web::Data<Addr<BotExecutor>>) -> Result<HttpResponse, Error> { let bot_datas = match bot.send(BotDataListRequest).await.unwrap() { Ok(data) => data, Err(_) => Vec::with_capacity(0), @@ -108,6 +158,38 @@ async fn index(bot: web::Data<Addr<BotExecutor>>) -> impl Responder { .into_response() } +async fn tmtu_index(bot: web::Data<Addr<BotExecutor>>) -> Result<HttpResponse, Error> { + let bot_names = bot.send(BotNameListRequest).await.unwrap().unwrap(); + + TmtuTemplate { + bot_names, + bot: None, + } + .into_response() +} + +#[get("/tmtu/{name}")] +async fn tmtu_bot( + bot: web::Data<Addr<BotExecutor>>, + name: web::Path<String>, + front: FrontEnd, +) -> Result<HttpResponse, Error> { + if front != FrontEnd::Tmtu { + return Ok(HttpResponse::Found().header(header::LOCATION, "/").finish()); + } + + let bot_names = bot.send(BotNameListRequest).await.unwrap().unwrap(); + if let Some(bot) = bot.send(BotDataRequest(name.into_inner())).await.unwrap() { + TmtuTemplate { + bot_names, + bot: Some(bot), + } + .into_response() + } else { + Ok(HttpResponse::Found().header(header::LOCATION, "/").finish()) + } +} + #[get("/bots")] async fn get_bot_list(bot: web::Data<Addr<BotExecutor>>) -> impl Responder { let bot_datas = match bot.send(BotDataListRequest).await.unwrap() { @@ -149,3 +231,19 @@ async fn get_bot(bot: web::Data<Addr<BotExecutor>>, name: web::Path<String>) -> Err(ApiErrorKind::NotFound) } } + +mod filters { + use std::time::Duration; + + pub fn fmt_duration(duration: &Option<Duration>) -> Result<String, askama::Error> { + if let Some(duration) = duration { + let secs = duration.as_secs(); + let mins = secs / 60; + let submin_secs = secs % 60; + + Ok(format!("{:02}:{:02}", mins, submin_secs)) + } else { + Ok(String::from("--:--")) + } + } +} |
