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 LookupMetadata,
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 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}