# Aletheia
> 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](https://www.theguardian.com)'s [content API](https://open-platform.theguardian.com) written in Rust.
[![Crates.io][crates-badge]][crates-url]
[![Build Status][actions-badge]][actions-url]
[crates-badge]: https://img.shields.io/crates/v/aletheia.svg
[crates-url]: https://crates.io/crates/aletheia
[actions-badge]: https://github.com/marsavar/aletheia/workflows/CI/badge.svg
[actions-url]: https://github.com/marsavar/aletheia/actions?query=workflow%3ACI+branch%3Amain
## How to use it
You need an API key to be able to make requests.
Keys can be requested [here](https://open-platform.theguardian.com/access/).
Aletheia provides two versions of the client: [asynchronous](#async-example) (default behaviour) and [blocking](#blocking-example).\
The default behaviour is asynchronous, which means the client can be used inside `async fn`.
### Async example
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.
```toml
[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:
1) Constructing the HTTP client
2) Building the query
3) Parsing the response [*](#debug)
```rust
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
```
### Blocking example
Add `aletheia` to the list of dependencies in your `Cargo.toml` file with the `blocking` feature enabled.
```toml
[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:
```rust
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(())
}
```
#### Debug
[*] You can pretty-print the whole output response with the format specifier `#?`:
```rust
println!("{response:#?}");
```
or by using the `dbg!` macro:
```rust
dbg!(response);
```