1use serde::{Deserialize, Serialize};
2use strum_macros::EnumIter;
3
4use super::error::AnimeApiError;
5
6#[derive(Debug, Serialize)]
8pub struct GetAnimeList {
9 q: String,
10 nsfw: bool,
11 limit: u16,
12 offset: u32,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 fields: Option<String>,
15}
16
17impl GetAnimeList {
18 pub fn new<T: Into<String>>(
22 q: T,
23 nsfw: bool,
24 fields: Option<&AnimeCommonFields>,
25 limit: Option<u16>,
26 offset: Option<u32>,
27 ) -> Result<Self, AnimeApiError> {
28 let limit = limit.map(|l| l.clamp(1, 100));
29 let q: String = q.into();
30
31 if q.is_empty() {
32 return Err(AnimeApiError::new("Query cannot be empty".to_string()));
33 }
34
35 Ok(Self {
36 q,
37 nsfw,
38 limit: limit.unwrap_or(100),
39 offset: offset.unwrap_or(0),
40 fields: fields.map(|f| f.into()),
41 })
42 }
43
44 pub fn builder<T: Into<String>>(q: T) -> GetAnimeListBuilder<'static> {
46 GetAnimeListBuilder::new(q.into())
47 }
48}
49
50#[derive(Debug)]
51pub struct GetAnimeListBuilder<'a> {
52 q: String,
53 nsfw: bool,
54 limit: Option<u16>,
55 offset: Option<u32>,
56 fields: Option<&'a AnimeCommonFields>,
57}
58
59impl<'a> GetAnimeListBuilder<'a> {
60 pub fn new(q: String) -> Self {
61 Self {
62 q,
63 nsfw: false,
64 limit: None,
65 offset: None,
66 fields: None,
67 }
68 }
69
70 pub fn q<T: Into<String>>(mut self, value: T) -> Self {
71 self.q = value.into();
72 self
73 }
74
75 pub fn enable_nsfw(mut self) -> Self {
76 self.nsfw = true;
77 self
78 }
79
80 pub fn limit(mut self, value: u16) -> Self {
81 self.limit = Some(value.clamp(1, 100));
82 self
83 }
84
85 pub fn offset(mut self, value: u32) -> Self {
86 self.offset = Some(value);
87 self
88 }
89
90 pub fn fields(mut self, value: &'a AnimeCommonFields) -> Self {
91 self.fields = Some(value);
92 self
93 }
94
95 pub fn build(self) -> Result<GetAnimeList, AnimeApiError> {
96 GetAnimeList::new(self.q, self.nsfw, self.fields, self.limit, self.offset)
97 }
98}
99
100#[derive(Debug, Serialize)]
102pub struct GetAnimeDetails {
103 #[serde(skip_serializing)]
104 pub(crate) anime_id: u32,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 fields: Option<String>,
107}
108
109impl GetAnimeDetails {
110 pub fn new(anime_id: u32, fields: Option<&AnimeDetailFields>) -> Result<Self, AnimeApiError> {
112 if anime_id == 0 {
113 return Err(AnimeApiError::new(
114 "anime_id must be greater than 0".to_string(),
115 ));
116 }
117
118 Ok(Self {
119 anime_id,
120 fields: fields.map(|f| f.into()),
121 })
122 }
123
124 pub fn builder(anime_id: u32) -> GetAnimeDetailsBuilder<'static> {
126 GetAnimeDetailsBuilder::new(anime_id)
127 }
128}
129
130pub struct GetAnimeDetailsBuilder<'a> {
131 anime_id: u32,
132 fields: Option<&'a AnimeDetailFields>,
133}
134
135impl<'a> GetAnimeDetailsBuilder<'a> {
136 pub fn new(anime_id: u32) -> Self {
137 Self {
138 anime_id,
139 fields: None,
140 }
141 }
142
143 pub fn anime_id(mut self, value: u32) -> Self {
144 self.anime_id = value;
145 self
146 }
147
148 pub fn fields(mut self, value: &'a AnimeDetailFields) -> Self {
149 self.fields = Some(value);
150 self
151 }
152
153 pub fn build(self) -> Result<GetAnimeDetails, AnimeApiError> {
154 GetAnimeDetails::new(self.anime_id, self.fields)
155 }
156}
157
158#[derive(Debug, Serialize, Deserialize, Clone)]
159#[serde(rename_all = "lowercase")]
160pub enum RankingType {
161 All,
162 Airing,
163 Upcoming,
164 Tv,
165 Ova,
166 Movie,
167 Special,
168 ByPopularity,
169 Favorite,
170}
171
172#[derive(Debug, Serialize)]
174pub struct GetAnimeRanking {
175 ranking_type: RankingType,
176 nsfw: bool,
177 limit: u16,
178 offset: u32,
179 #[serde(skip_serializing_if = "Option::is_none")]
180 fields: Option<String>,
181}
182
183impl GetAnimeRanking {
184 pub fn new(
188 ranking_type: RankingType,
189 nsfw: bool,
190 fields: Option<&AnimeCommonFields>,
191 limit: Option<u16>,
192 offset: Option<u32>,
193 ) -> Self {
194 let limit = limit.map(|l| l.clamp(1, 500));
195
196 Self {
197 ranking_type,
198 nsfw,
199 limit: limit.unwrap_or(100),
200 offset: offset.unwrap_or(0),
201 fields: fields.map(|f| f.into()),
202 }
203 }
204
205 pub fn builder(ranking_type: RankingType) -> GetAnimeRankingBuilder<'static> {
207 GetAnimeRankingBuilder::new(ranking_type)
208 }
209}
210
211pub struct GetAnimeRankingBuilder<'a> {
212 ranking_type: RankingType,
213 nsfw: bool,
214 limit: Option<u16>,
215 offset: Option<u32>,
216 fields: Option<&'a AnimeCommonFields>,
217}
218
219impl<'a> GetAnimeRankingBuilder<'a> {
220 pub fn new(ranking_type: RankingType) -> Self {
221 Self {
222 ranking_type,
223 nsfw: false,
224 limit: None,
225 offset: None,
226 fields: None,
227 }
228 }
229
230 pub fn ranking_type(mut self, value: RankingType) -> Self {
231 self.ranking_type = value;
232 self
233 }
234
235 pub fn enable_nsfw(mut self) -> Self {
236 self.nsfw = true;
237 self
238 }
239
240 pub fn limit(mut self, value: u16) -> Self {
241 self.limit = Some(value.clamp(1, 500));
242 self
243 }
244
245 pub fn offset(mut self, value: u32) -> Self {
246 self.offset = Some(value);
247 self
248 }
249
250 pub fn fields(mut self, value: &'a AnimeCommonFields) -> Self {
251 self.fields = Some(value.into());
252 self
253 }
254
255 pub fn build(self) -> GetAnimeRanking {
256 GetAnimeRanking::new(
257 self.ranking_type,
258 self.nsfw,
259 self.fields,
260 self.limit,
261 self.offset,
262 )
263 }
264}
265
266#[derive(Debug, Serialize, Deserialize, Clone)]
267#[serde(rename_all = "lowercase")]
268pub enum Season {
269 Winter,
270 Spring,
271 Summer,
272 Fall,
273}
274
275impl std::fmt::Display for Season {
276 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277 match self {
278 Self::Winter => {
279 write!(f, "winter")
280 }
281 Self::Fall => {
282 write!(f, "fall")
283 }
284 Self::Summer => {
285 write!(f, "summer")
286 }
287 Self::Spring => {
288 write!(f, "spring")
289 }
290 }
291 }
292}
293
294#[derive(Debug, Serialize, Clone)]
295#[serde(rename_all = "snake_case")]
296pub enum SeasonalAnimeSort {
297 AnimeScore,
298 AnimeNumListUsers,
299}
300
301#[derive(Debug, Serialize)]
303pub struct GetSeasonalAnime {
304 #[serde(skip_serializing)]
305 pub(crate) year: u16,
306 #[serde(skip_serializing)]
307 pub(crate) season: Season,
308 nsfw: bool,
309 #[serde(skip_serializing_if = "Option::is_none")]
310 sort: Option<SeasonalAnimeSort>,
311 limit: u16,
312 offset: u32,
313 fields: Option<String>,
314}
315
316impl GetSeasonalAnime {
317 pub fn new(
321 year: u16,
322 season: Season,
323 nsfw: bool,
324 fields: Option<&AnimeCommonFields>,
325 sort: Option<SeasonalAnimeSort>,
326 limit: Option<u16>,
327 offset: Option<u32>,
328 ) -> Self {
329 let limit = limit.map(|l| l.clamp(1, 500));
330
331 Self {
332 year,
333 season,
334 nsfw,
335 sort,
336 limit: limit.unwrap_or(100),
337 offset: offset.unwrap_or(0),
338 fields: fields.map(|f| f.into()),
339 }
340 }
341
342 pub fn builder(year: u16, season: Season) -> GetSeasonalAnimeBuilder<'static> {
344 GetSeasonalAnimeBuilder::new(year, season)
345 }
346}
347
348pub struct GetSeasonalAnimeBuilder<'a> {
349 year: u16,
350 season: Season,
351 nsfw: bool,
352 sort: Option<SeasonalAnimeSort>,
353 limit: Option<u16>,
354 offset: Option<u32>,
355 fields: Option<&'a AnimeCommonFields>,
356}
357
358impl<'a> GetSeasonalAnimeBuilder<'a> {
359 pub fn new(year: u16, season: Season) -> Self {
360 Self {
361 year,
362 season,
363 nsfw: false,
364 sort: None,
365 limit: None,
366 offset: None,
367 fields: None,
368 }
369 }
370
371 pub fn year(mut self, value: u16) -> Self {
372 self.year = value;
373 self
374 }
375
376 pub fn season(mut self, value: Season) -> Self {
377 self.season = value;
378 self
379 }
380
381 pub fn enable_nsfw(mut self) -> Self {
382 self.nsfw = true;
383 self
384 }
385
386 pub fn sort(mut self, value: SeasonalAnimeSort) -> Self {
387 self.sort = Some(value);
388 self
389 }
390
391 pub fn limit(mut self, value: u16) -> Self {
392 self.limit = Some(value);
393 self
394 }
395
396 pub fn offset(mut self, value: u32) -> Self {
397 self.offset = Some(value);
398 self
399 }
400
401 pub fn fields(mut self, value: &'a AnimeCommonFields) -> Self {
402 self.fields = Some(value.into());
403 self
404 }
405
406 pub fn build(self) -> GetSeasonalAnime {
407 GetSeasonalAnime::new(
408 self.year,
409 self.season,
410 self.nsfw,
411 self.fields,
412 self.sort,
413 self.limit,
414 self.offset,
415 )
416 }
417}
418
419#[derive(Debug, Serialize)]
421pub struct GetSuggestedAnime {
422 nsfw: bool,
423 limit: u16,
424 offset: u32,
425 #[serde(skip_serializing_if = "Option::is_none")]
426 fields: Option<String>,
427}
428
429impl GetSuggestedAnime {
430 pub fn new(
434 nsfw: bool,
435 fields: Option<&AnimeCommonFields>,
436 limit: Option<u16>,
437 offset: Option<u32>,
438 ) -> Self {
439 let limit = limit.map(|l| l.clamp(1, 100));
440
441 Self {
442 nsfw,
443 limit: limit.unwrap_or(100),
444 offset: offset.unwrap_or(0),
445 fields: fields.map(|f| f.into()),
446 }
447 }
448
449 pub fn builder() -> GetSuggestedAnimeBuilder<'static> {
451 GetSuggestedAnimeBuilder::new()
452 }
453}
454
455pub struct GetSuggestedAnimeBuilder<'a> {
456 nsfw: bool,
457 fields: Option<&'a AnimeCommonFields>,
458 limit: Option<u16>,
459 offset: Option<u32>,
460}
461
462impl<'a> GetSuggestedAnimeBuilder<'a> {
463 pub fn new() -> Self {
464 Self {
465 nsfw: false,
466 fields: None,
467 limit: None,
468 offset: None,
469 }
470 }
471
472 pub fn enable_nsfw(mut self) -> Self {
473 self.nsfw = true;
474 self
475 }
476
477 pub fn fields(mut self, value: &'a AnimeCommonFields) -> Self {
478 self.fields = Some(value.into());
479 self
480 }
481
482 pub fn limit(mut self, value: u16) -> Self {
483 self.limit = Some(value.clamp(1, 100));
484 self
485 }
486
487 pub fn offset(mut self, value: u32) -> Self {
488 self.offset = Some(value);
489 self
490 }
491
492 pub fn build(self) -> GetSuggestedAnime {
493 GetSuggestedAnime::new(self.nsfw, self.fields, self.limit, self.offset)
494 }
495}
496
497#[derive(Debug, Serialize, Deserialize, Clone)]
498#[serde(rename_all = "snake_case")]
499pub enum UserAnimeListStatus {
500 Watching,
501 Completed,
502 OnHold,
503 Dropped,
504 PlanToWatch,
505}
506
507#[derive(Debug, Serialize)]
508#[serde(rename_all = "snake_case")]
509pub enum UserAnimeListSort {
510 ListScore,
511 ListUpdatedAt,
512 AnimeTitle,
513 AnimeStartDate,
514 }
517
518#[derive(Debug, Serialize)]
520pub struct GetUserAnimeList {
521 #[serde(skip_serializing)]
522 pub(crate) user_name: String,
523 nsfw: bool,
524 #[serde(skip_serializing_if = "Option::is_none")]
525 status: Option<UserAnimeListStatus>,
526 #[serde(skip_serializing_if = "Option::is_none")]
527 sort: Option<UserAnimeListSort>,
528 limit: u16,
529 offset: u32,
530 #[serde(skip_serializing_if = "Option::is_none")]
531 fields: Option<String>,
532}
533
534impl GetUserAnimeList {
535 pub fn new(
543 user_name: String,
544 nsfw: bool,
545 fields: Option<&AnimeCommonFields>,
546 status: Option<UserAnimeListStatus>,
547 sort: Option<UserAnimeListSort>,
548 limit: Option<u16>,
549 offset: Option<u32>,
550 ) -> Result<Self, AnimeApiError> {
551 let limit = limit.map(|l| l.clamp(1, 1000));
552
553 if user_name.is_empty() {
554 return Err(AnimeApiError::new("user_name cannot be empty".to_string()));
555 }
556
557 Ok(Self {
558 user_name,
559 nsfw,
560 status,
561 sort,
562 limit: limit.unwrap_or(100),
563 offset: offset.unwrap_or(0),
564 fields: fields.map(|f| f.into()),
565 })
566 }
567
568 pub fn builder(user_name: &str) -> GetUserAnimeListBuilder<'static> {
570 GetUserAnimeListBuilder::new(user_name.to_string())
571 }
572}
573
574pub struct GetUserAnimeListBuilder<'a> {
575 user_name: String,
576 nsfw: bool,
577 fields: Option<&'a AnimeCommonFields>,
578 status: Option<UserAnimeListStatus>,
579 sort: Option<UserAnimeListSort>,
580 limit: Option<u16>,
581 offset: Option<u32>,
582}
583
584impl<'a> GetUserAnimeListBuilder<'a> {
585 pub fn new<T: Into<String>>(user_name: T) -> Self {
586 let user_name = user_name.into();
587 Self {
588 user_name,
589 nsfw: false,
590 fields: None,
591 status: None,
592 sort: None,
593 limit: None,
594 offset: None,
595 }
596 }
597
598 pub fn user_name<T: Into<String>>(mut self, value: T) -> Self {
599 self.user_name = value.into();
600 self
601 }
602
603 pub fn enable_nsfw(mut self) -> Self {
604 self.nsfw = true;
605 self
606 }
607
608 pub fn fields(mut self, value: &'a AnimeCommonFields) -> Self {
609 self.fields = Some(value.into());
610 self
611 }
612
613 pub fn status(mut self, value: UserAnimeListStatus) -> Self {
614 self.status = Some(value);
615 self
616 }
617
618 pub fn sort(mut self, value: UserAnimeListSort) -> Self {
619 self.sort = Some(value);
620 self
621 }
622
623 pub fn limit(mut self, value: u16) -> Self {
624 self.limit = Some(value.clamp(1, 1000));
625 self
626 }
627
628 pub fn offset(mut self, value: u32) -> Self {
629 self.offset = Some(value);
630 self
631 }
632
633 pub fn build(self) -> Result<GetUserAnimeList, AnimeApiError> {
634 GetUserAnimeList::new(
635 self.user_name,
636 self.nsfw,
637 self.fields,
638 self.status,
639 self.sort,
640 self.limit,
641 self.offset,
642 )
643 }
644}
645
646#[derive(Debug, Serialize)]
648pub struct UpdateMyAnimeListStatus {
649 #[serde(skip_serializing)]
650 pub(crate) anime_id: u32,
651 #[serde(skip_serializing_if = "Option::is_none")]
652 status: Option<UserAnimeListStatus>,
653 #[serde(skip_serializing_if = "Option::is_none")]
654 is_rewatching: Option<bool>,
655 #[serde(skip_serializing_if = "Option::is_none")]
656 score: Option<u8>,
657 #[serde(skip_serializing_if = "Option::is_none")]
658 num_watched_episodes: Option<u32>,
659 #[serde(skip_serializing_if = "Option::is_none")]
660 priority: Option<u8>,
661 #[serde(skip_serializing_if = "Option::is_none")]
662 num_times_rewatched: Option<u32>,
663 #[serde(skip_serializing_if = "Option::is_none")]
664 rewatch_value: Option<u8>,
665 #[serde(skip_serializing_if = "Option::is_none")]
666 tags: Option<String>,
667 #[serde(skip_serializing_if = "Option::is_none")]
668 comments: Option<String>,
669}
670
671impl UpdateMyAnimeListStatus {
672 pub fn new(
680 anime_id: u32,
681 status: Option<UserAnimeListStatus>,
682 is_rewatching: Option<bool>,
683 score: Option<u8>,
684 num_watched_episodes: Option<u32>,
685 priority: Option<u8>,
686 num_times_rewatched: Option<u32>,
687 rewatch_value: Option<u8>,
688 tags: Option<String>,
689 comments: Option<String>,
690 ) -> Result<Self, AnimeApiError> {
691 if let Some(score) = score {
693 if score > 10 {
694 return Err(AnimeApiError::new(
695 "Score must be between 0 and 10 inclusive".to_string(),
696 ));
697 }
698 }
699 if let Some(priority) = priority {
700 if priority > 2 {
701 return Err(AnimeApiError::new(
702 "Priority must be between 0 and 2 inclusive".to_string(),
703 ));
704 }
705 }
706 if let Some(rewatch_value) = rewatch_value {
707 if rewatch_value > 5 {
708 return Err(AnimeApiError::new(
709 "Rewatch value must be between 0 and 5 inclusive".to_string(),
710 ));
711 }
712 }
713
714 if anime_id == 0 {
715 return Err(AnimeApiError::new(
716 "anime_id must be greater than 0".to_string(),
717 ));
718 }
719
720 if !(status.is_some()
722 || is_rewatching.is_some()
723 || score.is_some()
724 || num_watched_episodes.is_some()
725 || priority.is_some()
726 || num_times_rewatched.is_some()
727 || rewatch_value.is_some()
728 || tags.is_some()
729 || comments.is_some())
730 {
731 return Err(AnimeApiError::new(
732 "At least one of the optional arguments must be Some".to_string(),
733 ));
734 }
735
736 Ok(Self {
737 anime_id,
738 status,
739 is_rewatching,
740 score,
741 num_watched_episodes,
742 priority,
743 num_times_rewatched,
744 rewatch_value,
745 tags,
746 comments,
747 })
748 }
749
750 pub fn builder(anime_id: u32) -> UpdateMyAnimeListStatusBuilder {
752 UpdateMyAnimeListStatusBuilder::new(anime_id)
753 }
754}
755
756pub struct UpdateMyAnimeListStatusBuilder {
757 anime_id: u32,
758 status: Option<UserAnimeListStatus>,
759 is_rewatching: Option<bool>,
760 score: Option<u8>,
761 num_watched_episodes: Option<u32>,
762 priority: Option<u8>,
763 num_times_rewatched: Option<u32>,
764 rewatch_value: Option<u8>,
765 tags: Option<String>,
766 comments: Option<String>,
767}
768
769impl UpdateMyAnimeListStatusBuilder {
770 pub fn new(anime_id: u32) -> Self {
771 Self {
772 anime_id,
773 status: None,
774 is_rewatching: None,
775 score: None,
776 num_watched_episodes: None,
777 priority: None,
778 num_times_rewatched: None,
779 rewatch_value: None,
780 tags: None,
781 comments: None,
782 }
783 }
784
785 pub fn anime_id(mut self, value: u32) -> Self {
786 self.anime_id = value;
787 self
788 }
789
790 pub fn status(mut self, value: UserAnimeListStatus) -> Self {
791 self.status = Some(value);
792 self
793 }
794
795 pub fn is_rewatching(mut self, value: bool) -> Self {
796 self.is_rewatching = Some(value);
797 self
798 }
799
800 pub fn score(mut self, value: u8) -> Self {
801 self.score = Some(value);
802 self
803 }
804
805 pub fn num_watched_episodes(mut self, value: u32) -> Self {
806 self.num_watched_episodes = Some(value);
807 self
808 }
809
810 pub fn priority(mut self, value: u8) -> Self {
811 self.priority = Some(value);
812 self
813 }
814
815 pub fn num_times_rewatched(mut self, value: u32) -> Self {
816 self.num_times_rewatched = Some(value);
817 self
818 }
819
820 pub fn rewatch_value(mut self, value: u8) -> Self {
821 self.rewatch_value = Some(value);
822 self
823 }
824
825 pub fn tags(mut self, value: &str) -> Self {
826 self.tags = Some(value.to_string());
827 self
828 }
829
830 pub fn comments(mut self, value: &str) -> Self {
831 self.comments = Some(value.to_string());
832 self
833 }
834
835 pub fn build(self) -> Result<UpdateMyAnimeListStatus, AnimeApiError> {
836 UpdateMyAnimeListStatus::new(
837 self.anime_id,
838 self.status,
839 self.is_rewatching,
840 self.score,
841 self.num_watched_episodes,
842 self.priority,
843 self.num_times_rewatched,
844 self.rewatch_value,
845 self.tags,
846 self.comments,
847 )
848 }
849}
850
851#[derive(Debug)]
853pub struct DeleteMyAnimeListItem {
854 pub(crate) anime_id: u32,
855}
856
857impl DeleteMyAnimeListItem {
858 pub fn new(anime_id: u32) -> Self {
860 Self { anime_id }
861 }
862}
863
864#[derive(Debug, EnumIter, PartialEq)]
865#[allow(non_camel_case_types)]
866pub enum AnimeField {
867 id,
868 title,
869 main_picture,
870 alternative_titles,
871 start_date,
872 end_date,
873 synopsis,
874 mean,
875 rank,
876 popularity,
877 num_list_users,
878 num_scoring_users,
879 nsfw,
880 genres,
881 created_at,
882 updated_at,
883 media_type,
884 status,
885 my_list_status,
886 num_episodes,
887 start_season,
888 broadcast,
889 source,
890 average_episode_duration,
891 rating,
892 studios,
893}
894
895#[derive(Debug, EnumIter, PartialEq)]
896#[allow(non_camel_case_types)]
897pub enum AnimeDetail {
898 id,
900 title,
901 main_picture,
902 alternative_titles,
903 start_date,
904 end_date,
905 synopsis,
906 mean,
907 rank,
908 popularity,
909 num_list_users,
910 num_scoring_users,
911 nsfw,
912 genres,
913 created_at,
914 updated_at,
915 media_type,
916 status,
917 my_list_status,
918 num_episodes,
919 start_season,
920 broadcast,
921 source,
922 average_episode_duration,
923 rating,
924 studios,
925
926 pictures,
928 background,
929 related_anime,
930 related_manga,
931 recommendations,
932 statistics,
933}
934
935#[derive(Debug)]
937pub struct AnimeCommonFields(pub Vec<AnimeField>);
938
939#[derive(Debug)]
941pub struct AnimeDetailFields(pub Vec<AnimeDetail>);
942
943impl<'a> Into<String> for &'a AnimeCommonFields {
944 fn into(self) -> String {
945 let result = self
946 .0
947 .iter()
948 .map(|e| format!("{:?}", e))
949 .collect::<Vec<String>>()
950 .join(",");
951 result
952 }
953}
954
955impl<'a> Into<String> for &'a AnimeDetailFields {
956 fn into(self) -> String {
957 let result = self
958 .0
959 .iter()
960 .map(|e| format!("{:?}", e))
961 .collect::<Vec<String>>()
962 .join(",");
963 result
964 }
965}
966
967#[cfg(test)]
968mod tests {
969 use super::*;
970 use crate::anime::all_common_fields;
971
972 #[test]
973 fn test_get_anime_list() {
974 let fields = all_common_fields();
975 let query = GetAnimeList::new("".to_string(), false, Some(&fields), Some(100), None);
976 assert!(query.is_err());
977
978 let query = GetAnimeList::new("one".to_string(), false, Some(&fields), Some(999), None);
979 assert!(query.is_ok());
980
981 let query = GetAnimeList::new("one".to_string(), false, Some(&fields), Some(0), None);
982 assert_eq!(query.unwrap().limit, 1);
983
984 let query = GetAnimeList::new("one".to_string(), false, Some(&fields), Some(50), None);
985 assert_eq!(query.unwrap().limit, 50);
986
987 let query = GetAnimeList::new("one".to_string(), false, Some(&fields), None, None);
988 assert!(&query.is_ok());
989 assert_eq!(query.unwrap().limit, 100);
990 }
991
992 #[test]
993 fn test_get_anime_ranking() {
994 let fields = all_common_fields();
995 let query = GetAnimeRanking::new(RankingType::All, false, Some(&fields), Some(1000), None);
996 assert_eq!(query.limit, 500);
997
998 let query = GetAnimeRanking::new(RankingType::All, false, Some(&fields), Some(0), None);
999 assert_eq!(query.limit, 1);
1000
1001 let query = GetAnimeRanking::new(RankingType::All, false, Some(&fields), Some(500), None);
1002 assert_eq!(query.limit, 500);
1003
1004 let query = GetAnimeRanking::new(RankingType::All, false, Some(&fields), None, None);
1005 assert_eq!(query.limit, 100);
1006 }
1007
1008 #[test]
1009 fn test_get_seasonal_anime() {
1010 let fields = all_common_fields();
1011 let query = GetSeasonalAnime::new(
1012 1000,
1013 Season::Spring,
1014 false,
1015 Some(&fields),
1016 Some(SeasonalAnimeSort::AnimeScore),
1017 Some(999),
1018 None,
1019 );
1020 assert_eq!(query.limit, 500);
1021
1022 let query = GetSeasonalAnime::new(
1023 1000,
1024 Season::Spring,
1025 false,
1026 Some(&fields),
1027 Some(SeasonalAnimeSort::AnimeScore),
1028 Some(0),
1029 None,
1030 );
1031 assert_eq!(query.limit, 1);
1032
1033 let query = GetSeasonalAnime::new(
1034 1000,
1035 Season::Spring,
1036 false,
1037 Some(&fields),
1038 Some(SeasonalAnimeSort::AnimeScore),
1039 Some(500),
1040 None,
1041 );
1042 assert_eq!(query.limit, 500);
1043 }
1044
1045 #[test]
1046 fn test_get_suggested_anime() {
1047 let fields = all_common_fields();
1048 let query = GetSuggestedAnime::new(false, Some(&fields), Some(500), None);
1049 assert_eq!(query.limit, 100);
1050
1051 let query = GetSuggestedAnime::new(false, Some(&fields), Some(0), None);
1052 assert_eq!(query.limit, 1);
1053
1054 let query = GetSuggestedAnime::new(false, Some(&fields), Some(10), None);
1055 assert_eq!(query.limit, 10);
1056
1057 let query = GetSuggestedAnime::new(false, Some(&fields), None, None);
1058 assert_eq!(query.limit, 100);
1059 }
1060
1061 #[test]
1062 fn test_get_user_anime_list() {
1063 let fields = all_common_fields();
1064 let query = GetUserAnimeList::new(
1065 "".to_string(),
1066 false,
1067 Some(&fields),
1068 Some(UserAnimeListStatus::Completed),
1069 Some(UserAnimeListSort::AnimeTitle),
1070 Some(1001),
1071 None,
1072 );
1073 assert!(query.is_err());
1074
1075 let query = GetUserAnimeList::new(
1076 "hello".to_string(),
1077 false,
1078 Some(&fields),
1079 Some(UserAnimeListStatus::Completed),
1080 Some(UserAnimeListSort::AnimeTitle),
1081 Some(0),
1082 None,
1083 );
1084 assert!(&query.is_ok());
1085 assert_eq!(query.unwrap().limit, 1);
1086
1087 let query = GetUserAnimeList::new(
1088 "hello".to_string(),
1089 false,
1090 Some(&fields),
1091 Some(UserAnimeListStatus::Completed),
1092 Some(UserAnimeListSort::AnimeTitle),
1093 Some(1000),
1094 None,
1095 );
1096 assert!(query.is_ok());
1097
1098 let query = GetUserAnimeList::new(
1099 "hello".to_string(),
1100 false,
1101 Some(&fields),
1102 Some(UserAnimeListStatus::Completed),
1103 Some(UserAnimeListSort::AnimeTitle),
1104 None,
1105 None,
1106 );
1107 assert!(query.is_ok());
1108 assert_eq!(query.unwrap().limit, 100);
1109 }
1110
1111 #[test]
1112 fn test_update_my_anime_list() {
1113 let query = UpdateMyAnimeListStatus::new(
1114 1234, None, None, None, None, None, None, None, None, None,
1115 );
1116 assert!(query.is_err());
1117
1118 let query = UpdateMyAnimeListStatus::new(
1119 1234,
1120 Some(UserAnimeListStatus::Dropped),
1121 None,
1122 Some(11),
1123 None,
1124 None,
1125 None,
1126 None,
1127 None,
1128 None,
1129 );
1130 assert!(query.is_err());
1131
1132 let query = UpdateMyAnimeListStatus::new(
1133 1234,
1134 Some(UserAnimeListStatus::Dropped),
1135 None,
1136 None,
1137 None,
1138 Some(3),
1139 None,
1140 None,
1141 None,
1142 None,
1143 );
1144 assert!(query.is_err());
1145
1146 let query = UpdateMyAnimeListStatus::new(
1147 1234,
1148 Some(UserAnimeListStatus::Dropped),
1149 None,
1150 None,
1151 None,
1152 None,
1153 None,
1154 Some(6),
1155 None,
1156 None,
1157 );
1158 assert!(query.is_err());
1159
1160 let query = UpdateMyAnimeListStatus::new(
1161 1234,
1162 Some(UserAnimeListStatus::Completed),
1163 None,
1164 Some(10),
1165 None,
1166 Some(2),
1167 None,
1168 Some(5),
1169 None,
1170 None,
1171 );
1172 assert!(query.is_ok());
1173 }
1174}