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