protozoa 0.1.8

A scraper for various anime websites
Documentation
use regex::{Regex, RegexBuilder};

const CHARSET: &str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";

fn int_2_base(x: i32, base: i32) -> String {
	let mut sign = 1;
	match x.cmp(&0) {
		std::cmp::Ordering::Less => sign = -1,
		std::cmp::Ordering::Equal => return "0".to_string(),
		std::cmp::Ordering::Greater => (),
	}
	let mut x = x * sign;
	let mut digits = Vec::new();
	while x != 0 {
		digits.push(CHARSET.chars().nth((x % base) as usize).unwrap());
		x /= base;
	}
	if sign < 0 {
		digits.push('-');
	}
	digits.reverse();
	digits.into_iter().collect()
}

fn filter_args(source: &str) -> Option<(&str, Vec<&str>, i32, i32)> {
	let regexes = [
		RegexBuilder::new(r"}\('(.*)', *(\d+), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)")
			.dot_matches_new_line(true)
			.build()
			.unwrap(),
		RegexBuilder::new(r"}\('(.*)', *(\d+), *(\d+), *'(.*)'\.split\('\|'\)")
			.dot_matches_new_line(true)
			.build()
			.unwrap(),
	];
	for regex in regexes.iter() {
		if let Some(args) = regex.captures(source) {
			let payload = args.get(1)?.as_str();
			let radix = args.get(2)?.as_str().parse::<i32>().ok()?;
			let count = args.get(3)?.as_str().parse::<i32>().ok()?;
			let symtab: Vec<&str> = args.get(4)?.as_str().split('|').collect();
			return Some((payload, symtab, radix, count));
		}
	}
	None
}

fn unpack(p: &str, a: i32, c: i32, k: Vec<&str>) -> String {
	let mut p = p.to_string();
	for i in (0..c).rev() {
		if !k[i as usize].is_empty() {
			let re = Regex::new(&format!(r"\b{}\b", int_2_base(i, a))).unwrap();
			p = re.replace_all(&p, k[i as usize]).to_string();
		}
	}
	p
}

pub fn unpack_source(source: &str) -> Option<String> {
	let (payload, symtab, radix, count) = filter_args(source)?;
	Some(unpack(payload, radix, count, symtab))
}