~nicohman/signal-rs

ref: f72f1012a4b1aa4cfc535e6e12dd722d3cb9b57a signal-rs/src/signal.rs -rw-r--r-- 4.8 KiB
f72f1012 — nicohman GTK start 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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use enum_variant_type::EnumVariantType;
use futures_util::future::*;
use futures_util::sink::SinkExt;
use futures_util::sink::*;
use futures_util::stream::*;
use futures_util::stream::{select_all, SelectAll};
use futures_util::*;
use futures_util::{future, pin_mut, StreamExt};
use mio::net::TcpStream;
use serde::*;
use serde::{Deserialize, Serialize};
use std::collections::*;
use std::convert::TryFrom;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::prelude::*;
use tokio::stream::*;
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 { lastId: 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>),
}
#[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,
}
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(mut socket: WebSocketStream<tokio::net::TcpStream>) -> SignalSession<'a> {
        let (mut write, mut read) = socket.split();
        let st = read.filter_map(|x| {
            if let Some(attempt) =
                serde_json::from_str::<SignalResponse>(&x.unwrap().into_text().unwrap()).ok()
            {
                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 Some(v) = T::try_from(x).ok() {
                    future::ready(Some(v))
                } else {
                    future::ready(None)
                }
            })
            .next()
            .await
            .unwrap())
    }
}
pub struct SignalManager {
    pub contacts: HashMap<String, Contact>,
}
impl SignalManager {
    pub fn new() -> SignalManager {
        SignalManager {
            contacts: HashMap::new(),
        }
    }
    pub fn process_responses(&mut self, responses: Vec<SignalResponse>) {
        for res in responses.into_iter() {
            match res {
                SignalResponse::ContactList(v) => {
                    for contact in v.into_iter() {
                        self.contacts.insert(contact.tel.clone(), contact);
                    }
                }
                _ => {}
            }
        }
    }
}