diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 045d3f1..2965186 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -271,10 +271,13 @@ dependencies = [ "byteorder", "bytes", "chrono", + "float-ord", "fs4", + "memchr", "notify", "num_enum", "parking_lot 0.12.4", + "prost", "reqwest", "reqwest-middleware", "reqwest-retry", @@ -292,6 +295,7 @@ dependencies = [ "tracing-appender", "tracing-subscriber", "uuid", + "yaserde", ] [[package]] @@ -867,6 +871,12 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "embed-resource" version = "3.0.4" @@ -996,6 +1006,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-ord" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + [[package]] name = "fnv" version = "1.0.7" @@ -1897,6 +1913,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -3065,6 +3090,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "quick-xml" version = "0.38.0" @@ -3587,6 +3635,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_tokenstream" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.104", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -5594,6 +5654,39 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "xml-rs" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" + +[[package]] +name = "yaserde" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bfa0d2b420fd005aa9b6f99f9584ebd964e6865d7ca787304cc1a3366c39231" +dependencies = [ + "log", + "xml-rs", + "yaserde_derive", +] + +[[package]] +name = "yaserde_derive" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f785831c0e09e0f1a83f917054fd59c088f6561db5b2a42c1c3e1687329325f" +dependencies = [ + "heck 0.5.0", + "log", + "proc-macro2", + "quote", + "serde", + "serde_tokenstream", + "syn 2.0.104", + "xml-rs", +] + [[package]] name = "yoke" version = "0.8.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 06dfe35..2f9b8dc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -45,6 +45,10 @@ bytes = { version = "1.10.1" } fs4 = { version = "0.13.1" } num_enum = { version = "0.7.4" } chrono = { version = "0.4.41" } +prost = { version = "0.14.1" } +yaserde = { version = "0.12.0", features = ["yaserde_derive"] } +float-ord = { version = "0.3.2" } +memchr = { version = "2.7.5" } [profile.release] strip = true diff --git a/src-tauri/src/bili_client.rs b/src-tauri/src/bili_client.rs index 8f80552..63583e7 100644 --- a/src-tauri/src/bili_client.rs +++ b/src-tauri/src/bili_client.rs @@ -3,6 +3,7 @@ use std::time::Duration; use anyhow::{anyhow, Context}; use bytes::Bytes; use parking_lot::RwLock; +use prost::Message; use reqwest::{Client, StatusCode}; use reqwest_middleware::ClientWithMiddleware; use reqwest_retry::{policies::ExponentialBackoff, Jitter, RetryTransientMiddleware}; @@ -16,6 +17,7 @@ use tokio::task::JoinSet; use crate::{ extensions::AppHandleExt, + protobuf::DmSegMobileReply, types::{ bangumi_info::BangumiInfo, bangumi_media_url::BangumiMediaUrl, cheese_info::CheeseInfo, cheese_media_url::CheeseMediaUrl, fav_folders::FavFolders, fav_info::FavInfo, @@ -617,6 +619,57 @@ impl BiliClient { url_with_content_length } + pub async fn get_danmaku( + &self, + aid: i64, + cid: i64, + duration: u64, + ) -> anyhow::Result> { + let client = self.api_client.read().clone(); + // 以6分钟为单位分段 + let segment_count = duration.div_ceil(360); + + let mut join_set = JoinSet::new(); + for segment_index in 1..=segment_count { + let client = client.clone(); + let cookie = self.get_cookie(); + + join_set.spawn(async move { + // 发送获取分段弹幕的请求 + let params = json!({ + "type": 1, + "oid": cid, + "pid": aid, + "segment_index": segment_index, + }); + let http_resp = client + .get("https://api.bilibili.com/x/v2/dm/web/seg.so") + .query(¶ms) + .header("cookie", cookie) + .send() + .await?; + let status = http_resp.status(); + if status != StatusCode::OK { + let body = http_resp.text().await?; + return Err(anyhow!("预料之外的状态码({status}): {body}")); + } + let body = http_resp.bytes().await?; + let reply = + DmSegMobileReply::decode(body).context("将body解析为DmSegMobileReply失败")?; + + Ok(reply) + }); + } + + let mut replies = Vec::new(); + while let Some(Ok(res)) = join_set.join_next().await { + let reply = res?; + replies.push(reply); + } + + Ok(replies) + } + fn get_cookie(&self) -> String { let sessdata = self.app.get_config().read().sessdata.clone(); format!("SESSDATA={sessdata}") diff --git a/src-tauri/src/bilibili.community.service.dm.v1.rs b/src-tauri/src/bilibili.community.service.dm.v1.rs new file mode 100644 index 0000000..c684908 --- /dev/null +++ b/src-tauri/src/bilibili.community.service.dm.v1.rs @@ -0,0 +1,1763 @@ +// This file is @generated by prost-build. +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Avatar { + /// + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// + #[prost(string, tag = "2")] + pub url: ::prost::alloc::string::String, + /// + #[prost(enumeration = "AvatarType", tag = "3")] + pub avatar_type: i32, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Bubble { + /// + #[prost(string, tag = "1")] + pub text: ::prost::alloc::string::String, + /// + #[prost(string, tag = "2")] + pub url: ::prost::alloc::string::String, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BubbleV2 { + /// + #[prost(string, tag = "1")] + pub text: ::prost::alloc::string::String, + /// + #[prost(string, tag = "2")] + pub url: ::prost::alloc::string::String, + /// + #[prost(enumeration = "BubbleType", tag = "3")] + pub bubble_type: i32, + /// + #[prost(bool, tag = "4")] + pub exposure_once: bool, + /// + #[prost(enumeration = "ExposureType", tag = "5")] + pub exposure_type: i32, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Button { + /// + #[prost(string, tag = "1")] + pub text: ::prost::alloc::string::String, + /// + #[prost(int32, tag = "2")] + pub action: i32, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BuzzwordConfig { + /// + #[prost(message, repeated, tag = "1")] + pub keywords: ::prost::alloc::vec::Vec, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BuzzwordShowConfig { + /// + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// + #[prost(string, tag = "2")] + pub schema: ::prost::alloc::string::String, + /// + #[prost(int32, tag = "3")] + pub source: i32, + /// + #[prost(int64, tag = "4")] + pub id: i64, + /// + #[prost(int64, tag = "5")] + pub buzzword_id: i64, + /// + #[prost(int32, tag = "6")] + pub schema_type: i32, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CheckBox { + /// + #[prost(string, tag = "1")] + pub text: ::prost::alloc::string::String, + /// + #[prost(enumeration = "CheckboxType", tag = "2")] + pub r#type: i32, + /// + #[prost(bool, tag = "3")] + pub default_value: bool, + /// + #[prost(bool, tag = "4")] + pub show: bool, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CheckBoxV2 { + /// + #[prost(string, tag = "1")] + pub text: ::prost::alloc::string::String, + /// + #[prost(int32, tag = "2")] + pub r#type: i32, + /// + #[prost(bool, tag = "3")] + pub default_value: bool, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClickButton { + /// + #[prost(string, repeated, tag = "1")] + pub portrait_text: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "2")] + pub landscape_text: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "3")] + pub portrait_text_focus: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "4")] + pub landscape_text_focus: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(enumeration = "RenderType", tag = "5")] + pub render_type: i32, + /// + #[prost(bool, tag = "6")] + pub show: bool, + /// + #[prost(message, optional, tag = "7")] + pub bubble: ::core::option::Option, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClickButtonV2 { + /// + #[prost(string, repeated, tag = "1")] + pub portrait_text: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "2")] + pub landscape_text: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "3")] + pub portrait_text_focus: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "4")] + pub landscape_text_focus: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(int32, tag = "5")] + pub render_type: i32, + /// + #[prost(bool, tag = "6")] + pub text_input_post: bool, + /// + #[prost(bool, tag = "7")] + pub exposure_once: bool, + /// + #[prost(int32, tag = "8")] + pub exposure_type: i32, +} +/// 互动弹幕条目信息 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommandDm { + /// 弹幕id + #[prost(int64, tag = "1")] + pub id: i64, + /// 对象视频cid + #[prost(int64, tag = "2")] + pub oid: i64, + /// 发送者mid + #[prost(string, tag = "3")] + pub mid: ::prost::alloc::string::String, + /// 互动弹幕指令 + #[prost(string, tag = "4")] + pub command: ::prost::alloc::string::String, + /// 互动弹幕正文 + #[prost(string, tag = "5")] + pub content: ::prost::alloc::string::String, + /// 出现时间 + #[prost(int32, tag = "6")] + pub progress: i32, + /// 创建时间 + #[prost(string, tag = "7")] + pub ctime: ::prost::alloc::string::String, + /// 发布时间 + #[prost(string, tag = "8")] + pub mtime: ::prost::alloc::string::String, + /// 扩展json数据 + #[prost(string, tag = "9")] + pub extra: ::prost::alloc::string::String, + /// 弹幕id str类型 + #[prost(string, tag = "10")] + pub id_str: ::prost::alloc::string::String, +} +/// 弹幕ai云屏蔽列表 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmakuAiFlag { + /// 弹幕ai云屏蔽条目 + #[prost(message, repeated, tag = "1")] + pub dm_flags: ::prost::alloc::vec::Vec, +} +/// 弹幕条目 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmakuElem { + /// 弹幕dmid + #[prost(int64, tag = "1")] + pub id: i64, + /// 弹幕出现位置(单位ms) + #[prost(int32, tag = "2")] + pub progress: i32, + /// 弹幕类型 1 2 3:普通弹幕 4:底部弹幕 5:顶部弹幕 6:逆向弹幕 7:高级弹幕 8:代码弹幕 9:BAS弹幕(pool必须为2) + #[prost(int32, tag = "3")] + pub mode: i32, + /// 弹幕字号 + #[prost(int32, tag = "4")] + pub fontsize: i32, + /// 弹幕颜色 + #[prost(uint32, tag = "5")] + pub color: u32, + /// 发送者mid hash + #[prost(string, tag = "6")] + pub mid_hash: ::prost::alloc::string::String, + /// 弹幕正文 + #[prost(string, tag = "7")] + pub content: ::prost::alloc::string::String, + /// 发送时间 + #[prost(int64, tag = "8")] + pub ctime: i64, + /// 权重 用于屏蔽等级 区间:\[1,10\] + #[prost(int32, tag = "9")] + pub weight: i32, + /// 动作 + #[prost(string, tag = "10")] + pub action: ::prost::alloc::string::String, + /// 弹幕池 0:普通池 1:字幕池 2:特殊池(代码/BAS弹幕) + #[prost(int32, tag = "11")] + pub pool: i32, + /// 弹幕dmid str + #[prost(string, tag = "12")] + pub id_str: ::prost::alloc::string::String, + /// 弹幕属性位(bin求AND) + /// bit0:保护 bit1:直播 bit2:高赞 + #[prost(int32, tag = "13")] + pub attr: i32, + /// + #[prost(string, tag = "22")] + pub animation: ::prost::alloc::string::String, + /// 大会员专属颜色 + #[prost(enumeration = "DmColorfulType", tag = "24")] + pub colorful: i32, +} +/// 弹幕ai云屏蔽条目 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DanmakuFlag { + /// 弹幕dmid + #[prost(int64, tag = "1")] + pub dmid: i64, + /// 评分 + #[prost(uint32, tag = "2")] + pub flag: u32, +} +/// 云屏蔽配置信息 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmakuFlagConfig { + /// 云屏蔽等级 + #[prost(int32, tag = "1")] + pub rec_flag: i32, + /// 云屏蔽文案 + #[prost(string, tag = "2")] + pub rec_text: ::prost::alloc::string::String, + /// 云屏蔽开关 + #[prost(int32, tag = "3")] + pub rec_switch: i32, +} +/// 弹幕默认配置 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmuDefaultPlayerConfig { + /// 是否使用推荐弹幕设置 + #[prost(bool, tag = "1")] + pub player_danmaku_use_default_config: bool, + /// 是否开启智能云屏蔽 + #[prost(bool, tag = "4")] + pub player_danmaku_ai_recommended_switch: bool, + /// 智能云屏蔽等级 + #[prost(int32, tag = "5")] + pub player_danmaku_ai_recommended_level: i32, + /// 是否屏蔽顶端弹幕 + #[prost(bool, tag = "6")] + pub player_danmaku_blocktop: bool, + /// 是否屏蔽滚动弹幕 + #[prost(bool, tag = "7")] + pub player_danmaku_blockscroll: bool, + /// 是否屏蔽底端弹幕 + #[prost(bool, tag = "8")] + pub player_danmaku_blockbottom: bool, + /// 是否屏蔽彩色弹幕 + #[prost(bool, tag = "9")] + pub player_danmaku_blockcolorful: bool, + /// 是否屏蔽重复弹幕 + #[prost(bool, tag = "10")] + pub player_danmaku_blockrepeat: bool, + /// 是否屏蔽高级弹幕 + #[prost(bool, tag = "11")] + pub player_danmaku_blockspecial: bool, + /// 弹幕不透明度 + #[prost(float, tag = "12")] + pub player_danmaku_opacity: f32, + /// 弹幕缩放比例 + #[prost(float, tag = "13")] + pub player_danmaku_scalingfactor: f32, + /// 弹幕显示区域 + #[prost(float, tag = "14")] + pub player_danmaku_domain: f32, + /// 弹幕速度 + #[prost(int32, tag = "15")] + pub player_danmaku_speed: i32, + /// 是否开启弹幕 + #[prost(bool, tag = "16")] + pub inline_player_danmaku_switch: bool, + /// + #[prost(int32, tag = "17")] + pub player_danmaku_senior_mode_switch: i32, + /// + #[prost(int32, tag = "18")] + pub player_danmaku_ai_recommended_level_v2: i32, + /// + #[prost(map = "int32, int32", tag = "19")] + pub player_danmaku_ai_recommended_level_v2_map: ::std::collections::HashMap< + i32, + i32, + >, +} +/// 弹幕配置 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmuPlayerConfig { + /// 是否开启弹幕 + #[prost(bool, tag = "1")] + pub player_danmaku_switch: bool, + /// 是否记录弹幕开关设置 + #[prost(bool, tag = "2")] + pub player_danmaku_switch_save: bool, + /// 是否使用推荐弹幕设置 + #[prost(bool, tag = "3")] + pub player_danmaku_use_default_config: bool, + /// 是否开启智能云屏蔽 + #[prost(bool, tag = "4")] + pub player_danmaku_ai_recommended_switch: bool, + /// 智能云屏蔽等级 + #[prost(int32, tag = "5")] + pub player_danmaku_ai_recommended_level: i32, + /// 是否屏蔽顶端弹幕 + #[prost(bool, tag = "6")] + pub player_danmaku_blocktop: bool, + /// 是否屏蔽滚动弹幕 + #[prost(bool, tag = "7")] + pub player_danmaku_blockscroll: bool, + /// 是否屏蔽底端弹幕 + #[prost(bool, tag = "8")] + pub player_danmaku_blockbottom: bool, + /// 是否屏蔽彩色弹幕 + #[prost(bool, tag = "9")] + pub player_danmaku_blockcolorful: bool, + /// 是否屏蔽重复弹幕 + #[prost(bool, tag = "10")] + pub player_danmaku_blockrepeat: bool, + /// 是否屏蔽高级弹幕 + #[prost(bool, tag = "11")] + pub player_danmaku_blockspecial: bool, + /// 弹幕不透明度 + #[prost(float, tag = "12")] + pub player_danmaku_opacity: f32, + /// 弹幕缩放比例 + #[prost(float, tag = "13")] + pub player_danmaku_scalingfactor: f32, + /// 弹幕显示区域 + #[prost(float, tag = "14")] + pub player_danmaku_domain: f32, + /// 弹幕速度 + #[prost(int32, tag = "15")] + pub player_danmaku_speed: i32, + /// 是否开启屏蔽列表 + #[prost(bool, tag = "16")] + pub player_danmaku_enableblocklist: bool, + /// 是否开启弹幕 + #[prost(bool, tag = "17")] + pub inline_player_danmaku_switch: bool, + /// + #[prost(int32, tag = "18")] + pub inline_player_danmaku_config: i32, + /// + #[prost(int32, tag = "19")] + pub player_danmaku_ios_switch_save: i32, + /// + #[prost(int32, tag = "20")] + pub player_danmaku_senior_mode_switch: i32, + /// + #[prost(int32, tag = "21")] + pub player_danmaku_ai_recommended_level_v2: i32, + /// + #[prost(map = "int32, int32", tag = "22")] + pub player_danmaku_ai_recommended_level_v2_map: ::std::collections::HashMap< + i32, + i32, + >, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmuPlayerConfigPanel { + /// + #[prost(string, tag = "1")] + pub selection_text: ::prost::alloc::string::String, +} +/// 弹幕显示区域自动配置 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DanmuPlayerDynamicConfig { + /// 时间 + #[prost(int32, tag = "1")] + pub progress: i32, + /// 弹幕显示区域 + #[prost(float, tag = "14")] + pub player_danmaku_domain: f32, +} +/// 弹幕配置信息 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmuPlayerViewConfig { + /// 弹幕默认配置 + #[prost(message, optional, tag = "1")] + pub danmuku_default_player_config: ::core::option::Option, + /// 弹幕用户配置 + #[prost(message, optional, tag = "2")] + pub danmuku_player_config: ::core::option::Option, + /// 弹幕显示区域自动配置列表 + #[prost(message, repeated, tag = "3")] + pub danmuku_player_dynamic_config: ::prost::alloc::vec::Vec< + DanmuPlayerDynamicConfig, + >, + /// + #[prost(message, optional, tag = "4")] + pub danmuku_player_config_panel: ::core::option::Option, +} +/// web端用户弹幕配置 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DanmuWebPlayerConfig { + /// 是否开启弹幕 + #[prost(bool, tag = "1")] + pub dm_switch: bool, + /// 是否开启智能云屏蔽 + #[prost(bool, tag = "2")] + pub ai_switch: bool, + /// 智能云屏蔽等级 + #[prost(int32, tag = "3")] + pub ai_level: i32, + /// 是否屏蔽顶端弹幕 + #[prost(bool, tag = "4")] + pub blocktop: bool, + /// 是否屏蔽滚动弹幕 + #[prost(bool, tag = "5")] + pub blockscroll: bool, + /// 是否屏蔽底端弹幕 + #[prost(bool, tag = "6")] + pub blockbottom: bool, + /// 是否屏蔽彩色弹幕 + #[prost(bool, tag = "7")] + pub blockcolor: bool, + /// 是否屏蔽重复弹幕 + #[prost(bool, tag = "8")] + pub blockspecial: bool, + /// + #[prost(bool, tag = "9")] + pub preventshade: bool, + /// + #[prost(bool, tag = "10")] + pub dmask: bool, + /// + #[prost(float, tag = "11")] + pub opacity: f32, + /// + #[prost(int32, tag = "12")] + pub dmarea: i32, + /// + #[prost(float, tag = "13")] + pub speedplus: f32, + /// 弹幕字号 + #[prost(float, tag = "14")] + pub fontsize: f32, + /// + #[prost(bool, tag = "15")] + pub screensync: bool, + /// + #[prost(bool, tag = "16")] + pub speedsync: bool, + /// + #[prost(string, tag = "17")] + pub fontfamily: ::prost::alloc::string::String, + /// 是否使用加粗 + #[prost(bool, tag = "18")] + pub bold: bool, + /// + #[prost(int32, tag = "19")] + pub fontborder: i32, + /// 弹幕渲染类型 + #[prost(string, tag = "20")] + pub draw_type: ::prost::alloc::string::String, + /// + #[prost(int32, tag = "21")] + pub senior_mode_switch: i32, + /// + #[prost(int32, tag = "22")] + pub ai_level_v2: i32, + /// + #[prost(map = "int32, int32", tag = "23")] + pub ai_level_v2_map: ::std::collections::HashMap, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmColorful { + /// 颜色类型 + #[prost(enumeration = "DmColorfulType", tag = "1")] + pub r#type: i32, + /// + #[prost(string, tag = "2")] + pub src: ::prost::alloc::string::String, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmExpoReportReq { + /// + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, + /// + #[prost(int64, tag = "2")] + pub oid: i64, + /// + #[prost(string, tag = "4")] + pub spmid: ::prost::alloc::string::String, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DmExpoReportRes {} +/// 修改弹幕配置-请求 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DmPlayerConfigReq { + /// + #[prost(int64, tag = "1")] + pub ts: i64, + /// 是否开启弹幕 + #[prost(message, optional, tag = "2")] + pub switch: ::core::option::Option, + /// 是否记录弹幕开关设置 + #[prost(message, optional, tag = "3")] + pub switch_save: ::core::option::Option, + /// 是否使用推荐弹幕设置 + #[prost(message, optional, tag = "4")] + pub use_default_config: ::core::option::Option, + /// 是否开启智能云屏蔽 + #[prost(message, optional, tag = "5")] + pub ai_recommended_switch: ::core::option::Option, + /// 智能云屏蔽等级 + #[prost(message, optional, tag = "6")] + pub ai_recommended_level: ::core::option::Option, + /// 是否屏蔽顶端弹幕 + #[prost(message, optional, tag = "7")] + pub blocktop: ::core::option::Option, + /// 是否屏蔽滚动弹幕 + #[prost(message, optional, tag = "8")] + pub blockscroll: ::core::option::Option, + /// 是否屏蔽底端弹幕 + #[prost(message, optional, tag = "9")] + pub blockbottom: ::core::option::Option, + /// 是否屏蔽彩色弹幕 + #[prost(message, optional, tag = "10")] + pub blockcolorful: ::core::option::Option, + /// 是否屏蔽重复弹幕 + #[prost(message, optional, tag = "11")] + pub blockrepeat: ::core::option::Option, + /// 是否屏蔽高级弹幕 + #[prost(message, optional, tag = "12")] + pub blockspecial: ::core::option::Option, + /// 弹幕不透明度 + #[prost(message, optional, tag = "13")] + pub opacity: ::core::option::Option, + /// 弹幕缩放比例 + #[prost(message, optional, tag = "14")] + pub scalingfactor: ::core::option::Option, + /// 弹幕显示区域 + #[prost(message, optional, tag = "15")] + pub domain: ::core::option::Option, + /// 弹幕速度 + #[prost(message, optional, tag = "16")] + pub speed: ::core::option::Option, + /// 是否开启屏蔽列表 + #[prost(message, optional, tag = "17")] + pub enableblocklist: ::core::option::Option, + /// 是否开启弹幕 + #[prost(message, optional, tag = "18")] + pub inline_player_danmaku_switch: ::core::option::Option, + /// + #[prost(message, optional, tag = "19")] + pub senior_mode_switch: ::core::option::Option, + /// + #[prost(message, optional, tag = "20")] + pub ai_recommended_level_v2: ::core::option::Option< + PlayerDanmakuAiRecommendedLevelV2, + >, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DmSegConfig { + /// + #[prost(int64, tag = "1")] + pub page_size: i64, + /// + #[prost(int64, tag = "2")] + pub total: i64, +} +/// 获取弹幕-响应 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmSegMobileReply { + /// 弹幕列表 + #[prost(message, repeated, tag = "1")] + pub elems: ::prost::alloc::vec::Vec, + /// 是否已关闭弹幕 + /// 0:未关闭 1:已关闭 + #[prost(int32, tag = "2")] + pub state: i32, + /// 弹幕云屏蔽ai评分值 + #[prost(message, optional, tag = "3")] + pub ai_flag: ::core::option::Option, + #[prost(message, repeated, tag = "5")] + pub colorful_src: ::prost::alloc::vec::Vec, +} +/// 获取弹幕-请求 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DmSegMobileReq { + /// 稿件avid/漫画epid + #[prost(int64, tag = "1")] + pub pid: i64, + /// 视频cid/漫画cid + #[prost(int64, tag = "2")] + pub oid: i64, + /// 弹幕类型 + /// 1:视频 2:漫画 + #[prost(int32, tag = "3")] + pub r#type: i32, + /// 分段(6min) + #[prost(int64, tag = "4")] + pub segment_index: i64, + /// 是否青少年模式 + #[prost(int32, tag = "5")] + pub teenagers_mode: i32, + /// + #[prost(int64, tag = "6")] + pub ps: i64, + /// + #[prost(int64, tag = "7")] + pub pe: i64, + /// + #[prost(int32, tag = "8")] + pub pull_mode: i32, + /// + #[prost(int32, tag = "9")] + pub from_scene: i32, +} +/// ott弹幕列表-响应 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmSegOttReply { + /// 是否已关闭弹幕 + /// 0:未关闭 1:已关闭 + #[prost(bool, tag = "1")] + pub closed: bool, + /// 弹幕列表 + #[prost(message, repeated, tag = "2")] + pub elems: ::prost::alloc::vec::Vec, +} +/// ott弹幕列表-请求 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DmSegOttReq { + /// 稿件avid/漫画epid + #[prost(int64, tag = "1")] + pub pid: i64, + /// 视频cid/漫画cid + #[prost(int64, tag = "2")] + pub oid: i64, + /// 弹幕类型 + /// 1:视频 2:漫画 + #[prost(int32, tag = "3")] + pub r#type: i32, + /// 分段(6min) + #[prost(int64, tag = "4")] + pub segment_index: i64, +} +/// 弹幕SDK-响应 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmSegSdkReply { + /// 是否已关闭弹幕 + /// 0:未关闭 1:已关闭 + #[prost(bool, tag = "1")] + pub closed: bool, + /// 弹幕列表 + #[prost(message, repeated, tag = "2")] + pub elems: ::prost::alloc::vec::Vec, +} +/// 弹幕SDK-请求 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct DmSegSdkReq { + /// 稿件avid/漫画epid + #[prost(int64, tag = "1")] + pub pid: i64, + /// 视频cid/漫画cid + #[prost(int64, tag = "2")] + pub oid: i64, + /// 弹幕类型 + /// 1:视频 2:漫画 + #[prost(int32, tag = "3")] + pub r#type: i32, + /// 分段(6min) + #[prost(int64, tag = "4")] + pub segment_index: i64, +} +/// 客户端弹幕元数据-响应 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmViewReply { + /// 是否已关闭弹幕 + /// 0:未关闭 1:已关闭 + #[prost(bool, tag = "1")] + pub closed: bool, + /// 智能防挡弹幕蒙版信息 + #[prost(message, optional, tag = "2")] + pub mask: ::core::option::Option, + /// 视频字幕 + #[prost(message, optional, tag = "3")] + pub subtitle: ::core::option::Option, + /// 高级弹幕专包url(bfs) + #[prost(string, repeated, tag = "4")] + pub special_dms: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// 云屏蔽配置信息 + #[prost(message, optional, tag = "5")] + pub ai_flag: ::core::option::Option, + /// 弹幕配置信息 + #[prost(message, optional, tag = "6")] + pub player_config: ::core::option::Option, + /// 弹幕发送框样式 + #[prost(int32, tag = "7")] + pub send_box_style: i32, + /// 是否允许 + #[prost(bool, tag = "8")] + pub allow: bool, + /// check box 是否展示 + #[prost(string, tag = "9")] + pub check_box: ::prost::alloc::string::String, + /// check box 展示文本 + #[prost(string, tag = "10")] + pub check_box_show_msg: ::prost::alloc::string::String, + /// 展示文案 + #[prost(string, tag = "11")] + pub text_placeholder: ::prost::alloc::string::String, + /// 弹幕输入框文案 + #[prost(string, tag = "12")] + pub input_placeholder: ::prost::alloc::string::String, + /// 用户举报弹幕 cid维度屏蔽的正则规则 + #[prost(string, repeated, tag = "13")] + pub report_filter_content: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(message, optional, tag = "14")] + pub expo_report: ::core::option::Option, + /// + #[prost(message, optional, tag = "15")] + pub buzzword_config: ::core::option::Option, + /// + #[prost(message, repeated, tag = "16")] + pub expressions: ::prost::alloc::vec::Vec, + /// + #[prost(message, repeated, tag = "17")] + pub post_panel: ::prost::alloc::vec::Vec, + /// + #[prost(string, repeated, tag = "18")] + pub activity_meta: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(message, repeated, tag = "19")] + pub post_panel2: ::prost::alloc::vec::Vec, +} +/// 客户端弹幕元数据-请求 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmViewReq { + /// 稿件avid/漫画epid + #[prost(int64, tag = "1")] + pub pid: i64, + /// 视频cid/漫画cid + #[prost(int64, tag = "2")] + pub oid: i64, + /// 弹幕类型 + /// 1:视频 2:漫画 + #[prost(int32, tag = "3")] + pub r#type: i32, + /// 页面spm + #[prost(string, tag = "4")] + pub spmid: ::prost::alloc::string::String, + /// 是否冷启 + #[prost(int32, tag = "5")] + pub is_hard_boot: i32, +} +/// web端弹幕元数据-响应 +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DmWebViewReply { + /// 是否已关闭弹幕 + /// 0:未关闭 1:已关闭 + #[prost(int32, tag = "1")] + pub state: i32, + /// + #[prost(string, tag = "2")] + pub text: ::prost::alloc::string::String, + /// + #[prost(string, tag = "3")] + pub text_side: ::prost::alloc::string::String, + /// 分段弹幕配置 + #[prost(message, optional, tag = "4")] + pub dm_sge: ::core::option::Option, + /// 云屏蔽配置信息 + #[prost(message, optional, tag = "5")] + pub flag: ::core::option::Option, + /// 高级弹幕专包url(bfs) + #[prost(string, repeated, tag = "6")] + pub special_dms: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// check box 是否展示 + #[prost(bool, tag = "7")] + pub check_box: bool, + /// 弹幕数 + #[prost(int64, tag = "8")] + pub count: i64, + /// 互动弹幕 + #[prost(message, repeated, tag = "9")] + pub command_dms: ::prost::alloc::vec::Vec, + /// 用户弹幕配置 + #[prost(message, optional, tag = "10")] + pub player_config: ::core::option::Option, + /// 用户举报弹幕 cid维度屏蔽 + #[prost(string, repeated, tag = "11")] + pub report_filter_content: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(message, repeated, tag = "12")] + pub expressions: ::prost::alloc::vec::Vec, + /// + #[prost(message, repeated, tag = "13")] + pub post_panel: ::prost::alloc::vec::Vec, + /// + #[prost(string, repeated, tag = "14")] + pub activity_meta: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct ExpoReport { + /// + #[prost(bool, tag = "1")] + pub should_report_at_end: bool, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Expression { + /// + #[prost(string, repeated, tag = "1")] + pub keyword: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, tag = "2")] + pub url: ::prost::alloc::string::String, + /// + #[prost(message, repeated, tag = "3")] + pub period: ::prost::alloc::vec::Vec, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Expressions { + /// + #[prost(message, repeated, tag = "1")] + pub data: ::prost::alloc::vec::Vec, +} +/// 是否开启弹幕 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct InlinePlayerDanmakuSwitch { + /// + #[prost(bool, tag = "1")] + pub value: bool, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Label { + /// + #[prost(string, tag = "1")] + pub title: ::prost::alloc::string::String, + /// + #[prost(string, repeated, tag = "2")] + pub content: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LabelV2 { + /// + #[prost(string, tag = "1")] + pub title: ::prost::alloc::string::String, + /// + #[prost(string, repeated, tag = "2")] + pub content: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(bool, tag = "3")] + pub exposure_once: bool, + /// + #[prost(int32, tag = "4")] + pub exposure_type: i32, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct Period { + /// + #[prost(int64, tag = "1")] + pub start: i64, + /// + #[prost(int64, tag = "2")] + pub end: i64, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuAiRecommendedLevel { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuAiRecommendedLevelV2 { + #[prost(int32, tag = "1")] + pub value: i32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuAiRecommendedSwitch { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuBlockbottom { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuBlockcolorful { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuBlockrepeat { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuBlockscroll { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuBlockspecial { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuBlocktop { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuDomain { + #[prost(float, tag = "1")] + pub value: f32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuEnableblocklist { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuOpacity { + #[prost(float, tag = "1")] + pub value: f32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuScalingfactor { + #[prost(float, tag = "1")] + pub value: f32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuSeniorModeSwitch { + #[prost(int32, tag = "1")] + pub value: i32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuSpeed { + #[prost(int32, tag = "1")] + pub value: i32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuSwitch { + #[prost(bool, tag = "1")] + pub value: bool, + #[prost(bool, tag = "2")] + pub can_ignore: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuSwitchSave { + #[prost(bool, tag = "1")] + pub value: bool, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct PlayerDanmakuUseDefaultConfig { + #[prost(bool, tag = "1")] + pub value: bool, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostPanel { + /// + #[prost(int64, tag = "1")] + pub start: i64, + /// + #[prost(int64, tag = "2")] + pub end: i64, + /// + #[prost(int64, tag = "3")] + pub priority: i64, + /// + #[prost(int64, tag = "4")] + pub biz_id: i64, + /// + #[prost(enumeration = "PostPanelBizType", tag = "5")] + pub biz_type: i32, + /// + #[prost(message, optional, tag = "6")] + pub click_button: ::core::option::Option, + /// + #[prost(message, optional, tag = "7")] + pub text_input: ::core::option::Option, + /// + #[prost(message, optional, tag = "8")] + pub check_box: ::core::option::Option, + /// + #[prost(message, optional, tag = "9")] + pub toast: ::core::option::Option, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostPanelV2 { + /// + #[prost(int64, tag = "1")] + pub start: i64, + /// + #[prost(int64, tag = "2")] + pub end: i64, + /// + #[prost(int32, tag = "3")] + pub biz_type: i32, + /// + #[prost(message, optional, tag = "4")] + pub click_button: ::core::option::Option, + /// + #[prost(message, optional, tag = "5")] + pub text_input: ::core::option::Option, + /// + #[prost(message, optional, tag = "6")] + pub check_box: ::core::option::Option, + /// + #[prost(message, optional, tag = "7")] + pub toast: ::core::option::Option, + /// + #[prost(message, optional, tag = "8")] + pub bubble: ::core::option::Option, + /// + #[prost(message, optional, tag = "9")] + pub label: ::core::option::Option, + /// + #[prost(int32, tag = "10")] + pub post_status: i32, +} +/// 修改弹幕配置-响应 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Response { + /// + #[prost(int32, tag = "1")] + pub code: i32, + /// + #[prost(string, tag = "2")] + pub message: ::prost::alloc::string::String, +} +/// 单个字幕信息 +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubtitleItem { + /// 字幕id + #[prost(int64, tag = "1")] + pub id: i64, + /// 字幕id str + #[prost(string, tag = "2")] + pub id_str: ::prost::alloc::string::String, + /// 字幕语言代码 + #[prost(string, tag = "3")] + pub lan: ::prost::alloc::string::String, + /// 字幕语言 + #[prost(string, tag = "4")] + pub lan_doc: ::prost::alloc::string::String, + /// 字幕文件url + #[prost(string, tag = "5")] + pub subtitle_url: ::prost::alloc::string::String, + /// 字幕作者信息 + #[prost(message, optional, tag = "6")] + pub author: ::core::option::Option, + /// 字幕类型 + #[prost(enumeration = "SubtitleType", tag = "7")] + pub r#type: i32, + /// + #[prost(string, tag = "8")] + pub lan_doc_brief: ::prost::alloc::string::String, + /// + #[prost(enumeration = "SubtitleAiType", tag = "9")] + pub ai_type: i32, + /// + #[prost(enumeration = "SubtitleAiStatus", tag = "10")] + pub ai_status: i32, +} +/// +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TextInput { + /// + #[prost(string, repeated, tag = "1")] + pub portrait_placeholder: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(string, repeated, tag = "2")] + pub landscape_placeholder: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// + #[prost(enumeration = "RenderType", tag = "3")] + pub render_type: i32, + /// + #[prost(bool, tag = "4")] + pub placeholder_post: bool, + /// + #[prost(bool, tag = "5")] + pub show: bool, + /// + #[prost(message, repeated, tag = "6")] + pub avatar: ::prost::alloc::vec::Vec, + /// + #[prost(enumeration = "PostStatus", tag = "7")] + pub post_status: i32, + /// + #[prost(message, optional, tag = "8")] + pub label: ::core::option::Option