Skip to main content

futu_backend/
message_center_push.rs

1//! Presence-safe CMD5300 message-center push decoders.
2
3use futu_core::error::{FutuError, Result};
4use prost::Message;
5
6use crate::proto_internal::{msgcenter, msgdefine, option_move_warn_msg_define};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct MessageCenterHead {
10    pub msg_id: Option<u64>,
11    pub create_time: Option<u64>,
12    pub modify_time: Option<u64>,
13    pub msg_sequence: Option<u64>,
14    pub inner_sequence: Option<u64>,
15    pub status: Option<u32>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct MessageCenterItem {
20    pub head: Option<MessageCenterHead>,
21    pub body: Option<Vec<u8>>,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct MessageCenterPush {
26    pub user_id: Option<u64>,
27    pub msg_category: Option<u32>,
28    pub notify_msg: Option<MessageCenterItem>,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct PriceWarningDetail {
33    pub key: Option<u64>,
34    pub warn_type: Option<u32>,
35    pub set_value: Option<i64>,
36    pub present_value: Option<i64>,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct PriceWarningPush {
41    pub stock_id: Option<u64>,
42    pub price: Option<u32>,
43    pub price_change_ratio: Option<i64>,
44    pub msg_content: Option<String>,
45    pub msg_content_tc: Option<String>,
46    pub msg_content_en: Option<String>,
47    pub note: Option<String>,
48    pub market_status: Option<i32>,
49    pub warn_detail: Option<PriceWarningDetail>,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct LocaleTextPush {
54    pub language_tag: Option<String>,
55    pub context: Option<String>,
56    pub language_id: Option<i32>,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct LocaleStringPush {
61    pub entries: Vec<LocaleTextPush>,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct OptionMoveWarningPush {
66    pub underlying_id: Option<u64>,
67    pub option_id: Option<u64>,
68    pub multi_lang_msg_content: Option<LocaleStringPush>,
69}
70
71pub fn decode_message_center_push(body: &[u8]) -> Result<MessageCenterPush> {
72    let wire = msgcenter::MsgCenterNotify::decode(body)
73        .map_err(|error| FutuError::Codec(format!("CMD5300 outer decode: {error}")))?;
74    Ok(MessageCenterPush {
75        user_id: wire.user_id,
76        msg_category: wire.msg_category,
77        notify_msg: wire.notify_msg.map(message_center_item),
78    })
79}
80
81pub fn decode_price_warning_push(body: &[u8]) -> Result<PriceWarningPush> {
82    let wire = msgdefine::PriceWarnMsg::decode(body)
83        .map_err(|error| FutuError::Codec(format!("CMD5300 price decode: {error}")))?;
84    Ok(PriceWarningPush {
85        stock_id: wire.stock_id,
86        price: wire.price,
87        price_change_ratio: wire.price_change_ratio,
88        msg_content: wire.msg_content,
89        msg_content_tc: wire.msg_content_tc,
90        msg_content_en: wire.msg_content_en,
91        note: wire.note,
92        market_status: wire.market_status,
93        warn_detail: wire.warn_detail.map(|detail| PriceWarningDetail {
94            key: detail.key,
95            warn_type: detail.r#type,
96            set_value: detail.set_value,
97            present_value: detail.present_value,
98        }),
99    })
100}
101
102pub fn decode_option_move_warning_push(body: &[u8]) -> Result<OptionMoveWarningPush> {
103    let wire = option_move_warn_msg_define::OptionMoveWarnMsg::decode(body)
104        .map_err(|error| FutuError::Codec(format!("CMD5300 option decode: {error}")))?;
105    Ok(OptionMoveWarningPush {
106        underlying_id: wire.underlying_id,
107        option_id: wire.option_id,
108        multi_lang_msg_content: wire.multi_lang_msg_content.map(|locale| LocaleStringPush {
109            entries: locale
110                .str_context
111                .into_iter()
112                .map(|entry| LocaleTextPush {
113                    language_tag: entry.language_tag,
114                    context: entry.context,
115                    language_id: entry.language_id,
116                })
117                .collect(),
118        }),
119    })
120}
121
122fn message_center_item(wire: msgcenter::MsgItem) -> MessageCenterItem {
123    MessageCenterItem {
124        head: wire.head.map(|head| MessageCenterHead {
125            msg_id: head.msg_id,
126            create_time: head.create_time,
127            modify_time: head.modify_time,
128            msg_sequence: head.msg_sequence,
129            inner_sequence: head.inner_sequence,
130            status: head.status,
131        }),
132        body: wire.body,
133    }
134}