2020-09-12 13:49:20 +00:00
import * as log from "../log" ;
import { LogCategory } from "../log" ;
import { AbstractServerConnection , CommandOptions , ServerCommand } from "../connection/ConnectionBase" ;
import { Sound } from "../sound/Sounds" ;
import { CommandResult } from "../connection/ServerConnectionDeclaration" ;
import { createErrorModal , createInfoModal , createInputModal , createModal } from "../ui/elements/Modal" ;
2020-03-30 11:44:18 +00:00
import {
ClientConnectionInfo ,
ClientEntry ,
ClientType ,
LocalClientEntry ,
MusicClientEntry ,
SongInfo
2020-09-12 13:49:20 +00:00
} from "../tree/Client" ;
import { ChannelEntry } from "../tree/Channel" ;
import { ConnectionHandler , ConnectionState , DisconnectReason , ViewReasonId } from "../ConnectionHandler" ;
import { formatMessage } from "../ui/frames/chat" ;
import { spawnPoke } from "../ui/modal/ModalPoke" ;
import { AbstractCommandHandler , AbstractCommandHandlerBoss } from "../connection/AbstractCommandHandler" ;
import { batch_updates , BatchUpdateType , flush_batched_updates } from "../ui/react-elements/ReactComponentBase" ;
import { OutOfViewClient } from "../ui/frames/side/PrivateConversationManager" ;
import { renderBBCodeAsJQuery } from "../text/bbcode" ;
import { tr } from "../i18n/localize" ;
import { EventClient , EventType } from "../ui/frames/log/Definitions" ;
import { ErrorCode } from "../connection/ErrorCode" ;
2020-09-24 09:24:31 +00:00
import { server_connections } from "tc-shared/ConnectionManager" ;
2020-03-30 11:44:18 +00:00
export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss {
constructor ( connection : AbstractServerConnection ) {
super ( connection ) ;
}
}
export class ConnectionCommandHandler extends AbstractCommandHandler {
readonly connection : AbstractServerConnection ;
readonly connection_handler : ConnectionHandler ;
constructor ( connection : AbstractServerConnection ) {
super ( connection ) ;
this . connection_handler = connection . client ;
this [ "error" ] = this . handleCommandResult ;
this [ "channellist" ] = this . handleCommandChannelList ;
this [ "channellistfinished" ] = this . handleCommandChannelListFinished ;
this [ "notifychannelcreated" ] = this . handleCommandChannelCreate ;
this [ "notifychanneldeleted" ] = this . handleCommandChannelDelete ;
this [ "notifychannelhide" ] = this . handleCommandChannelHide ;
this [ "notifychannelshow" ] = this . handleCommandChannelShow ;
this [ "notifyserverconnectioninfo" ] = this . handleNotifyServerConnectionInfo ;
this [ "notifyconnectioninfo" ] = this . handleNotifyConnectionInfo ;
this [ "notifycliententerview" ] = this . handleCommandClientEnterView ;
this [ "notifyclientleftview" ] = this . handleCommandClientLeftView ;
this [ "notifyclientmoved" ] = this . handleNotifyClientMoved ;
this [ "initserver" ] = this . handleCommandServerInit ;
this [ "notifychannelmoved" ] = this . handleNotifyChannelMoved ;
this [ "notifychanneledited" ] = this . handleNotifyChannelEdited ;
this [ "notifytextmessage" ] = this . handleNotifyTextMessage ;
this [ "notifyclientchatcomposing" ] = this . notifyClientChatComposing ;
this [ "notifyclientchatclosed" ] = this . handleNotifyClientChatClosed ;
this [ "notifyclientupdated" ] = this . handleNotifyClientUpdated ;
this [ "notifyserveredited" ] = this . handleNotifyServerEdited ;
this [ "notifyserverupdated" ] = this . handleNotifyServerUpdated ;
this [ "notifyclientpoke" ] = this . handleNotifyClientPoke ;
this [ "notifymusicplayerinfo" ] = this . handleNotifyMusicPlayerInfo ;
this [ "notifyservergroupclientadded" ] = this . handleNotifyServerGroupClientAdd ;
this [ "notifyservergroupclientdeleted" ] = this . handleNotifyServerGroupClientRemove ;
this [ "notifyclientchannelgroupchanged" ] = this . handleNotifyClientChannelGroupChanged ;
this [ "notifychannelsubscribed" ] = this . handleNotifyChannelSubscribed ;
this [ "notifychannelunsubscribed" ] = this . handleNotifyChannelUnsubscribed ;
2020-07-12 14:31:57 +00:00
//this["notifyconversationhistory"] = this.handleNotifyConversationHistory;
//this["notifyconversationmessagedelete"] = this.handleNotifyConversationMessageDelete;
2020-03-30 11:44:18 +00:00
this [ "notifymusicstatusupdate" ] = this . handleNotifyMusicStatusUpdate ;
this [ "notifymusicplayersongchange" ] = this . handleMusicPlayerSongChange ;
this [ "notifyplaylistsongadd" ] = this . handleNotifyPlaylistSongAdd ;
this [ "notifyplaylistsongremove" ] = this . handleNotifyPlaylistSongRemove ;
this [ "notifyplaylistsongreorder" ] = this . handleNotifyPlaylistSongReorder ;
this [ "notifyplaylistsongloaded" ] = this . handleNotifyPlaylistSongLoaded ;
}
2020-07-21 22:55:28 +00:00
private loggable_invoker ( unique_id , client_id , name ) : EventClient | undefined {
2020-03-30 11:44:18 +00:00
const id = parseInt ( client_id ) ;
if ( typeof ( client_id ) === "undefined" || Number . isNaN ( id ) )
return undefined ;
if ( id == 0 )
return {
client_id : 0 ,
client_unique_id : this.connection_handler.channelTree.server.properties.virtualserver_unique_identifier ,
client_name : this.connection_handler.channelTree.server.properties.virtualserver_name ,
} ;
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
return {
client_unique_id : unique_id ,
client_name : name ,
client_id : client_id
} ;
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
proxy_command_promise ( promise : Promise < CommandResult > , options : CommandOptions ) {
if ( ! options . process_result )
return promise ;
return promise . catch ( ex = > {
if ( options . process_result ) {
if ( ex instanceof CommandResult ) {
let res = ex ;
if ( ! res . success ) {
2020-08-22 20:23:19 +00:00
if ( res . id == ErrorCode . SERVER_INSUFFICIENT_PERMISSIONS ) { //Permission error
2020-03-30 11:44:18 +00:00
const permission = this . connection_handler . permissions . resolveInfo ( res . json [ "failed_permid" ] as number ) ;
res . message = tr ( "Insufficient client permissions. Failed on permission " ) + ( permission ? permission . name : "unknown" ) ;
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . ERROR_PERMISSION , {
2020-03-30 11:44:18 +00:00
permission : this.connection_handler.permissions.resolveInfo ( res . json [ "failed_permid" ] as number )
} ) ;
this . connection_handler . sound . play ( Sound . ERROR_INSUFFICIENT_PERMISSIONS ) ;
2020-08-22 20:23:19 +00:00
} else if ( res . id != ErrorCode . DATABASE_EMPTY_RESULT ) {
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . ERROR_CUSTOM , {
2020-03-30 11:44:18 +00:00
message : res.extra_message.length == 0 ? res.message : res.extra_message
} ) ;
}
}
} else if ( typeof ( ex ) === "string" ) {
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . CONNECTION_COMMAND_ERROR , { error : ex } ) ;
2020-03-30 11:44:18 +00:00
} else {
log . error ( LogCategory . NETWORKING , tr ( "Invalid promise result type: %s. Result: %o" ) , typeof ( ex ) , ex ) ;
}
}
return Promise . reject ( ex ) ;
} ) ;
}
handle_command ( command : ServerCommand ) : boolean {
if ( this [ command . command ] ) {
2020-04-18 17:37:30 +00:00
/* batch all updates the command applies to the channel tree */
batch_updates ( BatchUpdateType . CHANNEL_TREE ) ;
try {
this [ command . command ] ( command . arguments ) ;
} finally {
flush_batched_updates ( BatchUpdateType . CHANNEL_TREE ) ;
}
2020-03-30 11:44:18 +00:00
return true ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
return false ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
set_handler ( command : string , handler : any ) {
this [ command ] = handler ;
}
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
unset_handler ( command : string , handler? : any ) {
if ( handler && this [ command ] != handler ) return ;
this [ command ] = undefined ;
}
handleCommandResult ( json ) {
2020-06-10 16:13:56 +00:00
let code : string = json [ 0 ] [ "return_code" ] ;
2020-03-30 11:44:18 +00:00
if ( ! code || code . length == 0 ) {
log . warn ( LogCategory . NETWORKING , tr ( "Invalid return code! (%o)" ) , json ) ;
return ;
}
2020-07-23 22:29:36 +00:00
let retListeners = this . connection [ "_retListener" ] || this . connection [ "returnListeners" ] ;
2020-03-30 11:44:18 +00:00
for ( let e of retListeners ) {
if ( e . code != code ) continue ;
retListeners . remove ( e ) ;
let result = new CommandResult ( json ) ;
if ( result . success )
e . resolve ( result ) ;
else
e . reject ( result ) ;
break ;
2019-02-23 13:15:22 +00:00
}
}
2020-03-30 11:44:18 +00:00
handleCommandServerInit ( json ) {
json = json [ 0 ] ; //Only one bulk
2019-10-24 16:04:41 +00:00
2020-06-12 17:33:05 +00:00
this . connection . client . initializeLocalClient ( parseInt ( json [ "aclid" ] ) , json [ "acn" ] ) ;
2020-03-30 11:44:18 +00:00
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
for ( let key in json ) {
if ( key === "aclid" ) continue ;
if ( key === "acn" ) continue ;
updates . push ( { key : key , value : json [ key ] } ) ;
2019-10-24 16:04:41 +00:00
}
2020-03-30 11:44:18 +00:00
this . connection . client . channelTree . server . updateVariables ( false , . . . updates ) ;
const properties = this . connection . client . channelTree . server . properties ;
/* host message */
if ( properties . virtualserver_hostmessage_mode > 0 ) {
if ( properties . virtualserver_hostmessage_mode == 1 ) {
/* show in log */
2020-04-11 08:57:52 +00:00
if ( properties . virtualserver_hostmessage )
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . SERVER_HOST_MESSAGE , {
2020-04-11 08:57:52 +00:00
message : properties.virtualserver_hostmessage
} ) ;
2020-03-30 11:44:18 +00:00
} else {
/* create modal/create modal and quit */
2020-04-11 08:57:52 +00:00
if ( properties . virtualserver_hostmessage || properties . virtualserver_hostmessage_mode == 3 )
createModal ( {
header : tr ( "Host message" ) ,
2020-07-19 14:34:08 +00:00
body : renderBBCodeAsJQuery ( properties . virtualserver_hostmessage , { convertSingleUrls : false } ) ,
2020-04-11 08:57:52 +00:00
footer : undefined
} ) . open ( ) ;
2020-03-30 11:44:18 +00:00
if ( properties . virtualserver_hostmessage_mode == 3 ) {
/* first let the client initialize his stuff */
setTimeout ( ( ) = > {
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . SERVER_HOST_MESSAGE_DISCONNECT , {
2020-03-30 11:44:18 +00:00
message : properties.virtualserver_welcomemessage
} ) ;
2019-10-24 16:04:41 +00:00
2020-03-30 11:44:18 +00:00
this . connection . disconnect ( "host message disconnect" ) ;
this . connection_handler . handleDisconnect ( DisconnectReason . SERVER_HOSTMESSAGE ) ;
this . connection_handler . sound . play ( Sound . CONNECTION_DISCONNECTED ) ;
} , 100 ) ;
2019-04-18 11:19:08 +00:00
}
2020-03-30 11:44:18 +00:00
}
}
2019-04-18 11:19:08 +00:00
2020-03-30 11:44:18 +00:00
/* welcome message */
if ( properties . virtualserver_welcomemessage ) {
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . SERVER_WELCOME_MESSAGE , {
2020-03-30 11:44:18 +00:00
message : properties.virtualserver_welcomemessage
2019-04-18 11:19:08 +00:00
} ) ;
}
2020-03-30 11:44:18 +00:00
/* priviledge key */
if ( properties . virtualserver_ask_for_privilegekey ) {
createInputModal ( tr ( "Use a privilege key" ) , tr ( "This is a newly created server for which administrator privileges have not yet been claimed.<br>Please enter the \"privilege key\" that was automatically generated when this server was created to gain administrator permissions." ) , message = > message . length > 0 , result = > {
if ( ! result ) return ;
2020-04-09 13:10:14 +00:00
const scon = server_connections . active_connection ( ) ;
2020-03-30 11:44:18 +00:00
if ( scon . serverConnection . connected )
scon . serverConnection . send_command ( "tokenuse" , {
token : result
} ) . then ( ( ) = > {
createInfoModal ( tr ( "Use privilege key" ) , tr ( "Privilege key successfully used!" ) ) . open ( ) ;
} ) . catch ( error = > {
createErrorModal ( tr ( "Use privilege key" ) , formatMessage ( tr ( "Failed to use privilege key: {}" ) , error instanceof CommandResult ? error.message : error ) ) . open ( ) ;
} ) ;
2020-04-02 22:15:47 +00:00
} , { field_placeholder : tr ( "Enter Privilege Key" ) } ) . open ( ) ;
2019-02-23 13:15:22 +00:00
}
2020-04-09 13:10:14 +00:00
this . connection . updateConnectionState ( ConnectionState . CONNECTED ) ;
2020-03-30 11:44:18 +00:00
}
handleNotifyServerConnectionInfo ( json ) {
json = json [ 0 ] ;
/* everything is a number, so lets parse it */
for ( const key of Object . keys ( json ) )
json [ key ] = parseFloat ( json [ key ] ) ;
this . connection_handler . channelTree . server . set_connection_info ( json ) ;
}
handleNotifyConnectionInfo ( json ) {
json = json [ 0 ] ;
const object = new ClientConnectionInfo ( ) ;
/* everything is a number (except ip), so lets parse it */
for ( const key of Object . keys ( json ) ) {
if ( key === "connection_client_ip" )
object [ key ] = json [ key ] ;
else
object [ key ] = parseFloat ( json [ key ] ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
const client = this . connection_handler . channelTree . findClient ( parseInt ( json [ "clid" ] ) ) ;
if ( ! client ) {
log . warn ( LogCategory . NETWORKING , tr ( "Received client connection info for unknown client (%o)" ) , json [ "clid" ] ) ;
return ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
client . set_connection_info ( object ) ;
}
private createChannelFromJson ( json , ignoreOrder : boolean = false ) {
let tree = this . connection . client . channelTree ;
2019-02-23 13:15:22 +00:00
2020-04-18 17:37:30 +00:00
let channel = new ChannelEntry ( parseInt ( json [ "cid" ] ) , json [ "channel_name" ] ) ;
let parent , previous ;
2020-03-30 11:44:18 +00:00
if ( json [ "channel_order" ] !== "0" ) {
2020-04-18 17:37:30 +00:00
previous = tree . findChannel ( json [ "channel_order" ] ) ;
if ( ! previous && json [ "channel_order" ] != 0 ) {
2020-03-30 11:44:18 +00:00
if ( ! ignoreOrder ) {
log . error ( LogCategory . NETWORKING , tr ( "Invalid channel order id!" ) ) ;
return ;
}
}
2020-04-18 17:37:30 +00:00
}
2019-02-23 13:15:22 +00:00
2020-04-18 17:37:30 +00:00
parent = tree . findChannel ( json [ "cpid" ] ) ;
if ( ! parent && json [ "cpid" ] != 0 ) {
log . error ( LogCategory . NETWORKING , tr ( "Invalid channel parent" ) ) ;
return ;
2020-03-30 11:44:18 +00:00
}
2020-04-18 17:37:30 +00:00
tree . insertChannel ( channel , previous , parent ) ;
2020-03-30 11:44:18 +00:00
if ( ignoreOrder ) {
for ( let ch of tree . channels ) {
if ( ch . properties . channel_order == channel . channelId ) {
2020-09-26 19:34:46 +00:00
tree . moveChannel ( ch , channel , channel . parent , true ) ; //Corrent the order :)
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
}
}
2020-03-30 11:44:18 +00:00
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
2020-09-26 19:34:46 +00:00
for ( let key of Object . keys ( json ) ) {
2020-03-30 11:44:18 +00:00
if ( key === "cid" ) continue ;
if ( key === "cpid" ) continue ;
if ( key === "invokerid" ) continue ;
if ( key === "invokername" ) continue ;
if ( key === "invokeruid" ) continue ;
if ( key === "reasonid" ) continue ;
updates . push ( { key : key , value : json [ key ] } ) ;
}
channel . updateVariables ( . . . updates ) ;
}
2019-02-23 13:15:22 +00:00
2020-04-18 17:37:30 +00:00
private batch_update_finished_timeout ;
2020-03-30 11:44:18 +00:00
handleCommandChannelList ( json ) {
2020-04-18 17:37:30 +00:00
if ( this . batch_update_finished_timeout ) {
clearTimeout ( this . batch_update_finished_timeout ) ;
this . batch_update_finished_timeout = 0 ;
/* batch update is still active */
} else {
batch_updates ( BatchUpdateType . CHANNEL_TREE ) ;
}
2020-03-30 11:44:18 +00:00
for ( let index = 0 ; index < json . length ; index ++ )
this . createChannelFromJson ( json [ index ] , true ) ;
2020-04-18 17:37:30 +00:00
this . batch_update_finished_timeout = setTimeout ( ( ) = > {
} , 500 ) ;
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-07-12 14:31:57 +00:00
handleCommandChannelListFinished() {
2020-09-27 14:49:04 +00:00
this . connection . client . channelTree . channelsInitialized = true ;
2020-11-07 12:16:07 +00:00
this . connection . client . channelTree . events . fire_react ( "notify_channel_list_received" ) ;
2020-07-12 14:31:57 +00:00
2020-04-18 17:37:30 +00:00
if ( this . batch_update_finished_timeout ) {
clearTimeout ( this . batch_update_finished_timeout ) ;
this . batch_update_finished_timeout = 0 ;
flush_batched_updates ( BatchUpdateType . CHANNEL_TREE ) ;
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelCreate ( json ) {
this . createChannelFromJson ( json [ 0 ] ) ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelShow ( json ) {
this . createChannelFromJson ( json [ 0 ] ) ; //TODO may chat?
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelDelete ( json ) {
let tree = this . connection . client . channelTree ;
const conversations = this . connection . client . side_bar . channel_conversations ( ) ;
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
log . info ( LogCategory . NETWORKING , tr ( "Got %d channel deletions" ) , json . length ) ;
for ( let index = 0 ; index < json . length ; index ++ ) {
2020-07-12 14:31:57 +00:00
conversations . destroyConversation ( parseInt ( json [ index ] [ "cid" ] ) ) ;
2020-03-30 11:44:18 +00:00
let channel = tree . findChannel ( json [ index ] [ "cid" ] ) ;
if ( ! channel ) {
log . error ( LogCategory . NETWORKING , tr ( "Invalid channel onDelete (Unknown channel)" ) ) ;
continue ;
2019-08-21 08:00:01 +00:00
}
2020-03-30 11:44:18 +00:00
tree . deleteChannel ( channel ) ;
}
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelHide ( json ) {
let tree = this . connection . client . channelTree ;
const conversations = this . connection . client . side_bar . channel_conversations ( ) ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
log . info ( LogCategory . NETWORKING , tr ( "Got %d channel hides" ) , json . length ) ;
for ( let index = 0 ; index < json . length ; index ++ ) {
2020-07-12 14:31:57 +00:00
conversations . destroyConversation ( parseInt ( json [ index ] [ "cid" ] ) ) ;
2020-03-30 11:44:18 +00:00
let channel = tree . findChannel ( json [ index ] [ "cid" ] ) ;
if ( ! channel ) {
log . error ( LogCategory . NETWORKING , tr ( "Invalid channel on hide (Unknown channel)" ) ) ;
continue ;
}
tree . deleteChannel ( channel ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleCommandClientEnterView ( json ) {
let tree = this . connection . client . channelTree ;
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
let client : ClientEntry ;
let channel = undefined ;
let old_channel = undefined ;
let reason_id , reason_msg ;
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
let invokerid , invokername , invokeruid ;
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
for ( const entry of json ) {
/* attempt to update properties if given */
channel = typeof ( entry [ "ctid" ] ) !== "undefined" ? tree . findChannel ( parseInt ( entry [ "ctid" ] ) ) : channel ;
old_channel = typeof ( entry [ "cfid" ] ) !== "undefined" ? tree . findChannel ( parseInt ( entry [ "cfid" ] ) ) : old_channel ;
reason_id = typeof ( entry [ "reasonid" ] ) !== "undefined" ? entry [ "reasonid" ] : reason_id ;
reason_msg = typeof ( entry [ "reason_msg" ] ) !== "undefined" ? entry [ "reason_msg" ] : reason_msg ;
2019-08-30 21:06:39 +00:00
2020-03-30 11:44:18 +00:00
invokerid = typeof ( entry [ "invokerid" ] ) !== "undefined" ? parseInt ( entry [ "invokerid" ] ) : invokerid ;
invokername = typeof ( entry [ "invokername" ] ) !== "undefined" ? entry [ "invokername" ] : invokername ;
invokeruid = typeof ( entry [ "invokeruid" ] ) !== "undefined" ? entry [ "invokeruid" ] : invokeruid ;
client = tree . findClient ( parseInt ( entry [ "clid" ] ) ) ;
2019-08-30 21:06:39 +00:00
if ( ! client ) {
2020-03-30 11:44:18 +00:00
if ( parseInt ( entry [ "client_type_exact" ] ) == ClientType . CLIENT_MUSIC ) {
client = new MusicClientEntry ( parseInt ( entry [ "clid" ] ) , entry [ "client_nickname" ] ) ;
} else {
client = new ClientEntry ( parseInt ( entry [ "clid" ] ) , entry [ "client_nickname" ] ) ;
}
2019-08-30 21:06:39 +00:00
2020-07-17 21:56:20 +00:00
/* TODO: Apply all other properties here as well and than register him */
client . properties . client_unique_identifier = entry [ "client_unique_identifier" ] ;
2020-03-30 11:44:18 +00:00
client . properties . client_type = parseInt ( entry [ "client_type" ] ) ;
2020-07-17 21:56:20 +00:00
client = tree . insertClient ( client , channel , { reason : reason_id , isServerJoin : parseInt ( entry [ "cfid" ] ) === 0 } ) ;
2020-03-30 11:44:18 +00:00
} else {
tree . moveClient ( client , channel ) ;
}
2019-08-30 21:06:39 +00:00
2020-04-11 09:43:41 +00:00
if ( this . connection_handler . areQueriesShown ( ) || client . properties . client_type != ClientType . CLIENT_QUERY ) {
2020-03-30 11:44:18 +00:00
const own_channel = this . connection . client . getClient ( ) . currentChannel ( ) ;
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( channel == own_channel ? EventType.CLIENT_VIEW_ENTER_OWN_CHANNEL : EventType.CLIENT_VIEW_ENTER , {
2020-03-30 11:44:18 +00:00
channel_from : old_channel ? old_channel . log_data ( ) : undefined ,
channel_to : channel ? channel . log_data ( ) : undefined ,
client : client.log_data ( ) ,
invoker : this.loggable_invoker ( invokeruid , invokerid , invokername ) ,
message :reason_msg ,
reason : parseInt ( reason_id ) ,
} ) ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
if ( reason_id == ViewReasonId . VREASON_USER_ACTION ) {
if ( own_channel == channel )
if ( old_channel )
this . connection_handler . sound . play ( Sound . USER_ENTERED ) ;
else
this . connection_handler . sound . play ( Sound . USER_ENTERED_CONNECT ) ;
} else if ( reason_id == ViewReasonId . VREASON_MOVED ) {
if ( own_channel == channel )
this . connection_handler . sound . play ( Sound . USER_ENTERED_MOVED ) ;
} else if ( reason_id == ViewReasonId . VREASON_CHANNEL_KICK ) {
if ( own_channel == channel )
this . connection_handler . sound . play ( Sound . USER_ENTERED_KICKED ) ;
} else if ( reason_id == ViewReasonId . VREASON_SYSTEM ) {
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
} else {
console . warn ( tr ( "Unknown reasonid for %o" ) , reason_id ) ;
2019-02-23 13:15:22 +00:00
}
}
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
2020-03-30 11:44:18 +00:00
2020-09-07 10:42:00 +00:00
for ( let key of Object . keys ( entry ) ) {
2020-03-30 11:44:18 +00:00
if ( key == "cfid" ) continue ;
if ( key == "ctid" ) continue ;
2019-02-23 13:15:22 +00:00
if ( key === "invokerid" ) continue ;
if ( key === "invokername" ) continue ;
if ( key === "invokeruid" ) continue ;
if ( key === "reasonid" ) continue ;
2020-03-30 11:44:18 +00:00
updates . push ( { key : key , value : entry [ key ] } ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
client . updateVariables ( . . . updates ) ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
if ( client instanceof LocalClientEntry ) {
client . initializeListener ( ) ;
this . connection_handler . update_voice_status ( ) ;
this . connection_handler . side_bar . info_frame ( ) . update_channel_talk ( ) ;
const conversations = this . connection . client . side_bar . channel_conversations ( ) ;
2020-07-12 14:31:57 +00:00
conversations . setSelectedConversation ( client . currentChannel ( ) . channelId ) ;
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleCommandClientLeftView ( json ) {
let reason_id = - 1 ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
for ( const entry of json ) {
reason_id = entry [ "reasonid" ] || reason_id ;
2019-02-23 13:15:22 +00:00
let tree = this . connection . client . channelTree ;
2020-03-30 11:44:18 +00:00
let client = tree . findClient ( entry [ "clid" ] ) ;
if ( ! client ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown client left!" ) ) ;
return 0 ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
if ( client == this . connection . client . getClient ( ) ) {
if ( reason_id == ViewReasonId . VREASON_BAN ) {
this . connection . client . handleDisconnect ( DisconnectReason . CLIENT_BANNED , entry ) ;
} else if ( reason_id == ViewReasonId . VREASON_SERVER_KICK ) {
this . connection . client . handleDisconnect ( DisconnectReason . CLIENT_KICKED , entry ) ;
} else if ( reason_id == ViewReasonId . VREASON_SERVER_SHUTDOWN ) {
this . connection . client . handleDisconnect ( DisconnectReason . SERVER_CLOSED , entry ) ;
} else if ( reason_id == ViewReasonId . VREASON_SERVER_STOPPED ) {
this . connection . client . handleDisconnect ( DisconnectReason . SERVER_CLOSED , entry ) ;
} else {
this . connection . client . handleDisconnect ( DisconnectReason . UNKNOWN , entry ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
this . connection_handler . side_bar . info_frame ( ) . update_channel_talk ( ) ;
return ;
2019-02-23 13:15:22 +00:00
}
2020-07-17 21:56:20 +00:00
const targetChannelId = parseInt ( entry [ "ctid" ] ) ;
2020-04-11 09:43:41 +00:00
if ( this . connection_handler . areQueriesShown ( ) || client . properties . client_type != ClientType . CLIENT_QUERY ) {
2020-03-30 11:44:18 +00:00
const own_channel = this . connection . client . getClient ( ) . currentChannel ( ) ;
let channel_from = tree . findChannel ( entry [ "cfid" ] ) ;
2020-07-17 21:56:20 +00:00
let channel_to = tree . findChannel ( targetChannelId ) ;
2020-03-30 11:44:18 +00:00
const is_own_channel = channel_from == own_channel ;
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( is_own_channel ? EventType.CLIENT_VIEW_LEAVE_OWN_CHANNEL : EventType.CLIENT_VIEW_LEAVE , {
2020-03-30 11:44:18 +00:00
channel_from : channel_from ? channel_from . log_data ( ) : undefined ,
channel_to : channel_to ? channel_to . log_data ( ) : undefined ,
client : client.log_data ( ) ,
invoker : this.loggable_invoker ( entry [ "invokeruid" ] , entry [ "invokerid" ] , entry [ "invokername" ] ) ,
message : entry [ "reasonmsg" ] ,
reason : parseInt ( entry [ "reasonid" ] ) ,
ban_time : parseInt ( entry [ "bantime" ] ) ,
} ) ;
2019-07-09 22:52:08 +00:00
2020-03-30 11:44:18 +00:00
if ( is_own_channel ) {
2019-04-15 13:33:51 +00:00
if ( reason_id == ViewReasonId . VREASON_USER_ACTION ) {
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . USER_LEFT ) ;
} else if ( reason_id == ViewReasonId . VREASON_SERVER_LEFT ) {
this . connection_handler . sound . play ( Sound . USER_LEFT_DISCONNECT ) ;
} else if ( reason_id == ViewReasonId . VREASON_SERVER_KICK ) {
this . connection_handler . sound . play ( Sound . USER_LEFT_KICKED_SERVER ) ;
2019-04-15 13:33:51 +00:00
} else if ( reason_id == ViewReasonId . VREASON_CHANNEL_KICK ) {
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . USER_LEFT_KICKED_CHANNEL ) ;
} else if ( reason_id == ViewReasonId . VREASON_BAN ) {
this . connection_handler . sound . play ( Sound . USER_LEFT_BANNED ) ;
} else if ( reason_id == ViewReasonId . VREASON_TIMEOUT ) {
this . connection_handler . sound . play ( Sound . USER_LEFT_TIMEOUT ) ;
} else if ( reason_id == ViewReasonId . VREASON_MOVED ) {
this . connection_handler . sound . play ( Sound . USER_LEFT_MOVED ) ;
2019-04-15 13:33:51 +00:00
} else {
2020-03-30 11:44:18 +00:00
log . error ( LogCategory . NETWORKING , tr ( "Unknown client left reason %d!" ) , reason_id ) ;
2019-04-15 13:33:51 +00:00
}
}
2019-04-04 19:47:52 +00:00
}
2019-04-15 13:33:51 +00:00
2020-07-17 21:56:20 +00:00
tree . deleteClient ( client , { reason : reason_id , message : entry [ "reasonmsg" ] , serverLeave : targetChannelId === 0 } ) ;
2020-03-27 22:36:57 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyClientMoved ( json ) {
json = json [ 0 ] ; //Only one bulk
let tree = this . connection . client . channelTree ;
let client = tree . findClient ( json [ "clid" ] ) ;
let self = client instanceof LocalClientEntry ;
2019-04-04 19:47:52 +00:00
2020-03-30 11:44:18 +00:00
let channel_to = tree . findChannel ( parseInt ( json [ "ctid" ] ) ) ;
2020-08-19 17:33:57 +00:00
let channelFrom = tree . findChannel ( parseInt ( json [ "cfid" ] ) ) ;
2019-10-24 16:24:28 +00:00
2020-03-30 11:44:18 +00:00
if ( ! client ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown client move (Client)!" ) ) ;
return 0 ;
}
2019-04-15 13:33:51 +00:00
2020-03-30 11:44:18 +00:00
if ( ! channel_to ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown client move (Channel to)!" ) ) ;
return 0 ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
if ( ! self ) {
2020-08-19 17:33:57 +00:00
if ( ! channelFrom ) {
2020-03-30 11:44:18 +00:00
log . error ( LogCategory . NETWORKING , tr ( "Unknown client move (Channel from)!" ) ) ;
2020-08-19 17:33:57 +00:00
channelFrom = client . currentChannel ( ) ;
} else if ( channelFrom != client . currentChannel ( ) ) {
2020-03-30 11:44:18 +00:00
log . error ( LogCategory . NETWORKING ,
tr ( "Client move from invalid source channel! Local client registered in channel %d but server send %d." ) ,
2020-08-19 17:33:57 +00:00
client . currentChannel ( ) . channelId , channelFrom . channelId
2020-03-30 11:44:18 +00:00
) ;
2019-04-15 13:33:51 +00:00
}
2020-03-30 11:44:18 +00:00
} else {
2020-08-19 17:33:57 +00:00
channelFrom = client . currentChannel ( ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
tree . moveClient ( client , channel_to ) ;
2019-09-12 21:59:35 +00:00
2020-03-30 11:44:18 +00:00
if ( self ) {
2020-09-12 12:51:03 +00:00
this . connection_handler . update_voice_status ( ) ;
2019-02-23 13:15:22 +00:00
2020-08-19 17:33:57 +00:00
for ( const entry of client . channelTree . clientsByChannel ( channelFrom ) ) {
2020-09-07 10:42:00 +00:00
entry . getVoiceClient ( ) ? . abortReplay ( ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
const side_bar = this . connection_handler . side_bar ;
side_bar . info_frame ( ) . update_channel_talk ( ) ;
2020-08-19 17:33:57 +00:00
} else {
client . speaking = false ;
2020-03-29 10:54:15 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
const own_channel = this . connection . client . getClient ( ) . currentChannel ( ) ;
2020-08-19 17:33:57 +00:00
const event = self ? EventType . CLIENT_VIEW_MOVE_OWN : ( channelFrom == own_channel || channel_to == own_channel ? EventType.CLIENT_VIEW_MOVE_OWN_CHANNEL : EventType.CLIENT_VIEW_MOVE ) ;
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( event , {
2020-08-19 17:33:57 +00:00
channel_from : channelFrom ? {
channel_id : channelFrom.channelId ,
channel_name : channelFrom.channelName ( )
2020-03-30 11:44:18 +00:00
} : undefined ,
2020-08-19 17:33:57 +00:00
channel_from_own : channelFrom == own_channel ,
2020-03-30 11:44:18 +00:00
channel_to : channel_to ? {
channel_id : channel_to.channelId ,
channel_name : channel_to.channelName ( )
} : undefined ,
channel_to_own : channel_to == own_channel ,
client : {
client_id : client.clientId ( ) ,
client_name : client.clientNickName ( ) ,
client_unique_id : client.properties.client_unique_identifier
} ,
client_own : self ,
invoker : this.loggable_invoker ( json [ "invokeruid" ] , json [ "invokerid" ] , json [ "invokername" ] ) ,
message : json [ "reasonmsg" ] ,
reason : parseInt ( json [ "reasonid" ] ) ,
} ) ;
if ( json [ "reasonid" ] == ViewReasonId . VREASON_MOVED ) {
if ( self )
this . connection_handler . sound . play ( Sound . USER_MOVED_SELF ) ;
else if ( own_channel == channel_to )
this . connection_handler . sound . play ( Sound . USER_ENTERED_MOVED ) ;
2020-08-19 17:33:57 +00:00
else if ( own_channel == channelFrom )
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . USER_LEFT_MOVED ) ;
} else if ( json [ "reasonid" ] == ViewReasonId . VREASON_USER_ACTION ) {
if ( self ) { } //If we do an action we wait for the error response
else if ( own_channel == channel_to )
this . connection_handler . sound . play ( Sound . USER_ENTERED ) ;
2020-08-19 17:33:57 +00:00
else if ( own_channel == channelFrom )
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . USER_LEFT ) ;
} else if ( json [ "reasonid" ] == ViewReasonId . VREASON_CHANNEL_KICK ) {
2019-08-21 08:00:01 +00:00
if ( self ) {
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . CHANNEL_KICKED ) ;
} else if ( own_channel == channel_to )
this . connection_handler . sound . play ( Sound . USER_ENTERED_KICKED ) ;
2020-08-19 17:33:57 +00:00
else if ( own_channel == channelFrom )
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . USER_LEFT_KICKED_CHANNEL ) ;
} else {
console . warn ( tr ( "Unknown reason id %o" ) , json [ "reasonid" ] ) ;
}
}
2019-12-20 20:17:45 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyChannelMoved ( json ) {
json = json [ 0 ] ; //Only one bulk
2019-12-20 20:17:45 +00:00
2020-03-30 11:44:18 +00:00
let tree = this . connection . client . channelTree ;
let channel = tree . findChannel ( json [ "cid" ] ) ;
if ( ! channel ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown channel move (Channel)!" ) ) ;
return 0 ;
2020-03-29 10:54:15 +00:00
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
let prev = tree . findChannel ( json [ "order" ] ) ;
if ( ! prev && json [ "order" ] != 0 ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown channel move (prev)!" ) ) ;
return 0 ;
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
let parent = tree . findChannel ( json [ "cpid" ] ) ;
if ( ! parent && json [ "cpid" ] != 0 ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown channel move (parent)!" ) ) ;
return 0 ;
}
2019-08-21 08:00:01 +00:00
2020-09-26 19:34:46 +00:00
tree . moveChannel ( channel , prev , parent , true ) ;
2020-03-30 11:44:18 +00:00
}
2019-07-09 22:52:08 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyChannelEdited ( json ) {
json = json [ 0 ] ; //Only one bulk
2019-07-09 22:52:08 +00:00
2020-03-30 11:44:18 +00:00
let tree = this . connection . client . channelTree ;
let channel = tree . findChannel ( json [ "cid" ] ) ;
if ( ! channel ) {
log . error ( LogCategory . NETWORKING , tr ( "Unknown channel edit (Channel)!" ) ) ;
return 0 ;
}
2019-07-09 22:52:08 +00:00
2020-03-30 11:44:18 +00:00
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
for ( let key in json ) {
if ( key === "cid" ) continue ;
if ( key === "invokerid" ) continue ;
if ( key === "invokername" ) continue ;
if ( key === "invokeruid" ) continue ;
if ( key === "reasonid" ) continue ;
updates . push ( { key : key , value : json [ key ] } ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
channel . updateVariables ( . . . updates ) ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
if ( this . connection_handler . getClient ( ) . currentChannel ( ) === channel ) {
//TODO: Playback sound that your channel has been edited
this . connection_handler . update_voice_status ( ) ;
}
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyTextMessage ( json ) {
json = json [ 0 ] ; //Only one bulk
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
let mode = json [ "targetmode" ] ;
if ( mode == 1 ) {
2020-07-17 21:56:20 +00:00
const targetClientId = parseInt ( json [ "target" ] ) ;
const invokerClientId = parseInt ( json [ "invokerid" ] ) ;
const targetClientEntry = this . connection_handler . channelTree . findClient ( targetClientId ) ;
const targetIsOwn = targetClientEntry instanceof LocalClientEntry ;
2019-02-23 13:15:22 +00:00
2020-07-17 21:56:20 +00:00
if ( targetIsOwn && targetClientId === invokerClientId ) {
log . error ( LogCategory . NETWORKING , tr ( "Received conversation message from our self. This should be impossible." ) , json ) ;
2020-03-30 11:44:18 +00:00
return ;
2019-02-23 13:15:22 +00:00
}
2020-07-17 21:56:20 +00:00
const partnerClientEntry = targetIsOwn ? this . connection . client . channelTree . findClient ( invokerClientId ) : targetClientEntry ;
const chatPartner = partnerClientEntry ? partnerClientEntry : {
clientId : targetIsOwn ? invokerClientId : targetClientId ,
nickname : targetIsOwn ? json [ "invokername" ] : undefined ,
uniqueId : targetIsOwn ? json [ "invokeruid" ] : undefined
} as OutOfViewClient ;
2020-03-29 10:54:15 +00:00
const conversation_manager = this . connection_handler . side_bar . private_conversations ( ) ;
2020-07-17 21:56:20 +00:00
const conversation = conversation_manager . findOrCreateConversation ( chatPartner ) ;
2019-02-23 13:15:22 +00:00
2020-07-17 21:56:20 +00:00
conversation . handleIncomingMessage ( chatPartner , ! targetIsOwn , {
sender_database_id : targetClientEntry ? targetClientEntry.properties.client_database_id : 0 ,
sender_name : json [ "invokername" ] ,
sender_unique_id : json [ "invokeruid" ] ,
2019-09-12 21:59:35 +00:00
2020-07-17 21:56:20 +00:00
timestamp : Date.now ( ) ,
message : json [ "msg" ]
} ) ;
if ( targetIsOwn ) {
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . MESSAGE_RECEIVED , { default_volume : .5 } ) ;
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . PRIVATE_MESSAGE_RECEIVED , {
message : json [ "msg" ] ,
sender : {
client_unique_id : json [ "invokeruid" ] ,
client_name : json [ "invokername" ] ,
client_id : parseInt ( json [ "invokerid" ] )
}
} ) ;
2020-03-30 11:44:18 +00:00
} else {
this . connection_handler . sound . play ( Sound . MESSAGE_SEND , { default_volume : .5 } ) ;
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . PRIVATE_MESSAGE_SEND , {
message : json [ "msg" ] ,
target : {
client_unique_id : json [ "invokeruid" ] ,
client_name : json [ "invokername" ] ,
client_id : parseInt ( json [ "invokerid" ] )
}
} ) ;
2020-03-30 11:44:18 +00:00
}
2020-07-17 21:56:20 +00:00
this . connection_handler . side_bar . info_frame ( ) . update_chat_counter ( ) ;
2020-03-30 11:44:18 +00:00
} else if ( mode == 2 ) {
const invoker = this . connection_handler . channelTree . findClient ( parseInt ( json [ "invokerid" ] ) ) ;
const own_channel_id = this . connection . client . getClient ( ) . currentChannel ( ) . channelId ;
const channel_id = typeof ( json [ "cid" ] ) !== "undefined" ? parseInt ( json [ "cid" ] ) : own_channel_id ;
2020-06-12 17:33:05 +00:00
if ( json [ "invokerid" ] == this . connection . client . getClientId ( ) )
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . MESSAGE_SEND , { default_volume : .5 } ) ;
else if ( channel_id == own_channel_id ) {
this . connection_handler . sound . play ( Sound . MESSAGE_RECEIVED , { default_volume : .5 } ) ;
2019-09-12 21:59:35 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
const conversations = this . connection_handler . side_bar . channel_conversations ( ) ;
2020-07-12 14:31:57 +00:00
conversations . findOrCreateConversation ( channel_id ) . handleIncomingMessage ( {
2020-03-30 11:44:18 +00:00
sender_database_id : invoker ? invoker.properties.client_database_id : 0 ,
sender_name : json [ "invokername" ] ,
sender_unique_id : json [ "invokeruid" ] ,
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
timestamp : typeof ( json [ "timestamp" ] ) === "undefined" ? Date . now ( ) : parseInt ( json [ "timestamp" ] ) ,
2020-07-17 21:56:20 +00:00
message : json [ "msg" ]
} , invoker instanceof LocalClientEntry ) ;
2020-03-30 11:44:18 +00:00
} else if ( mode == 3 ) {
2020-07-21 22:55:28 +00:00
const invoker = this . connection_handler . channelTree . findClient ( parseInt ( json [ "invokerid" ] ) ) ;
const conversations = this . connection_handler . side_bar . channel_conversations ( ) ;
this . connection_handler . log . log ( EventType . GLOBAL_MESSAGE , {
isOwnMessage : invoker instanceof LocalClientEntry ,
2020-03-30 11:44:18 +00:00
message : json [ "msg" ] ,
sender : {
client_unique_id : json [ "invokeruid" ] ,
client_name : json [ "invokername" ] ,
client_id : parseInt ( json [ "invokerid" ] )
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
} ) ;
2019-08-21 08:00:01 +00:00
2020-07-12 14:31:57 +00:00
conversations . findOrCreateConversation ( 0 ) . handleIncomingMessage ( {
2020-03-30 11:44:18 +00:00
sender_database_id : invoker ? invoker.properties.client_database_id : 0 ,
sender_name : json [ "invokername" ] ,
sender_unique_id : json [ "invokeruid" ] ,
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
timestamp : typeof ( json [ "timestamp" ] ) === "undefined" ? Date . now ( ) : parseInt ( json [ "timestamp" ] ) ,
2020-07-17 21:56:20 +00:00
message : json [ "msg" ]
} , invoker instanceof LocalClientEntry ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
notifyClientChatComposing ( json ) {
json = json [ 0 ] ;
const conversation_manager = this . connection_handler . side_bar . private_conversations ( ) ;
2020-07-17 21:56:20 +00:00
const conversation = conversation_manager . findConversation ( json [ "cluid" ] ) ;
conversation ? . handleRemoteComposing ( parseInt ( json [ "clid" ] ) ) ;
2020-03-30 11:44:18 +00:00
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyClientChatClosed ( json ) {
json = json [ 0 ] ; //Only one bulk
const conversation_manager = this . connection_handler . side_bar . private_conversations ( ) ;
2020-07-17 21:56:20 +00:00
const conversation = conversation_manager . findConversation ( json [ "cluid" ] ) ;
2020-03-30 11:44:18 +00:00
if ( ! conversation ) {
log . warn ( LogCategory . GENERAL , tr ( "Received chat close for client, but we haven't a chat open." ) ) ;
return ;
2019-02-23 13:15:22 +00:00
}
2020-07-17 21:56:20 +00:00
conversation . handleChatRemotelyClosed ( parseInt ( json [ "clid" ] ) ) ;
2020-03-30 11:44:18 +00:00
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyClientUpdated ( json ) {
json = json [ 0 ] ; //Only one bulk
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
let client = this . connection . client . channelTree . findClient ( json [ "clid" ] ) ;
if ( ! client ) {
log . error ( LogCategory . NETWORKING , tr ( "Tried to update an non existing client" ) ) ;
return ;
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
for ( let key in json ) {
if ( key == "clid" ) continue ;
updates . push ( { key : key , value : json [ key ] } ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
client . updateVariables ( . . . updates ) ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyServerEdited ( json ) {
json = json [ 0 ] ;
2019-08-30 21:06:39 +00:00
2020-03-30 11:44:18 +00:00
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
for ( let key in json ) {
if ( key === "invokerid" ) continue ;
if ( key === "invokername" ) continue ;
if ( key === "invokeruid" ) continue ;
if ( key === "reasonid" ) continue ;
2019-08-30 21:06:39 +00:00
2020-03-30 11:44:18 +00:00
updates . push ( { key : key , value : json [ key ] } ) ;
2019-08-30 21:06:39 +00:00
}
2020-03-30 11:44:18 +00:00
this . connection . client . channelTree . server . updateVariables ( false , . . . updates ) ;
}
2019-08-30 21:06:39 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyServerUpdated ( json ) {
json = json [ 0 ] ;
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
let updates : {
key : string ,
value : string
} [ ] = [ ] ;
for ( let key in json ) {
if ( key === "invokerid" ) continue ;
if ( key === "invokername" ) continue ;
if ( key === "invokeruid" ) continue ;
if ( key === "reasonid" ) continue ;
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
updates . push ( { key : key , value : json [ key ] } ) ;
2019-03-17 11:15:39 +00:00
}
2020-03-30 11:44:18 +00:00
this . connection . client . channelTree . server . updateVariables ( true , . . . updates ) ;
}
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyMusicPlayerInfo ( json ) {
json = json [ 0 ] ;
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
let bot = this . connection . client . channelTree . find_client_by_dbid ( json [ "bot_id" ] ) ;
if ( ! bot || ! ( bot instanceof MusicClientEntry ) ) {
log . warn ( LogCategory . CLIENT , tr ( "Got music player info for unknown or invalid bot! (ID: %i, Entry: %o)" ) , json [ "bot_id" ] , bot ) ;
return ;
2019-03-17 11:15:39 +00:00
}
2020-03-30 11:44:18 +00:00
bot . handlePlayerInfo ( json ) ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyClientPoke ( json ) {
json = json [ 0 ] ;
spawnPoke ( this . connection_handler , {
id : parseInt ( json [ "invokerid" ] ) ,
name : json [ "invokername" ] ,
unique_id : json [ "invokeruid" ]
} , json [ "msg" ] ) ;
2019-02-23 13:15:22 +00:00
2020-07-21 22:55:28 +00:00
this . connection_handler . log . log ( EventType . CLIENT_POKE_RECEIVED , {
sender : this.loggable_invoker ( json [ "invokeruid" ] , json [ "invokerid" ] , json [ "invokername" ] ) ,
message : json [ "msg" ]
} ) ;
2020-03-30 11:44:18 +00:00
this . connection_handler . sound . play ( Sound . USER_POKED_SELF ) ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
//TODO server chat message
handleNotifyServerGroupClientAdd ( json ) {
json = json [ 0 ] ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
const self = this . connection . client . getClient ( ) ;
if ( json [ "clid" ] == self . clientId ( ) )
this . connection_handler . sound . play ( Sound . GROUP_SERVER_ASSIGNED_SELF ) ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
//TODO server chat message
handleNotifyServerGroupClientRemove ( json ) {
json = json [ 0 ] ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
const self = this . connection . client . getClient ( ) ;
if ( json [ "clid" ] == self . clientId ( ) ) {
this . connection_handler . sound . play ( Sound . GROUP_SERVER_REVOKED_SELF ) ;
} else {
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
//TODO server chat message
handleNotifyClientChannelGroupChanged ( json ) {
json = json [ 0 ] ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
const self = this . connection . client . getClient ( ) ;
if ( json [ "clid" ] == self . clientId ( ) ) {
this . connection_handler . sound . play ( Sound . GROUP_CHANNEL_CHANGED_SELF ) ;
2019-08-21 08:00:01 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyChannelSubscribed ( json ) {
2020-04-18 17:37:30 +00:00
batch_updates ( BatchUpdateType . CHANNEL_TREE ) ;
try {
for ( const entry of json ) {
const channel = this . connection . client . channelTree . findChannel ( parseInt ( entry [ "cid" ] ) ) ;
if ( ! channel ) {
console . warn ( tr ( "Received channel subscribed for not visible channel (cid: %d)" ) , entry [ 'cid' ] ) ;
continue ;
}
2019-02-23 13:15:22 +00:00
2020-04-18 17:37:30 +00:00
channel . flag_subscribed = true ;
}
} finally {
flush_batched_updates ( BatchUpdateType . CHANNEL_TREE ) ;
2020-03-30 11:44:18 +00:00
}
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyChannelUnsubscribed ( json ) {
for ( const entry of json ) {
const channel = this . connection . client . channelTree . findChannel ( entry [ "cid" ] ) ;
if ( ! channel ) {
console . warn ( tr ( "Received channel unsubscribed for not visible channel (cid: %d)" ) , entry [ 'cid' ] ) ;
continue ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
channel . flag_subscribed = false ;
for ( const client of channel . clients ( false ) )
2020-07-17 21:56:20 +00:00
this . connection . client . channelTree . deleteClient ( client , { reason : ViewReasonId.VREASON_SYSTEM , serverLeave : false } ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-07-12 14:31:57 +00:00
/ *
2020-03-30 11:44:18 +00:00
handleNotifyConversationMessageDelete ( json : any [ ] ) {
let conversation : Conversation ;
const conversations = this . connection . client . side_bar . channel_conversations ( ) ;
for ( const entry of json ) {
if ( typeof ( entry [ "cid" ] ) !== "undefined" )
conversation = conversations . conversation ( parseInt ( entry [ "cid" ] ) , false ) ;
2020-07-12 14:31:57 +00:00
2020-03-30 11:44:18 +00:00
if ( ! conversation )
continue ;
2020-03-27 22:36:57 +00:00
2020-03-30 11:44:18 +00:00
conversation . delete_messages ( parseInt ( entry [ "timestamp_begin" ] ) , parseInt ( entry [ "timestamp_end" ] ) , parseInt ( entry [ "cldbid" ] ) , parseInt ( entry [ "limit" ] ) ) ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
}
2020-07-12 14:31:57 +00:00
* /
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyMusicStatusUpdate ( json : any [ ] ) {
json = json [ 0 ] ;
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
const bot_id = parseInt ( json [ "bot_id" ] ) ;
const client = this . connection . client . channelTree . find_client_by_dbid ( bot_id ) ;
if ( ! client ) {
log . warn ( LogCategory . CLIENT , tr ( "Received music bot status update for unknown bot (%d)" ) , bot_id ) ;
return ;
2019-02-23 13:15:22 +00:00
}
2020-03-30 11:44:18 +00:00
client . events . fire ( "music_status_update" , {
player_replay_index : parseInt ( json [ "player_replay_index" ] ) ,
player_buffered_index : parseInt ( json [ "player_buffered_index" ] )
} ) ;
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleMusicPlayerSongChange ( json : any [ ] ) {
json = json [ 0 ] ;
const bot_id = parseInt ( json [ "bot_id" ] ) ;
const client = this . connection . client . channelTree . find_client_by_dbid ( bot_id ) ;
if ( ! client ) {
log . warn ( LogCategory . CLIENT , tr ( "Received music bot status update for unknown bot (%d)" ) , bot_id ) ;
return ;
2019-02-23 13:15:22 +00:00
}
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
const song_id = parseInt ( json [ "song_id" ] ) ;
let song : SongInfo ;
if ( song_id ) {
song = new SongInfo ( ) ;
JSON . map_to ( song , json ) ;
}
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
client . events . fire ( "music_song_change" , {
song : song
} ) ;
}
2020-02-02 14:05:36 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyPlaylistSongAdd ( json : any [ ] ) {
json = json [ 0 ] ;
2020-03-27 22:36:57 +00:00
2020-03-30 11:44:18 +00:00
const playlist_id = parseInt ( json [ "playlist_id" ] ) ;
const client = this . connection . client . channelTree . clients . find ( e = > e instanceof MusicClientEntry && e . properties . client_playlist_id === playlist_id ) ;
if ( ! client ) {
log . warn ( LogCategory . CLIENT , tr ( "Received playlist song add event, but we've no music bot for the playlist (%d)" ) , playlist_id ) ;
return ;
2019-03-17 11:15:39 +00:00
}
2020-03-30 11:44:18 +00:00
client . events . fire ( "playlist_song_add" , {
song : {
song_id : parseInt ( json [ "song_id" ] ) ,
song_invoker : json [ "song_invoker" ] ,
song_previous_song_id : parseInt ( json [ "song_previous_song_id" ] ) ,
song_url : json [ "song_url" ] ,
song_url_loader : json [ "song_url_loader" ] ,
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
song_loaded : json [ "song_loaded" ] == true || json [ "song_loaded" ] == "1" ,
song_metadata : json [ "song_metadata" ]
2019-03-17 11:15:39 +00:00
}
2020-03-30 11:44:18 +00:00
} ) ;
}
2020-02-02 14:05:36 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyPlaylistSongRemove ( json : any [ ] ) {
json = json [ 0 ] ;
const playlist_id = parseInt ( json [ "playlist_id" ] ) ;
const client = this . connection . client . channelTree . clients . find ( e = > e instanceof MusicClientEntry && e . properties . client_playlist_id === playlist_id ) ;
if ( ! client ) {
log . warn ( LogCategory . CLIENT , tr ( "Received playlist song remove event, but we've no music bot for the playlist (%d)" ) , playlist_id ) ;
return ;
2019-03-17 11:15:39 +00:00
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
const song_id = parseInt ( json [ "song_id" ] ) ;
client . events . fire ( "playlist_song_remove" , { song_id : song_id } ) ;
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyPlaylistSongReorder ( json : any [ ] ) {
json = json [ 0 ] ;
2019-09-12 21:59:35 +00:00
2020-03-30 11:44:18 +00:00
const playlist_id = parseInt ( json [ "playlist_id" ] ) ;
const client = this . connection . client . channelTree . clients . find ( e = > e instanceof MusicClientEntry && e . properties . client_playlist_id === playlist_id ) ;
if ( ! client ) {
log . warn ( LogCategory . CLIENT , tr ( "Received playlist song reorder event, but we've no music bot for the playlist (%d)" ) , playlist_id ) ;
return ;
2019-08-21 08:00:01 +00:00
}
2020-03-30 11:44:18 +00:00
const song_id = parseInt ( json [ "song_id" ] ) ;
const previous_song_id = parseInt ( json [ "song_previous_song_id" ] ) ;
client . events . fire ( "playlist_song_reorder" , { song_id : song_id , previous_song_id : previous_song_id } ) ;
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleNotifyPlaylistSongLoaded ( json : any [ ] ) {
json = json [ 0 ] ;
2020-03-29 10:54:15 +00:00
2020-03-30 11:44:18 +00:00
const playlist_id = parseInt ( json [ "playlist_id" ] ) ;
const client = this . connection . client . channelTree . clients . find ( e = > e instanceof MusicClientEntry && e . properties . client_playlist_id === playlist_id ) ;
if ( ! client ) {
log . warn ( LogCategory . CLIENT , tr ( "Received playlist song loaded event, but we've no music bot for the playlist (%d)" ) , playlist_id ) ;
return ;
2019-08-21 08:00:01 +00:00
}
2020-03-30 11:44:18 +00:00
const song_id = parseInt ( json [ "song_id" ] ) ;
client . events . fire ( "playlist_song_loaded" , {
song_id : song_id ,
success : json [ "success" ] == 1 ,
error_msg : json [ "load_error_msg" ] ,
metadata : json [ "song_metadata" ]
} ) ;
2019-02-23 13:15:22 +00:00
}
}