~nicohman/signal-rs

ref: notif signal-rs/src/signal.rs -rw-r--r-- 4.4 KiB
7e6d9d84 — nicohman Try notifications 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use enum_variant_type::EnumVariantType;
use futures_util::sink::SinkExt;
use futures_util::stream::*;
use futures_util::{future, StreamExt};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use tokio_tungstenite::tungstenite::protocol::*;
use tokio_tungstenite::*;

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "request")]
pub enum SignalRequest {
    SendMessage { to: String, message: String },
    GetMessageList { id: String },
    CreateChat { tel: String },
    OpenChat { id: String },
    DelChat { id: String },
    GetChatList,
    GetContactList,
    GetDevices,
    GetMoreMessages { last_id: String },
    LeaveChat,
    ToggleNotifications { chat: String },
    CreateNewGroup { name: String, members: Vec<String> },
    GetConfig,
    AddContact { name: String, phone: String },
}
#[derive(Serialize, Deserialize, Clone, EnumVariantType, Debug)]
pub enum SignalResponse {
    #[evt(derive(Clone, Serialize, Deserialize, Debug))]
    ContactList(Vec<Contact>),
    #[evt(derive(Clone, Serialize, Deserialize, Debug))]
    ChatList(Vec<Chat>),
    #[evt(derive(Clone, Serialize, Deserialize, Debug))]
    MessageList(SignalMessageList),
    #[evt(derive(Clone, Serialize, Deserialize, Debug))]
    ShowMessages(String),
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct SignalMessageList {
    #[serde(rename = "ID")]
    pub ID: String,
    pub messages: Vec<SignalMessage>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct Chat {
    #[serde(rename = "ID")]
    pub ID: i32,
    pub name: String,
    pub tel: String,
    pub is_group: bool,
    pub last: String,
    pub timestamp: i64,
    pub when: String,
    pub c_type: i32,
    pub messages: Vec<SignalMessage>,
    pub unread: i32,
    pub active: bool,
    pub len: i32,
    pub notification: bool,
    pub expire_timer: i32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct SignalMessage {
    #[serde(rename = "ID")]
    pub ID: i32,
    #[serde(rename = "SID")]
    pub SID: i32,
    #[serde(rename = "ChatID")]
    pub chat_id: String,
    pub source: String,
    pub message: String,
    pub outgoing: bool,
    pub sent_at: i64,
    pub received_at: i64,
    pub h_time: String,
    pub c_type: i32,
    pub attachment: Option<String>,
    pub is_sent: bool,
    pub is_read: bool,
    pub flags: i32,
    pub expire_timer: i32,
    pub sending_error: bool,
    pub receipt: bool,
    pub status_message: bool,
}
impl PartialEq for SignalMessage {
    fn eq(&self, other: &Self) -> bool {
        self.ID == other.ID && self.message == other.message
    }
}
trait SignalResponseTrait {}
impl SignalResponseTrait for SignalResponse {}
#[serde(rename_all = "PascalCase")]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Contact {
    pub tel: String,
    pub uuid: String,
    pub name: String,
    pub color: String,
    pub avatar: String,
    pub blocked: bool,
    pub expire_timer: i32,
}
pub struct SignalSession<'a> {
    pub sink: SplitSink<WebSocketStream<tokio::net::TcpStream>, Message>,
    pub stream: BoxStream<'a, SignalResponse>,
}
impl<'a> SignalSession<'a> {
    pub fn from_socket(socket: WebSocketStream<tokio::net::TcpStream>) -> SignalSession<'a> {
        let (write, read) = socket.split();
        let st = read.filter_map(|x| {
            if let Ok(attempt) =
                serde_json::from_str::<SignalResponse>(&x.unwrap().into_text().unwrap())
            {
                return future::ready(Some(attempt));
            }
            future::ready(None)
        });
        SignalSession {
            sink: write,
            stream: st.boxed(),
        }
    }
    pub async fn send(&mut self, req: SignalRequest) -> Result<(), Box<dyn std::error::Error>> {
        Ok(self
            .sink
            .send(Message::Text(serde_json::to_string(&req)?))
            .await?)
    }
    pub async fn send_res<T>(&mut self, req: SignalRequest) -> Result<T, Box<dyn std::error::Error>>
    where
        T: TryFrom<SignalResponse>,
    {
        self.send(req).await?;
        Ok(self
            .stream
            .by_ref()
            .filter_map(|x| {
                if let Ok(v) = T::try_from(x) {
                    future::ready(Some(v))
                } else {
                    future::ready(None)
                }
            })
            .next()
            .await
            .unwrap())
    }
}