feat: schedule content
This commit is contained in:
parent
12ad788452
commit
381c086eba
6 changed files with 150 additions and 16 deletions
|
|
@ -7,7 +7,7 @@ pub struct Args {
|
|||
/// URL host of the ErsatzTv service
|
||||
pub host: String,
|
||||
/// UUID of the build
|
||||
pub build_id: Uuid,
|
||||
pub build_id: String,
|
||||
/// The playout build mode
|
||||
pub playout_mode: PlayoutMode,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,32 @@
|
|||
use anyhow::anyhow;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::ersatz_tv::models::ContextModel;
|
||||
use crate::ersatz_tv::models::{ContextModel, ScheduleAllContentDto, SearchQueryDto};
|
||||
|
||||
pub mod models;
|
||||
|
||||
pub struct Client {
|
||||
_client: reqwest::Client,
|
||||
host: String,
|
||||
build_id: String,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(host: String) -> anyhow::Result<Self> {
|
||||
pub fn new(host: &String, build_id: &String) -> anyhow::Result<Self> {
|
||||
let _client = reqwest::Client::builder().gzip(true).build()?;
|
||||
Ok(Self { _client, host })
|
||||
Ok(Self {
|
||||
_client,
|
||||
host: host.clone(),
|
||||
build_id: build_id.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_context(&self, build_id: Uuid) -> anyhow::Result<ContextModel> {
|
||||
pub async fn get_context(&self) -> anyhow::Result<ContextModel> {
|
||||
let response = self
|
||||
._client
|
||||
.get(format!(
|
||||
"{}/api/scripted/playout/build/{}/context",
|
||||
self.host, build_id
|
||||
self.host, self.build_id
|
||||
))
|
||||
.send()
|
||||
.await?;
|
||||
|
|
@ -39,4 +44,72 @@ impl Client {
|
|||
|
||||
Ok(context)
|
||||
}
|
||||
|
||||
async fn _load_content(&self, content: &SearchQueryDto) -> anyhow::Result<()> {
|
||||
let response = self
|
||||
._client
|
||||
.post(format!(
|
||||
"{}/api/scripted/playout/build/{}/add_search",
|
||||
self.host, self.build_id
|
||||
))
|
||||
.json(content)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if let Err(err) = &response.error_for_status_ref() {
|
||||
return Err(anyhow!(
|
||||
"Request for {} returned with status {}:\n{}",
|
||||
err.url().unwrap().path(),
|
||||
err.status().unwrap_or_default(),
|
||||
response.text().await?
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn load_content<T: IntoIterator<Item = SearchQueryDto>>(
|
||||
&self,
|
||||
content: T,
|
||||
) -> anyhow::Result<()> {
|
||||
for item in content {
|
||||
self._load_content(&item).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn _schedule_content(&self, content: &ScheduleAllContentDto) -> anyhow::Result<()> {
|
||||
let response = self
|
||||
._client
|
||||
.post(format!(
|
||||
"{}/api/scripted/playout/build/{}/add_all",
|
||||
self.host, self.build_id
|
||||
))
|
||||
.json(content)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if let Err(err) = &response.error_for_status_ref() {
|
||||
return Err(anyhow!(
|
||||
"Request for {} returned with status {}:\n{}",
|
||||
err.url().unwrap().path(),
|
||||
err.status().unwrap_or_default(),
|
||||
response.text().await?
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn schedule_content<T: IntoIterator<Item = ScheduleAllContentDto>>(
|
||||
&self,
|
||||
content: T,
|
||||
) -> anyhow::Result<()> {
|
||||
for item in content {
|
||||
self._schedule_content(&item).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,3 +8,42 @@ pub struct ContextModel {
|
|||
finish_time: chrono::DateTime<chrono::Local>,
|
||||
is_done: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SearchQueryDto {
|
||||
pub key: String,
|
||||
pub order: SearchQueryOrder,
|
||||
pub query: SearchQueryValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ScheduleAllContentDto {
|
||||
#[serde(rename = "content")]
|
||||
pub key: String,
|
||||
pub custom_title: String,
|
||||
pub disable_watermarks: bool,
|
||||
pub filler_kind: FillerKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum SearchQueryValue {
|
||||
SongTitle(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SearchQueryOrder {
|
||||
Chronological,
|
||||
Shuffle,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum FillerKind {
|
||||
None,
|
||||
Preroll,
|
||||
Midroll,
|
||||
Postroll,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ impl Client {
|
|||
));
|
||||
}
|
||||
|
||||
println!("{}", response.url());
|
||||
|
||||
let context: GetItemsResponseModel = response.json().await?;
|
||||
|
||||
Ok(context)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub struct GetItemsResponseModel {
|
|||
pub struct ItemModel {
|
||||
pub name: String,
|
||||
pub id: String,
|
||||
pub path: String,
|
||||
pub path: std::path::PathBuf,
|
||||
pub production_year: Option<i64>,
|
||||
pub is_folder: bool,
|
||||
#[serde(rename = "Type")]
|
||||
|
|
|
|||
38
src/main.rs
38
src/main.rs
|
|
@ -1,20 +1,44 @@
|
|||
use clap::Parser;
|
||||
use tv_scheduler::{config::Args, ersatz_tv, jellyfin};
|
||||
use tv_scheduler::{
|
||||
config::Args,
|
||||
ersatz_tv::{
|
||||
self,
|
||||
models::{
|
||||
FillerKind, ScheduleAllContentDto, SearchQueryDto, SearchQueryOrder, SearchQueryValue,
|
||||
},
|
||||
},
|
||||
jellyfin,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let args = Args::parse();
|
||||
// let tv = ersatz_tv::Client::new(args.host)?;
|
||||
|
||||
// let context = tv.get_context(args.build_id).await?;
|
||||
|
||||
// println!("{:?}", context);
|
||||
|
||||
let jelly = jellyfin::Client::new("https://media.hoshikusu.xyz")?;
|
||||
|
||||
let item = jelly.get_random_vgm_album().await?;
|
||||
let songs = jelly.get_songs(item.id).await?;
|
||||
println!("{:#?}", songs);
|
||||
|
||||
let tv = ersatz_tv::Client::new(&args.host, &args.build_id)?;
|
||||
|
||||
let content_payload = songs.items.iter().map(|song| SearchQueryDto {
|
||||
key: song.id.clone(),
|
||||
order: SearchQueryOrder::Chronological,
|
||||
query: SearchQueryValue::SongTitle(format!(r#"title:"{}" AND library_id:9"#, song.name)),
|
||||
});
|
||||
|
||||
tv.load_content(content_payload).await?;
|
||||
|
||||
let schedule_payload = songs.items.iter().map(|song| ScheduleAllContentDto {
|
||||
key: song.id.clone(),
|
||||
custom_title: song.name.clone(),
|
||||
disable_watermarks: false,
|
||||
filler_kind: FillerKind::None,
|
||||
});
|
||||
|
||||
tv.schedule_content(schedule_payload).await?;
|
||||
|
||||
// println!("{:#?}", songs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue