2020-09-12 13:49:20 +00:00
import { decode_identity , IdentitifyType , Identity } from "../profiles/Identity" ;
import { guid } from "../crypto/uid" ;
import { TeaForumIdentity } from "../profiles/identities/TeaForumIdentity" ;
import { TeaSpeakIdentity } from "../profiles/identities/TeamSpeakIdentity" ;
import { AbstractServerConnection } from "../connection/ConnectionBase" ;
import { HandshakeIdentityHandler } from "../connection/HandshakeHandler" ;
import { createErrorModal } from "../ui/elements/Modal" ;
import { formatMessage } from "../ui/frames/chat" ;
2020-03-30 11:44:18 +00:00
export class ConnectionProfile {
id : string ;
profile_name : string ;
default_username : string ;
default_password : string ;
selected_identity_type : string = "unset" ;
identities : { [ key : string ] : Identity } = { } ;
constructor ( id : string ) {
this . id = id ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
connect_username ( ) : string {
if ( this . default_username && this . default_username !== "Another TeaSpeak user" )
return this . default_username ;
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
let selected = this . selected_identity ( ) ;
let name = selected ? selected . fallback_name ( ) : undefined ;
return name || "Another TeaSpeak user" ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
selected_identity ( current_type? : IdentitifyType ) : Identity {
if ( ! current_type )
current_type = this . selected_type ( ) ;
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
if ( current_type === undefined )
return undefined ;
2019-10-19 15:13:40 +00:00
2020-03-30 11:44:18 +00:00
if ( current_type == IdentitifyType . TEAFORO ) {
return TeaForumIdentity . identity ( ) ;
} else if ( current_type == IdentitifyType . TEAMSPEAK || current_type == IdentitifyType . NICKNAME ) {
return this . identities [ IdentitifyType [ current_type ] . toLowerCase ( ) ] ;
2020-03-29 10:54:15 +00:00
}
2019-10-19 15:13:40 +00:00
2020-03-30 11:44:18 +00:00
return undefined ;
}
2019-01-19 12:42:18 +00:00
2020-03-30 11:44:18 +00:00
selected_type ? ( ) : IdentitifyType {
return this . selected_identity_type ? IdentitifyType [ this . selected_identity_type . toUpperCase ( ) ] : undefined ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
set_identity ( type : IdentitifyType , identity : Identity ) {
this . identities [ IdentitifyType [ type ] . toLowerCase ( ) ] = identity ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
spawn_identity_handshake_handler ? ( connection : AbstractServerConnection ) : HandshakeIdentityHandler {
const identity = this . selected_identity ( ) ;
if ( ! identity )
2018-12-28 14:39:23 +00:00
return undefined ;
2020-03-30 11:44:18 +00:00
return identity . spawn_identity_handshake_handler ( connection ) ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
encode ? ( ) : string {
const identity_data = { } ;
for ( const key in this . identities )
if ( this . identities [ key ] )
identity_data [ key ] = this . identities [ key ] . encode ( ) ;
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
return JSON . stringify ( {
version : 1 ,
username : this.default_username ,
password : this.default_password ,
profile_name : this.profile_name ,
identity_type : this.selected_identity_type ,
identity_data : identity_data ,
id : this.id
} ) ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
valid ( ) : boolean {
const identity = this . selected_identity ( ) ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
return ! ! identity && identity . valid ( ) ;
2018-12-28 14:39:23 +00:00
}
2020-03-30 11:44:18 +00:00
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
async function decode_profile ( data ) : Promise < ConnectionProfile | string > {
data = JSON . parse ( data ) ;
if ( data . version !== 1 )
return "invalid version" ;
2020-03-27 15:15:15 +00:00
2020-03-30 11:44:18 +00:00
const result : ConnectionProfile = new ConnectionProfile ( data . id ) ;
result . default_username = data . username ;
result . default_password = data . password ;
result . profile_name = data . profile_name ;
result . selected_identity_type = ( data . identity_type || "" ) . toLowerCase ( ) ;
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
if ( data . identity_data ) {
for ( const key of Object . keys ( data . identity_data ) ) {
const type = IdentitifyType [ key . toUpperCase ( ) as string ] ;
const _data = data . identity_data [ key ] ;
if ( type == undefined ) continue ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
const identity = await decode_identity ( type , _data ) ;
if ( identity == undefined ) continue ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
result . identities [ key . toLowerCase ( ) ] = identity ;
2020-03-29 10:54:15 +00:00
}
2020-03-27 22:36:57 +00:00
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
return result ;
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
interface ProfilesData {
version : number ;
profiles : string [ ] ;
}
2020-03-27 15:15:15 +00:00
2020-03-30 11:44:18 +00:00
let available_profiles : ConnectionProfile [ ] = [ ] ;
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
export async function load() {
available_profiles = [ ] ;
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
const profiles_json = localStorage . getItem ( "profiles" ) ;
let profiles_data : ProfilesData = ( ( ) = > {
try {
return profiles_json ? JSON . parse ( profiles_json ) : { version : 0 } as any ;
} catch ( error ) {
debugger ;
console . error ( tr ( "Invalid profile json! Resetting profiles :( (%o)" ) , profiles_json ) ;
createErrorModal ( tr ( "Profile data invalid" ) , formatMessage ( tr ( "The profile data is invalid.{:br:}This might cause data loss." ) ) ) . open ( ) ;
return { version : 0 } ;
2020-03-27 22:36:57 +00:00
}
2020-03-30 11:44:18 +00:00
} ) ( ) ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
if ( profiles_data . version === 0 ) {
profiles_data = {
2020-03-27 22:36:57 +00:00
version : 1 ,
2020-03-30 11:44:18 +00:00
profiles : [ ]
} ;
2020-03-29 10:54:15 +00:00
}
2020-03-30 11:44:18 +00:00
if ( profiles_data . version == 1 ) {
for ( const profile_data of profiles_data . profiles ) {
const profile = await decode_profile ( profile_data ) ;
2020-07-19 15:12:41 +00:00
if ( typeof profile === "string" ) {
2020-03-30 11:44:18 +00:00
console . error ( tr ( "Failed to load profile. Reason: %s, Profile data: %s" ) , profile , profiles_data ) ;
2020-07-19 15:12:41 +00:00
} else {
available_profiles . push ( profile as ConnectionProfile ) ;
2020-03-30 11:44:18 +00:00
}
}
2020-03-29 10:54:15 +00:00
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
if ( ! find_profile ( "default" ) ) { //Create a default profile and teaforo profile
{
const profile = create_new_profile ( "default" , "default" ) ;
profile . default_password = "" ;
profile . default_username = "" ;
profile . profile_name = "Default Profile" ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
/* generate default identity */
try {
const identity = await TeaSpeakIdentity . generate_new ( ) ;
let active = true ;
setTimeout ( ( ) = > {
active = false ;
} , 1000 ) ;
await identity . improve_level ( 8 , 1 , ( ) = > active ) ;
profile . set_identity ( IdentitifyType . TEAMSPEAK , identity ) ;
profile . selected_identity_type = IdentitifyType [ IdentitifyType . TEAMSPEAK ] ;
} catch ( error ) {
createErrorModal ( tr ( "Failed to generate default identity" ) , tr ( "Failed to generate default identity!<br>Please manually generate the identity within your settings => profiles" ) ) . open ( ) ;
}
}
2018-12-28 14:39:23 +00:00
2020-03-30 11:44:18 +00:00
{ /* forum identity (works only when connected to the forum) */
const profile = create_new_profile ( "TeaSpeak Forum" , "teaforo" ) ;
profile . default_password = "" ;
profile . default_username = "" ;
profile . profile_name = "TeaSpeak Forum profile" ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
profile . set_identity ( IdentitifyType . TEAFORO , TeaForumIdentity . identity ( ) ) ;
profile . selected_identity_type = IdentitifyType [ IdentitifyType . TEAFORO ] ;
}
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
save ( ) ;
2018-12-28 14:39:23 +00:00
}
2020-03-30 11:44:18 +00:00
}
export function create_new_profile ( name : string , id? : string ) : ConnectionProfile {
const profile = new ConnectionProfile ( id || guid ( ) ) ;
profile . profile_name = name ;
profile . default_username = "" ;
available_profiles . push ( profile ) ;
return profile ;
}
let _requires_save = false ;
export function save() {
const profiles : string [ ] = [ ] ;
for ( const profile of available_profiles )
profiles . push ( profile . encode ( ) ) ;
const data = JSON . stringify ( {
version : 1 ,
profiles : profiles
} ) ;
localStorage . setItem ( "profiles" , data ) ;
}
export function mark_need_save() {
_requires_save = true ;
}
export function requires_save ( ) : boolean {
return _requires_save ;
}
export function profiles ( ) : ConnectionProfile [ ] {
return available_profiles ;
}
export function find_profile ( id : string ) : ConnectionProfile | undefined {
for ( const profile of profiles ( ) )
if ( profile . id == id )
return profile ;
return undefined ;
}
export function find_profile_by_name ( name : string ) : ConnectionProfile | undefined {
name = name . toLowerCase ( ) ;
for ( const profile of profiles ( ) )
if ( ( profile . profile_name || "" ) . toLowerCase ( ) == name )
return profile ;
return undefined ;
}
export function default_profile ( ) : ConnectionProfile {
return find_profile ( "default" ) ;
}
export function set_default_profile ( profile : ConnectionProfile ) {
const old_default = default_profile ( ) ;
if ( old_default && old_default != profile ) {
old_default . id = guid ( ) ;
2020-03-29 10:54:15 +00:00
}
2020-03-30 11:44:18 +00:00
profile . id = "default" ;
return old_default ;
}
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
export function delete_profile ( profile : ConnectionProfile ) {
available_profiles . remove ( profile ) ;
2020-08-22 15:50:38 +00:00
}
window . addEventListener ( "beforeunload" , event = > {
if ( requires_save ( ) )
save ( ) ;
} ) ;