nyaa 0.9.1

A tui tool for browsing and downloading torrents from nyaa.si
Documentation
use std::error::Error;

use crossterm::event::{KeyCode, KeyModifiers, MediaKeyCode, ModifierKeyCode};
use reqwest::Url;

pub fn get_hash(magnet: String) -> Option<String> {
    magnet
        .split_once("xt=urn:btih:")
        .and_then(|m| m.1.split_once('&').map(|m| m.0.to_owned()))
}

pub fn add_protocol<S: Into<String>>(
    url: S,
    default_https: bool,
) -> Result<Url, Box<dyn Error + Send + Sync>> {
    let url = url.into();
    if let Some((method, other)) = url.split_once(':') {
        if matches!(method, "http" | "https" | "socks5") && matches!(other.get(..2), Some("//")) {
            return Ok(url.parse::<Url>()?);
        }
    }
    let protocol = match default_https {
        true => "https",
        false => "http",
    };
    Ok(format!("{}://{}", protocol, url).parse::<Url>()?)
}

pub fn to_bytes(size: &str) -> usize {
    let mut split = size.split_whitespace();
    let f = split
        .next()
        .and_then(|b| b.parse::<f64>().ok())
        .unwrap_or(-1.);
    let power = match split.last().and_then(|u| u.chars().next()) {
        Some('T') => 4,
        Some('G') => 3,
        Some('M') => 2,
        Some('K') => 1,
        _ => 0,
    };
    (1024_f64.powi(power) * f) as usize
}

pub fn shorten_number(n: u32) -> String {
    if n >= 10000 {
        format!("{}K", n / 1000)
    } else {
        n.to_string()
    }
}

pub fn key_to_string(key: KeyCode, modifier: KeyModifiers) -> String {
    let key = match key {
        KeyCode::Backspace => "BS".to_owned(),
        KeyCode::Enter => "CR".to_owned(),
        KeyCode::Left => "Left".to_owned(),
        KeyCode::Right => "Right".to_owned(),
        KeyCode::Up => "Up".to_owned(),
        KeyCode::Down => "Down".to_owned(),
        KeyCode::Home => "Home".to_owned(),
        KeyCode::End => "End".to_owned(),
        KeyCode::PageUp => "PgUp".to_owned(),
        KeyCode::PageDown => "PgDown".to_owned(),
        KeyCode::Tab | KeyCode::BackTab => "Tab".to_owned(),
        KeyCode::Delete => "Del".to_owned(),
        KeyCode::Insert => "Ins".to_owned(),
        KeyCode::F(f) => format!("F{}", f),
        KeyCode::Char(' ') => "Space".to_owned(),
        KeyCode::Char(c) => match modifier {
            KeyModifiers::NONE | KeyModifiers::SHIFT => return c.to_string(),
            _ => c.to_string(),
        },
        KeyCode::Esc => "Esc".to_owned(),
        KeyCode::Null => "Null".to_owned(),
        KeyCode::CapsLock => "CapsLock".to_owned(),
        KeyCode::ScrollLock => "ScrollLock".to_owned(),
        KeyCode::NumLock => "NumLock".to_owned(),
        KeyCode::PrintScreen => "Print".to_owned(),
        KeyCode::Pause => "Pause".to_owned(),
        KeyCode::Menu => "Menu".to_owned(),
        KeyCode::KeypadBegin => "Begin".to_owned(),
        KeyCode::Media(m) => match m {
            MediaKeyCode::Play => "MediaPlay",
            MediaKeyCode::Pause => "MediaPause",
            MediaKeyCode::PlayPause => "MediaPlayPause",
            MediaKeyCode::Reverse => "MediaReverse",
            MediaKeyCode::Stop => "MediaStop",
            MediaKeyCode::FastForward => "MediaFastForward",
            MediaKeyCode::Rewind => "MediaRewind",
            MediaKeyCode::TrackNext => "MediaTrackNext",
            MediaKeyCode::TrackPrevious => "MediaTrackPrevious",
            MediaKeyCode::Record => "MediaRecord",
            MediaKeyCode::LowerVolume => "MediaLowerVolume",
            MediaKeyCode::RaiseVolume => "MediaRaiseVolume",
            MediaKeyCode::MuteVolume => "MediaMuteVolume",
        }
        .to_owned(),
        KeyCode::Modifier(m) => match m {
            ModifierKeyCode::LeftShift => "LeftShift",
            ModifierKeyCode::LeftControl => "LeftControl",
            ModifierKeyCode::LeftAlt => "LeftAlt",
            ModifierKeyCode::LeftSuper => "LeftSuper",
            ModifierKeyCode::LeftHyper => "LeftHyper",
            ModifierKeyCode::LeftMeta => "LeftMeta",
            ModifierKeyCode::RightShift => "RightShift",
            ModifierKeyCode::RightControl => "RightControl",
            ModifierKeyCode::RightAlt => "RightAlt",
            ModifierKeyCode::RightSuper => "RightSuper",
            ModifierKeyCode::RightHyper => "RightHyper",
            ModifierKeyCode::RightMeta => "RightMeta",
            ModifierKeyCode::IsoLevel3Shift => "IsoLevel3Shift",
            ModifierKeyCode::IsoLevel5Shift => "IsoLevel5Shift",
        }
        .to_owned(),
    };
    let modifier = match modifier {
        KeyModifiers::CONTROL => "C-",
        KeyModifiers::SHIFT => "S-",
        KeyModifiers::ALT => "A-",
        KeyModifiers::SUPER => "U-",
        KeyModifiers::META => "M-",
        KeyModifiers::HYPER => "H-",
        _ => "",
    };
    format!("<{}{}>", modifier, key)
}