binary_options_tools 0.2.0

High-level library for binary options trading automation. Supports PocketOption and ExpertOption with real-time data streaming, WebSocket API access, and automated trading strategies.
Documentation
use binary_options_tools_macros::RegionImpl;

use crate::pocketoption::{
    error::PocketResult,
    utils::{calculate_distance, get_public_ip, get_user_location},
};

#[derive(RegionImpl)]
#[region(path = "data/pocket_options_regions.json")]
pub struct Regions;

impl Regions {
    async fn get_closest_server(&self, ip_address: &str) -> PocketResult<(&str, f64)> {
        let user_location = get_user_location(ip_address).await?;

        let mut closest = ("", f64::INFINITY);
        Self::regions().iter().for_each(|(server, lat, lon)| {
            let distance = calculate_distance(user_location.0, user_location.1, *lat, *lon);
            if distance < closest.1 {
                closest = (*server, distance)
            }
        });
        Ok(closest)
    }

    async fn sort_servers(&self, ip_address: &str) -> PocketResult<Vec<&str>> {
        let user_location = get_user_location(ip_address).await?;
        let mut distances = Self::regions()
            .iter()
            .map(|(server, lat, lon)| {
                (
                    *server,
                    calculate_distance(user_location.0, user_location.1, *lat, *lon),
                )
            })
            .collect::<Vec<(&str, f64)>>();
        distances.sort_by(|(_, a), (_, b)| a.total_cmp(b));
        Ok(distances.into_iter().map(|(s, _)| s).collect())
    }

    pub async fn get_server_for_ip(&self, ip: &str) -> PocketResult<&str> {
        let server = self.get_closest_server(ip).await?;
        Ok(server.0)
    }

    pub async fn get_servers_for_ip(&self, ip: &str) -> PocketResult<Vec<&str>> {
        self.sort_servers(ip).await
    }

    pub async fn get_server(&self) -> PocketResult<&str> {
        let ip = get_public_ip().await?;
        self.get_server_for_ip(&ip).await
    }

    pub async fn get_servers(&self) -> PocketResult<Vec<&str>> {
        let ip = get_public_ip().await?;
        self.get_servers_for_ip(&ip).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_get_closest_server() -> anyhow::Result<()> {
        // let ip = get_public_ip().await?;
        let server = Regions.get_server().await?;
        dbg!(server);
        Ok(())
    }
}