use std::time::SystemTime;
use moonbase::{
ActivationMethod, DeviceIdDescription, ErrorType, License, Product, ReleaseAccess, SubProduct,
SubProductCatalogEntry, User, serde_iso8601,
};
use serde::Serialize;
use serde_json::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum Status {
Loading,
Unlicensed,
Activating,
Licensed,
Trial,
TrialExpired,
NotCovered,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum LockReason {
Deactivated,
Expired,
Invalid,
Unverified,
NotCovered,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PendingActivation {
pub browser_url: Option<String>,
pub method: ActivationMethod,
pub browser_open_failed: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NotCovered {
pub license: LicenseView,
pub app_version: String,
pub release_access: Option<ReleaseAccess>,
pub upgrade_url: Option<String>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum AddOnsPhase {
#[default]
Idle,
Loading,
Ready,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AddOnsState {
pub phase: AddOnsPhase,
pub currency: Option<String>,
pub add_ons: Vec<SubProductCatalogEntry>,
pub error: Option<String>,
pub busy_id: Option<String>,
pub action_error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Failure {
pub message: String,
pub detail: String,
pub kind: Option<ErrorType>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateHint {
pub current_version: String,
pub latest_version: String,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LicenseState {
pub status: Status,
pub licensed: bool,
pub license: Option<LicenseView>,
pub expired_trial: Option<LicenseView>,
pub not_covered: Option<NotCovered>,
pub lock_reason: Option<LockReason>,
pub activation: Option<PendingActivation>,
pub busy: bool,
pub refreshing: bool,
pub error: Option<Failure>,
pub update: Option<UpdateHint>,
pub active_sub_products: Vec<String>,
pub add_ons: AddOnsState,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInfo {
pub name: String,
pub platform: String,
pub description: Option<DeviceIdDescription>,
pub error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateInfo {
pub available: bool,
pub current_version: String,
pub latest_version: Option<String>,
pub release_notes: String,
pub has_downloads: bool,
pub can_download: bool,
pub covered: bool,
pub release_access: Option<ReleaseAccess>,
pub upgrade_url: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LicenseView {
pub id: String,
pub activation_id: String,
pub trial: bool,
#[serde(rename = "activationMethod")]
pub method: ActivationMethod,
#[serde(rename = "product")]
pub licensed_product: Product,
pub issued_to: User,
#[serde(with = "serde_iso8601")]
pub issued_at: SystemTime,
#[serde(with = "serde_iso8601::option", skip_serializing_if = "Option::is_none")]
pub expires_at: Option<SystemTime>,
#[serde(with = "serde_iso8601")]
pub validated_at: SystemTime,
pub owned_sub_product_ids: Vec<String>,
pub sub_products: Vec<SubProduct>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seat_count: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seats_used: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub release_access: Option<ReleaseAccess>,
pub properties: Value,
pub days_remaining: Option<u64>,
}
impl From<&License> for LicenseView {
fn from(license: &License) -> Self {
let License {
id,
activation_id,
trial,
method,
licensed_product,
issued_to,
issued_at,
expires_at,
validated_at,
owned_sub_product_ids,
sub_products,
subscription_id,
seat_count,
seats_used,
release_access,
properties,
token: _,
} = license.clone();
let days_remaining = expires_at.map(|expires| match expires.duration_since(SystemTime::now()) {
Ok(left) => left.as_secs().div_ceil(86_400),
Err(_) => 0,
});
Self {
id,
activation_id,
trial,
method,
licensed_product,
issued_to,
issued_at,
expires_at,
validated_at,
owned_sub_product_ids,
sub_products,
subscription_id,
seat_count,
seats_used,
release_access,
properties,
days_remaining,
}
}
}