Skip to main content

rs_plugin_common_interfaces/
lib.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use strum_macros::EnumString;
4
5pub use domain::{
6    element_type::ElementType,
7    external_images::{ExternalImage, ImageType},
8    other_ids::OtherIds,
9};
10pub use lookup::{
11    RsLookupBook, RsLookupEpisode, RsLookupMedia, RsLookupMovie, RsLookupPerson, RsLookupQuery,
12    RsLookupSerie, RsLookupSerieSeason, RsLookupSong, RsLookupSourceResult, RsLookupWrapper,
13};
14pub use request::{
15    RsCookie, RsCookies, RsRequest, RsRequestFiles, RsRequestPluginRequest, RsRequestStatus,
16};
17pub use url::{RsLink, RsLinkType};
18
19pub use video::{RsAudio, RsResolution, RsVideoCodec, RsVideoFormat};
20
21#[cfg(feature = "rusqlite")]
22pub mod rusqlite;
23
24pub mod lookup;
25pub mod provider;
26pub mod request;
27pub mod url;
28
29pub mod video;
30
31pub mod domain;
32
33pub const INTERFACE_VERSION: u16 = 1;
34
35#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
36#[serde(rename_all = "camelCase")]
37pub struct CustomParam {
38    pub name: String,
39    pub param: CustomParamTypes,
40    pub description: Option<String>,
41    #[serde(default)]
42    pub required: bool,
43}
44
45#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
46#[serde(rename_all = "camelCase")]
47pub struct PluginInformation {
48    pub name: String,
49    pub capabilities: Vec<PluginType>,
50    pub publisher: String,
51    pub description: String,
52    pub credential_kind: Option<CredentialType>,
53    pub repo: Option<String>,
54    pub oauth_url: Option<String>,
55    pub version: u16,
56
57    #[serde(default)]
58    pub settings: Vec<CustomParam>,
59
60    pub interface_version: u16,
61}
62
63impl PluginInformation {
64    pub fn capabilities_tostring(&self) -> String {
65        self.capabilities
66            .iter()
67            .map(|plugin| plugin.to_string())
68            .collect::<Vec<_>>()
69            .join(", ")
70    }
71}
72
73#[derive(
74    Debug, Serialize, Deserialize, Clone, PartialEq, strum_macros::Display, EnumString, Default,
75)]
76#[serde(rename_all = "camelCase")]
77#[strum(serialize_all = "camelCase")]
78pub enum PluginType {
79    ImageClassification,
80    UrlParser,
81    Request,
82    Lookup,
83    LookupMetadata,
84    Provider,
85    VideoConvert,
86    #[default]
87    Other,
88}
89
90#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
91#[serde(rename_all = "camelCase")]
92pub struct RsRemainingCredits {
93    pub number: u64,
94    pub unit: String,
95}
96
97#[derive(
98    Debug, Serialize, Deserialize, Clone, PartialEq, strum_macros::Display, EnumString, Default,
99)]
100#[serde(rename_all = "camelCase", tag = "type")]
101#[strum(serialize_all = "camelCase")]
102pub enum CredentialType {
103    Url,
104    Password,
105    Oauth {
106        /// Oauth url to get code from user; use #redirecturi# in the url
107        url: String,
108    },
109    #[default]
110    Token,
111}
112
113#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, strum_macros::Display, EnumString)]
114#[serde(rename_all = "camelCase")]
115#[strum(serialize_all = "camelCase")]
116pub enum CustomParamTypes {
117    Text(Option<String>),
118    Url(Option<String>),
119    Integer(Option<i64>),
120    UInteger(Option<u64>),
121    Float(Option<f64>),
122}
123
124#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
125#[serde(rename_all = "camelCase")]
126pub struct PluginCredential {
127    pub kind: CredentialType,
128    pub login: Option<String>,
129    pub password: Option<String>,
130    pub settings: Value,
131    pub user_ref: Option<String>,
132    pub refresh_token: Option<String>,
133    pub expires: Option<i64>,
134}
135
136#[derive(
137    Debug, Serialize, Deserialize, Clone, PartialEq, strum_macros::Display, EnumString, Default,
138)]
139#[strum(serialize_all = "camelCase")]
140#[serde(rename_all = "camelCase")]
141pub enum RsFileType {
142    Directory,
143    Photo,
144    Video,
145    Archive,
146    Album,
147    Book,
148    #[default]
149    Other,
150}
151
152#[derive(
153    Debug, Serialize, Deserialize, Clone, PartialEq, strum_macros::Display, EnumString, Default,
154)]
155#[serde(rename_all = "camelCase")]
156#[strum(serialize_all = "camelCase")]
157pub enum MediaType {
158    Movie,
159    Episode,
160    Book,
161    Song,
162    #[strum(default)]
163    Custom(String),
164    #[default]
165    Unknown,
166}
167
168#[derive(
169    Debug, Serialize, Deserialize, Clone, PartialEq, strum_macros::Display, EnumString, Default,
170)]
171#[serde(rename_all = "camelCase")]
172#[strum(serialize_all = "camelCase")]
173pub enum Gender {
174    Male,
175    Female,
176    Animal,
177    Other,
178    #[strum(default)]
179    Custom(String),
180    #[default]
181    Unknown,
182}
183
184#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
185#[serde(rename_all = "camelCase")]
186pub struct RsPluginRequest<T> {
187    pub request: T,
188    pub plugin_settings: Value,
189    pub credential: Option<PluginCredential>,
190}
191
192#[cfg(test)]
193mod tests {
194    use std::str::FromStr;
195
196    use super::*;
197
198    #[test]
199    fn resolution_parsing() {
200        assert_eq!(
201            RsResolution::from_filename("Test.2024.S01E01.1080p.VOSTFR.DSNP.WEB-DL.DDP5.1.H.264"),
202            RsResolution::FullHD
203        );
204        assert_eq!(
205            RsResolution::from_filename("Test.2024.S01E01_720p VOSTFR.DSNP.WEB-DL.DDP5.1.H.264"),
206            RsResolution::HD
207        );
208        assert_eq!(
209            RsResolution::from_filename("TestIn4k.2024.S01E01_VOSTFR.DSNP.WEB-DL.DDP5.1.H.264"),
210            RsResolution::Unknown
211        );
212        assert_eq!(
213            RsResolution::from_filename(
214                "TestIn4k.2024.S01E01_4K_VOSTFR.DSNP.WEB-DL.DDP5.Atmos.1.H.264"
215            ),
216            RsResolution::UHD
217        );
218    }
219
220    #[test]
221    fn resolution_string() {
222        assert_eq!("4K", RsResolution::UHD.to_string());
223        assert_eq!(
224            RsResolution::from_str("1080p").unwrap(),
225            RsResolution::FullHD
226        );
227        assert_eq!(
228            RsResolution::from_str("erzr").unwrap(),
229            RsResolution::Custom("erzr".to_owned())
230        );
231    }
232    #[test]
233    fn audio_parsing() {
234        assert_eq!(
235            RsAudio::from_filename("Test.2024.S01E01.1080p.VOSTFR.DSNP.WEB-DL.DDP5.1.H.264"),
236            RsAudio::DDP51
237        );
238        assert_eq!(
239            RsAudio::from_filename("Test.2024.S01E01_720p VOSTFR.DSNP.WEB-DL.DDP5.1._atmos_H.264"),
240            RsAudio::Atmos
241        );
242        let list = RsAudio::list_from_filename(
243            "TestIn4k.2024.S01E01_4K_VOSTFR.DSNP.WEB-DL.DDP5.1.Atmos.H.264",
244        );
245        assert_eq!(list.len(), 2);
246        assert!(list.contains(&RsAudio::Atmos));
247        assert!(list.contains(&RsAudio::DDP51));
248    }
249
250    #[test]
251    fn videocodec_parsing() {
252        assert_eq!(
253            RsVideoCodec::from_filename("Test.2024.S01E01.1080p.VOSTFR.DSNP.WEB-DL.DDP5.1.H.264"),
254            RsVideoCodec::H264
255        );
256        assert_eq!(
257            RsVideoCodec::from_filename("Test.2024.S01E01_720p VOSTFR.DSNP.WEB-DL.DDP5.1.HEVC"),
258            RsVideoCodec::H265
259        );
260        assert_eq!(
261            RsVideoCodec::from_filename("TestIn4k.2024.S01E01_VOSTFR.DSNP.WEB-DL.DDP5.1.X.265"),
262            RsVideoCodec::H265
263        );
264    }
265
266    #[test]
267    fn video_format_parsing() {
268        assert_eq!(
269            RsVideoFormat::from_filename(
270                "Test.2024.S01E01.1080p.VOSTFR.DSNP.WEB-DL.DDP5.1.H.264.mp4"
271            ),
272            RsVideoFormat::Mp4
273        );
274        assert_eq!(
275            RsVideoFormat::from_filename(
276                "Test.2024.S01E01_720p VOSTFR.DSNP.WEB-DL.DDP5.1._atmos_H.264"
277            ),
278            RsVideoFormat::Other
279        );
280        assert_eq!(
281            RsVideoFormat::from_filename(
282                "Test.2024.S01E01.1080p.VOSTFR.DSNP.WEB-DL.DDP5.1.H.264.WMV"
283            ),
284            RsVideoFormat::Wmv
285        );
286
287        assert_eq!(RsVideoFormat::Mp4.to_string(), "mp4");
288        assert_eq!(RsVideoFormat::from_str("mkv").unwrap(), RsVideoFormat::Mkv);
289    }
290}