Skip to main content

vndb_api/format/
ulist.rs

1use serde::{Deserialize, Serialize};
2use serde_repr::*;
3use strum::IntoEnumIterator;
4use strum_macros::EnumIter;
5
6use crate::format::release::*;
7use crate::format::schema::Platform;
8use crate::format::vn::VisualNovel;
9
10#[derive(Deserialize, Serialize, Debug)]
11pub struct UList {
12    /// Vn id
13    pub id: Option<String>,
14    /// Unix timestamp
15    pub added: Option<u64>,
16    /// Unix timestamp of when the user voted on this VN
17    pub voted: Option<u64>,
18    /// Unix timestamp when the user last modified their list for this VN
19    pub lastmod: Option<u64>,
20    /// 10 - 100
21    pub vote: Option<u8>,
22    /// Start date “YYYY-MM-DD” format
23    pub started: Option<String>,
24    /// Finish date
25    pub finished: Option<String>,
26    pub notes: Option<String>,
27    /// User labels assigned to this VN private labels are only listed when the user is authenticated
28    pub labels: Option<Vec<UListLabel>>,
29    pub vn: Option<VisualNovel>,
30    pub releases: Option<Vec<UListRelease>>,
31}
32
33#[derive(Deserialize, Serialize, Debug)]
34pub struct UListLabel {
35    pub id: Option<u32>,
36    pub label: Option<String>,
37}
38
39#[derive(Deserialize, Serialize, Debug)]
40pub struct UListRelease {
41    pub list_status: Option<UListStatus>,
42    /// All /release fields can be selected here
43    pub id: Option<String>,
44    pub title: Option<String>,
45    pub alttitle: Option<String>,
46    pub languages: Option<Vec<ReleaseLanguage>>,
47    pub platforms: Option<Vec<Platform>>,
48    pub medium: Option<Vec<ReleaseMedia>>,
49    pub vns: Option<Vec<ReleaseVnRelation>>,
50    pub producers: Option<Vec<ReleaseProducer>>,
51    pub released: Option<String>,
52    pub minage: Option<u8>,
53    pub patch: Option<bool>,
54    pub freeware: Option<bool>,
55    pub uncensored: Option<bool>,
56    pub official: Option<bool>,
57    pub has_ero: Option<bool>,
58    pub resolution: Option<Resolution>,
59    pub engine: Option<String>,
60    pub voiced: Option<VoicedType>,
61    pub notes: Option<String>,
62    pub gtin: Option<String>,
63    pub catalog: Option<String>,
64    pub extlinks: Option<Vec<ExtLink>>,
65}
66
67#[derive(Deserialize_repr, Serialize_repr, PartialEq, Debug)]
68#[repr(u8)]
69pub enum UListStatus {
70    Unknown = 0,
71    Pending = 1,
72    Obtained = 2,
73    OnLoan = 3,
74    Deleted = 4,
75}
76
77#[derive(Deserialize, Serialize, Debug)]
78pub struct UListLabels {
79    pub labels: Option<Vec<UListLabelsInst>>,
80}
81
82#[derive(Deserialize, Serialize, Debug)]
83pub struct UListLabelsInst {
84    /// Integer identifier of the label
85    pub id: Option<u32>,
86    /// Whether this label is private, private labels are only included when authenticated with the listread permission
87    pub private: Option<bool>,
88    pub label: Option<String>,
89    pub count: Option<u32>,
90}
91
92pub struct UListLabelsFieldChoices(pub Vec<UListLabelsField>);
93
94#[derive(Serialize, EnumIter)]
95#[serde(rename_all = "snake_case")]
96pub enum UListLabelsField {
97    Count,
98}
99
100impl UListLabelsFieldChoices {
101    pub fn new() -> Self {
102        UListLabelsFieldChoices(vec![])
103    }
104
105    pub fn from(vec: Vec<UListLabelsField>) -> Self {
106        UListLabelsFieldChoices(vec)
107    }
108
109    pub fn all() -> Self {
110        let mut vec = Vec::with_capacity(UListLabelsField::iter().len());
111        for variant in UListLabelsField::iter() {
112            vec.push(variant);
113        }
114        UListLabelsFieldChoices(vec)
115    }
116
117    pub fn to_csv(&self) -> String {
118        self.0
119            .iter()
120            .map(|field| serde_json::to_string(&field).unwrap().replace("\"", ""))
121            .collect::<Vec<String>>()
122            .join(",")
123    }
124}
125
126#[derive(Deserialize, Serialize, Debug)]
127pub struct UListPatch {
128    #[serde(skip_serializing_if = "Option::is_none")]
129    vote: Option<u8>,
130    #[serde(skip_serializing_if = "Option::is_none")]
131    notes: Option<String>,
132    #[serde(skip_serializing_if = "Option::is_none")]
133    started: Option<String>,
134    #[serde(skip_serializing_if = "Option::is_none")]
135    finished: Option<String>,
136    /// Setting this will overwrite any existing labels assigned to the VN with the given array
137    #[serde(skip_serializing_if = "Option::is_none")]
138    labels: Option<Vec<LabelId>>,
139    /// Label ids to add to the VN any already existing labels will be unaffected
140    #[serde(skip_serializing_if = "Option::is_none")]
141    labels_set: Option<Vec<LabelId>>,
142    /// Label ids to remove from the VN
143    #[serde(skip_serializing_if = "Option::is_none")]
144    labels_unset: Option<Vec<LabelId>>,
145}
146
147pub struct Date {
148    pub year: u16,
149    pub month: u8,
150    pub day: u8,
151}
152
153impl Date {
154    fn format(self) -> String {
155        let s = format!("{:04}-{:02}-{:02}", self.year, self.month, self.day);
156        s
157    }
158}
159
160#[derive(Deserialize_repr, Serialize_repr, PartialEq, Debug)]
161#[repr(u8)]
162pub enum LabelId {
163    Playing = 1,
164    Finished = 2,
165    Stalled = 3,
166    Dropped = 4,
167    WishList = 5,
168    BlackList = 6,
169}
170
171pub struct UListPatchBuilder {
172    pub vote: Option<u8>,
173    pub notes: Option<String>,
174    pub started: Option<String>,
175    pub finished: Option<String>,
176    pub labels: Option<Vec<LabelId>>,
177    pub labels_set: Option<Vec<LabelId>>,
178    pub labels_unset: Option<Vec<LabelId>>,
179}
180
181impl UListPatchBuilder {
182    pub fn new() -> Self {
183        UListPatchBuilder {
184            vote: None,
185            notes: None,
186            started: None,
187            finished: None,
188            labels: None,
189            labels_set: None,
190            labels_unset: None,
191        }
192    }
193
194    pub fn vote(mut self, num: u8) -> Self {
195        self.vote = Some(num.clamp(10, 100));
196        self
197    }
198
199    pub fn notes(mut self, ctx: String) -> Self {
200        self.notes = Some(ctx);
201        self
202    }
203
204    pub fn started(mut self, start: Date) -> Self {
205        self.started = Some(start.format());
206        self
207    }
208
209    pub fn finished(mut self, finish: Date) -> Self {
210        self.finished = Some(finish.format());
211        self
212    }
213
214    pub fn labels(mut self, l: Vec<LabelId>) -> Self {
215        self.labels = Some(l);
216        self
217    }
218
219    pub fn labels_set(mut self, l: Vec<LabelId>) -> Self {
220        self.labels_set = Some(l);
221        self
222    }
223
224    pub fn labels_unset(mut self, l: Vec<LabelId>) -> Self {
225        self.labels_unset = Some(l);
226        self
227    }
228
229    pub fn build(self) -> UListPatch {
230        UListPatch {
231            vote: self.vote,
232            notes: self.notes,
233            started: self.started,
234            finished: self.finished,
235            labels: self.labels,
236            labels_set: self.labels_set,
237            labels_unset: self.labels_unset,
238        }
239    }
240}