use super::Inoreader;
use super::config::AccountConfig;
use super::oauth::InoreaderOAuth;
use crate::feed_api::{ApiMetadata, FeedApi, FeedApiError, FeedApiResult, Portal};
use crate::models::{
ApiSecret, LoginGUI, OAuthLoginGUI, PluginID, PluginIcon, PluginInfo, ServiceLicense, ServicePrice, ServiceType, Url, VectorIcon,
};
use crate::util;
use greader_api::{AuthData, GReaderApi, InoreaderAuth};
use rust_embed::RustEmbed;
use std::path::Path;
use std::str;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(RustEmbed)]
#[folder = "src/feed_api_implementations/inoreader/icons"]
struct InoreaderResources;
pub struct InoreaderMetadata;
impl InoreaderMetadata {
pub fn get_id() -> PluginID {
PluginID::new("inoreader")
}
}
impl ApiMetadata for InoreaderMetadata {
fn id(&self) -> PluginID {
Self::get_id()
}
fn info(&self) -> FeedApiResult<PluginInfo> {
let icon_data = InoreaderResources::get("feed-service-inoreader.svg").ok_or(FeedApiError::Resource)?;
let icon = VectorIcon {
data: icon_data.data.to_vec(),
width: 48,
height: 48,
};
let icon = PluginIcon::Vector(icon);
let symbolic_icon_data = InoreaderResources::get("feed-service-inoreader-symbolic.svg").ok_or(FeedApiError::Resource)?;
let symbolic_icon = VectorIcon {
data: symbolic_icon_data.data.to_vec(),
width: 48,
height: 48,
};
let symbolic_icon = PluginIcon::Vector(symbolic_icon);
let login_fn = move |secret: Option<&ApiSecret>| Url::parse(&InoreaderOAuth::new().login_url(secret)).ok();
let api_info = InoreaderOAuth::new();
let login_gui = LoginGUI::OAuth(Box::new(OAuthLoginGUI {
login_website: Box::new(login_fn),
catch_redirect: Some(api_info.redirect_uri()),
custom_api_secret: true,
custom_api_secret_url: Some(api_info.create_secret_url.clone()),
embeded_api_secret: true,
create_secret_url: Some(api_info.create_secret_url),
}));
Ok(PluginInfo {
id: self.id(),
name: String::from("Inoreader"),
icon: Some(icon),
icon_symbolic: Some(symbolic_icon),
website: Some(crate::models::Url::parse("https://inoreader.com").unwrap()),
service_type: ServiceType::Remote { self_hosted: false },
license_type: ServiceLicense::GenericProprietary,
service_price: ServicePrice::PaidPremimum,
login_gui,
})
}
fn get_instance(&self, path: &Path, portal: Box<dyn Portal>, user_api_secret: Option<ApiSecret>) -> FeedApiResult<Box<dyn FeedApi>> {
let mut account_config = AccountConfig::load(path)?;
let mut api: Option<GReaderApi> = None;
let mut logged_in: bool = false;
let (client_id, client_secret) = if let Some(user_api_secret) = user_api_secret {
account_config.set_custom_api_secret(Some(&user_api_secret));
(user_api_secret.client_id, user_api_secret.client_secret)
} else if let Some(user_api_secret) = account_config.get_custom_api_secret() {
(user_api_secret.client_id, user_api_secret.client_secret)
} else {
let api_info = InoreaderOAuth::new();
(api_info.client_id, api_info.client_secret)
};
if let Some(access_token) = account_config.get_access_token()
&& let Some(refresh_token) = account_config.get_refresh_token()
&& let Some(expires_at) = account_config.get_token_expires()
{
let timestamp = expires_at.parse::<i64>().map_err(|_| FeedApiError::Unknown)?;
let expires_at = util::timestamp_to_datetime(timestamp);
api = Some(GReaderApi::new(
&crate::models::Url::parse("https://inoreader.com").unwrap(),
AuthData::Inoreader(InoreaderAuth {
client_id,
client_secret,
access_token,
refresh_token,
expires_at,
}),
));
logged_in = true;
}
let inoreader = Inoreader {
api,
portal: Arc::new(portal),
logged_in,
config: Arc::new(RwLock::new(account_config)),
};
let template = Box::new(inoreader);
Ok(template)
}
}