favicons: use a shared client

This commit is contained in:
Bilal Elmoussaoui 2020-12-19 23:13:05 +01:00
parent ea250e9580
commit 9d82a33c80
3 changed files with 20 additions and 19 deletions

View file

@ -1,3 +1,4 @@
use super::CLIENT;
use image::io::Reader as ImageReader;
use quick_xml::events::{attributes::Attribute, BytesStart, Event};
use std::io::Cursor;
@ -42,9 +43,8 @@ impl std::fmt::Display for FaviconError {
}
}
#[derive(Debug)]
pub struct Favicon(Vec<Url>, surf::Client);
pub struct Favicon(Vec<Url>);
impl Favicon {
pub async fn find_best(&self) -> Option<&Url> {
@ -63,7 +63,7 @@ impl Favicon {
}
pub async fn get_size(&self, url: &Url) -> Option<(u32, u32)> {
let mut response = self.1.get(url).await.ok()?;
let mut response = CLIENT.get(url).await.ok()?;
let ext = std::path::Path::new(url.path())
.extension()
@ -86,36 +86,31 @@ impl Favicon {
}
}
#[derive(Debug)]
pub struct FaviconScrapper(surf::Client);
pub struct FaviconScrapper;
impl FaviconScrapper {
pub fn new() -> Self {
let client = surf::client().with(surf::middleware::Redirect::default());
Self(client)
}
pub async fn from_url(&self, url: Url) -> Result<Favicon, FaviconError> {
let mut res = self.0.get(&url).header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15").await?;
pub async fn from_url(url: Url) -> Result<Favicon, FaviconError> {
let mut res = CLIENT.get(&url).header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15").await?;
let body = res.body_string().await?;
let mut reader = quick_xml::Reader::from_str(&body);
reader.check_end_names(false);
reader.trim_markup_names_in_closing_tags(true);
let icons = self.from_reader(&mut reader, &url);
let icons = Self::from_reader(&mut reader, &url);
if icons.is_empty() {
return Err(FaviconError::NoResults);
}
Ok(Favicon(icons, self.0.clone()))
Ok(Favicon(icons))
}
fn from_reader(&self, reader: &mut quick_xml::Reader<&[u8]>, base_url: &Url) -> Vec<Url> {
fn from_reader(reader: &mut quick_xml::Reader<&[u8]>, base_url: &Url) -> Vec<Url> {
let mut buf = Vec::new();
let mut urls = Vec::new();
loop {
match reader.read_event(&mut buf) {
Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e)) => {
if let b"link" = e.name() {
if let Some(url) = self.from_link(e, base_url) {
if let Some(url) = Self::from_link(e, base_url) {
urls.push(url);
}
}
@ -129,7 +124,7 @@ impl FaviconScrapper {
urls
}
fn from_link(&self, e: &BytesStart, base_url: &Url) -> Option<Url> {
fn from_link(e: &BytesStart, base_url: &Url) -> Option<Url> {
let mut url = None;
let mut has_proper_rel = false;

View file

@ -1,3 +1,5 @@
use once_cell::sync::Lazy;
mod account;
mod account_sorter;
mod accounts;
@ -9,6 +11,9 @@ mod provider;
mod provider_sorter;
mod providers;
pub static CLIENT: Lazy<surf::Client> =
Lazy::new(|| surf::Client::new().with(surf::middleware::Redirect::default()));
pub use self::{
account::Account,
account_sorter::AccountSorter,

View file

@ -1,10 +1,11 @@
use super::algorithm::{Algorithm, OTPMethod};
use super::CLIENT;
use crate::{
models::{database, Account, AccountsModel, FaviconError, FaviconScrapper},
schema::providers,
};
use async_std::prelude::*;
use anyhow::Result;
use async_std::prelude::*;
use core::cmp::Ordering;
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use gio::subclass::ObjectSubclass;
@ -363,7 +364,7 @@ impl Provider {
pub async fn favicon(&self) -> Result<gio::File, Box<dyn std::error::Error>> {
if let Some(ref website) = self.website() {
let website_url = Url::parse(website)?;
let favicon = FaviconScrapper::new().from_url(website_url).await?;
let favicon = FaviconScrapper::from_url(website_url).await?;
let icon_name = format!("{}_{}", self.id(), self.name().replace(' ', "_"));
let cache_path = glib::get_user_cache_dir()
@ -373,7 +374,7 @@ impl Provider {
let mut dest = async_std::fs::File::create(cache_path.clone()).await?;
if let Some(best_favicon) = favicon.find_best().await {
let mut res = surf::get(best_favicon).await?;
let mut res = CLIENT.get(best_favicon).await?;
let body = res.body_bytes().await?;
dest.write_all(&body).await?;