wikifeet 1.0.0

WikiFeet (The collaborative celebrity feet website) crawler
Documentation
/*
 * Copyright 2021 XXIV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
use std::io::Read;
use regex::Regex;
use crate::error::WikiFeetError;

#[doc(hidden)]
const PATTERN_ROMAN_FEET: &str = r#"Liked Roman / Egyptian feet better(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_GREEK_FEET: &str = r#"Liked Greek feet / Morton's toe better(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_NOT_FOOT_TATTOOS: &str = r#"I Don't like foot tattoos(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_MAYBE_FOOT_TATTOOS: &str = r#"I Sometimes like foot tattoos(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_FOOT_TATTOOS: &str = r#"I Like foot tattoos(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_NATURAL_TOES: &str = r#"I like natural toes better(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_PAINTED_TOES: &str = r#"I like painted toes better(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_SECRET_FEET_LOVER: &str = r#"No, I keep it to myself(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;
#[doc(hidden)]
const PATTERN_OPEN_FEET_LOVER: &str = r#"Yes, I am open about it(.*?) width:(.*?)%'>(.*?)</div></td></tr>"#;

/// Gets WikiFeet stats.
pub struct WikiFeetStats;

#[doc(hidden)]
fn http(url: &str) -> Option<String> {
    match reqwest::blocking::get(url.to_string()) {
        Ok(mut data) => {
            let mut body = String::new();
            match data.read_to_string(&mut body) {
                Ok(_) => Some(body),
                Err(_) => None
            }
        },
        Err(_) => None
    }
}

impl WikiFeetStats {
    pub fn new() -> Self {
        Self
    }

    /// Return stats of the people who like roman feet.
    pub fn roman_feet(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/1") {
            Some(data) => {
                match Regex::new(PATTERN_ROMAN_FEET) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who like greek feet.
    pub fn greek_feet(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/1") {
            Some(data) => {
                match Regex::new(PATTERN_GREEK_FEET) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who don't like foot tattoos.
    pub fn not_foot_tattoos(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/2") {
            Some(data) => {
                match Regex::new(PATTERN_NOT_FOOT_TATTOOS) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who sometimes like foot tattoos.
    pub fn maybe_foot_tattoos(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/2") {
            Some(data) => {
                match Regex::new(PATTERN_MAYBE_FOOT_TATTOOS) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who like foot tattoos.
    pub fn foot_tattoos(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/2") {
            Some(data) => {
                match Regex::new(PATTERN_FOOT_TATTOOS) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who like natural toes.
    pub fn natural_toes(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/3") {
            Some(data) => {
                match Regex::new(PATTERN_NATURAL_TOES) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who like painted toes.
    pub fn painted_toes(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/3") {
            Some(data) => {
                match Regex::new(PATTERN_PAINTED_TOES) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who like feet and keep it secret.
    pub fn secret_feet_lover(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/4") {
            Some(data) => {
                match Regex::new(PATTERN_SECRET_FEET_LOVER) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }

    /// Return stats of the people who like feet and open about it.
    pub fn open_feet_lover(&self) -> Result<String, WikiFeetError> {
        match http("https://www.wikifeet.com/polls/4") {
            Some(data) => {
                match Regex::new(PATTERN_OPEN_FEET_LOVER) {
                    Ok(regex) => {
                        match regex.captures(&data) {
                            Some(cap) => {
                                let capture = match cap.get(3) {
                                    Some(data) => data.as_str(),
                                    None => return Err(WikiFeetError::Null(String::from("null")))
                                };
                                Ok(capture.to_string())
                            },
                            None => Err(WikiFeetError::Null(String::from("null")))
                        }
                    },
                    Err(_) => Err(WikiFeetError::Null(String::from("null")))
                }
            },
            None => Err(WikiFeetError::Null(String::from("null")))
        }
    }
}