# favicon-picker
[![Crates.io][crates-badge]][crates-url]
[![Crates.io (recent)](https://img.shields.io/crates/dr/favicon-picker)][crates-url]
[crates-badge]: https://img.shields.io/crates/v/favicon-picker.svg
[crates-url]: https://crates.io/crates/favicon-picker
[docs-badge]: https://img.shields.io/docsrs/favicon-picker.svg
This is just a small library that allows you to get websites [favicons](https://en.wikipedia.org/wiki/Favicon).
This library is similar to [`site_icons`](https://github.com/samdenty/site_icons) but i just wanted something simple and flexible to use for various side-project.
## Usage
Just add `favicon-picker` into your cargo dependencies or run:
```bash
cargo add favicon-picker
```
## Example
### Simple
```rust
use favicon_picker::get_favicons_from_url;
use reqwest::{header::{HeaderMap, HeaderValue, USER_AGENT}, Client};
use url::Url;
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let client = Client::builder().default_headers({
// the `User-Agent` is not required here
let mut headers = HeaderMap::new();
headers.append(USER_AGENT, HeaderValue::from_str("favicon-picker/1.0.0")?);
headers
}).build()?;
let base_url = Url::parse("https://comic-walker.com/")?;
for favs in get_favicons_from_url(&client, &base_url).await.map_err(|e| anyhow::Error::msg(e.to_string()))? {
// I just printed the value to the standard output
println!("{:#?}", favs);
}
Ok(())
}
```
### Download
```rust
use std::{
fs::{create_dir_all, File},
io::{BufWriter, Write},
path::Path,
};
use favicon_picker::get_favicons_from_url;
use reqwest::{
header::{HeaderMap, HeaderValue, USER_AGENT},
Client,
};
use url::Url;
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let dowload_path = Path::new("output");
create_dir_all(dowload_path)?;
let client = Client::builder()
.default_headers({
// the `User-Agent` is not required here
let mut headers = HeaderMap::new();
headers.append(USER_AGENT, HeaderValue::from_str("favicon-picker/1.0.0")?);
headers
})
.build()?;
let base_url = Url::parse("https://comic-walker.com/")?;
/// get existing favicons on the page
for favs in get_favicons_from_url(&client, &base_url)
.await
.map_err(|e| anyhow::Error::msg(e.to_string()))?
{
// i just need the favicon file name here
let file_name = favs
.href
.path_segments()
.ok_or_else(|| anyhow::Error::msg("cannot be base"))?
.last()
.ok_or_else(|| anyhow::Error::msg("can't get the last url fragments"))?;
let filepath = dowload_path.join(file_name);
let data = favs.get_image_bytes(&client).await?;
let mut file = BufWriter::new(File::create(filepath)?);
file.write_all(&data)?;
file.flush()?;
}
Ok(())
}
```
## How does it work ??
When you call the [`favicon_picker::get_favicons_from_url`](https://github.com/tonymushah/favicon-picker/blob/main/src/lib.rs#L48), it will just fetch, and parse the existing HTML page. Then it will lookup to existing `` and that's it.
If it finds no favicon, it will give you the default favicon url which is `http:///favicon.ico`
## Feature flags
- `non_exhaustive`: Will make the `Favicon` struct `#[non_exhaustive]` *Enabled by default*
- `serde`: Allows the `Favicon` struct to be serialized and deserialized with the [`serde`](https:/serde.rs) framework
- `blocking`: Allows you to use the `reqwest::blocking::Client`. Useful if you don't want to use `async/await`
## Contribution
All pull request are welcome!!
## License
GNU GENERAL PUBLIC LICENSE version 3