use rand::seq::SliceRandom;
use sauron::html::attributes::{class, id};
use sauron::html::events::on_click;
use sauron::html::{div, text};
use sauron::prelude::*;
use sauron::{Cmd, Component, Node, Program};
mod tlds;
pub enum Msg {
Click,
ReceivedWords(Result, JsValue>),
}
pub struct App {
output: Option,
words: Vec,
}
impl App {
pub fn new() -> Self {
App {
output: None,
words: vec![],
}
}
fn generate_domain(&mut self) -> String {
let mut domain: String = String::from("");
while domain.is_empty() {
let tld = self.get_random_tld();
tld.map(|tld| {
let word = self.get_random_word(&tld);
if word.is_some() {
let mut word = word.unwrap();
word.truncate(word.len() - 2);
domain = format!("{}.{}", word, tld);
}
});
}
domain
}
fn get_random_tld(&mut self) -> Option {
crate::tlds::tlds()
.choose(&mut rand::thread_rng())
.map(|v| String::from(v))
}
fn get_random_word(&self, tld: &str) -> Option {
self.words
.clone()
.into_iter()
.filter(|word| word.ends_with(tld))
.collect::>()
.choose(&mut rand::thread_rng())
.map(|v| v.to_string().to_lowercase())
}
}
impl Component for App {
fn init(&self) -> Cmd {
Http::fetch_with_text_response_decoder(
"/words.txt",
|r: String| r.lines().map(|l| l.to_string()).collect(),
Msg::ReceivedWords,
)
}
fn view(&self) -> Node {
let output = match &self.output {
Some(s) => vec![text(s)],
None => vec![],
};
let loading = self.words.len() == 0;
sauron::html::main(
vec![],
vec![div(
vec![class("container")],
vec![
h1(vec![class("heading")], vec![text("Domain Hack Generator")]),
div(
vec![class("button-container")],
vec![
button(
vec![
class("button"),
disabled(loading),
on_click(|_: MouseEvent| Msg::Click),
],
vec![text(if loading { "Loading..." } else { "Generate" })],
),
p(
vec![
id("result"),
class(if output.is_empty() { "empty" } else { "" }),
],
output,
),
],
),
],
)],
)
}
fn update(&mut self, msg: Msg) -> Cmd {
match msg {
Msg::Click => self.output = Some(self.generate_domain()),
Msg::ReceivedWords(result) => match result {
Ok(words) => self.words = words,
Err(_) => {}
},
}
Cmd::none()
}
}
#[wasm_bindgen(start)]
pub fn main() {
console_log::init_with_level(log::Level::Trace).unwrap();
console_error_panic_hook::set_once();
Program::mount_to_body(App::new());
}