Added Functionality for Sending Current play position
This commit is contained in:
@@ -24,6 +24,65 @@ struct AuthenticateUserByName<'a> {
|
||||
pw: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct PlaybackStartInfo<'a> {
|
||||
#[serde(rename = "ItemId")]
|
||||
item_id: &'a str,
|
||||
|
||||
#[serde(rename = "PositionTicks", skip_serializing_if = "Option::is_none")]
|
||||
position_ticks: Option<i64>,
|
||||
|
||||
#[serde(rename = "CanSeek")]
|
||||
can_seek: bool,
|
||||
|
||||
#[serde(rename = "IsPaused")]
|
||||
is_paused: bool,
|
||||
|
||||
#[serde(rename = "IsMuted")]
|
||||
is_muted: bool,
|
||||
|
||||
// Optional but harmless to include; some servers like seeing it present.
|
||||
#[serde(rename = "MediaSourceId", skip_serializing_if = "Option::is_none")]
|
||||
media_source_id: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct PlaybackProgressInfo<'a> {
|
||||
#[serde(rename = "ItemId")]
|
||||
item_id: &'a str,
|
||||
|
||||
#[serde(rename = "PositionTicks", skip_serializing_if = "Option::is_none")]
|
||||
position_ticks: Option<i64>,
|
||||
|
||||
#[serde(rename = "CanSeek")]
|
||||
can_seek: bool,
|
||||
|
||||
#[serde(rename = "IsPaused")]
|
||||
is_paused: bool,
|
||||
|
||||
#[serde(rename = "IsMuted")]
|
||||
is_muted: bool,
|
||||
|
||||
#[serde(rename = "MediaSourceId", skip_serializing_if = "Option::is_none")]
|
||||
media_source_id: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct PlaybackStopInfo<'a> {
|
||||
#[serde(rename = "ItemId")]
|
||||
item_id: &'a str,
|
||||
|
||||
#[serde(rename = "PositionTicks", skip_serializing_if = "Option::is_none")]
|
||||
position_ticks: Option<i64>,
|
||||
|
||||
#[serde(rename = "MediaSourceId", skip_serializing_if = "Option::is_none")]
|
||||
media_source_id: Option<&'a str>,
|
||||
|
||||
#[serde(rename = "Failed")]
|
||||
failed: bool,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AuthenticationResult {
|
||||
#[serde(rename = "AccessToken")]
|
||||
@@ -52,6 +111,7 @@ struct PlaylistItemsResponse {
|
||||
total_record_count: Option<usize>,
|
||||
}
|
||||
|
||||
|
||||
impl JellyfinClient {
|
||||
pub fn from_config(cfg: &Config) -> Result<Self, String> {
|
||||
let token = cfg
|
||||
@@ -179,6 +239,87 @@ impl JellyfinClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn report_playback_start(&self, item_id: &str, position_ticks: Option<i64>) -> Result<(), String> {
|
||||
let base = self.base_url.trim_end_matches('/');
|
||||
let url = format!("{base}/Sessions/Playing");
|
||||
|
||||
let body = PlaybackStartInfo {
|
||||
item_id,
|
||||
position_ticks,
|
||||
can_seek: true,
|
||||
is_paused: false,
|
||||
is_muted: false,
|
||||
media_source_id: Some(item_id),
|
||||
};
|
||||
|
||||
let resp = self
|
||||
.client
|
||||
.post(url)
|
||||
.header("X-Emby-Token", &self.token)
|
||||
.json(&body)
|
||||
.send()
|
||||
.map_err(|e| format!("report_playback_start request failed: {e}"))?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("report_playback_start HTTP {}", resp.status()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn report_playback_progress(&self, item_id: &str, position_ticks: Option<i64>, is_paused: bool) -> Result<(), String> {
|
||||
let base = self.base_url.trim_end_matches('/');
|
||||
let url = format!("{base}/Sessions/Playing/Progress");
|
||||
|
||||
let body = PlaybackProgressInfo {
|
||||
item_id,
|
||||
position_ticks,
|
||||
can_seek: true,
|
||||
is_paused,
|
||||
is_muted: false,
|
||||
media_source_id: Some(item_id),
|
||||
};
|
||||
|
||||
let resp = self
|
||||
.client
|
||||
.post(url)
|
||||
.header("X-Emby-Token", &self.token)
|
||||
.json(&body)
|
||||
.send()
|
||||
.map_err(|e| format!("report_playback_progress request failed: {e}"))?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("report_playback_progress HTTP {}", resp.status()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn report_playback_stopped(&self, item_id: &str, position_ticks: Option<i64>, failed: bool) -> Result<(), String> {
|
||||
let base = self.base_url.trim_end_matches('/');
|
||||
let url = format!("{base}/Sessions/Playing/Stopped");
|
||||
|
||||
let body = PlaybackStopInfo {
|
||||
item_id,
|
||||
position_ticks,
|
||||
media_source_id: Some(item_id),
|
||||
failed,
|
||||
};
|
||||
|
||||
let resp = self
|
||||
.client
|
||||
.post(url)
|
||||
.header("X-Emby-Token", &self.token)
|
||||
.json(&body)
|
||||
.send()
|
||||
.map_err(|e| format!("report_playback_stopped request failed: {e}"))?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("report_playback_stopped HTTP {}", resp.status()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn list_views(&self, user_id: &str) -> Result<Vec<JfItem>, String> {
|
||||
let url = format!("{}/Users/{}/Views", self.base_url, user_id);
|
||||
|
||||
Reference in New Issue
Block a user