Internet
Mấy cái xung quanh việc tương tác với Internet sử dụng Rust.
Encode URL
Dùng cái này: open = "5.0.1"
let encoded_query =
percent_encoding::utf8_percent_encode(&args.query, NON_ALPHANUMERIC).to_string();
for site in config.sites {
let url = site.url.replace("%s", &encoded_query);
println!("{}:\t{}", site.name, url);
// Phần này là dùng "open" rồi, hơi ngoài lề chút
open::that(url).context("could not open the URL")?;
}
Request
Sử dụng ureq.
pub fn fetch(url: &str, refer_site: &str) -> Result<Response, ureq::Error> {
let user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36";
let ureq_agent: Agent = ureq::AgentBuilder::new()
.timeout_read(Duration::from_secs(30))
.build();
let body = ureq_agent.get(url)
.set("User-Agent", user_agent)
.set("Referer", refer_site)
.call();
body
}
Lấy thông tin từ API
#[derive(Debug, Serialize, Deserialize, Default)]
struct Fact {
id: String,
text: String,
source: String,
source_url: String,
language: String,
permalink: String,
}
const FACT_BASE_URL: &str = "https://uselessfacts.jsph.pl";
const FACT_RANDOM: &str = "/api/v2/facts/random?language=en";
const FACT_DAILY: &str = "/api/v2/facts/today?language=en";
fn get_fact(url: &str) -> Result<Fact, Box<dyn std::error::Error>> {
let resp = reqwest::blocking::get(url)?.json::<Fact>()?;
Ok(resp)
}
fn get_random_fact() -> Result<Fact, Box<dyn std::error::Error>> {
let url = format!("{}{}", FACT_BASE_URL, FACT_RANDOM);
get_fact(&url)
}
fn get_daily_fact() -> Result<Fact, Box<dyn std::error::Error>> {
let url = format!("{}{}", FACT_BASE_URL, FACT_DAILY);
get_fact(&url)
}
fn get_help() -> Result<Fact, Box<dyn std::error::Error>> {
let mut fact = Fact::default();
fact.text = String::from("Usage: fact [t]oday | [r]andom");
Ok(fact)
}
fn print_fact(fact: Fact) {
println!("Fact: {}", fact.text);
println!("Source: {}", fact.source_url);
}
Mở trình duyệt
pub fn show_news(new: &NewsLink) -> Result<(), Box<dyn std::error::Error>> {
let link = &new.link;
let response = ureq::get(link).call()?;
let url = response.get_url();
// if is a video of youtube
if url.contains("youtube") {
if webbrowser::open(new.link.as_str()).is_ok() {}
return Ok(());
}
let view_select = Select::new(
"What view do you like to do?",
vec!["Web", "Terminal", "Ia Draft"],
)
.with_help_message("Enter the view of the new")
.prompt()
.unwrap_or("Cancel");
if view_select == "Cancel" {
manage_exit("No view provided")
}
let view = View::from_str(view_select).expect("failed to parse view");
match view {
View::Terminal => {
let html = response.into_string()?;
let markdown = get_markdown_content(&html);
if markdown.is_empty() {
println!("Content of new cannot be loaded in terminal");
println!("Opening browser instead");
if webbrowser::open(new.link.as_str()).is_ok() {}
} else {
generate_view(markdown.as_str()).expect("failed to generate a markdown view");
}
}
View::Web => {
webbrowser::open(new.link.as_str())?;
}
View::Ia => {
let html = response.into_string()?;
let markdown = get_markdown_content(&html);
get_resume(&markdown)?;
}
}