/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ use crate::{ USER_AGENT, plugins::{ImportPlugin, PluginInfo}, }; use anyhow::{Context, Result}; use jellycache::{Cache, EscapeKey}; use reqwest::{ Client, ClientBuilder, header::{HeaderMap, HeaderName, HeaderValue}, redirect::Policy, }; use tokio::runtime::Handle; pub struct WikimediaCommons { client: Client, } impl Default for WikimediaCommons { fn default() -> Self { Self::new() } } impl WikimediaCommons { pub fn new() -> Self { let client = ClientBuilder::new() .default_headers(HeaderMap::from_iter([( HeaderName::from_static("user-agent"), HeaderValue::from_static(USER_AGENT), )])) .redirect(Policy::limited(5)) .build() .unwrap(); Self { client } } pub fn image_by_filename( &self, cache: &Cache, filename: String, rt: &Handle, ) -> Result { cache .store( format!("ext/wikimedia-commons/image/{}.image", EscapeKey(&filename)), move || { rt.block_on(async { Ok(self .client .get(format!( "https://commons.wikimedia.org/wiki/Special:FilePath/{}", filename.replace(" ", "_") )) .send() .await? .error_for_status()? .bytes() .await? .to_vec()) }) }, ) .context("mediawiki image by filename") } } impl ImportPlugin for WikimediaCommons { fn info(&self) -> PluginInfo { PluginInfo { name: "wikimedia-commons", ..Default::default() } } }