aboutsummaryrefslogtreecommitdiffstats
path: root/src/web_server.rs
diff options
context:
space:
mode:
authorJokler <jokler@protonmail.com>2020-02-22 22:46:06 +0100
committerJokler <jokler@protonmail.com>2020-02-22 23:20:10 +0100
commit84804836f5c1e782c77f1bbf676177151558e008 (patch)
tree55f0ee9664018f6ed0cc41d2cfcf13ca3e0ffe60 /src/web_server.rs
parent5eea11a03c11551091b2c72f48590aec7f5410f0 (diff)
downloadpokebot-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.rs104
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("--:--"))
+ }
+ }
+}