use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct ExportUrls {
#[serde(default)]
pub epub: Option<String>,
#[serde(default)]
pub html: Option<String>,
#[serde(default)]
pub txt: Option<String>,
#[serde(default)]
pub md: Option<String>,
#[serde(default)]
pub mobi: Option<String>,
#[serde(default)]
pub pdf: Option<String>,
#[serde(default)]
pub azw3: Option<String>,
#[serde(default)]
pub docx: Option<String>,
#[serde(default)]
pub fb2: Option<String>,
#[serde(default)]
pub kepub: Option<String>,
}
impl ExportUrls {
pub fn preferred(&self) -> Option<(String, String)> {
if let Some(e) = &self.epub {
return Some(("epub".to_string(), e.clone()));
}
self.first()
}
pub fn first(&self) -> Option<(String, String)> {
macro_rules! try_fmt {
($name:literal, $field:ident) => {
if let Some(u) = &self.$field {
return Some(($name.to_string(), u.clone()));
}
};
}
try_fmt!("html", html);
try_fmt!("txt", txt);
try_fmt!("md", md);
try_fmt!("mobi", mobi);
try_fmt!("pdf", pdf);
try_fmt!("azw3", azw3);
try_fmt!("docx", docx);
try_fmt!("fb2", fb2);
try_fmt!("kepub", kepub);
None
}
pub fn available(&self) -> Vec<(String, String)> {
let mut out = Vec::new();
macro_rules! push {
($name:literal, $field:ident) => {
if let Some(u) = &self.$field {
out.push(($name.to_string(), u.clone()));
}
};
}
push!("epub", epub);
push!("html", html);
push!("txt", txt);
push!("md", md);
push!("mobi", mobi);
push!("pdf", pdf);
push!("azw3", azw3);
push!("docx", docx);
push!("fb2", fb2);
push!("kepub", kepub);
out
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FicMeta {
pub id: String,
#[serde(default)]
pub work_id: Option<i64>,
pub title: String,
pub author: String,
pub chapters: i64,
pub words: i64,
pub description: String,
pub status: String,
pub source: String,
pub created: String,
pub updated: String,
#[serde(default)]
pub extra_meta: Option<serde_json::Value>,
#[serde(default)]
pub raw_extended_meta: Option<serde_json::Value>,
pub author_url: String,
pub author_local_id: String,
pub source_id: i64,
pub author_id: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ExportResponse {
pub err: i32,
#[serde(default)]
pub q: Option<String>,
#[serde(default)]
pub msg: Option<String>,
#[serde(default)]
pub url_id: Option<String>,
#[serde(default)]
pub slug: Option<String>,
#[serde(default)]
pub meta: Option<FicMeta>,
#[serde(default)]
pub hashes: Option<serde_json::Map<String, serde_json::Value>>,
#[serde(default)]
pub urls: Option<ExportUrls>,
#[serde(default)]
pub epub_url: Option<String>,
#[serde(default)]
pub html_url: Option<String>,
#[serde(default)]
pub txt_url: Option<String>,
#[serde(default)]
pub md_url: Option<String>,
#[serde(default)]
pub mobi_url: Option<String>,
#[serde(default)]
pub pdf_url: Option<String>,
#[serde(default)]
pub azw3_url: Option<String>,
#[serde(default)]
pub docx_url: Option<String>,
#[serde(default)]
pub fb2_url: Option<String>,
#[serde(default)]
pub kepub_url: Option<String>,
#[serde(default)]
pub notes: Option<Vec<String>>,
}
impl ExportResponse {
pub fn flat_urls(&self) -> ExportUrls {
ExportUrls {
epub: self.epub_url.clone(),
html: self.html_url.clone(),
txt: self.txt_url.clone(),
md: self.md_url.clone(),
mobi: self.mobi_url.clone(),
pdf: self.pdf_url.clone(),
azw3: self.azw3_url.clone(),
docx: self.docx_url.clone(),
fb2: self.fb2_url.clone(),
kepub: self.kepub_url.clone(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ConvertResponse {
pub err: i32,
#[serde(default)]
pub q: Option<String>,
#[serde(default)]
pub msg: Option<String>,
#[serde(default)]
pub url_id: Option<String>,
#[serde(default)]
pub format: Option<String>,
#[serde(default)]
pub hash: Option<String>,
#[serde(default)]
pub url: Option<String>,
#[serde(default)]
pub cached: Option<bool>,
#[serde(default)]
pub elapsed_ms: Option<i64>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct RecResult {
pub url_id: String,
pub title: String,
pub author: String,
#[serde(default)]
pub words: i64,
#[serde(default)]
pub chapters: i64,
#[serde(default)]
pub status: String,
#[serde(default)]
pub site_domain: String,
#[serde(default)]
pub summary: String,
#[serde(default)]
pub score: f64,
#[serde(default)]
pub community_score: f64,
#[serde(default)]
pub download_urls: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RecommendationsResponse {
pub err: i32,
#[serde(default)]
pub url_id: String,
#[serde(default)]
pub site_domain: Option<String>,
#[serde(default)]
pub recommendations: Vec<RecResult>,
#[serde(default)]
pub generated_at: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PersonalRecommendationsResponse {
pub err: i32,
#[serde(default)]
pub enough_data: bool,
#[serde(default)]
pub recs: Vec<RecResult>,
#[serde(default)]
pub based_on: Vec<serde_json::Value>,
#[serde(default)]
pub strategies: Vec<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Suggestion {
pub id: i64,
pub suggested_url_id: String,
#[serde(default)]
pub comment: Option<String>,
pub net_votes: i64,
#[serde(default)]
pub created: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct VotesResponse {
pub err: i32,
pub url_id: String,
#[serde(default)]
pub suggestions: Vec<Suggestion>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SearchResult {
pub url_id: String,
pub title: String,
pub author: String,
pub source: String,
pub words: i64,
pub chapters: i64,
pub status: String,
pub description: String,
#[serde(default)]
pub updated: Option<String>,
#[serde(default)]
pub rank: Option<f64>,
#[serde(default)]
pub snippet: Option<String>,
#[serde(default)]
pub tags: Vec<serde_json::Value>,
#[serde(default)]
pub total_freeform: usize,
#[serde(default)]
pub comment_count: i64,
#[serde(default)]
pub kudos_count: i64,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct SearchFacets {
#[serde(default)]
pub fandoms: Vec<serde_json::Value>,
#[serde(default)]
pub tags: Vec<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SearchResponse {
pub total: i64,
pub page: usize,
pub per_page: usize,
pub results: Vec<SearchResult>,
#[serde(default)]
pub facets: SearchFacets,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AskResponse {
#[serde(flatten)]
pub search: SearchResponse,
#[serde(default)]
pub used_ask: bool,
#[serde(default)]
pub ask_query: Option<String>,
#[serde(default)]
pub translation: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct BodySearchResponse {
pub err: i32,
#[serde(default)]
pub total: i64,
#[serde(default)]
pub page: usize,
#[serde(default)]
pub per_page: usize,
#[serde(default)]
pub results: Vec<BodySearchHit>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct BodySearchHit {
pub url_id: String,
#[serde(default)]
pub work_id: Option<i64>,
pub title: String,
pub author: String,
#[serde(default)]
pub source: String,
#[serde(default)]
pub words: i64,
#[serde(default)]
pub chapters: i64,
#[serde(default)]
pub status: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub body_snippet: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FeedItem {
#[serde(default)]
pub work_id: i64,
#[serde(default)]
pub url_id: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub author: String,
#[serde(default)]
pub updated: String,
#[serde(default)]
pub format: String,
#[serde(default)]
pub note: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FeedResponse {
pub err: i32,
#[serde(default)]
pub items: Vec<FeedItem>,
#[serde(default)]
pub page: i64,
#[serde(default)]
pub per_page: i64,
#[serde(default)]
pub total: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RequestItem {
pub id: i64,
pub title: String,
pub body: String,
#[serde(default)]
pub seed_work_id: Option<i64>,
pub status: String,
#[serde(default)]
pub created_at: String,
#[serde(default)]
pub answer_count: i64,
#[serde(default)]
pub upvotes: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RequestsResponse {
pub err: i32,
#[serde(default)]
pub items: Vec<RequestItem>,
#[serde(default)]
pub page: i64,
#[serde(default)]
pub status: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ClusterRow {
pub id: i64,
pub text: String,
#[serde(default)]
pub elo_rating: f64,
#[serde(default)]
pub matches_played: i64,
#[serde(default)]
pub times_picked_best: i64,
#[serde(default)]
pub times_picked_worst: i64,
#[serde(default)]
pub suggestions: i64,
#[serde(default)]
pub status: String,
#[serde(default)]
pub controversy: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ConsensusResponse {
pub err: i32,
#[serde(default)]
pub leaderboard: Vec<ClusterRow>,
#[serde(default)]
pub controversy: Vec<ClusterRow>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AuthResponse {
pub token: String,
pub user: AuthUserModel,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AuthUserModel {
pub id: i64,
pub username: String,
pub role: i16,
pub reputation: i64,
#[serde(default)]
pub email: Option<String>,
#[serde(default)]
pub level: i16,
#[serde(default)]
pub exp: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct MeResponse {
pub err: i32,
#[serde(default)]
pub user: Option<AuthUserModel>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumCategory {
pub id: i64,
pub slug: String,
pub title: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub position: i32,
#[serde(default)]
pub is_mod_only: bool,
#[serde(default)]
pub created_at: String,
#[serde(default)]
pub topic_count: i64,
#[serde(default)]
pub last_activity_at: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumCategoriesResponse {
pub err: i32,
#[serde(default)]
pub items: Vec<ForumCategory>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumTopic {
pub id: i64,
pub title: String,
#[serde(default)]
pub topic_slug: Option<String>,
pub author_id: i64,
#[serde(default)]
pub author_username: String,
#[serde(default)]
pub reply_count: i64,
#[serde(default)]
pub vote_score: i64,
#[serde(default)]
pub view_count: i64,
#[serde(default)]
pub last_post_id: Option<i64>,
#[serde(default)]
pub status: String,
#[serde(default)]
pub last_activity_at: String,
#[serde(default)]
pub created_at: String,
#[serde(default)]
pub unread: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumTopicList {
pub err: i32,
#[serde(default)]
pub items: Vec<ForumTopic>,
#[serde(default)]
pub next_cursor: Option<i64>,
#[serde(default)]
pub category: String,
#[serde(default)]
pub limit: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumQuote {
#[serde(default)]
pub author_username: String,
#[serde(default)]
pub preview: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumPost {
pub id: i64,
pub author_id: i64,
#[serde(default)]
pub author_username: String,
#[serde(default)]
pub body: String,
#[serde(default)]
pub quote_of: Option<i64>,
#[serde(default)]
pub quote: Option<ForumQuote>,
#[serde(default)]
pub edited_at: Option<String>,
#[serde(default)]
pub deleted_at: Option<String>,
#[serde(default)]
pub created_at: String,
#[serde(default)]
pub score: i32,
#[serde(default)]
pub is_op: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumTopicDetail {
pub err: i32,
pub id: i64,
pub title: String,
#[serde(default)]
pub topic_slug: Option<String>,
pub author_id: i64,
#[serde(default)]
pub author_username: String,
#[serde(default)]
pub category_slug: String,
#[serde(default)]
pub category_title: String,
#[serde(default)]
pub status: String,
#[serde(default)]
pub body: String,
#[serde(default)]
pub payload: serde_json::Value,
#[serde(default)]
pub view_count: i64,
#[serde(default)]
pub created_at: String,
#[serde(default)]
pub updated_at: Option<String>,
#[serde(default)]
pub items: Vec<ForumPost>,
#[serde(default)]
pub next_cursor: Option<i64>,
#[serde(default)]
pub limit: i64,
#[serde(default)]
pub view_count_before: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumSearchHit {
#[serde(default)]
pub r#type: String,
pub topic_id: i64,
#[serde(default)]
pub topic_slug: Option<String>,
#[serde(default)]
pub post_id: Option<i64>,
pub author_id: i64,
#[serde(default)]
pub author_username: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub body: String,
#[serde(default)]
pub snippet: Option<String>,
#[serde(default)]
pub category_slug: String,
#[serde(default)]
pub category_title: String,
#[serde(default)]
pub created_at: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumSearchResponse {
pub err: i32,
#[serde(default)]
pub q: String,
#[serde(default)]
pub results: Vec<ForumSearchHit>,
#[serde(default)]
pub next_cursor: Option<i64>,
#[serde(default)]
pub limit: i64,
#[serde(default)]
pub total: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumCreateTopicResponse {
pub err: i32,
#[serde(default)]
pub id: i64,
#[serde(default)]
pub post_id: i64,
#[serde(default)]
pub topic_slug: Option<String>,
#[serde(default)]
pub msg: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumPostCreated {
pub err: i32,
#[serde(default)]
pub id: i64,
#[serde(default)]
pub msg: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumFollowState {
pub err: i32,
#[serde(default)]
pub following: bool,
#[serde(default)]
pub follower_count: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumMarkRead {
pub err: i32,
#[serde(default)]
pub last_read_post_id: i64,
#[serde(default)]
pub updated_at: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumModerationStatus {
pub err: i32,
#[serde(default)]
pub points_left: i16,
#[serde(default)]
pub expires_at: Option<String>,
#[serde(default)]
pub eligible: bool,
#[serde(default)]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumModQueueItem {
pub post_id: i64,
pub topic_id: i64,
#[serde(default)]
pub author_username: String,
#[serde(default)]
pub body: String,
#[serde(default)]
pub score: i32,
#[serde(default)]
pub mod_count: i32,
#[serde(default)]
pub reason: Option<String>,
#[serde(default)]
pub created_at: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumModerationQueue {
pub err: i32,
#[serde(default)]
pub items: Vec<ForumModQueueItem>,
#[serde(default)]
pub count: i64,
#[serde(default)]
pub pool_too_small: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumModerateResponse {
pub err: i32,
#[serde(default)]
pub delta: i16,
#[serde(default)]
pub score_after: i32,
#[serde(default)]
pub hidden_until: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumMetamodItem {
pub action_id: i64,
pub post_id: i64,
pub topic_id: i64,
#[serde(default)]
pub excerpt: String,
#[serde(default)]
pub reason: String,
#[serde(default)]
pub delta: i16,
#[serde(default)]
pub score_after: i32,
#[serde(default)]
pub created_at: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumMetamodQueue {
pub err: i32,
#[serde(default)]
pub items: Vec<ForumMetamodItem>,
#[serde(default)]
pub count: i64,
#[serde(default)]
pub pool_too_small: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForumMetamodVoteResponse {
pub err: i32,
}