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
|
/// URL host of the ErsatzTv service
|
||||||
pub host: String,
|
pub host: String,
|
||||||
/// UUID of the build
|
/// UUID of the build
|
||||||
pub build_id: Uuid,
|
pub build_id: String,
|
||||||
/// The playout build mode
|
/// The playout build mode
|
||||||
pub playout_mode: PlayoutMode,
|
pub playout_mode: PlayoutMode,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,32 @@
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::ersatz_tv::models::ContextModel;
|
use crate::ersatz_tv::models::{ContextModel, ScheduleAllContentDto, SearchQueryDto};
|
||||||
|
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
_client: reqwest::Client,
|
_client: reqwest::Client,
|
||||||
host: String,
|
host: String,
|
||||||
|
build_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
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()?;
|
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
|
let response = self
|
||||||
._client
|
._client
|
||||||
.get(format!(
|
.get(format!(
|
||||||
"{}/api/scripted/playout/build/{}/context",
|
"{}/api/scripted/playout/build/{}/context",
|
||||||
self.host, build_id
|
self.host, self.build_id
|
||||||
))
|
))
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
@ -39,4 +44,72 @@ impl Client {
|
||||||
|
|
||||||
Ok(context)
|
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>,
|
finish_time: chrono::DateTime<chrono::Local>,
|
||||||
is_done: bool,
|
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?;
|
let context: GetItemsResponseModel = response.json().await?;
|
||||||
|
|
||||||
Ok(context)
|
Ok(context)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ pub struct GetItemsResponseModel {
|
||||||
pub struct ItemModel {
|
pub struct ItemModel {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub path: String,
|
pub path: std::path::PathBuf,
|
||||||
pub production_year: Option<i64>,
|
pub production_year: Option<i64>,
|
||||||
pub is_folder: bool,
|
pub is_folder: bool,
|
||||||
#[serde(rename = "Type")]
|
#[serde(rename = "Type")]
|
||||||
|
|
|
||||||
38
src/main.rs
38
src/main.rs
|
|
@ -1,20 +1,44 @@
|
||||||
use clap::Parser;
|
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]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let args = Args::parse();
|
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 jelly = jellyfin::Client::new("https://media.hoshikusu.xyz")?;
|
||||||
|
|
||||||
let item = jelly.get_random_vgm_album().await?;
|
let item = jelly.get_random_vgm_album().await?;
|
||||||
let songs = jelly.get_songs(item.id).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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue