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