plex_api/myplex/
account.rs

1use secrecy::SecretString;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use serde_repr::Deserialize_repr;
5use serde_with::{json::JsonString, serde_as};
6use std::collections::HashMap;
7use time::OffsetDateTime;
8
9#[derive(Deserialize, Debug, Clone)]
10#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
11#[serde(rename_all = "camelCase")]
12pub struct SubscriptionSummary {
13    pub active: bool,
14    #[serde(with = "time::serde::rfc3339::option")]
15    pub subscribed_at: Option<OffsetDateTime>,
16    pub status: SubscriptionStatus,
17    pub payment_service: Option<String>,
18    pub plan: Option<String>,
19    pub features: Vec<crate::media_container::server::Feature>,
20}
21
22#[derive(Deserialize, Debug, Clone, Copy)]
23pub enum SubscriptionStatus {
24    Active,
25    Inactive,
26    Canceled,
27    PendingCancellation,
28    Ended,
29    Lapsed,
30    #[cfg(not(feature = "tests_deny_unknown_fields"))]
31    #[serde(other)]
32    Unknown,
33}
34
35#[derive(Deserialize_repr, Debug, Clone, Copy)]
36#[repr(u8)]
37pub enum AutoSelectSubtitleMode {
38    ManuallySelected = 0,
39    ShownWithForeignAudio = 1,
40    AlwaysEnabled = 2,
41    #[cfg(not(feature = "tests_deny_unknown_fields"))]
42    #[serde(other)]
43    Unknown,
44}
45
46#[allow(clippy::enum_variant_names)]
47#[derive(Deserialize_repr, Debug, Clone, Copy)]
48#[repr(u8)]
49pub enum DefaultSubtitleAccessibility {
50    PreferNonSdhSubtitles = 0,
51    PreferSdhSubtitles = 1,
52    OnlyShowSdhSubtitles = 2,
53    OnlyShowNonSdhSubtitles = 3,
54    #[cfg(not(feature = "tests_deny_unknown_fields"))]
55    #[serde(other)]
56    Unknown,
57}
58
59#[allow(clippy::enum_variant_names)]
60#[derive(Deserialize_repr, Debug, Clone, Copy)]
61#[repr(u8)]
62pub enum DefaultSubtitleForced {
63    PreferNonForcedSubtitles = 0,
64    PreferForcedSubtitles = 1,
65    OnlyShowForcedSubtitles = 2,
66    OnlyShowNonForcedSubtitles = 3,
67    #[cfg(not(feature = "tests_deny_unknown_fields"))]
68    #[serde(other)]
69    Unknown,
70}
71
72#[derive(Deserialize, Debug, Clone)]
73#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
74#[serde(rename_all = "camelCase")]
75pub struct Profile {
76    pub auto_select_audio: bool,
77    pub auto_select_subtitle: AutoSelectSubtitleMode,
78    pub default_subtitle_accessibility: DefaultSubtitleAccessibility,
79    pub default_subtitle_forced: DefaultSubtitleForced,
80    pub default_audio_language: Option<String>,
81    pub default_subtitle_language: Option<String>,
82}
83
84#[derive(Deserialize, Debug, Clone)]
85#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
86#[serde(rename_all = "camelCase")]
87pub struct Subscription {
88    pub id: Option<i32>,
89    pub mode: String,
90    pub state: String,
91    pub renews_at: Option<OffsetDateTime>,
92    pub ends_at: Option<OffsetDateTime>,
93    pub r#type: Option<String>,
94    pub transfer: Option<bool>,
95    pub billing: Option<Value>,
96    pub canceled: Option<bool>,
97    pub grace_period: Option<bool>,
98    pub on_hold: Option<bool>,
99    pub can_upgrade: Option<bool>,
100    pub can_reactivate: Option<bool>,
101    pub can_downgrade: Option<bool>,
102    pub can_convert: Option<bool>,
103}
104
105#[derive(Deserialize, Debug, Clone)]
106#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
107pub struct Service {
108    pub identifier: String,
109    pub endpoint: String,
110    pub token: Option<SecretString>,
111    pub secret: Option<SecretString>,
112    pub status: String,
113}
114
115#[derive(Deserialize, Debug, Clone)]
116#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
117#[serde(rename_all = "camelCase")]
118pub struct MyPlexAccount {
119    pub id: u64,
120    pub uuid: String,
121    pub username: String,
122    pub friendly_name: String,
123    pub confirmed: bool,
124    pub title: String,
125    pub email: String,
126    pub thumb: String,
127    pub locale: Option<String>,
128    pub email_only_auth: bool,
129    pub has_password: bool,
130    pub cloud_sync_device: Option<String>,
131    pub auth_token: SecretString,
132    pub mailing_list_status: Option<String>,
133    pub mailing_list_active: bool,
134    pub scrobble_types: String,
135    pub pin: Option<String>,
136    pub subscription: SubscriptionSummary,
137    pub subscription_description: Option<String>,
138    pub restricted: bool,
139    pub home: bool,
140    pub guest: bool,
141    pub queue_email: Option<String>,
142    pub queue_uid: Option<HashMap<String, String>>,
143    pub home_size: i32,
144    pub max_home_size: i32,
145    #[serde(with = "time::serde::timestamp::option")]
146    pub remember_expires_at: Option<OffsetDateTime>,
147    pub profile: Profile,
148    pub entitlements: Vec<String>,
149    pub roles: Option<Vec<String>>,
150    pub services: Vec<Service>,
151    pub protected: bool,
152    pub country: String,
153    pub home_admin: bool,
154    pub ads_consent: Option<bool>,
155    #[serde(with = "time::serde::timestamp::option")]
156    pub ads_consent_set_at: Option<OffsetDateTime>,
157    #[serde(with = "time::serde::timestamp::option")]
158    pub ads_consent_reminder_at: Option<OffsetDateTime>,
159    pub anonymous: Option<bool>,
160    pub experimental_features: bool,
161    pub two_factor_enabled: bool,
162    pub backup_codes_created: bool,
163    #[serde(with = "time::serde::timestamp")]
164    pub joined_at: OffsetDateTime,
165
166    pub restriction_profile: Option<RestrictionProfile>,
167    pub mapped_restriction_profile: Option<RestrictionProfile>,
168
169    // Some managed guest users don't have subscription info
170    pub subscriptions: Option<Vec<Subscription>>,
171    pub past_subscriptions: Option<Vec<Subscription>>,
172    pub trials: Option<Vec<Subscription>>,
173
174    // TODO: The next field was met only once
175    pub settings: Option<Vec<Settings>>,
176
177    // TODO: I don't have a valid example with the data yet for the following fields
178    pub custom_restrictions: Option<CustomRestrictions>,
179    pub providers: Option<Vec<String>>,
180}
181
182#[derive(Deserialize, Debug, Clone)]
183#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
184pub struct CustomRestrictions {
185    pub all: Option<bool>,
186    pub movies: Option<bool>,
187    pub music: Option<bool>,
188    pub photos: Option<bool>,
189    pub television: Option<bool>,
190}
191
192#[derive(Debug, Deserialize, Clone)]
193#[serde(tag = "id", rename_all = "camelCase")]
194pub enum Settings {
195    Experience(ExperienceSettingsContainer),
196    #[cfg(not(feature = "tests_deny_unknown_fields"))]
197    #[serde(other)]
198    Unknown,
199}
200
201#[derive(Debug, Deserialize, Clone)]
202#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
203#[serde(rename_all = "camelCase")]
204pub struct ExperienceSettingsContainer {
205    pub hidden: bool,
206    #[serde(with = "time::serde::timestamp")]
207    pub updated_at: OffsetDateTime,
208
209    #[serde(flatten)]
210    pub settings: ExperienceSettingsFormat,
211}
212
213#[serde_as]
214#[derive(Debug, Deserialize, Clone)]
215#[serde(tag = "type", content = "value", rename_all = "camelCase")]
216pub enum ExperienceSettingsFormat {
217    Json(#[serde_as(as = "JsonString")] ExperienceSettings),
218    #[cfg(not(feature = "tests_deny_unknown_fields"))]
219    #[serde(other)]
220    Unknown,
221}
222
223#[derive(Debug, Deserialize, Clone)]
224#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
225#[serde(rename_all = "camelCase")]
226pub struct ExperienceSettings {
227    pub auto_home_hubs_enabled: bool,
228    pub auto_pinned_providers: Vec<String>,
229    pub schema_version: i32,
230    pub home_settings: ExperienceHomeSettings,
231    pub sidebar_settings: ExperienceSidebarSettings,
232    pub reminders: Vec<String>,
233}
234
235#[derive(Debug, Deserialize, Clone)]
236#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
237#[serde(rename_all = "camelCase")]
238pub struct ExperienceHomeSettings {
239    pub settings_key: String,
240    pub hubs: Vec<String>,
241}
242
243#[derive(Debug, Deserialize, Clone)]
244#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
245#[serde(rename_all = "camelCase")]
246pub struct ExperienceSidebarSettings {
247    pub has_completed_setup: bool,
248    pub pinned_sources: Vec<SidebarSource>,
249}
250
251#[derive(Debug, Deserialize, Clone)]
252#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
253#[serde(rename_all = "camelCase")]
254pub struct SidebarSource {
255    pub key: String,
256    pub source_type: String,
257    pub machine_identifier: String,
258    pub provider_identifier: String,
259    #[serde(rename = "directoryID")]
260    pub directory_id: String,
261    pub directory_icon: String,
262    pub title: String,
263    pub server_friendly_name: String,
264    pub provider_source_title: String,
265    pub is_cloud: bool,
266    pub is_full_owned_server: bool,
267}
268
269#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
270#[serde(rename_all = "snake_case")]
271pub enum RestrictionProfile {
272    LittleKid,
273    OlderKid,
274    Teen,
275    #[cfg(not(feature = "tests_deny_unknown_fields"))]
276    #[serde(other)]
277    Unknown,
278}