2021-09-16 01:57:36 +00:00
use crate ::structs ::ConnectionState ::Disconnected ;
2022-04-05 01:10:02 +00:00
use crate ::CwtchLib ;
2021-09-04 03:36:35 +00:00
use serde ::{ Deserialize , Serialize } ;
2021-09-15 19:17:45 +00:00
use serde_with ::{ serde_as , DefaultOnError } ;
2021-09-04 03:36:35 +00:00
use std ::collections ::HashMap ;
2021-09-15 19:17:45 +00:00
#[ derive(Serialize, Deserialize, Debug) ]
/// Defines the states a Cwtch connection can be in
pub enum ConnectionState {
/// The Cwtch connection is not conected at all
Disconnected ,
/// Cwtch is attempting to connect to the address, it may or may not be online
Connecting ,
/// Cwtch has made a basic connection to the address, but not done authorization. The address is online but unverified as the desired target
Connected ,
/// Cwtch has authenticated the desired connection
Authenticated ,
/// In the case of a server connection, Cwtch has finished syncing messages from the server and is caught up
Synced ,
/// The connection attempt failed
Failed ,
/// The connection has been killed
2021-09-16 01:57:36 +00:00
Killed ,
2021-09-15 19:17:45 +00:00
}
impl Default for ConnectionState {
fn default ( ) -> ConnectionState {
Disconnected
}
}
2022-04-05 01:10:02 +00:00
impl ConnectionState {
/// Creates a ConnectionState from a string sent from libcwtch-go
pub fn new ( name : & str ) -> Self {
match name {
" Disconnected " = > ConnectionState ::Disconnected ,
" Connecting " = > ConnectionState ::Connecting ,
" Connected " = > ConnectionState ::Connected ,
" Authenticated " = > ConnectionState ::Authenticated ,
" Synced " = > ConnectionState ::Synced ,
" Failed " = > ConnectionState ::Failed ,
" Killed " = > ConnectionState ::Killed ,
_ = > ConnectionState ::Disconnected ,
}
}
}
2021-09-15 19:17:45 +00:00
#[ derive(Serialize, Deserialize, Debug) ]
#[ serde(rename_all = " lowercase " ) ]
/// Defines the various authorization modes a contact can be in
pub enum ContactAuthorization {
/// This is an unknown (new?) contact. The user has not approved them
Unknown ,
/// The contact is approved by the user (manual action)
Approved ,
/// The contact is blocked by the user, should be ignored
2021-09-16 01:57:36 +00:00
Blocked ,
2021-09-15 19:17:45 +00:00
}
2021-09-04 03:36:35 +00:00
#[ derive(Serialize, Deserialize, Debug) ]
#[ serde(rename_all = " PascalCase " ) ]
2021-09-11 04:57:57 +00:00
#[ allow(non_snake_case) ]
2021-09-08 07:32:56 +00:00
/// Struct to serialize/deserialize events coming off the Cwtch appbus
2021-09-04 03:36:35 +00:00
pub struct CwtchEvent {
2021-09-11 04:57:57 +00:00
/// the type of event, as defined in https://git.openprivacy.ca/cwtch.im/cwtch/src/branch/master/event/common.go
2021-09-04 03:36:35 +00:00
pub event_type : String ,
2021-09-11 04:57:57 +00:00
/// event ID that can be used to respond to some events and keep them differentiated (event_ID because golang naming conventions in libCwtch-go)
pub event_ID : String ,
/// a map of keys and values of arguments for the event as defined in https://git.openprivacy.ca/cwtch.im/cwtch/src/branch/master/event/common.go
2021-09-04 03:36:35 +00:00
pub data : HashMap < String , String > ,
}
2021-09-15 19:17:45 +00:00
#[ serde_as ]
2021-09-04 03:36:35 +00:00
#[ derive(Serialize, Deserialize, Debug) ]
2021-09-08 07:32:56 +00:00
#[ serde(rename_all = " camelCase " ) ]
2022-04-06 04:11:37 +00:00
/// Struct to serialize/deserialize conversations coming from libcwtch-go
pub struct Conversation {
/// onion address / id of the conversation
#[ serde(alias = " onion " ) ]
pub handle : String ,
2022-04-05 01:10:02 +00:00
/// unique identifier of the contact/conversation to be used in API access
pub identifier : i32 ,
2022-04-06 04:11:37 +00:00
/// display name of the conversation, as determined in libcwtch-go from name specified by contact
2021-09-04 03:36:35 +00:00
pub name : String ,
2021-09-16 01:57:36 +00:00
#[ serde_as(deserialize_as = " DefaultOnError " ) ]
2022-04-06 04:11:37 +00:00
// cwtch loads profile/conversation from storage and leaves status blank, it's filled in "soon" by events...
2021-09-15 19:17:45 +00:00
/// contact connection status
pub status : ConnectionState ,
2022-04-06 04:11:37 +00:00
/// has the conversation been manually accpted
2022-04-05 01:10:02 +00:00
pub accepted : bool ,
2022-04-06 04:11:37 +00:00
/// has the conversation been manually blocked
2022-04-05 01:10:02 +00:00
pub blocked : bool ,
2022-04-06 04:11:37 +00:00
/// is this conversation a group? if so "onion" will be a group ID
/// FIXME: deprecate
2021-09-08 07:32:56 +00:00
pub is_group : bool ,
2021-09-04 03:36:35 +00:00
//attr: HashMap<String, String>,
}
#[ derive(Serialize, Deserialize, Debug) ]
2021-09-08 07:32:56 +00:00
/// Struct to serialize/deserialize servers coming from libcwtch-go
2021-09-04 03:36:35 +00:00
pub struct Server {
2021-09-11 04:57:57 +00:00
/// onion address of the server
2021-09-04 03:36:35 +00:00
pub onion : String ,
2021-09-15 19:17:45 +00:00
/// server connection status
pub status : ConnectionState ,
2021-09-04 03:36:35 +00:00
}
#[ derive(Debug) ]
2021-09-08 07:32:56 +00:00
/// Struct to serialize/deserialize profiles coming from libcwtch-go
2021-09-04 03:36:35 +00:00
pub struct Profile {
2021-09-11 04:57:57 +00:00
/// onion address / ID of the profile
2021-09-04 03:36:35 +00:00
pub onion : String ,
2021-09-11 04:57:57 +00:00
/// nick name of the onion as supplied by libcwtch-go based on "name" attribute
2021-09-04 03:36:35 +00:00
pub nick : String ,
2021-09-11 04:57:57 +00:00
/// path to a profile image, controled by "picture" attribute
2021-09-08 07:32:56 +00:00
pub image_path : String ,
2021-09-11 04:57:57 +00:00
/// all profile attributes
2021-09-16 01:57:36 +00:00
pub attr : HashMap < String , String > ,
2022-04-06 04:11:37 +00:00
/// map of conversation [ onion => conversation ]
pub conversations : HashMap < String , Conversation > ,
2021-09-11 04:57:57 +00:00
/// map of servers [ onion => server ]
2021-09-04 03:36:35 +00:00
pub servers : HashMap < String , Server > ,
}
#[ derive(Debug, Serialize, Deserialize) ]
2022-04-06 04:11:37 +00:00
/// Struct to serialize/deserialize messages sent over Cwtch between profiles / conversation
2021-09-04 03:36:35 +00:00
pub struct Message {
2021-09-11 04:57:57 +00:00
/// overlay id that the message is targeting as defined in cwtch/model/overlay.go
/// [ OverlayChat = 1, OverlayInviteContact = 100, OverlayInviteGroup = 101, OverlayFileSharing = 200 ]
2021-09-04 03:36:35 +00:00
pub o : i64 ,
2021-09-11 04:57:57 +00:00
/// data of the message
2021-09-16 01:57:36 +00:00
pub d : String ,
2021-09-04 03:36:35 +00:00
}
2022-04-05 01:10:02 +00:00
#[ derive(Debug, Serialize, Deserialize) ]
/// Settings as defined in libcwtch-go/utils/settings.go and should be populated by handeling the UpdateGlobalSettings event emited during cwtch.start()
#[ allow(non_snake_case) ]
pub struct Settings {
/// locale for the UI to use
pub Locale : String ,
/// theme of the UI
pub Theme : String ,
/// Theme mode of the ui, light or dark
pub ThemeMode : String ,
/// previous pid of the run, managed by libcwtch-go
pub PreviousPid : i64 ,
/// controls if subsequent experiments are enabled at all
pub ExperimentsEnabled : bool ,
/// map of experiment names and their enabled status
pub Experiments : HashMap < String , bool > ,
2022-04-06 04:11:37 +00:00
/// Should the app block unknown conversations
2022-04-05 01:10:02 +00:00
pub BlockUnknownConnections : bool ,
// Notification policy of a UI app
//pub NotificationPolicy: String, //Todo: NotificationPolicy struct
// Notification content to show for a UI app
//pub NotificationContent: String,
2022-04-06 04:11:37 +00:00
/// Should the UI hide conversation IDs
2022-04-05 01:10:02 +00:00
pub StreamerMode : bool ,
/// Unused?
pub StateRootPane : i32 ,
/// is this the first run
pub FirstTime : bool ,
/// UI column mode
pub UIColumnModePortrait : String ,
/// UI column mode
pub UIColumnModeLandscape : String ,
/// Path to download files to
pub DownloadPath : String ,
// Turn on advanced tor config in the UI
//pub AllowAdvancedTorConfig: bool,
// Custom torrc value
//pub CustomTorrc: String,
// Use the value of CustomTorrc with tor
//pub UseCustomTorrc: bool,
// Unused? delete
//pub UseExternalTor: bool,
// Tor socks port, if not default
//pub CustomSocksPort: i32,
// Tor control port if not default
//pub CustomControlPort: i32,
// Use tor cache for faster start
//pub UseTorCache: bool,
// Tor config dir
//pub TorCacheDir: String,
}
/// Enum of experiment types that can be managed in Settings
pub enum Experiments {
2022-04-06 04:11:37 +00:00
/// experiment enabling in app management and running of Cwtch servers
2022-04-05 01:10:02 +00:00
ServersExperiment ,
2022-04-06 04:11:37 +00:00
/// experiment enabling use of Cwtch groups
2022-04-05 01:10:02 +00:00
GroupExperiment ,
2022-04-06 04:11:37 +00:00
/// experiment enabling filesharing
2022-04-05 01:10:02 +00:00
FileSharingExperiment ,
2022-04-06 04:11:37 +00:00
/// experiment enabling auto downloading of image files to Settings::DownloadPath
2022-04-05 01:10:02 +00:00
ImagePreviewsExperiment ,
}
impl Experiments {
/// returns the experiment settings key
pub fn to_key_string ( self ) -> String {
match self {
Experiments ::ServersExperiment = > " servers-experiment " . to_string ( ) ,
Experiments ::GroupExperiment = > " tapir-groups-experiment " . to_string ( ) ,
Experiments ::FileSharingExperiment = > " filesharing " . to_string ( ) ,
Experiments ::ImagePreviewsExperiment = > " filesharing-images " . to_string ( ) ,
}
}
}
impl Settings {
/// Given a CwtchLib, handles sending an event to it with updated settings represented by this struct for saving
pub fn save ( & self , cwtch : & dyn CwtchLib ) -> Result < ( ) , String > {
let settings_json = match serde_json ::to_string ( & self ) {
Ok ( s ) = > s ,
Err ( e ) = > return Err ( e . to_string ( ) ) ,
} ;
let save_settings_event : CwtchEvent = CwtchEvent {
event_type : " UpdateGlobalSettings " . to_string ( ) ,
event_ID : " 0 " . to_string ( ) ,
data : HashMap ::from ( [ ( " Data " . to_string ( ) , settings_json ) ] ) ,
} ;
let event_json = match serde_json ::to_string ( & save_settings_event ) {
Ok ( s ) = > s ,
Err ( e ) = > return Err ( e . to_string ( ) ) ,
} ;
cwtch . send_app_event ( & event_json ) ;
return Ok ( ( ) ) ;
}
}
2021-09-04 03:36:35 +00:00
impl Profile {
2021-09-11 04:57:57 +00:00
/// Create a new profile populated from supplied data
2022-04-06 04:11:37 +00:00
/// contacts_json as supplied by libcwtch-go, a map of conversations
2021-09-11 04:57:57 +00:00
/// server_list as supplied by libcwtch-go, a map of servers
2021-09-16 01:57:36 +00:00
pub fn new (
identity : & str ,
name : & str ,
picture : & str ,
2022-04-06 04:11:37 +00:00
conversations_json : & str ,
2021-09-16 01:57:36 +00:00
server_list : & str ,
2022-01-16 19:24:22 +00:00
) -> Result < Profile , String > {
2022-04-06 04:11:37 +00:00
let conversations = match Profile ::process_conversations ( conversations_json ) {
2022-01-16 19:24:22 +00:00
Ok ( c ) = > c ,
2022-01-17 23:24:58 +00:00
Err ( e ) = > return Err ( e ) ,
2022-01-16 19:24:22 +00:00
} ;
let servers = match Profile ::process_servers ( server_list ) {
Ok ( s ) = > s ,
2022-01-17 23:24:58 +00:00
Err ( e ) = > return Err ( e ) ,
2022-01-16 19:24:22 +00:00
} ;
Ok ( Profile {
2021-09-16 01:57:36 +00:00
onion : identity . to_string ( ) ,
nick : name . to_string ( ) ,
image_path : picture . to_string ( ) ,
attr : Default ::default ( ) ,
2022-04-06 04:11:37 +00:00
conversations ,
2021-09-16 01:57:36 +00:00
servers : servers ,
2022-01-16 19:24:22 +00:00
} )
2021-09-04 03:36:35 +00:00
}
2022-04-06 04:11:37 +00:00
fn process_conversations ( conversations_json : & str ) -> Result < HashMap < String , Conversation > , String > {
let mut conversations : HashMap < String , Conversation > = HashMap ::new ( ) ;
if conversations_json = = " null " {
return Ok ( conversations ) ;
2021-09-04 03:36:35 +00:00
}
2022-04-06 04:11:37 +00:00
let conversations_map : Vec < Conversation > = match serde_json ::from_str ( conversations_json ) {
2022-01-16 19:24:22 +00:00
Ok ( cm ) = > cm ,
2022-01-17 23:24:58 +00:00
Err ( e ) = > return Err ( format! ( " invalid json: {:?} " , e ) ) ,
2022-01-16 19:24:22 +00:00
} ;
2022-04-06 04:11:37 +00:00
for conversation in conversations_map {
conversations . insert ( conversation . handle . clone ( ) , conversation ) ;
2021-09-04 03:36:35 +00:00
}
2022-04-06 04:11:37 +00:00
Ok ( conversations )
2021-09-04 03:36:35 +00:00
}
2022-01-16 19:24:22 +00:00
fn process_servers ( servers_json : & str ) -> Result < HashMap < String , Server > , String > {
2021-09-04 03:36:35 +00:00
let mut servers : HashMap < String , Server > = HashMap ::new ( ) ;
if servers_json = = " null " {
2022-01-16 19:24:22 +00:00
return Ok ( servers ) ;
2021-09-04 03:36:35 +00:00
}
2022-01-16 19:24:22 +00:00
let servers_map : Vec < Server > = match serde_json ::from_str ( servers_json ) {
Ok ( sm ) = > sm ,
2022-01-17 23:24:58 +00:00
Err ( e ) = > return Err ( format! ( " invalid json: {:?} " , e ) ) ,
2022-01-16 19:24:22 +00:00
} ;
2021-09-04 03:36:35 +00:00
for server in servers_map {
servers . insert ( server . onion . clone ( ) , server ) ;
}
2022-01-16 19:24:22 +00:00
Ok ( servers )
2021-09-04 03:36:35 +00:00
}
2021-09-16 01:57:36 +00:00
}