diff --git a/plugins/src/web/config.ron b/plugins/src/web/config.ron index a78933e..a6e82eb 100644 --- a/plugins/src/web/config.ron +++ b/plugins/src/web/config.ron @@ -87,10 +87,10 @@ matches: ["lib"], queries: [(name: "Libraries.io", query: "libraries.io/search?q=")] ), - ( - matches: ["mdn"], - queries: [(name: "Mozilla Developer Network", query: "developer.mozilla.org/search?q=")] - ), + ( + matches: ["mdn"], + queries: [(name: "Mozilla Developer Network", query: "developer.mozilla.org/search?q=")] + ), ( matches: ["npm"], queries: [(name: "npm", query: "npmjs.com/search?q=")] @@ -115,10 +115,10 @@ matches: ["stack"], queries: [(name: "Stack Overflow", query: "stackoverflow.com/search?q=")] ), - ( - matches: ["sp", "startpage"], - queries: [(name: "Startpage", query: "startpage.com/sp/search?query=")] - ), + ( + matches: ["sp", "startpage"], + queries: [(name: "Startpage", query: "startpage.com/sp/search?query=")] + ), ( matches: ["twitch"], queries: [(name: "Twitch", query: "twitch.tv/search?term=")] @@ -131,6 +131,14 @@ matches: ["wiki"], queries: [(name: "Wikipedia", query: "wikipedia.org/w/index.php?search=")] ), + ( + matches: ["www"], + queries: [( + name: "Open Website", + query: "https://", + icon: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Crystal128-browser.svg/179px-Crystal128-browser.svg.png", + )] + ), ( matches: ["xaut", "arxauth", "arxivauthor"], queries: [(name: "ArXiv", query: "https://arxiv.org/search/?searchtype=author&source=header&query=")] diff --git a/plugins/src/web/mod.rs b/plugins/src/web/mod.rs index e4e8249..700797f 100644 --- a/plugins/src/web/mod.rs +++ b/plugins/src/web/mod.rs @@ -130,17 +130,17 @@ impl App { async fn fetch_icon_in_background(&self, def: &Definition, favicon_path: &Path) { let client = self.client.clone(); - let url = build_query(def, ""); - let url = Url::parse(&url).expect("invalid url"); let icon_source = def.icon.clone(); - let domain = url - .domain() - .map(|domain| domain.to_string()) - .expect("url have no domain"); - let favicon_path = favicon_path.to_path_buf(); + let query = build_query(def, ""); + let domain = Url::parse(&query).ok().map(|url| { + url.domain() + .map(|d| d.to_string()) + .expect("url has no domain") + }); + tokio::spawn(async move { let client = &client; let favicon_path = &favicon_path; @@ -155,19 +155,24 @@ impl App { Some(icon_source) .filter(|s| !s.is_empty()) .map(|url| fetch(url)), - // Searches for the favicon if it's not defined at the root of the domain. - favicon_from_page(&domain, client) - .await - .map(|url| fetch(url)), - // If not found, fetch from root domain. - Some(fetch(["https://", &domain, "/favicon.ico"].concat())), - // If all else fails, try Google. - Some(fetch(format!( - "https://www.google.com/s2/favicons?domain={}&sz=32", - domain - ))), ]; + if let Some(domain) = domain { + icon_sources.append(&mut vec![ + // Searches for the favicon if it's not defined at the root of the domain. + favicon_from_page(&domain, client) + .await + .map(|url| fetch(url)), + // If not found, fetch from root domain. + Some(fetch(["https://", &domain, "/favicon.ico"].concat())), + // If all else fails, try Google. + Some(fetch(format!( + "https://www.google.com/s2/favicons?domain={}&sz=32", + domain + ))), + ]); + } + // await every single source and take the first one, which does not return None let mut result = None; for f in icon_sources.drain(..).flatten() { @@ -190,7 +195,7 @@ impl App { tracing::error!("error writing favicon to {:?}: {}", &favicon_path, err); } } - None => tracing::error!("no icon found for {}", domain), + None => tracing::error!("no icon found for {}", query), } }); }