477 lines
18 KiB
Rust
477 lines
18 KiB
Rust
|
use std::collections::HashMap;
|
||
|
|
||
|
use chrono::{DateTime, FixedOffset};
|
||
|
use chrono::format::Fixed::TimezoneOffset;
|
||
|
use chrono::prelude::*;
|
||
|
use chrono::offset::LocalResult;
|
||
|
|
||
|
use crate::structs::{ACL, ConnectionState, CwtchEvent};
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum MessageNotification {
|
||
|
// NotificationNone enum for message["notification"] that means no notification
|
||
|
None,
|
||
|
// NotificationEvent enum for message["notification"] that means emit a notification that a message event happened only
|
||
|
SimpleEvent,
|
||
|
// NotificationConversation enum for message["notification"] that means emit a notification event with Conversation handle included
|
||
|
ContactInfo,
|
||
|
}
|
||
|
|
||
|
impl From<String> for MessageNotification {
|
||
|
fn from(str: String) -> MessageNotification {
|
||
|
match str.as_str() {
|
||
|
"None" => MessageNotification::None,
|
||
|
"SimpleEvent" => MessageNotification::SimpleEvent,
|
||
|
"ContactInfo" => MessageNotification::ContactInfo,
|
||
|
_ => MessageNotification::None,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum NetworkCheckStatus {
|
||
|
Error,
|
||
|
Success
|
||
|
}
|
||
|
|
||
|
impl From<String> for NetworkCheckStatus {
|
||
|
fn from(str: String) -> NetworkCheckStatus {
|
||
|
match str.as_str() {
|
||
|
"Error" => NetworkCheckStatus::Error,
|
||
|
"Success" => NetworkCheckStatus::Success,
|
||
|
_ => NetworkCheckStatus::Error,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum ServerStorageType {
|
||
|
DefaultPassword,
|
||
|
Password,
|
||
|
NoPassword
|
||
|
}
|
||
|
|
||
|
impl From<String> for ServerStorageType {
|
||
|
fn from(str: String) -> ServerStorageType {
|
||
|
match str.as_str() {
|
||
|
"storage-default-password" => ServerStorageType::DefaultPassword,
|
||
|
"storage-password" => ServerStorageType::Password,
|
||
|
"storage-no-password" => ServerStorageType::NoPassword,
|
||
|
_ => ServerStorageType::DefaultPassword,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum ServerIntent {
|
||
|
Running,
|
||
|
Stopped
|
||
|
}
|
||
|
|
||
|
impl From<String> for ServerIntent {
|
||
|
fn from(str: String) -> ServerIntent {
|
||
|
match str.as_str() {
|
||
|
"running" => ServerIntent::Running,
|
||
|
"stopped" => ServerIntent::Stopped,
|
||
|
_ => ServerIntent::Stopped,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum Event {
|
||
|
|
||
|
// App events
|
||
|
|
||
|
CwtchStarted,
|
||
|
NewPeer {
|
||
|
identity: String,
|
||
|
tag: String,
|
||
|
created: bool,
|
||
|
name: String,
|
||
|
default_picture: String,
|
||
|
picture: String,
|
||
|
online: String,
|
||
|
contacts_json: String,
|
||
|
server_json: String, //ServerList
|
||
|
},
|
||
|
AppError {
|
||
|
error: String
|
||
|
},
|
||
|
UpdateGlobalSettings {
|
||
|
settings: HashMap<String, String>,
|
||
|
},
|
||
|
ErrUnhandled {
|
||
|
name: String,
|
||
|
data: HashMap<String, String>,
|
||
|
},
|
||
|
PeerError {
|
||
|
error: String
|
||
|
},
|
||
|
PeerDeleted {
|
||
|
identity: String
|
||
|
},
|
||
|
Shutdown,
|
||
|
ACNStatus {
|
||
|
progress: i8,
|
||
|
status: String
|
||
|
},
|
||
|
ACNVersion {
|
||
|
verstion: String,
|
||
|
},
|
||
|
StartingStorageMiragtion,
|
||
|
DoneStorageMigration,
|
||
|
|
||
|
// app server events
|
||
|
|
||
|
NewServer {
|
||
|
onion: String,
|
||
|
server_bundle: String,
|
||
|
description: String,
|
||
|
storage_type: ServerStorageType,
|
||
|
autostart: bool,
|
||
|
running: bool,
|
||
|
},
|
||
|
ServerIntentUpdate {
|
||
|
identity: String,
|
||
|
intent: ServerIntent
|
||
|
},
|
||
|
ServerDeleted {
|
||
|
identity: String,
|
||
|
success: bool,
|
||
|
error: Option<String>,
|
||
|
},
|
||
|
ServerStatsUpdate {
|
||
|
identity: String,
|
||
|
total_messages: i32,
|
||
|
connections: i32,
|
||
|
},
|
||
|
|
||
|
// profile events
|
||
|
|
||
|
NewMessageFromPeer {
|
||
|
conversation_id: i32,
|
||
|
handle: String,
|
||
|
nick: String,
|
||
|
timestamp_received: DateTime<FixedOffset>,
|
||
|
message: String,
|
||
|
notification: MessageNotification,
|
||
|
picture: String,
|
||
|
},
|
||
|
ContactCreated {
|
||
|
conversation_id: i32,
|
||
|
remote_peer: String,
|
||
|
nick: String,
|
||
|
status: ConnectionState,
|
||
|
unread: i32,
|
||
|
picture: String,
|
||
|
default_picture: String,
|
||
|
num_messages: i32,
|
||
|
accepted: bool,
|
||
|
access_control_list: ACL,
|
||
|
blocked: bool,
|
||
|
loading: bool,
|
||
|
last_msg_time: DateTime<FixedOffset>,
|
||
|
|
||
|
},
|
||
|
PeerStateChange {
|
||
|
remote_peer: String,
|
||
|
connection_state: ConnectionState,
|
||
|
},
|
||
|
NetworkStatus {
|
||
|
address: String,
|
||
|
error: String,
|
||
|
status: NetworkCheckStatus,
|
||
|
},
|
||
|
ACNInfo {
|
||
|
handle: String,
|
||
|
key: String,
|
||
|
data: String,
|
||
|
},
|
||
|
UpdatedProfileAttribute {
|
||
|
key: String,
|
||
|
value: String,
|
||
|
},
|
||
|
IndexedAcknowledgement {
|
||
|
conversation_id: i32,
|
||
|
index: i32,
|
||
|
},
|
||
|
IndexedFailure {
|
||
|
conversation_id: i32,
|
||
|
index: i32,
|
||
|
handle: String,
|
||
|
error: String
|
||
|
},
|
||
|
PeerAcknowledgement {
|
||
|
event_id: String,
|
||
|
remote_peer: String,
|
||
|
conversation_id: i32,
|
||
|
},
|
||
|
NewMessageFromGroup {
|
||
|
conversation_id: i32,
|
||
|
timestamp_sent: DateTime<FixedOffset>,
|
||
|
remote_peer: String,
|
||
|
index: i32,
|
||
|
message: String,
|
||
|
content_hash: String,
|
||
|
picture: String,
|
||
|
nick: String,
|
||
|
notification: MessageNotification,
|
||
|
},
|
||
|
GroupCreated {
|
||
|
conversation_id: i32,
|
||
|
group_id: String,
|
||
|
group_server: String,
|
||
|
group_name: String,
|
||
|
picture: String,
|
||
|
access_control_list: ACL,
|
||
|
},
|
||
|
NewGroup {
|
||
|
conversation_id: i32,
|
||
|
group_id: String,
|
||
|
group_server: String,
|
||
|
group_invite: String,
|
||
|
group_name: String,
|
||
|
picture: String,
|
||
|
access_control_list: ACL,
|
||
|
},
|
||
|
ServerStateChange {
|
||
|
group_server: String,
|
||
|
state: ConnectionState
|
||
|
},
|
||
|
NewRetValMessageFromPeer {
|
||
|
remote_peer: String,
|
||
|
scope: String,
|
||
|
path: String,
|
||
|
exists: bool,
|
||
|
data: String,
|
||
|
file_path: Option<String>
|
||
|
},
|
||
|
ShareManifest {
|
||
|
filekey: String,
|
||
|
serializedManifest: String,
|
||
|
},
|
||
|
ManifestSizeReceived {
|
||
|
filekey: String,
|
||
|
manifest_size: i32,
|
||
|
handle: String,
|
||
|
},
|
||
|
ManifestError {
|
||
|
handle: String,
|
||
|
filekey: String,
|
||
|
},
|
||
|
ManifestReceived {
|
||
|
handle: String,
|
||
|
filekey: String,
|
||
|
serialized_manifest: String,
|
||
|
},
|
||
|
ManifestSaved {
|
||
|
handle: String,
|
||
|
filekey: String,
|
||
|
serialized_manifest: String,
|
||
|
temp_file: String,
|
||
|
name_suggestion: String,
|
||
|
},
|
||
|
FileDownloadProgressUpdate {
|
||
|
filekey: String,
|
||
|
progress: i32,
|
||
|
filesize_in_chunks: i32,
|
||
|
name_suggestion: String,
|
||
|
},
|
||
|
// FileDownloaded, ??
|
||
|
}
|
||
|
|
||
|
impl From<&CwtchEvent> for Event {
|
||
|
fn from(cwtch_event: &CwtchEvent) -> Self {
|
||
|
match cwtch_event.event_type.as_str() {
|
||
|
"CwtchStarted" => Event::CwtchStarted,
|
||
|
"NewPeer" => Event::NewPeer {
|
||
|
identity: cwtch_event.data["Identity"].clone(),
|
||
|
tag: cwtch_event.data["tag"].clone(),
|
||
|
created: cwtch_event.data["Created"] == "true",
|
||
|
name: cwtch_event.data["name"].clone(),
|
||
|
default_picture: cwtch_event.data["defaultPicture"].clone(),
|
||
|
picture: cwtch_event.data["picture"].clone(),
|
||
|
online: cwtch_event.data["Online"].clone(),
|
||
|
contacts_json: cwtch_event.data["ContactsJson"].clone(),
|
||
|
server_json: cwtch_event.data["ServerList"].clone(),
|
||
|
},
|
||
|
"NewMessageFromPeer" => Event::NewMessageFromPeer {
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2),
|
||
|
handle: cwtch_event.data["RemotePeer"].clone(),
|
||
|
nick: cwtch_event.data["Nick"].clone(),
|
||
|
timestamp_received: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampReceived"].as_str()).unwrap_or( DateTime::from(Utc::now())),
|
||
|
message: cwtch_event.data["Data"].clone(),
|
||
|
notification: MessageNotification::from(cwtch_event.data["notification"].clone()),
|
||
|
picture: cwtch_event.data["Picture"].clone(),
|
||
|
},
|
||
|
"PeerError" => Event::PeerError { error: cwtch_event.data["Error"].clone() },
|
||
|
"AppError" => Event::AppError {
|
||
|
error: cwtch_event.data["Error"].clone(),
|
||
|
},
|
||
|
"ContactCreated" => Event::ContactCreated {
|
||
|
conversation_id: cwtch_event.data["ConversationID"].clone().parse().unwrap_or(-2),
|
||
|
remote_peer: cwtch_event.data["RemotePeer"].clone(),
|
||
|
unread: cwtch_event.data["unread"].clone().parse().unwrap_or(0),
|
||
|
picture: cwtch_event.data["picture"].clone(),
|
||
|
default_picture: cwtch_event.data["defaultPicture"].clone(),
|
||
|
num_messages: cwtch_event.data["numMessages"].clone().parse().unwrap_or(0),
|
||
|
nick: cwtch_event.data["nick"].clone(),
|
||
|
accepted: cwtch_event.data["accepted"].clone().parse().unwrap_or(false),
|
||
|
status: ConnectionState::from(cwtch_event.data["status"].as_str()),
|
||
|
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
|
||
|
blocked: cwtch_event.data["blocked"].clone().parse().unwrap_or(false),
|
||
|
loading: cwtch_event.data["loading"].clone().parse().unwrap_or(false),
|
||
|
last_msg_time: DateTime::parse_from_rfc3339(cwtch_event.data["lastMsgTime"].as_str()).unwrap_or(DateTime::from(Utc::now())),
|
||
|
},
|
||
|
"PeerStateChange" => Event::PeerStateChange {
|
||
|
remote_peer: cwtch_event.data["RemotePeer"].clone(),
|
||
|
connection_state: ConnectionState::from(cwtch_event.data["ConnectionState"].as_str()),
|
||
|
},
|
||
|
"UpdateGlobalSettings" => Event::UpdateGlobalSettings {
|
||
|
settings: serde_json::from_str(cwtch_event.data["Data"].as_str()).unwrap_or(HashMap::new()),
|
||
|
},
|
||
|
"PeerDeleted" => Event::PeerDeleted { identity: cwtch_event.data["Identity"].clone() },
|
||
|
|
||
|
"ACNStatus" => Event::ACNStatus {
|
||
|
progress: cwtch_event.data["Progress"].parse().unwrap_or(0),
|
||
|
status: cwtch_event.data["Status"].clone(),
|
||
|
},
|
||
|
"ACNVersion" => Event::ACNVersion { verstion: cwtch_event.data["Data"].clone()},
|
||
|
"NetworkError" => Event::NetworkStatus {
|
||
|
address: cwtch_event.data["Onion"].clone(),
|
||
|
error: cwtch_event.data["Error"].clone(),
|
||
|
status: NetworkCheckStatus::from(cwtch_event.data["Status"].clone())
|
||
|
},
|
||
|
"ACNInfo" => Event::ACNInfo {
|
||
|
handle: cwtch_event.data["Handle"].clone(),
|
||
|
key: cwtch_event.data["Key"].clone(),
|
||
|
data: cwtch_event.data["Data"].clone(),
|
||
|
},
|
||
|
"UpdatedProfileAttribute" => Event::UpdatedProfileAttribute {
|
||
|
key: cwtch_event.data["Key"].clone(),
|
||
|
value: cwtch_event.data["Data"].clone(),
|
||
|
},
|
||
|
"IndexedAcknowledgement" => Event::IndexedAcknowledgement {
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-1),
|
||
|
index: cwtch_event.data["Index"].parse().unwrap_or(-1),
|
||
|
},
|
||
|
"IndexedAcknowledgement" => Event::IndexedFailure {
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-1),
|
||
|
index: cwtch_event.data["Index"].parse().unwrap_or(-1),
|
||
|
handle: cwtch_event.data["Handle"].clone(),
|
||
|
error: cwtch_event.data["Error"].clone(),
|
||
|
},
|
||
|
"ShareManifest" => Event::ShareManifest {
|
||
|
filekey: cwtch_event.data["FileKey"].clone(),
|
||
|
serializedManifest: cwtch_event.data["SerializedManifest"].clone(),
|
||
|
},
|
||
|
"NewServer" => Event::NewServer {
|
||
|
onion: cwtch_event.data["Onion"].clone(),
|
||
|
server_bundle: cwtch_event.data["ServerBundle"].clone(),
|
||
|
description: cwtch_event.data["Description"].clone(),
|
||
|
storage_type: ServerStorageType::from(cwtch_event.data["StorageType"].clone()),
|
||
|
autostart: cwtch_event.data["Autostart"].parse().unwrap_or(false),
|
||
|
running: cwtch_event.data["Running"].parse().unwrap_or(false),
|
||
|
},
|
||
|
"ServerIntentUpdate" => Event::ServerIntentUpdate {
|
||
|
identity: cwtch_event.data["Identity"].clone(),
|
||
|
intent: ServerIntent::from(cwtch_event.data["Intent"].clone())
|
||
|
},
|
||
|
"ServerDeleted" => Event::ServerDeleted {
|
||
|
identity: cwtch_event.data["Identity"].clone(),
|
||
|
success: cwtch_event.data["Status"].clone() == "success",
|
||
|
error: match cwtch_event.data.get("Error") {
|
||
|
Some(e) => Some(e.clone()),
|
||
|
None => None,
|
||
|
}
|
||
|
},
|
||
|
"ServerStatsUpdate" => Event::ServerStatsUpdate {
|
||
|
identity: cwtch_event.data["Identity"].clone(),
|
||
|
total_messages: cwtch_event.data["TotalMessages"].parse().unwrap_or(0),
|
||
|
connections: cwtch_event.data["Connections"].parse().unwrap_or(0),
|
||
|
},
|
||
|
"ManifestSizeReceived" => Event::ManifestSizeReceived {
|
||
|
filekey: cwtch_event.data["FileKey"].clone(),
|
||
|
manifest_size: cwtch_event.data["ManifestSize"].parse().unwrap_or(0),
|
||
|
handle: cwtch_event.data["Handle"].clone(),
|
||
|
},
|
||
|
"ManifestError" => Event::ManifestError {
|
||
|
handle: cwtch_event.data["Handle"].clone(),
|
||
|
filekey: cwtch_event.data["FileKey"].clone(),
|
||
|
},
|
||
|
"ManifestReceived" => Event::ManifestReceived {
|
||
|
handle: cwtch_event.data["Handle"].clone(),
|
||
|
filekey: cwtch_event.data["FileKey"].clone(),
|
||
|
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
|
||
|
},
|
||
|
"ManifestSaved" => Event::ManifestSaved {
|
||
|
handle: cwtch_event.data["Handle"].clone(),
|
||
|
filekey: cwtch_event.data["FileKey"].clone(),
|
||
|
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
|
||
|
temp_file: cwtch_event.data["TempFile"].clone(),
|
||
|
name_suggestion: cwtch_event.data["NameSuggestion"].clone(),
|
||
|
},
|
||
|
"FileDownloadProgressUpdate" => Event::FileDownloadProgressUpdate {
|
||
|
filekey: cwtch_event.data["FileKey"].clone(),
|
||
|
progress: cwtch_event.data["Progress"].parse().unwrap_or(0),
|
||
|
filesize_in_chunks: cwtch_event.data["FileSizeInChunks"].parse().unwrap_or(0),
|
||
|
name_suggestion: cwtch_event.data["NameSuggestion"].clone(),
|
||
|
},
|
||
|
"PeerAcknowledgement" => Event::PeerAcknowledgement {
|
||
|
event_id: cwtch_event.data["EventId"].clone(),
|
||
|
remote_peer: cwtch_event.data["RemotePeer"].clone(),
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(0)
|
||
|
},
|
||
|
"NewMessageFromGroup" => Event::NewMessageFromGroup {
|
||
|
timestamp_sent: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampSent"].as_str()).unwrap_or( DateTime::from(Utc::now())),
|
||
|
index: cwtch_event.data["RemotePeer"].parse().unwrap_or(-1),
|
||
|
content_hash: cwtch_event.data["ContentHash"].clone(),
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2),
|
||
|
remote_peer: cwtch_event.data["RemotePeer"].clone(),
|
||
|
nick: cwtch_event.data["Nick"].clone(),
|
||
|
message: cwtch_event.data["Data"].clone(),
|
||
|
notification: MessageNotification::from(cwtch_event.data["notification"].clone()),
|
||
|
picture: cwtch_event.data["Picture"].clone(),
|
||
|
},
|
||
|
"GroupCreated" => Event::GroupCreated {
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2),
|
||
|
group_id: cwtch_event.data["GroupID"].clone(),
|
||
|
group_server: cwtch_event.data["GroupServer"].clone(),
|
||
|
group_name: cwtch_event.data["GroupName"].clone(),
|
||
|
picture: cwtch_event.data["picture"].clone(),
|
||
|
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
|
||
|
},
|
||
|
"NewGroup" => Event::NewGroup {
|
||
|
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2),
|
||
|
group_id: cwtch_event.data["GroupID"].clone(),
|
||
|
group_server: cwtch_event.data["GroupServer"].clone(),
|
||
|
group_invite: cwtch_event.data["GroupInvite"].clone(),
|
||
|
group_name: cwtch_event.data["GroupName"].clone(),
|
||
|
picture: cwtch_event.data["picture"].clone(),
|
||
|
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
|
||
|
},
|
||
|
"ServerStateChange" => Event::ServerStateChange {
|
||
|
group_server: cwtch_event.data["GroupServer"].clone(),
|
||
|
state: ConnectionState::from(cwtch_event.data["ConnectionState"].as_str()),
|
||
|
},
|
||
|
"NewRetValMessageFromPeer" => Event::NewRetValMessageFromPeer {
|
||
|
remote_peer: cwtch_event.data["RemotePeer"].clone(),
|
||
|
scope: cwtch_event.data["Scope"].clone(),
|
||
|
path: cwtch_event.data["Path"].clone(),
|
||
|
exists: cwtch_event.data["Exists"].parse().unwrap_or(false),
|
||
|
data: cwtch_event.data["Data"].clone(),
|
||
|
file_path: match cwtch_event.data.get("FilePath") {
|
||
|
Some(fp) => Some(fp.to_string()),
|
||
|
None => None,
|
||
|
},
|
||
|
},
|
||
|
|
||
|
_ => Event::ErrUnhandled {
|
||
|
name: cwtch_event.event_type.to_string(),
|
||
|
data: cwtch_event.data.clone(),
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
}
|