use serde::Serialize;
use super::enums::{
DouyinActivityStatus, DouyinAuthorSortBy, DouyinAuthorType, DouyinLiveStatus,
DouyinOrderQueryType, DouyinProductTag, DouyinSearchType, DouyinShareStatus, DouyinSortType,
};
#[derive(Debug, Clone, Serialize)]
pub struct DouyinGoodsConvertRequest {
pub sid: String,
pub product_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_info: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub need_qr_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub use_coupon: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub need_share_link: Option<String>,
}
impl DouyinGoodsConvertRequest {
pub fn new(sid: impl Into<String>, product_url: impl Into<String>) -> Self {
Self {
sid: sid.into(),
product_url: product_url.into(),
external_info: None,
need_qr_code: None,
use_coupon: None,
need_share_link: None,
}
}
pub fn external_info(mut self, external_info: impl Into<String>) -> Self {
self.external_info = Some(external_info.into());
self
}
pub fn need_qr_code(mut self, need_qr_code: bool) -> Self {
self.need_qr_code = Some(need_qr_code.to_string());
self
}
pub fn use_coupon(mut self, use_coupon: bool) -> Self {
self.use_coupon = Some(use_coupon.to_string());
self
}
pub fn need_share_link(mut self, need_share_link: bool) -> Self {
self.need_share_link = Some(need_share_link.to_string());
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinLiveConvertRequest {
pub sid: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub buyin_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dy_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_info: Option<String>,
}
impl DouyinLiveConvertRequest {
pub fn with_buyin_id(sid: impl Into<String>, buyin_id: impl Into<String>) -> Self {
Self {
sid: sid.into(),
buyin_id: Some(buyin_id.into()),
dy_code: None,
external_info: None,
}
}
pub fn with_dy_code(sid: impl Into<String>, dy_code: impl Into<String>) -> Self {
Self {
sid: sid.into(),
buyin_id: None,
dy_code: Some(dy_code.into()),
external_info: None,
}
}
pub fn external_info(mut self, external_info: impl Into<String>) -> Self {
self.external_info = Some(external_info.into());
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinActivityConvertRequest {
pub sid: String,
pub material_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_info: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub need_qr_code: Option<String>,
}
impl DouyinActivityConvertRequest {
pub fn new(sid: impl Into<String>, material_id: impl Into<String>) -> Self {
Self {
sid: sid.into(),
material_id: material_id.into(),
external_info: None,
need_qr_code: None,
}
}
pub fn external_info(mut self, external_info: impl Into<String>) -> Self {
self.external_info = Some(external_info.into());
self
}
pub fn need_qr_code(mut self, need_qr_code: bool) -> Self {
self.need_qr_code = Some(need_qr_code.to_string());
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinGoodsDetailRequest {
pub sid: String,
pub product_ids: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<String>,
}
impl DouyinGoodsDetailRequest {
pub fn new(sid: impl Into<String>, product_ids: impl Into<String>) -> Self {
Self {
sid: sid.into(),
product_ids: product_ids.into(),
fields: None,
}
}
pub fn fields(mut self, fields: impl Into<String>) -> Self {
self.fields = Some(fields.into());
self
}
pub fn with_all_fields(mut self) -> Self {
self.fields = Some("base_info,promotion_info".to_string());
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinSearchGoodsRequest {
pub sid: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub first_cids: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub second_cids: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub third_cids: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub price_min: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub price_max: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sell_num_min: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sell_num_max: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub search_type: Option<DouyinSearchType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_type: Option<DouyinSortType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cos_fee_min: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cos_fee_max: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cos_ratio_min: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cos_ratio_max: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub share_status: Option<DouyinShareStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<DouyinProductTag>,
}
impl DouyinSearchGoodsRequest {
pub fn new(sid: impl Into<String>) -> Self {
Self {
sid: sid.into(),
title: None,
first_cids: None,
second_cids: None,
third_cids: None,
price_min: None,
price_max: None,
sell_num_min: None,
sell_num_max: None,
search_type: None,
sort_type: None,
cos_fee_min: None,
cos_fee_max: None,
cos_ratio_min: None,
cos_ratio_max: None,
page: None,
page_size: None,
share_status: None,
tag: None,
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn first_cids(mut self, first_cids: impl Into<String>) -> Self {
self.first_cids = Some(first_cids.into());
self
}
pub fn price_range(mut self, min: u64, max: u64) -> Self {
self.price_min = Some(min.to_string());
self.price_max = Some(max.to_string());
self
}
pub fn sell_num_range(mut self, min: u64, max: u64) -> Self {
self.sell_num_min = Some(min.to_string());
self.sell_num_max = Some(max.to_string());
self
}
pub fn search_type(mut self, search_type: DouyinSearchType) -> Self {
self.search_type = Some(search_type);
self
}
pub fn sort_type(mut self, sort_type: DouyinSortType) -> Self {
self.sort_type = Some(sort_type);
self
}
pub fn page(mut self, page: u32) -> Self {
self.page = Some(page);
self
}
pub fn page_size(mut self, page_size: u32) -> Self {
self.page_size = Some(page_size);
self
}
pub fn share_status(mut self, share_status: DouyinShareStatus) -> Self {
self.share_status = Some(share_status);
self
}
pub fn tag(mut self, tag: DouyinProductTag) -> Self {
self.tag = Some(tag);
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinParseCommandRequest {
pub sid: String,
pub command: String,
}
impl DouyinParseCommandRequest {
pub fn new(sid: impl Into<String>, command: impl Into<String>) -> Self {
Self {
sid: sid.into(),
command: command.into(),
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinOrderQueryRequest {
#[serde(rename = "type")]
pub query_type: DouyinOrderQueryType,
pub page: u32,
pub page_size: u32,
#[serde(rename = "startTime", skip_serializing_if = "Option::is_none")]
pub start_time: Option<String>,
#[serde(rename = "endTime", skip_serializing_if = "Option::is_none")]
pub end_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub orderid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub san_pingtai_id: Option<String>,
}
impl DouyinOrderQueryRequest {
pub fn by_pay_time(start_time: impl Into<String>, end_time: impl Into<String>) -> Self {
Self {
query_type: DouyinOrderQueryType::PayTime,
page: 1,
page_size: 50,
start_time: Some(start_time.into()),
end_time: Some(end_time.into()),
orderid: None,
sid: None,
san_pingtai_id: Some("9".to_string()), }
}
pub fn by_update_time(start_time: impl Into<String>, end_time: impl Into<String>) -> Self {
Self {
query_type: DouyinOrderQueryType::UpdateTime,
page: 1,
page_size: 50,
start_time: Some(start_time.into()),
end_time: Some(end_time.into()),
orderid: None,
sid: None,
san_pingtai_id: Some("9".to_string()),
}
}
pub fn by_order_id(orderid: impl Into<String>) -> Self {
Self {
query_type: DouyinOrderQueryType::OrderId,
page: 1,
page_size: 50,
start_time: None,
end_time: None,
orderid: Some(orderid.into()),
sid: None,
san_pingtai_id: Some("9".to_string()),
}
}
pub fn page(mut self, page: u32) -> Self {
self.page = page;
self
}
pub fn page_size(mut self, page_size: u32) -> Self {
self.page_size = page_size;
self
}
pub fn sid(mut self, sid: impl Into<String>) -> Self {
self.sid = Some(sid.into());
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinActivityListRequest {
pub sid: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub page: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub activity_status: Option<DouyinActivityStatus>,
}
impl DouyinActivityListRequest {
pub fn new(sid: impl Into<String>) -> Self {
Self {
sid: sid.into(),
page: None,
page_size: None,
activity_status: None,
}
}
pub fn page(mut self, page: u32) -> Self {
self.page = Some(page);
self
}
pub fn page_size(mut self, page_size: u32) -> Self {
self.page_size = Some(page_size);
self
}
pub fn activity_status(mut self, activity_status: DouyinActivityStatus) -> Self {
self.activity_status = Some(activity_status);
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinAuthorListRequest {
pub sid: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub author_type: Option<DouyinAuthorType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub author_levels: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub frist_cids: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub author_info: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_by: Option<DouyinAuthorSortBy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_type: Option<DouyinSortType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub live_status: Option<DouyinLiveStatus>,
}
impl DouyinAuthorListRequest {
pub fn new(sid: impl Into<String>) -> Self {
Self {
sid: sid.into(),
author_type: None,
author_levels: None,
frist_cids: None,
author_info: None,
page: None,
page_size: None,
sort_by: None,
sort_type: None,
live_status: None,
}
}
pub fn author_type(mut self, author_type: DouyinAuthorType) -> Self {
self.author_type = Some(author_type);
self
}
pub fn author_info(mut self, author_info: impl Into<String>) -> Self {
self.author_info = Some(author_info.into());
self
}
pub fn page(mut self, page: u32) -> Self {
self.page = Some(page);
self
}
pub fn page_size(mut self, page_size: u32) -> Self {
self.page_size = Some(page_size);
self
}
pub fn sort_by(mut self, sort_by: DouyinAuthorSortBy) -> Self {
self.sort_by = Some(sort_by);
self
}
pub fn live_status(mut self, live_status: DouyinLiveStatus) -> Self {
self.live_status = Some(live_status);
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DouyinLiveProductListRequest {
pub sid: String,
pub author_buyin_id: String,
}
impl DouyinLiveProductListRequest {
pub fn new(sid: impl Into<String>, author_buyin_id: impl Into<String>) -> Self {
Self {
sid: sid.into(),
author_buyin_id: author_buyin_id.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_goods_convert_request_serialize() {
let request = DouyinGoodsConvertRequest::new("sid123", "https://xxx.douyin.com/xxx");
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["sid"], "sid123");
assert_eq!(json["product_url"], "https://xxx.douyin.com/xxx");
assert!(json.get("external_info").is_none());
}
#[test]
fn test_goods_convert_request_with_options() {
let request = DouyinGoodsConvertRequest::new("sid123", "https://xxx.douyin.com/xxx")
.external_info("12345678901")
.need_qr_code(true);
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["external_info"], "12345678901");
assert_eq!(json["need_qr_code"], "true");
}
#[test]
fn test_live_convert_request_with_buyin_id() {
let request = DouyinLiveConvertRequest::with_buyin_id("sid123", "buyin123");
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["sid"], "sid123");
assert_eq!(json["buyin_id"], "buyin123");
assert!(json.get("dy_code").is_none());
}
#[test]
fn test_activity_convert_request_serialize() {
let request = DouyinActivityConvertRequest::new("sid123", "material123");
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["sid"], "sid123");
assert_eq!(json["material_id"], "material123");
}
#[test]
fn test_goods_detail_request_serialize() {
let request = DouyinGoodsDetailRequest::new("sid123", "123,456,789").with_all_fields();
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["product_ids"], "123,456,789");
assert_eq!(json["fields"], "base_info,promotion_info");
}
#[test]
fn test_search_goods_request_serialize() {
let request = DouyinSearchGoodsRequest::new("sid123")
.title("测试商品")
.page(1)
.page_size(20)
.search_type(DouyinSearchType::Sales);
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["title"], "测试商品");
assert_eq!(json["page"], 1);
assert_eq!(json["page_size"], 20);
assert_eq!(json["search_type"], 1);
}
#[test]
fn test_parse_command_request_serialize() {
let request = DouyinParseCommandRequest::new("sid123", "口令内容");
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["sid"], "sid123");
assert_eq!(json["command"], "口令内容");
}
#[test]
fn test_order_query_request_by_pay_time() {
let request =
DouyinOrderQueryRequest::by_pay_time("2024-01-01 00:00:00", "2024-01-31 23:59:59");
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["type"], 1);
assert_eq!(json["startTime"], "2024-01-01 00:00:00");
assert_eq!(json["endTime"], "2024-01-31 23:59:59");
assert_eq!(json["san_pingtai_id"], "9");
}
#[test]
fn test_order_query_request_by_order_id() {
let request = DouyinOrderQueryRequest::by_order_id("123456789");
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["type"], 3);
assert_eq!(json["orderid"], "123456789");
}
#[test]
fn test_activity_list_request_serialize() {
let request = DouyinActivityListRequest::new("sid123")
.page(1)
.page_size(20)
.activity_status(DouyinActivityStatus::Active);
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["page"], 1);
assert_eq!(json["activity_status"], 2);
}
#[test]
fn test_optional_fields_not_serialized() {
let request = DouyinGoodsConvertRequest::new("sid", "url");
let json_str = serde_json::to_string(&request).unwrap();
assert!(!json_str.contains("external_info"));
assert!(!json_str.contains("need_qr_code"));
}
}