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_audio_accessibility: Option<u32>,
83 pub default_audio_languages: Option<Vec<String>>,
85 pub default_subtitle_language: Option<String>,
86 pub default_subtitle_languages: Option<Vec<String>>,
88 pub watched_indicator: Option<u32>,
90 pub media_reviews_visibility: Option<u32>,
92 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 pub subscriptions: Option<Vec<Subscription>>,
183 pub past_subscriptions: Option<Vec<Subscription>>,
184 pub trials: Option<Vec<Subscription>>,
185
186 pub settings: Option<Vec<Settings>>,
188
189 pub custom_restrictions: Option<CustomRestrictions>,
191 pub providers: Option<Vec<String>>,
192
193 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}