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    // TODO the meaning of this is unknown
82    pub default_audio_accessibility: Option<u32>,
83    // TODO the type of this is unknown
84    pub default_audio_languages: Option<Vec<String>>,
85    pub default_subtitle_language: Option<String>,
86    // TODO the type of this is unknown
87    pub default_subtitle_languages: Option<Vec<String>>,
88    // TODO the meaning of this is unknown
89    pub watched_indicator: Option<u32>,
90    // TODO the meaning of this is unknown
91    pub media_reviews_visibility: Option<u32>,
92    // TODO the type of this is unknown
93    pub media_reviews_languages: Option<Vec<String>>,
94}
95
96#[derive(Deserialize, Debug, Clone)]
97#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
98#[serde(rename_all = "camelCase")]
99pub struct Subscription {
100    pub id: Option<i32>,
101    pub mode: String,
102    pub state: String,
103    pub renews_at: Option<OffsetDateTime>,
104    pub ends_at: Option<OffsetDateTime>,
105    pub r#type: Option<String>,
106    pub transfer: Option<bool>,
107    pub billing: Option<Value>,
108    pub canceled: Option<bool>,
109    pub grace_period: Option<bool>,
110    pub on_hold: Option<bool>,
111    pub can_upgrade: Option<bool>,
112    pub can_reactivate: Option<bool>,
113    pub can_downgrade: Option<bool>,
114    pub can_convert: Option<bool>,
115}
116
117#[derive(Deserialize, Debug, Clone)]
118#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
119pub struct Service {
120    pub identifier: String,
121    pub endpoint: String,
122    pub token: Option<SecretString>,
123    pub secret: Option<SecretString>,
124    pub status: String,
125}
126
127#[derive(Deserialize, Debug, Clone)]
128#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
129#[serde(rename_all = "camelCase")]
130pub struct MyPlexAccount {
131    pub id: u64,
132    pub uuid: String,
133    pub username: String,
134    pub friendly_name: String,
135    pub confirmed: bool,
136    pub title: String,
137    pub email: String,
138    pub thumb: String,
139    pub locale: Option<String>,
140    pub email_only_auth: bool,
141    pub has_password: bool,
142    pub cloud_sync_device: Option<String>,
143    pub auth_token: SecretString,
144    pub mailing_list_status: Option<String>,
145    pub mailing_list_active: bool,
146    pub scrobble_types: String,
147    pub pin: Option<String>,
148    pub subscription: SubscriptionSummary,
149    pub subscription_description: Option<String>,
150    pub restricted: bool,
151    pub home: bool,
152    pub guest: bool,
153    pub queue_email: Option<String>,
154    pub queue_uid: Option<HashMap<String, String>>,
155    pub home_size: i32,
156    pub max_home_size: i32,
157    #[serde(with = "time::serde::timestamp::option")]
158    pub remember_expires_at: Option<OffsetDateTime>,
159    pub profile: Profile,
160    pub entitlements: Vec<String>,
161    pub roles: Option<Vec<String>>,
162    pub services: Vec<Service>,
163    pub protected: bool,
164    pub country: String,
165    pub home_admin: bool,
166    pub ads_consent: Option<bool>,
167    #[serde(with = "time::serde::timestamp::option")]
168    pub ads_consent_set_at: Option<OffsetDateTime>,
169    #[serde(with = "time::serde::timestamp::option")]
170    pub ads_consent_reminder_at: Option<OffsetDateTime>,
171    pub anonymous: Option<bool>,
172    pub experimental_features: bool,
173    pub two_factor_enabled: bool,
174    pub backup_codes_created: bool,
175    #[serde(with = "time::serde::timestamp")]
176    pub joined_at: OffsetDateTime,
177
178    pub restriction_profile: Option<RestrictionProfile>,
179    pub mapped_restriction_profile: Option<RestrictionProfile>,
180
181    // Some managed guest users don't have subscription info
182    pub subscriptions: Option<Vec<Subscription>>,
183    pub past_subscriptions: Option<Vec<Subscription>>,
184    pub trials: Option<Vec<Subscription>>,
185
186    // TODO: The next field was met only once
187    pub settings: Option<Vec<Settings>>,
188
189    // TODO: I don't have a valid example with the data yet for the following fields
190    pub custom_restrictions: Option<CustomRestrictions>,
191    pub providers: Option<Vec<String>>,
192
193    // TODO the type of this is unknown
194    pub attribution_partner: Option<String>,
195}
196
197#[derive(Deserialize, Debug, Clone)]
198#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
199pub struct CustomRestrictions {
200    pub all: Option<bool>,
201    pub movies: Option<bool>,
202    pub music: Option<bool>,
203    pub photos: Option<bool>,
204    pub television: Option<bool>,
205}
206
207#[derive(Debug, Deserialize, Clone)]
208#[serde(tag = "id", rename_all = "camelCase")]
209pub enum Settings {
210    Experience(ExperienceSettingsContainer),
211    #[cfg(not(feature = "tests_deny_unknown_fields"))]
212    #[serde(other)]
213    Unknown,
214}
215
216#[derive(Debug, Deserialize, Clone)]
217#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
218#[serde(rename_all = "camelCase")]
219pub struct ExperienceSettingsContainer {
220    pub hidden: bool,
221    #[serde(with = "time::serde::timestamp")]
222    pub updated_at: OffsetDateTime,
223
224    #[serde(flatten)]
225    pub settings: ExperienceSettingsFormat,
226}
227
228#[serde_as]
229#[derive(Debug, Deserialize, Clone)]
230#[serde(tag = "type", content = "value", rename_all = "camelCase")]
231pub enum ExperienceSettingsFormat {
232    Json(#[serde_as(as = "JsonString")] ExperienceSettings),
233    #[cfg(not(feature = "tests_deny_unknown_fields"))]
234    #[serde(other)]
235    Unknown,
236}
237
238#[derive(Debug, Deserialize, Clone)]
239#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
240#[serde(rename_all = "camelCase")]
241pub struct ExperienceSettings {
242    pub auto_home_hubs_enabled: bool,
243    pub auto_pinned_providers: Vec<String>,
244    pub schema_version: i32,
245    pub home_settings: ExperienceHomeSettings,
246    pub sidebar_settings: ExperienceSidebarSettings,
247    pub reminders: Vec<String>,
248}
249
250#[derive(Debug, Deserialize, Clone)]
251#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
252#[serde(rename_all = "camelCase")]
253pub struct ExperienceHomeSettings {
254    pub settings_key: String,
255    pub hubs: Vec<String>,
256}
257
258#[derive(Debug, Deserialize, Clone)]
259#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
260#[serde(rename_all = "camelCase")]
261pub struct ExperienceSidebarSettings {
262    pub has_completed_setup: bool,
263    pub pinned_sources: Vec<SidebarSource>,
264}
265
266#[derive(Debug, Deserialize, Clone)]
267#[cfg_attr(feature = "tests_deny_unknown_fields", serde(deny_unknown_fields))]
268#[serde(rename_all = "camelCase")]
269pub struct SidebarSource {
270    pub key: String,
271    pub source_type: String,
272    pub machine_identifier: String,
273    pub provider_identifier: String,
274    #[serde(rename = "directoryID")]
275    pub directory_id: String,
276    pub directory_icon: String,
277    pub title: String,
278    pub server_friendly_name: String,
279    pub provider_source_title: String,
280    pub is_cloud: bool,
281    pub is_full_owned_server: bool,
282}
283
284#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
285#[serde(rename_all = "snake_case")]
286pub enum RestrictionProfile {
287    LittleKid,
288    OlderKid,
289    Teen,
290    #[cfg(not(feature = "tests_deny_unknown_fields"))]
291    #[serde(other)]
292    Unknown,
293}