plex_api/server/
prefs.rs

1use crate::{
2    media_container::{
3        preferences::{Preferences as MediaContainerPreferences, Setting, Value},
4        MediaContainerWrapper,
5    },
6    url::SERVER_PREFS,
7    HttpClient, Result,
8};
9use std::mem::discriminant;
10
11#[derive(Debug, Clone)]
12pub struct Preferences<'a> {
13    client: HttpClient,
14    settings: Vec<Setting>,
15    changed: Vec<&'a str>,
16}
17
18impl<'a> Preferences<'a> {
19    #[tracing::instrument(level = "debug", skip(client))]
20    pub async fn new<C: Into<HttpClient>>(client: C) -> Result<Preferences<'a>> {
21        let client = client.into();
22        let mc: MediaContainerWrapper<MediaContainerPreferences> =
23            client.get(SERVER_PREFS).json().await?;
24
25        Ok(Preferences {
26            client,
27            settings: mc.media_container.settings,
28            changed: vec![],
29        })
30    }
31
32    pub fn get(&self, key: &str) -> Option<&Setting> {
33        self.settings.iter().find(|s| s.id == key)
34    }
35
36    pub fn all(&self) -> &[Setting] {
37        &self.settings
38    }
39
40    pub fn set(&mut self, key: &'a str, value: Value) -> Result<&mut Self> {
41        if let Some(setting) = self.settings.iter_mut().find(|s| s.id == key) {
42            if discriminant(&setting.value) == discriminant(&value) {
43                setting.value = value;
44                self.changed.push(key);
45                Ok(self)
46            } else {
47                Err(crate::Error::IncompatibleSettingValues)
48            }
49        } else {
50            Err(crate::Error::RequestedSettingNotFound(key.to_string()))
51        }
52    }
53
54    #[tracing::instrument(level = "debug")]
55    pub async fn commit(self) -> Result<Preferences<'a>> {
56        if self.changed.is_empty() {
57            return Ok(self);
58        }
59
60        let mut params = vec![];
61        for s in self
62            .settings
63            .iter()
64            .filter(|s| self.changed.contains(&s.id.as_str()))
65        {
66            params.push((s.id.as_str(), s.value.to_string()));
67        }
68
69        let uri = format!("{}?{}", SERVER_PREFS, serde_urlencoded::to_string(params)?);
70
71        self.client.put(uri).consume().await?;
72
73        Ok(Preferences {
74            client: self.client,
75            settings: self.settings,
76            changed: vec![],
77        })
78    }
79}