otter/src/server/gpodder/models.rs

185 lines
4.8 KiB
Rust

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::gpodder;
#[derive(Deserialize, Debug)]
pub struct SubscriptionDelta {
pub add: Vec<String>,
pub remove: Vec<String>,
}
#[derive(Serialize, Default)]
pub struct SubscriptionDeltaResponse {
pub add: Vec<String>,
pub remove: Vec<String>,
pub timestamp: i64,
}
#[derive(Serialize)]
pub struct UpdatedUrlsResponse {
pub timestamp: i64,
pub update_urls: Vec<(String, String)>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DeviceType {
Desktop,
Laptop,
Mobile,
Server,
Other,
}
#[derive(Serialize)]
pub struct Device {
pub id: String,
pub caption: String,
pub r#type: DeviceType,
pub subscriptions: i64,
}
#[derive(Deserialize)]
pub struct DevicePatch {
pub caption: Option<String>,
pub r#type: Option<DeviceType>,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
#[serde(tag = "action")]
pub enum EpisodeActionType {
Download,
Play {
#[serde(default)]
started: Option<i32>,
position: i32,
#[serde(default)]
total: Option<i32>,
},
Delete,
New,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct EpisodeAction {
pub podcast: String,
pub episode: String,
pub timestamp: Option<i64>,
#[serde(default)]
pub device: Option<String>,
#[serde(flatten)]
pub action: EpisodeActionType,
}
impl From<gpodder::DeviceType> for DeviceType {
fn from(value: gpodder::DeviceType) -> Self {
match value {
gpodder::DeviceType::Other => Self::Other,
gpodder::DeviceType::Laptop => Self::Laptop,
gpodder::DeviceType::Mobile => Self::Mobile,
gpodder::DeviceType::Server => Self::Server,
gpodder::DeviceType::Desktop => Self::Desktop,
}
}
}
impl From<DeviceType> for gpodder::DeviceType {
fn from(value: DeviceType) -> Self {
match value {
DeviceType::Other => gpodder::DeviceType::Other,
DeviceType::Laptop => gpodder::DeviceType::Laptop,
DeviceType::Mobile => gpodder::DeviceType::Mobile,
DeviceType::Server => gpodder::DeviceType::Server,
DeviceType::Desktop => gpodder::DeviceType::Desktop,
}
}
}
impl From<gpodder::Device> for Device {
fn from(value: gpodder::Device) -> Self {
Self {
id: value.id,
caption: value.caption,
r#type: value.r#type.into(),
subscriptions: value.subscriptions,
}
}
}
impl From<DevicePatch> for gpodder::DevicePatch {
fn from(value: DevicePatch) -> Self {
Self {
caption: value.caption,
r#type: value.r#type.map(Into::into),
}
}
}
impl From<gpodder::EpisodeActionType> for EpisodeActionType {
fn from(value: gpodder::EpisodeActionType) -> Self {
match value {
gpodder::EpisodeActionType::New => Self::New,
gpodder::EpisodeActionType::Delete => Self::Delete,
gpodder::EpisodeActionType::Download => Self::Download,
gpodder::EpisodeActionType::Play {
started,
position,
total,
} => Self::Play {
started,
position,
total,
},
}
}
}
impl From<EpisodeActionType> for gpodder::EpisodeActionType {
fn from(value: EpisodeActionType) -> Self {
match value {
EpisodeActionType::New => gpodder::EpisodeActionType::New,
EpisodeActionType::Delete => gpodder::EpisodeActionType::Delete,
EpisodeActionType::Download => gpodder::EpisodeActionType::Download,
EpisodeActionType::Play {
started,
position,
total,
} => gpodder::EpisodeActionType::Play {
started,
position,
total,
},
}
}
}
impl From<gpodder::EpisodeAction> for EpisodeAction {
fn from(value: gpodder::EpisodeAction) -> Self {
Self {
podcast: value.podcast,
episode: value.episode,
timestamp: value.timestamp.map(|ts| ts.timestamp()),
device: value.device,
action: value.action.into(),
}
}
}
impl From<EpisodeAction> for gpodder::EpisodeAction {
fn from(value: EpisodeAction) -> Self {
Self {
podcast: value.podcast,
episode: value.episode,
// TODO remove this unwrap
timestamp: value
.timestamp
.map(|ts| DateTime::from_timestamp(ts, 0).unwrap()),
device: value.device,
action: value.action.into(),
time_changed: DateTime::<Utc>::MIN_UTC,
}
}
}