Aletheia is truth or disclosure (...) The literal meaning of the word ἀλήθεια is "the state of not being hidden; the state of being evident."
Aletheia is an HTTP client library for the Guardian's content API written in Rust.
You need an API key to be able to make requests. Keys can be requested here.
Aletheia provides two versions of the client: asynchronous (default behaviour) and blocking.
The default behaviour is asynchronous, which means the client can be used inside async fn.
Aletheia requires Tokio as a dependency to execute asynchronous code.
Simply add aletheia and tokio to the list of dependencies in your Cargo.toml file.
[dependencies]
aletheia = "1.1.0"
tokio = { version = "1", features = ["full"] }Let's say you were interested in finding five film, play or album reviews with a rating of 5 stars containing the word "politics" published from January to December 2022. The code would look something like the example below, and would consist of three steps:
- Constructing the HTTP client
- Building the query
- Parsing the response *
use aletheia::enums::*;
use aletheia::GuardianContentClient;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// The client is constructed by passing your API key
// as the only parameter
let client = GuardianContentClient::new("YOUR_API_KEY");
// Query parameters are built incrementally
let response = client
.build_request()
.search("politics")
.date_from(2022, 1, 1)
.date_to(2022, 12, 31)
.star_rating(5)
.page_size(5)
.show_fields(vec![Field::Byline])
.order_by(OrderBy::Newest)
.send()
.await?;
// Parsing the response.
// The response objects are deserialized, for the most part,
// into Option values that need to be handled safely with
// `let else` or `if let`.
if let Some(results) = response.results {
for result in results {
let Some(pub_date) = result.web_publication_date else { continue };
let Some(fields) = result.fields else { continue };
let Some(byline) = fields.byline else { continue };
println!(
"[{}] {} ({})\n{}\n",
pub_date.format("%Y-%m-%d"),
result.web_title.trim(),
byline,
result.web_url,
)
}
}
Ok(())
}The above will return the following results.
[2022-12-15] Children of the Taliban review – this beautiful documentary is an absolute must-watch (Rebecca Nicholson)
https://www.theguardian.com/tv-and-radio/2022/dec/15/children-of-the-taliban-review-this-beautiful-documentary-is-an-absolute-must-watch
[2022-10-25] The White Lotus season two review – this immaculate show’s writing is utterly unrivalled (Lucy Mangan)
https://www.theguardian.com/tv-and-radio/2022/oct/25/the-white-lotus-season-two-review-this-immaculate-seriess-writing-is-utterly-unrivalled
[2022-10-09] The Doctor review – a repeat prescription for acute intellectual stimulation (Arifa Akbar)
https://www.theguardian.com/stage/2022/oct/10/the-doctor-review-duke-of-yorks-theatre-robert-icke-juliet-stevenson
[2022-09-27] Make Me Prime Minister review – absolute, exquisite agony (Lucy Mangan)
https://www.theguardian.com/tv-and-radio/2022/sep/27/make-me-prime-minister-review-absolute-exquisite-agony
[2022-09-02] Bones and All review – cannibal romance is a heartbreaking banquet of brilliance (Peter Bradshaw)
https://www.theguardian.com/film/2022/sep/02/bones-and-all-review-luca-guadagnino-timothee-chalamet-venice-film-festival
Add aletheia to the list of dependencies in your Cargo.toml file with the blocking feature enabled.
[dependencies]
aletheia = { version = "1.1.0", features = ["blocking"] }This makes GuardianContentClient blocking, which can be useful in situations where a full async runtime is not
needed. Note that invoking the blocking client from an async block causes a panic.
It can still be used in async fn, however, if invoked from a blocking context, for example inside
tokio::task::spawn_blocking.
The above example then becomes:
use aletheia::enums::*;
use aletheia::GuardianContentClient;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let client = GuardianContentClient::new("YOUR_API_KEY");
let response = client
.build_request()
.search("politics")
.date_from(2022, 1, 1)
.date_to(2022, 12, 31)
.star_rating(5)
.page_size(5)
.show_fields(vec![Field::Byline])
.order_by(OrderBy::Newest)
.send();
if let Some(results) = response.results {
for result in results {
let Some(pub_date) = result.web_publication_date else { continue };
let Some(fields) = result.fields else { continue };
let Some(byline) = fields.byline else { continue };
println!(
"[{}] {} ({})\n{}\n",
pub_date.format("%Y-%m-%d"),
result.web_title.trim(),
byline,
result.web_url,
)
}
}
Ok(())
}[*] You can pretty-print the whole output response with the format specifier #?:
println!("{response:#?}");or by using the dbg! macro:
dbg!(response);