dnspod_lib/
action.rs

1//! 定义各个 Action 请求
2//! 
3//! 添加具体 Action 时可以通过 `@[url = consts::DNSPOD_URL]` 覆盖掉默认公共参数。可以覆盖的还有 region 和 version
4//! 
5
6#![allow(non_snake_case)]
7
8
9use crate::utils::none_to_empty_string;
10
11use crate::data_types::*;
12use crate::consts;
13
14/// for `#[serde(crate = "dnspod_lib::serde")]`
15mod dnspod_lib {
16    pub use crate::data_types;
17    pub use crate::serde;
18    pub use crate::consts;
19}
20
21#[macro_export]
22macro_rules! overloading_common_params {
23    (url = $expr: expr) => {
24        #[inline] fn url(&self) -> &'static str { $expr }
25    };
26    (version = $expr: expr) => {
27        #[inline] fn version(&self) -> $crate::data_types::Version { $expr }
28    };
29    (region = $expr: expr) => {
30        #[inline] fn region(&self) -> Option<$crate::data_types::Region> { Some($expr) }
31    };
32    ($($tt: tt)*) => {
33        compile_error!("This macro only accepts `url` `region` `version`");
34    };
35}
36
37#[macro_export]
38macro_rules! impl_define_action_list {
39    (
40        $(
41            $(#[$meta: meta])*
42            $(@[$($my_meta: tt)*])*
43            $vis: vis struct $name: ident $body: tt
44        )*
45    ) => {
46        $(
47            $(#[$meta])*
48            $vis struct $name $body
49
50            const _: () = {
51                use $crate::ExtractCommonParams;
52                use $crate::serde_json;
53
54                impl ExtractCommonParams for $name {
55                    #[inline] fn action(&self) -> &'static str { stringify!($name) }
56                    #[inline] fn body(&self) -> Vec<u8> { serde_json::to_vec(self).unwrap() }
57                    $(
58                        $crate::overloading_common_params! { $($my_meta)* }
59                    )*
60                }
61            };
62        )*
63    };
64
65    (
66        $(#[$enum_meta: meta])*
67        $enum_vis: vis enum $enum_name: ident {}
68        ,
69        $(
70            $(#[$meta: meta])*
71            $(@[$($my_meta: tt)*])*
72            $vis: vis struct $name: ident $body: tt
73        )*
74    ) => {
75        $crate::impl_define_action_list! {
76            $(
77                $(#[$meta])*
78                $(@[$($my_meta)*])*
79                $vis struct $name $body
80            )*
81        }
82
83        $(
84            impl From<$name> for $enum_name {
85                #[inline] fn from(v: $name) -> Self { Self::$name(v) }
86            }
87        )*
88
89        $(#[$enum_meta])*
90        $enum_vis enum $enum_name {
91            $($name($name),)*
92        }
93
94        impl $crate::ExtractCommonParams for $enum_name {
95            #[inline]
96            fn action(&self) -> &'static str {
97                #[allow(unreachable_patterns)]
98                match self {
99                    $(Self::$name(v) => v.action(),)*
100                    _ => Default::default(),
101                }
102            }
103            #[inline]
104            fn body(&self) -> Vec<u8> {
105                #[allow(unreachable_patterns)]
106                match self {
107                    $(Self::$name(v) => v.body(), )*
108                    _ => Default::default(),
109                }
110            }
111            #[inline]
112            fn url(&self) -> &'static str {
113                #[allow(unreachable_patterns)]
114                match self {
115                    $(Self::$name(v) => v.url(), )*
116                    _ => Default::default(),
117                }
118            }
119            #[inline]
120            fn version(&self) -> $crate::data_types::Version {
121                #[allow(unreachable_patterns)]
122                match self {
123                    $(Self::$name(v) => v.version(), )*
124                    _ => Default::default(),
125                }
126            }
127            #[inline]
128            fn region(&self) -> Option<$crate::data_types::Region> {
129                #[allow(unreachable_patterns)]
130                match self {
131                    $(Self::$name(v) => v.region(), )*
132                    _ => Default::default(),
133                }
134            }
135        }
136    };
137}
138
139/// 供外部 crate 调用
140#[macro_export]
141macro_rules! define_action_list {
142    (
143        $($tt: tt)*
144    ) => {
145        $crate::custom_meta_struct! {
146            (
147                // callback macro
148                $crate::impl_define_action_list,
149                // common metas
150                #[derive(Debug, Clone, $crate::serde::Serialize, $crate::serde::Deserialize)]
151                #[serde(crate = "dnspod_lib::serde")]
152            ),
153            $($tt)*
154        }
155    };
156}
157
158macro_rules! define_action_list_private {
159    (
160        $($tt: tt)*
161    ) => {
162        $crate::impl_define_action_list! {
163            #[derive(Debug, Clone)]
164            #[cfg_attr(feature = "clap", derive(clap::Subcommand))]
165            #[allow(non_snake_case)]
166            pub enum Action {}
167            ,
168            $($tt)*
169        }
170    };
171}
172
173
174crate::custom_meta_struct! {
175    (
176        define_action_list_private, // callback macro
177
178        // 公共 meta attribute, 赋给每个 struct 
179        #[cfg_attr(feature = "clap", derive(clap::Parser))]
180        #[derive(Debug, Clone, crate::serde::Serialize, crate::serde::Deserialize)]
181        #[serde(crate = "dnspod_lib::serde")]
182    ),
183
184    /// 获取域名列表
185    /// <https://cloud.tencent.com/document/api/1427/56172>
186    @[url = consts::DNSPOD_URL]
187    @[version = Version::Version2021_03_23]
188    pub struct DescribeDomainList {
189        /// 域名分组类型,默认为ALL
190        #[cfg_attr(feature = "clap", arg(long, value_enum, default_value_t=Default::default()))]
191        pub Type: DomainType,
192        /// 记录开始的偏移, 第一条记录为 0, 依次类推。默认值为0。
193        /// 示例值:0
194        #[cfg_attr(feature = "clap", arg(long, default_value_t=0))]
195        pub Offset: Integer,
196        /// 要获取的域名数量, 比如获取20个, 则为20。默认值为3000。
197        /// 示例值:20
198        #[cfg_attr(feature = "clap", arg(long, default_value_t=3000))]
199        pub Limit: Integer,
200        /// 分组ID, 第一个组为 0, 获取指定分组的域名
201        /// 示例值:1
202        #[cfg_attr(feature = "clap", arg(long, default_value_t=0))]
203        pub GroupId: Integer,
204        /// 根据关键字搜索域名
205        /// 示例值:qq
206        #[cfg_attr(feature = "clap", arg(long, default_value=""))]
207        pub Keyword: Option<String>,
208    }
209
210    /// 添加域名 <https://cloud.tencent.com/document/api/1427/56184>
211    pub struct CreateDomain {
212        Domain: String,
213    }
214    /// 删除域名 <https://cloud.tencent.com/document/api/1427/56178>
215    pub struct DeleteDomain {
216        Domain: String,
217    }
218
219    /// 添加记录 <https://cloud.tencent.com/document/api/1427/56180>
220    pub struct CreateRecord {
221        /// 域名
222        /// 示例值:dnspod.cn
223        #[cfg_attr(feature = "clap", arg(long))]
224        pub Domain: String,
225        /// 主机记录,如 www,如果不传,默认为 @。
226        /// 示例值:www
227        #[cfg_attr(feature = "clap", arg(long, default_value = "@"))]
228        pub SubDomain: String,
229        /// 记录类型,通过 API 记录类型获得,大写英文,比如:A 。
230        /// 示例值:A
231        #[cfg_attr(feature = "clap", arg(long, value_enum, rename_all = "UPPER"))]
232        pub RecordType: RecordType,
233        /// 记录线路,通过 API 记录线路获得,中文,比如:默认。
234        /// 示例值:默认
235        #[cfg_attr(feature = "clap", arg(long, value_enum, default_value_t=Default::default()))]
236        pub RecordLine: RecordLine,
237        /// 记录值,如 IP : 200.200.200.200, CNAME : cname.dnspod.com., MX : mail.dnspod.com.。
238        /// 示例值:200.200.200.200
239        #[cfg_attr(feature = "clap", arg(long))]
240        pub Value: String,
241    }
242
243    /// 删除记录
244    /// <https://cloud.tencent.com/document/api/1427/56176>
245    pub struct DeleteRecord {
246        /// 域名
247        /// 示例值:dnspod.cn
248        #[cfg_attr(feature = "clap", arg(long))]
249        pub Domain: String,
250        /// 记录 ID 。可以通过接口 [DescribeRecordList] 查到所有的解析记录列表以及对应的 RecordId
251        /// 示例值:162
252        #[cfg_attr(feature = "clap", arg(long))]
253        pub RecordId: u64,
254    }
255
256    /// 获取域名的解析记录列表
257    /// <https://cloud.tencent.com/document/api/1427/56166>
258    pub struct DescribeRecordList {
259        /// 要获取的解析记录所属的域名
260        /// 示例值:example.com
261        #[cfg_attr(feature = "clap", arg(long))]
262        pub Domain: String,
263        /// 解析记录的主机头,如果传了此参数,则只会返回此主机头对应的解析记录
264        /// 示例值:www
265        #[serde(serialize_with = "none_to_empty_string")]
266        #[cfg_attr(feature = "clap", arg(long, default_value=""))]
267        pub Subdomain: Option<String>,
268        /// 通过关键字搜索解析记录,当前支持搜索主机头和记录值
269        /// 示例值:book
270        #[serde(skip_serializing_if = "Option::is_none")]
271        #[cfg_attr(feature = "clap", arg(long, default_value=""))]
272        pub Keyword: Option<String>,
273    }
274
275    /// 获取记录信息
276    /// <https://cloud.tencent.com/document/api/1427/56168>
277    pub struct DescribeRecord {
278        /// 域名
279        /// 示例值:dnspod.cn
280        #[cfg_attr(feature = "clap", arg(long))]
281        pub Domain: String,
282        /// 记录 ID 。可以通过接口 [DescribeRecordList] 查到所有的解析记录列表以及对应的 RecordId
283        /// 示例值:162
284        #[cfg_attr(feature = "clap", arg(long))]
285        pub RecordId: u64,
286    }
287
288    /// 获取等级允许的记录类型 <https://cloud.tencent.com/document/api/1427/56165>
289    pub struct DescribeRecordType {
290        /// 域名等级。
291        /// 
292        /// + 旧套餐:D_FREE、D_PLUS、D_EXTRA、D_EXPERT、D_ULTRA 分别对应免费套餐、个人豪华、企业1、企业2、企业3。
293        /// 
294        /// + 新套餐:DP_FREE、DP_PLUS、DP_EXTRA、DP_EXPERT、DP_ULTRA 分别对应新免费、个人专业版、企业创业版、企业标准版、企业旗舰版。
295        /// 
296        /// 示例值:DP_Plus
297        #[cfg_attr(feature = "clap", arg(long))]
298        pub DomainGrade: DomainGrade,
299    }
300    /// 获取等级允许的线路 <https://cloud.tencent.com/document/api/1427/56167>
301    pub struct DescribeRecordLineList {
302        /// 域名。
303        /// 示例值:dnspod.cn
304        pub Domain: String,
305        #[cfg_attr(feature = "clap", arg(long))]
306        /// 域名等级
307        pub DomainGrade: DomainGrade,
308    }
309
310    /// 更新动态 DNS 记录
311    /// <https://cloud.tencent.com/document/api/1427/56158>
312    pub struct ModifyDynamicDNS {
313        /// 域名
314        /// 示例值:dnspod.cn
315        #[cfg_attr(feature = "clap", arg(long))]
316        pub Domain: String,
317        /// 主机记录,如 www,如果不传,默认为 @。
318        /// 示例值:www
319        #[cfg_attr(feature = "clap", arg(long, default_value="@"))]
320        pub SubDomain: String,
321        /// 记录 ID 。可以通过接口 [DescribeRecordList] 查到所有的解析记录列表以及对应的 RecordId
322        /// 示例值:162
323        #[cfg_attr(feature = "clap", arg(long))]
324        pub RecordId: u64,
325        /// 记录线路,通过 API 记录线路获得,中文,比如:默认。
326        /// 示例值:默认
327        #[cfg_attr(feature = "clap", arg(value_enum, default_value_t=Default::default()))]
328        pub RecordLine: RecordLine,
329        /// 记录值,如 IP : 200.200.200.200, CNAME : cname.dnspod.com., MX : mail.dnspod.com.。
330        /// 示例值:200.200.200.200
331        #[cfg_attr(feature = "clap", arg(long))]
332        pub Value: String,
333        /// TTL值,如果不传,默认为域名的TTL值。
334        /// 示例值:600
335        #[cfg_attr(feature = "clap", arg(long, default_value_t=600))]
336        pub Ttl: Integer,
337    }
338
339    /// 修改记录
340    /// <https://cloud.tencent.com/document/api/1427/56157>
341    pub struct ModifyRecord {
342        /// 域名
343        /// 示例值:dnspod.cn
344        #[cfg_attr(feature = "clap", arg(long))]
345        pub Domain: String,
346        /// 主机记录,如 www,如果不传,默认为 @。
347        /// 示例值:www
348        #[cfg_attr(feature = "clap", arg(long, default_value="@"))]
349        pub SubDomain: String,
350        /// 记录 ID 。可以通过接口 [DescribeRecordList] 查到所有的解析记录列表以及对应的 RecordId
351        /// 示例值:162
352        #[cfg_attr(feature = "clap", arg(long))]
353        pub RecordId: u64,
354        /// 记录类型,通过 API 记录类型获得,大写英文,比如:A 。
355        /// 示例值:A
356        #[cfg_attr(feature = "clap", arg(long))]
357        pub RecordType: RecordType,
358        /// 记录线路,通过 API 记录线路获得,中文,比如:默认。
359        /// 示例值:默认
360        #[cfg_attr(feature = "clap", arg(long, value_enum, default_value_t=Default::default()))]
361        pub RecordLine: RecordLine,
362        /// 记录值,如 IP : 200.200.200.200, CNAME : cname.dnspod.com., MX : mail.dnspod.com.。
363        /// 示例值:200.200.200.200
364        #[cfg_attr(feature = "clap", arg(long))]
365        pub Value: String,
366    }
367}
368
369
370
371#[cfg(test)]
372mod tests {
373    use super::*;
374
375    super::super::define_action_list! {}
376
377    crate::define_action_list! {
378        /// fuckme 
379        @[url = "https://hangj.cnblogs.com"]
380        struct A;
381        /// hey
382        struct B;
383    }
384    
385    crate::define_action_list! {
386        /// 获取域名信息
387        /// <https://cloud.tencent.com/document/api/1427/56173>
388        @[url = "https://example.com"] // 公共参数可以重载 url, version, region
389        pub struct DescribeDomain {
390            /// 域名分组类型,默认为ALL
391            #[serde(rename = "Domain")]
392            pub domain: String,
393        }
394    
395        @[version = dnspod_lib::data_types::Version::Version2021_03_23]
396        #[allow(non_snake_case)]
397        pub struct CustomAction {
398            /// 域名分组类型,默认为ALL
399            pub Domain: String,
400        }
401    }    
402}