2020-09-12 13:49:20 +00:00
import * as log from "../log" ;
2020-12-18 16:06:38 +00:00
import { LogCategory , logError , logWarn } from "../log" ;
2020-09-12 13:49:20 +00:00
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 { 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" ;
2020-12-09 12:36:56 +00:00
import { OutOfViewClient } from "../ui/frames/side/PrivateConversationController" ;
2020-09-12 13:49:20 +00:00
import { renderBBCodeAsJQuery } from "../text/bbcode" ;
import { tr } from "../i18n/localize" ;
import { ErrorCode } from "../connection/ErrorCode" ;
2020-09-24 09:24:31 +00:00
import { server_connections } from "tc-shared/ConnectionManager" ;
2020-12-04 12:36:34 +00:00
import { ChannelEntry } from "tc-shared/tree/Channel" ;
2020-12-18 16:06:38 +00:00
import { EventClient } from "tc-shared/connectionlog/Definitions" ;
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 ;
2020-12-18 16:06:38 +00:00
this [ "notifychanneldescriptionchanged" ] = this . handleNotifyChannelDescriptionChanged ;
2020-03-30 11:44:18 +00:00
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 ;
this [ "notifymusicstatusupdate" ] = this . handleNotifyMusicStatusUpdate ;
this [ "notifymusicplayersongchange" ] = this . handleMusicPlayerSongChange ;
}
2020-12-04 12:36:34 +00:00
private loggable_invoker ( uniqueId , clientId , clientName ) : EventClient | undefined {
const id = typeof clientId === "string" ? parseInt ( clientId ) : clientId ;
if ( typeof ( clientId ) === "undefined" || Number . isNaN ( id ) ) {
2020-03-30 11:44:18 +00:00
return undefined ;
2020-12-04 12:36:34 +00:00
}
2020-03-30 11:44:18 +00:00
2020-12-04 12:36:34 +00:00
if ( id == 0 ) {
2020-03-30 11:44:18 +00:00
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 ,
} ;
2020-12-04 12:36:34 +00:00
}
2019-03-17 11:15:39 +00:00
2020-03-30 11:44:18 +00:00
return {
2020-12-04 12:36:34 +00:00
client_unique_id : uniqueId ,
client_name : clientName ,
client_id : clientId
2020-03-30 11:44:18 +00:00
} ;
}
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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "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 ;
2021-01-10 15:26:45 +00:00
const scon = server_connections . getActiveConnectionHandler ( ) ;
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 ) ;
}
2020-12-04 12:36:34 +00:00
private createChannelFromJson ( json , ignoreMissingPreviousChannel : boolean = false ) : ChannelEntry {
2020-03-30 11:44:18 +00:00
let tree = this . connection . client . channelTree ;
2019-02-23 13:15:22 +00:00
2020-12-04 12:36:34 +00:00
let channelId = parseInt ( json [ "cid" ] ) ;
let channelName = json [ "channel_name" ] ;
2019-02-23 13:15:22 +00:00
2020-12-04 12:36:34 +00:00
let previousChannelId = parseInt ( json [ "channel_order" ] ) ;
let parentChannelId = parseInt ( json [ "cpid" ] ) ;
2020-12-05 21:21:14 +00:00
if ( Number . isNaN ( channelId ) || Number . isNaN ( previousChannelId ) || Number . isNaN ( parentChannelId ) ) {
logError ( LogCategory . NETWORKING , tr ( "Tried to create a channel with invalid ids (%o - %o - %o)" ) , channelId , previousChannelId , parentChannelId ) ;
return ;
}
2020-12-04 12:36:34 +00:00
let parentChannel : ChannelEntry ;
let previousChannel : ChannelEntry ;
if ( previousChannelId !== 0 ) {
previousChannel = tree . findChannel ( previousChannelId ) ;
if ( ! previousChannel && ! ignoreMissingPreviousChannel ) {
logError ( LogCategory . NETWORKING , tr ( "Received a channel with an invalid order id (%d)" ) , previousChannelId ) ;
/* maybe disconnect? */
}
2020-03-30 11:44:18 +00:00
}
2020-04-18 17:37:30 +00:00
2020-12-04 12:36:34 +00:00
if ( parentChannelId !== 0 ) {
parentChannel = tree . findChannel ( parentChannelId ) ;
if ( ! parentChannel ) {
logError ( LogCategory . NETWORKING , tr ( "Received a channel with an invalid parent channel (%d)" ) , parentChannelId ) ;
/* maybe disconnect? */
2019-02-23 13:15:22 +00:00
}
}
2020-12-04 12:36:34 +00:00
const channel = tree . handleChannelCreated ( previousChannel , parentChannel , channelId , channelName ) ;
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 ) ;
2020-12-03 16:58:13 +00:00
if ( tree . channelsInitialized ) {
2020-12-04 11:48:19 +00:00
channel . updateSubscribeMode ( ) . then ( undefined ) ;
2020-12-03 16:58:13 +00:00
}
2020-12-04 12:36:34 +00:00
return channel ;
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-12-04 12:36:34 +00:00
private batchTreeUpdateFinishedTimeout ;
2020-03-30 11:44:18 +00:00
handleCommandChannelList ( json ) {
2020-12-04 12:36:34 +00:00
if ( this . batchTreeUpdateFinishedTimeout ) {
clearTimeout ( this . batchTreeUpdateFinishedTimeout ) ;
this . batchTreeUpdateFinishedTimeout = 0 ;
2020-04-18 17:37:30 +00:00
/* batch update is still active */
} else {
batch_updates ( BatchUpdateType . CHANNEL_TREE ) ;
}
2020-12-04 12:36:34 +00:00
for ( let index = 0 ; index < json . length ; index ++ ) {
2020-03-30 11:44:18 +00:00
this . createChannelFromJson ( json [ index ] , true ) ;
2020-12-04 12:36:34 +00:00
}
2020-04-18 17:37:30 +00:00
2020-12-04 12:36:34 +00:00
this . batchTreeUpdateFinishedTimeout = setTimeout ( ( ) = > {
flush_batched_updates ( BatchUpdateType . CHANNEL_TREE ) ;
this . batchTreeUpdateFinishedTimeout = 0 ;
2020-04-18 17:37:30 +00:00
} , 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 ;
2021-01-06 20:51:51 +00:00
this . connection . client . channelTree . events . fire ( "notify_channel_list_received" ) ;
2020-07-12 14:31:57 +00:00
2020-12-04 12:36:34 +00:00
if ( this . batchTreeUpdateFinishedTimeout ) {
clearTimeout ( this . batchTreeUpdateFinishedTimeout ) ;
this . batchTreeUpdateFinishedTimeout = 0 ;
2020-04-18 17:37:30 +00:00
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 ) {
2020-12-04 12:36:34 +00:00
json = json [ 0 ] ;
const channel = this . createChannelFromJson ( json ) ;
if ( ! channel ) { return ; }
const ownAction = parseInt ( json [ "invokerid" ] ) === this . connection . client . getClientId ( ) ;
if ( ownAction ) {
this . connection . client . sound . play ( Sound . CHANNEL_CREATED ) ;
}
const log = this . connection . client . log ;
log . log ( "channel.create" , {
channel : channel.log_data ( ) ,
creator : this.loggable_invoker ( json [ "invokeruid" ] , json [ "invokerid" ] , json [ "invokername" ] ) ,
ownAction : ownAction
} ) ;
2020-03-30 11:44:18 +00:00
}
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelShow ( json ) {
2020-12-04 12:36:34 +00:00
json = json [ 0 ] ;
const channel = this . createChannelFromJson ( json ) ;
const log = this . connection . client . log ;
log . log ( "channel.show" , {
channel : channel.log_data ( ) ,
} ) ;
2020-03-30 11:44:18 +00:00
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelDelete ( json ) {
let tree = this . connection . client . channelTree ;
2020-12-09 12:36:56 +00:00
const conversations = this . connection . client . getChannelConversations ( ) ;
2019-08-21 08:00:01 +00:00
2020-12-04 12:36:34 +00:00
let playSound = false ;
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 ) {
2020-12-04 12:36:34 +00:00
logError ( LogCategory . NETWORKING , tr ( "Invalid channel onDelete (Unknown channel)" ) ) ;
2020-03-30 11:44:18 +00:00
continue ;
2019-08-21 08:00:01 +00:00
}
2020-03-30 11:44:18 +00:00
tree . deleteChannel ( channel ) ;
2020-12-04 12:36:34 +00:00
const ownAction = parseInt ( json [ index ] [ "invokerid" ] ) === this . connection . client . getClientId ( ) ;
const log = this . connection . client . log ;
log . log ( "channel.delete" , {
channel : channel.log_data ( ) ,
deleter : this.loggable_invoker ( json [ index ] [ "invokeruid" ] , json [ index ] [ "invokerid" ] , json [ index ] [ "invokername" ] ) ,
ownAction : ownAction
} ) ;
if ( ownAction ) {
playSound = true ;
}
}
if ( playSound ) {
this . connection . client . sound . play ( Sound . CHANNEL_DELETED ) ;
2020-03-30 11:44:18 +00:00
}
}
2019-08-21 08:00:01 +00:00
2020-03-30 11:44:18 +00:00
handleCommandChannelHide ( json ) {
let tree = this . connection . client . channelTree ;
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 ++ ) {
let channel = tree . findChannel ( json [ index ] [ "cid" ] ) ;
if ( ! channel ) {
2020-12-04 12:36:34 +00:00
logError ( LogCategory . NETWORKING , tr ( "Invalid channel on hide (Unknown channel)" ) ) ;
2020-03-30 11:44:18 +00:00
continue ;
}
tree . deleteChannel ( channel ) ;
2020-12-04 12:36:34 +00:00
const log = this . connection . client . log ;
log . log ( "channel.hide" , {
channel : channel.log_data ( ) ,
} ) ;
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 ;
2020-12-29 15:53:04 +00:00
let reasonId , reasonMsg ;
2019-08-21 08:00:01 +00:00
2020-12-29 15:53:04 +00:00
let invokerId , invokerName , invokerUniqueId ;
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 ;
2020-12-29 15:53:04 +00:00
reasonId = typeof ( entry [ "reasonid" ] ) !== "undefined" ? entry [ "reasonid" ] : reasonId ;
reasonMsg = typeof ( entry [ "reason_msg" ] ) !== "undefined" ? entry [ "reason_msg" ] : reasonMsg ;
2019-08-30 21:06:39 +00:00
2020-12-29 15:53:04 +00:00
invokerId = typeof ( entry [ "invokerid" ] ) !== "undefined" ? parseInt ( entry [ "invokerid" ] ) : invokerId ;
invokerName = typeof ( entry [ "invokername" ] ) !== "undefined" ? entry [ "invokername" ] : invokerName ;
invokerUniqueId = typeof ( entry [ "invokeruid" ] ) !== "undefined" ? entry [ "invokeruid" ] : invokerUniqueId ;
2020-03-30 11:44:18 +00:00
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 ) {
2020-12-29 15:53:04 +00:00
client = new MusicClientEntry ( parseInt ( entry [ "clid" ] ) , entry [ "client_nickname" ] ) as any ;
2020-03-30 11:44:18 +00:00
} 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-12-29 15:53:04 +00:00
client = tree . insertClient ( client , channel , { reason : reasonId , 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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( channel == own_channel ? "client.view.enter.own.channel" : "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 ( ) ,
2020-12-29 15:53:04 +00:00
invoker : this.loggable_invoker ( invokerUniqueId , invokerId , invokerName ) ,
message :reasonMsg ,
reason : parseInt ( reasonId ) ,
2020-03-30 11:44:18 +00:00
} ) ;
2019-02-23 13:15:22 +00:00
2020-12-29 15:53:04 +00:00
if ( reasonId == ViewReasonId . VREASON_USER_ACTION ) {
2020-03-30 11:44:18 +00:00
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 ) ;
2020-12-29 15:53:04 +00:00
} else if ( reasonId == ViewReasonId . VREASON_MOVED ) {
2020-03-30 11:44:18 +00:00
if ( own_channel == channel )
this . connection_handler . sound . play ( Sound . USER_ENTERED_MOVED ) ;
2020-12-29 15:53:04 +00:00
} else if ( reasonId == ViewReasonId . VREASON_CHANNEL_KICK ) {
2020-03-30 11:44:18 +00:00
if ( own_channel == channel )
this . connection_handler . sound . play ( Sound . USER_ENTERED_KICKED ) ;
2020-12-29 15:53:04 +00:00
} else if ( reasonId == ViewReasonId . VREASON_SYSTEM ) {
2019-02-23 13:15:22 +00:00
2020-03-30 11:44:18 +00:00
} else {
2020-12-29 15:53:04 +00:00
console . warn ( tr ( "Unknown reasonid for %o" ) , reasonId ) ;
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 ) {
this . connection_handler . update_voice_status ( ) ;
2020-12-09 12:36:56 +00:00
const conversations = this . connection . client . getChannelConversations ( ) ;
conversations . setSelectedConversation ( conversations . findOrCreateConversation ( 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
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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( is_own_channel ? "client.view.leave.own.channel" : "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-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-12-18 16:06:38 +00:00
const event = self ? "client.view.move.own" : ( channelFrom == own_channel || channel_to == own_channel ? "client.view.move.own.channel" : "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-12-12 13:18:50 +00:00
tree . moveChannel ( channel , prev , parent , false ) ;
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-12-18 16:06:38 +00:00
handleNotifyChannelDescriptionChanged ( json ) {
json = json [ 0 ] ;
let tree = this . connection . client . channelTree ;
let channel = tree . findChannel ( parseInt ( json [ "cid" ] ) ) ;
if ( ! channel ) {
logWarn ( LogCategory . NETWORKING , tr ( "Received channel description changed notify for invalid channel: %o" ) , json [ "cid" ] ) ;
return ;
}
channel . handleDescriptionChanged ( ) ;
}
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-12-09 12:36:56 +00:00
const conversationManager = this . connection_handler . getPrivateConversations ( ) ;
const conversation = conversationManager . 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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "private.message.received" , {
2020-07-21 22:55:28 +00:00
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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "private.message.send" , {
2020-07-21 22:55:28 +00:00
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
}
} 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-12-09 12:36:56 +00:00
const conversations = this . connection_handler . getChannelConversations ( ) ;
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" ] ) ) ;
2020-12-09 12:36:56 +00:00
const conversations = this . connection_handler . getChannelConversations ( ) ;
2020-07-21 22:55:28 +00:00
2020-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "global.message" , {
2020-07-21 22:55:28 +00:00
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 ] ;
2020-12-09 12:36:56 +00:00
const conversation_manager = this . connection_handler . getPrivateConversations ( ) ;
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
2020-12-09 12:36:56 +00:00
const conversationManager = this . connection_handler . getPrivateConversations ( ) ;
const conversation = conversationManager . 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
} [ ] = [ ] ;
2020-12-29 15:53:04 +00:00
2020-03-30 11:44:18 +00:00
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-12-18 16:06:38 +00:00
this . connection_handler . log . log ( "client.poke.received" , {
2020-07-21 22:55:28 +00:00
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-12-04 12:36:34 +00:00
channel . setSubscribed ( true ) ;
2020-04-18 17:37:30 +00:00
}
} 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-12-04 12:36:34 +00:00
channel . setSubscribed ( 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 } ) ;
2020-12-04 12:36:34 +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
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 ) ;
2020-12-29 15:53:04 +00:00
if ( ! client || ! ( client instanceof MusicClientEntry ) ) {
2020-03-30 11:44:18 +00:00
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-12-29 15:53:04 +00:00
client . events . fire ( "notify_music_player_timestamp" , {
replayIndex : parseInt ( json [ "player_replay_index" ] ) ,
bufferedIndex : parseInt ( json [ "player_buffered_index" ] )
2020-03-30 11:44:18 +00:00
} ) ;
}
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 ) ;
2020-12-29 15:53:04 +00:00
if ( ! client || ! ( client instanceof MusicClientEntry ) ) {
2020-03-30 11:44:18 +00:00
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-12-29 15:53:04 +00:00
client . events . fire ( "notify_music_player_song_change" , {
newSong : song
2020-03-30 11:44:18 +00:00
} ) ;
2019-02-23 13:15:22 +00:00
}
}