use std::fmt::{Formatter, Display};
use thiserror::Error as Error;
use crate::convert::Argument;
#[derive(Copy, Clone, Debug)]
pub enum R18 {
NonR18,
R18,
Mixin,
}
#[derive(Debug, Clone)]
pub(crate) struct Keyword(pub(crate) Option<String>);
#[derive(Debug, Clone)]
pub(crate) struct Size(pub(crate) Option<Vec<ImageSize>>);
#[derive(Debug, Clone)]
pub enum ImageSize {
Original,
Regular,
Small,
Thumb,
Mini,
}
#[derive(Debug, Clone)]
pub(crate) struct Proxy(pub(crate) Option<String>);
#[derive(Debug, Clone)]
pub(crate) struct DateAfter(pub(crate) Option<u64>);
#[derive(Debug, Clone)]
pub(crate) struct DateBefore(pub(crate) Option<u64>);
impl std::fmt::Display for ImageSize {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let parameter = match self {
ImageSize::Original => "original",
ImageSize::Regular => "regular",
ImageSize::Small => "small",
ImageSize::Thumb => "thumb",
ImageSize::Mini => "mini",
};
write!(f, "{}", parameter)
}
}
#[derive(Debug, Error, Copy, Clone)]
pub enum LoliError {
IllegalNum,
IllegalSize,
IllegalUidLen,
IllegalTags,
}
impl std::fmt::Display for LoliError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{:?}", self)?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct Request {
r18: Option<R18>,
num: Option<u8>,
uid: Option<Vec<u32>>,
keyword: Keyword,
tag: Option<Vec<String>>,
size: Size,
proxy: Proxy,
date_after: DateAfter,
date_before: DateBefore,
dsc: Option<bool>,
}
impl std::default::Default for Request {
fn default() -> Self {
Request {
r18: None, num: None, uid: None,
keyword: Keyword(None),
tag: None,
size: Size(None), proxy: Proxy(None), date_after: DateAfter(None),
date_before: DateBefore(None),
dsc: None, }
}
}
impl Request {
pub fn r18(mut self, r: R18) -> Self {
self.r18 = Some(r);
self
}
pub fn num(mut self, amount: u8) -> Result<Self, LoliError> {
match amount {
1..=100 => {
self.num = Some(amount);
Ok(self)
}
_ => Err(LoliError::IllegalNum),
}
}
pub fn uid(mut self, authors: &[u32]) -> Result<Self, LoliError> {
match authors.len() {
1..=20 => {
self.uid = Some(authors.into());
Ok(self)
}
_ => Err(LoliError::IllegalUidLen),
}
}
pub fn keyword(mut self, keyword: impl Into<String>) -> Self {
self.keyword.0 = Some(keyword.into());
self
}
pub fn tag(mut self, tag: &[String]) -> Result<Self, LoliError> {
match tag.len() {
1..=20 => {
self.tag = Some(tag.into());
Ok(self)
}
_ => Err(LoliError::IllegalTags),
}
}
pub fn size(mut self, size_list: &[ImageSize]) -> Result<Self, LoliError> {
match size_list.len() {
1..=5 => {
self.size.0 = Some(size_list.into());
Ok(self)
}
_ => Err(LoliError::IllegalSize),
}
}
pub fn proxy(mut self, proxy: impl Into<String>) -> Self {
self.proxy.0 = Some(proxy.into());
self
}
pub fn date_after(mut self, date_after: u64) -> Self {
self.date_after.0 = Some(date_after);
self
}
pub fn date_before(mut self, date_before: u64) -> Self {
self.date_before.0 = Some(date_before);
self
}
pub fn dsc(mut self, dsc: bool) -> Self {
self.dsc = Some(dsc);
self
}
}
impl Display for Request {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut url: String = "https://api.lolicon.app/setu/v2?".into();
url.add_argument(&self.r18);
url.add_argument(&self.num);
url.add_argument(&self.uid);
url.add_argument(&self.keyword);
url.add_argument(&self.tag);
url.add_argument(&self.size);
url.add_argument(&self.proxy);
url.add_argument(&self.date_after);
url.add_argument(&self.date_before);
url.add_argument(&self.dsc);
write!(f, "{}", url)
}
}
impl From<Request> for String {
fn from(request: Request) -> Self {
request.to_string()
}
}
trait AddArgument {
fn add_argument(&mut self, object: &impl Argument);
}
impl AddArgument for String {
fn add_argument(&mut self, object: &impl Argument) {
object.argument(self);
}
}