use std::str::FromStr;
use tosho_macros::AutoGetter;
use crate::helper::SubscriptionPlan;
use super::ChapterPosition;
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct Chapter {
#[prost(uint64, tag = "1")]
title_id: u64,
#[prost(uint64, tag = "2")]
chapter_id: u64,
#[prost(string, tag = "3")]
title: ::prost::alloc::string::String,
#[prost(string, optional, tag = "4")]
#[skip_field]
subtitle: ::core::option::Option<::prost::alloc::string::String>,
#[prost(string, tag = "5")]
thumbnail: ::prost::alloc::string::String,
#[prost(int64, tag = "6")]
published_at: i64,
#[prost(int64, optional, tag = "7")]
#[skip_field]
end_at: ::core::option::Option<i64>,
#[prost(bool, tag = "8")]
viewed: bool,
#[prost(bool, tag = "9")]
vertical_only: bool,
#[prost(int64, optional, tag = "10")]
#[skip_field]
ticket_end_at: ::core::option::Option<i64>,
#[prost(bool, tag = "11")]
free: bool,
#[prost(bool, tag = "12")]
horizontal_only: bool,
#[prost(uint64, tag = "13")]
view_count: u64,
#[prost(uint64, tag = "14")]
comment_count: u64,
#[prost(enumeration = "super::ChapterPosition", tag = "999")]
#[skip_field]
position: i32,
}
impl Chapter {
pub fn is_free(&self) -> bool {
if self.free {
return true;
}
if self.position() == ChapterPosition::First {
return true;
}
if self.position() != ChapterPosition::Middle {
if let Some(end_at) = self.end_at {
let current_time = chrono::Utc::now().timestamp();
current_time < end_at
} else {
false
}
} else {
false
}
}
pub fn is_ticketed(&self) -> bool {
if let Some(ticket_end_at) = self.ticket_end_at {
let current_time = chrono::Utc::now().timestamp();
current_time < ticket_end_at
} else {
false
}
}
pub fn default_view_mode(&self) -> &'static str {
if self.vertical_only {
"vertical"
} else {
"horizontal"
}
}
pub fn as_chapter_title(&self) -> String {
let base_title = self.title.clone();
if let Some(subtitle) = self.subtitle.clone() {
format!("{} — {}", base_title, subtitle)
} else {
base_title
}
}
}
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct ChapterGroup {
#[prost(string, tag = "1")]
chapters: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "2")]
first_chapters: ::prost::alloc::vec::Vec<Chapter>,
#[prost(message, repeated, tag = "3")]
mid_chapters: ::prost::alloc::vec::Vec<Chapter>,
#[prost(message, repeated, tag = "4")]
last_chapters: ::prost::alloc::vec::Vec<Chapter>,
}
impl ChapterGroup {
pub fn flatten(&self) -> Vec<Chapter> {
let mut chapters = Vec::new();
chapters.extend_from_slice(&self.first_chapters);
chapters.extend_from_slice(&self.mid_chapters);
chapters.extend_from_slice(&self.last_chapters);
chapters
}
pub fn first_chapters_mut(&mut self) -> &mut Vec<Chapter> {
&mut self.first_chapters
}
pub fn mid_chapters_mut(&mut self) -> &mut Vec<Chapter> {
&mut self.mid_chapters
}
pub fn last_chapters_mut(&mut self) -> &mut Vec<Chapter> {
&mut self.last_chapters
}
}
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct ChapterPage {
#[prost(string, tag = "1")]
url: ::prost::alloc::string::String,
#[prost(uint64, tag = "2")]
width: u64,
#[prost(uint64, tag = "3")]
height: u64,
#[prost(enumeration = "super::PageType", tag = "4")]
#[skip_field]
kind: i32,
#[prost(string, optional, tag = "5")]
#[skip_field]
key: ::core::option::Option<::prost::alloc::string::String>,
}
impl ChapterPage {
pub fn file_name(&self) -> String {
let url = self.url.clone();
let split: Vec<&str> = url.rsplitn(2, '/').collect();
let file_name: Vec<&str> = split[0].split('?').collect();
file_name[0].to_string()
}
pub fn extension(&self) -> String {
let file_name = self.file_name();
let split: Vec<&str> = file_name.rsplitn(2, '.').collect();
if split.len() == 2 {
split[0].to_string()
} else {
"".to_string()
}
}
pub fn file_stem(&self) -> String {
let file_name = self.file_name();
let split: Vec<&str> = file_name.rsplitn(2, '.').collect();
if split.len() == 2 {
split[1].to_string()
} else {
file_name
}
}
}
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct ChapterPageBanner {
#[prost(string, optional, tag = "1")]
#[skip_field]
title: ::core::option::Option<::prost::alloc::string::String>,
#[prost(message, repeated, tag = "2")]
banners: ::prost::alloc::vec::Vec<super::common::Banner>,
}
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct ChapterPageLastPage {
#[prost(message, optional, tag = "1")]
chapter: ::core::option::Option<Chapter>,
#[prost(message, optional, tag = "2")]
next_chapter: ::core::option::Option<Chapter>,
#[prost(message, repeated, tag = "3")]
top_comments: ::prost::alloc::vec::Vec<super::comments::Comment>,
#[prost(bool, tag = "4")]
subscribed: bool,
#[prost(int64, optional, tag = "5")]
#[skip_field]
next_chapter_at: ::core::option::Option<i64>,
#[prost(enumeration = "super::ChapterType", tag = "6")]
#[skip_field]
chapter_type: i32,
#[prost(message, optional, tag = "9")]
banner: ::core::option::Option<super::common::Banner>,
#[prost(message, repeated, tag = "10")]
title_tickets: ::prost::alloc::vec::Vec<super::titles::Title>,
#[prost(message, optional, tag = "11")]
publisher_banner: ::core::option::Option<super::common::Banner>,
#[prost(message, optional, tag = "12")]
#[copyable]
user_tickets: ::core::option::Option<super::accounts::UserTickets>,
#[prost(bool, tag = "13")]
next_chapter_ticket: bool,
#[prost(bool, tag = "14")]
next_chapter_free: bool,
#[prost(bool, tag = "16")]
next_chapter_subscription: bool,
}
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct ChapterPageResponse {
#[prost(message, optional, tag = "1")]
page: ::core::option::Option<ChapterPage>,
#[prost(message, optional, tag = "2")]
banner: ::core::option::Option<ChapterPageBanner>,
#[prost(message, optional, tag = "3")]
last_page: ::core::option::Option<ChapterPageLastPage>,
#[prost(message, optional, tag = "5")]
insert_banner: ::core::option::Option<ChapterPageBanner>,
}
#[derive(Clone, AutoGetter, PartialEq, ::prost::Message)]
pub struct ChapterViewer {
#[prost(message, repeated, tag = "1")]
pages: ::prost::alloc::vec::Vec<ChapterPageResponse>,
#[prost(uint64, tag = "2")]
chapter_id: u64,
#[prost(message, repeated, tag = "3")]
chapters: ::prost::alloc::vec::Vec<Chapter>,
#[prost(string, tag = "5")]
title: ::prost::alloc::string::String,
#[prost(string, tag = "6")]
chapter_title: ::prost::alloc::string::String,
#[prost(uint64, tag = "7")]
comment_count: u64,
#[prost(bool, tag = "8")]
vertical_only: bool,
#[prost(uint64, tag = "9")]
title_id: u64,
#[prost(bool, tag = "10")]
first_page_right: bool,
#[prost(string, tag = "11")]
region_code: ::prost::alloc::string::String,
#[prost(bool, tag = "12")]
horizontal_only: bool,
#[prost(message, optional, tag = "13")]
user_subscription: ::core::option::Option<super::accounts::UserSubscription>,
#[prost(string, tag = "14")]
#[skip_field]
plan_type: ::prost::alloc::string::String,
}
impl ChapterViewer {
pub fn plan_type(&self) -> SubscriptionPlan {
match SubscriptionPlan::from_str(&self.plan_type) {
Ok(plan) => plan,
Err(_) => SubscriptionPlan::Basic,
}
}
}