@ -3,225 +3,243 @@
* /
* /
import { Observable } from "rxjs" ;
import { Observable } from "rxjs" ;
import { WebSocketSubject } from 'rxjs/observable/dom/WebSocketSubject' ;
import { WebSocketSubject } from "rxjs/observable/dom/WebSocketSubject" ;
import { v4 as uuid } from "uuid" ;
import { v4 as uuid } from "uuid" ;
import { SHA256 } from "crypto-js" ;
import { SHA256 } from "crypto-js" ;
export class RealTimeAPI {
export class RealTimeAPI {
public url : string ;
public url : string ;
public webSocket : WebSocketSubject < { } > ;
public webSocket : WebSocketSubject < { } > ;
constructor ( param : string | WebSocketSubject < { } > ) {
constructor ( param : string | WebSocketSubject < { } > ) {
switch ( typeof param ) {
switch ( typeof param ) {
case "string" :
case "string" :
this . url = param as string ;
this . url = param as string ;
this . webSocket = Observable . webSocket ( this . url ) ;
this . webSocket = Observable . webSocket ( this . url ) ;
break ;
break ;
case "object" :
case "object" :
this . webSocket = param as WebSocketSubject < { } > ;
this . webSocket = param as WebSocketSubject < { } > ;
this . url = this . webSocket . url ;
this . url = this . webSocket . url ;
break ;
break ;
default :
default :
throw new Error ( ` Invalid Parameter to the Constructor, Parameter must be of Type WebSocketSubject or URL but was found of type " ${ typeof param } " ` ) ;
throw new Error (
}
` Invalid Parameter to the Constructor, Parameter must be of Type WebSocketSubject or URL but was found of type " ${ typeof param } " `
}
/ * *
* Returns the Observable to the RealTime API Socket
* /
public getObservable() {
return this . webSocket . catch ( err = > Observable . of ( err ) ) ;
}
/ * *
* Disconnect the WebSocket Connection between client and RealTime API
* /
public disconnect() {
return this . webSocket . unsubscribe ( ) ;
}
/ * *
* onMessage
* /
public onMessage ( messageHandler ? : ( ( value : { } ) = > void ) | undefined ) : void {
this . subscribe ( messageHandler , undefined , undefined ) ;
}
/ * *
* onError
* /
public onError ( errorHandler ? : ( ( error : any ) = > void ) | undefined ) : void {
this . subscribe ( undefined , errorHandler , undefined ) ;
}
/ * *
* onCompletion
* /
public onCompletion ( completionHandler ? : ( ( ) = > void ) | undefined ) : void {
this . subscribe ( undefined , undefined , completionHandler ) ;
}
/ * *
* Subscribe to the WebSocket of the RealTime API
* /
public subscribe ( messageHandler ? : ( ( value : { } ) = > void ) | undefined , errorHandler ? : ( ( error : any ) = > void ) | undefined , completionHandler ? : ( ( ) = > void ) | undefined ) {
this . getObservable ( ) . subscribe ( messageHandler , errorHandler , completionHandler ) ;
}
/ * *
* sendMessage to Rocket . Chat Server
* /
public sendMessage ( messageObject : { } ) : void {
this . webSocket . next ( JSON . stringify ( messageObject ) ) ;
}
/ * *
* getObservableFilteredByMessageType
* /
public getObservableFilteredByMessageType ( messageType : string ) {
return this . getObservable ( ) . filter ( ( message : any ) = > message . msg === messageType ) ;
}
/ * *
* getObservableFilteredByID
* /
public getObservableFilteredByID ( id : string ) {
return this . getObservable ( ) . filter ( ( message : any ) = > message . id === id ) ;
}
/ * *
* connectToServer
* /
public connectToServer() {
this . sendMessage ( { "msg" : "connect" , "version" : "1" , "support" : [ "1" , "pre2" , "pre1" ] } ) ;
return this . getObservableFilteredByMessageType ( "connected" ) ;
}
/ * *
* keepAlive , Ping and Pong to the Rocket . Chat Server to Keep the Connection Alive .
* /
public keepAlive ( ) : void {
this . getObservableFilteredByMessageType ( "ping" ) . subscribe (
message = > this . sendMessage ( { msg : "pong" } )
) ;
) ;
}
}
}
/ * *
* Login with Username and Password
/ * *
* /
* Returns the Observable to the RealTime API Socket
public login ( username : string , password : string ) {
* /
let id = uuid ( ) ;
public getObservable() {
let usernameType = username . indexOf ( "@" ) !== - 1 ? "email" : "username" ;
return this . webSocket . catch ( err = > Observable . of ( err ) ) ;
this . sendMessage ( {
}
"msg" : "method" ,
"method" : "login" ,
/ * *
"id" : id ,
* Disconnect the WebSocket Connection between client and RealTime API
"params" : [
* /
{
public disconnect() {
"user" : { [ usernameType ] : username } ,
return this . webSocket . unsubscribe ( ) ;
"password" : {
}
"digest" : SHA256 ( password ) . toString ( ) ,
"algorithm" : "sha-256"
/ * *
}
* onMessage
}
* /
]
public onMessage ( messageHandler ? : ( ( value : { } ) = > void ) | undefined ) : void {
} ) ;
this . subscribe ( messageHandler , undefined , undefined ) ;
return this . getLoginObservable ( id ) ;
}
}
/ * *
/ * *
* onError
* Login with Authentication Token
* /
* /
public onError ( errorHandler ? : ( ( error : any ) = > void ) | undefined ) : void {
public loginWithAuthToken ( authToken : string ) {
this . subscribe ( undefined , errorHandler , undefined ) ;
let id = uuid ( ) ;
}
this . sendMessage ( {
"msg" : "method" ,
/ * *
"method" : "login" ,
* onCompletion
"id" : id ,
* /
"params" : [
public onCompletion ( completionHandler ? : ( ( ) = > void ) | undefined ) : void {
{ "resume" : authToken }
this . subscribe ( undefined , undefined , completionHandler ) ;
]
}
} ) ;
return this . getLoginObservable ( id ) ;
/ * *
}
* Subscribe to the WebSocket of the RealTime API
* /
/ * *
public subscribe (
* Login with OAuth , with Client Token and Client Secret
messageHandler ? : ( ( value : { } ) = > void ) | undefined ,
* /
errorHandler ? : ( ( error : any ) = > void ) | undefined ,
public loginWithOAuth ( credToken : string , credSecret : string ) {
completionHandler ? : ( ( ) = > void ) | undefined
let id = uuid ( ) ;
) {
this . sendMessage ( {
this . getObservable ( ) . subscribe (
"msg" : "method" ,
messageHandler ,
"method" : "login" ,
errorHandler ,
"id" : id ,
completionHandler
"params" : [
) ;
{
}
"oauth" : {
"credentialToken" : credToken ,
/ * *
"credentialSecret" : credSecret
* sendMessage to Rocket . Chat Server
}
* /
}
public sendMessage ( messageObject : { } ) : void {
]
this . webSocket . next ( JSON . stringify ( messageObject ) ) ;
} ) ;
}
return this . getLoginObservable ( id ) ;
}
/ * *
* getObservableFilteredByMessageType
/ * *
* /
* getLoginObservable
public getObservableFilteredByMessageType ( messageType : string ) {
* /
return this . getObservable ( ) . filter (
public getLoginObservable ( id : string ) {
( message : any ) = > message . msg === messageType
let resultObservable = this . getObservableFilteredByID ( id ) ;
) ;
let resultId : string ;
}
let addedObservable = this . getObservable ( )
/ * *
. buffer (
* getObservableFilteredByID
resultObservable . map ( ( { msg , error , result } ) = > {
* /
if ( msg === "result" && ! error )
public getObservableFilteredByID ( id : string ) {
return resultId = result . id // Setting resultId to get Result from the buffer
return this . getObservable ( ) . filter ( ( message : any ) = > message . id === id ) ;
} )
}
)
. flatMap ( x = > x ) // Flattening the Buffered Messages
/ * *
. filter ( ( { id : msgId } ) = > resultId !== undefined && msgId === resultId ) //Filtering the "added" result message.
* connectToServer
* /
return Observable . merge ( resultObservable , addedObservable ) ; //Merging "result" and "added" messages.
public connectToServer() {
}
this . sendMessage ( {
msg : "connect" ,
/ * *
version : "1" ,
* Get Observalble to the Result of Method Call from Rocket . Chat Realtime API
support : [ "1" , "pre2" , "pre1" ]
* /
} ) ;
public callMethod ( method : string , . . . params : Array < { } > ) {
return this . getObservableFilteredByMessageType ( "connected" ) ;
let id = uuid ( ) ;
}
this . sendMessage ( {
"msg" : "method" ,
/ * *
method ,
* keepAlive , Ping and Pong to the Rocket . Chat Server to Keep the Connection Alive .
id ,
* /
params
public keepAlive ( ) : void {
} ) ;
this . getObservableFilteredByMessageType ( "ping" ) . subscribe ( message = >
return this . getObservableFilteredByID ( id ) ;
this . sendMessage ( { msg : "pong" } )
}
) ;
}
/ * *
* getSubscription
/ * *
* /
* Login with Username and Password
public getSubscription ( streamName : string , streamParam : string , addEvent : boolean ) {
* /
let id = uuid ( ) ;
public login ( username : string , password : string ) {
let subscription = this . webSocket . multiplex (
let id = uuid ( ) ;
( ) = > JSON . stringify ( {
let usernameType = username . indexOf ( "@" ) !== - 1 ? "email" : "username" ;
"msg" : "sub" ,
this . sendMessage ( {
"id" : id ,
msg : "method" ,
"name" : streamName ,
method : "login" ,
"params" : [
id : id ,
streamParam ,
params : [
addEvent
{
]
user : { [ usernameType ] : username } ,
} ) ,
password : {
( ) = > JSON . stringify ( {
digest : SHA256 ( password ) . toString ( ) ,
"msg" : "unsub" ,
algorithm : "sha-256"
"id" : id
}
} ) ,
}
( message : any ) = > typeof message . collection === "string" && message . collection === streamName && message . fields . eventName === streamParam // Proper Filtering to be done. This is temporary filter just for the stream-room-messages subscription
]
) ;
} ) ;
return subscription ;
return this . getLoginObservable ( id ) ;
}
}
/ * *
* Login with Authentication Token
* /
public loginWithAuthToken ( authToken : string ) {
let id = uuid ( ) ;
this . sendMessage ( {
msg : "method" ,
method : "login" ,
id : id ,
params : [ { resume : authToken } ]
} ) ;
return this . getLoginObservable ( id ) ;
}
/ * *
* Login with OAuth , with Client Token and Client Secret
* /
public loginWithOAuth ( credToken : string , credSecret : string ) {
let id = uuid ( ) ;
this . sendMessage ( {
msg : "method" ,
method : "login" ,
id : id ,
params : [
{
oauth : {
credentialToken : credToken ,
credentialSecret : credSecret
}
}
]
} ) ;
return this . getLoginObservable ( id ) ;
}
/ * *
* getLoginObservable
* /
public getLoginObservable ( id : string ) {
let resultObservable = this . getObservableFilteredByID ( id ) ;
let resultId : string ;
let addedObservable = this . getObservable ( )
. buffer (
resultObservable . map ( ( { msg , error , result } ) = > {
if ( msg === "result" && ! error ) return ( resultId = result . id ) ; // Setting resultId to get Result from the buffer
} )
)
. flatMap ( x = > x ) // Flattening the Buffered Messages
. filter ( ( { id : msgId } ) = > resultId !== undefined && msgId === resultId ) ; //Filtering the "added" result message.
return Observable . merge ( resultObservable , addedObservable ) ; //Merging "result" and "added" messages.
}
/ * *
* Get Observalble to the Result of Method Call from Rocket . Chat Realtime API
* /
public callMethod ( method : string , . . . params : Array < { } > ) {
let id = uuid ( ) ;
this . sendMessage ( {
msg : "method" ,
method ,
id ,
params
} ) ;
return this . getObservableFilteredByID ( id ) ;
}
/ * *
* getSubscription
* /
public getSubscription (
streamName : string ,
streamParam : string ,
addEvent : boolean
) {
let id = uuid ( ) ;
let subscription = this . webSocket . multiplex (
( ) = >
JSON . stringify ( {
msg : "sub" ,
id : id ,
name : streamName ,
params : [ streamParam , addEvent ]
} ) ,
( ) = >
JSON . stringify ( {
msg : "unsub" ,
id : id
} ) ,
( message : any ) = >
typeof message . collection === "string" &&
message . collection === streamName &&
message . fields . eventName === streamParam // Proper Filtering to be done. This is temporary filter just for the stream-room-messages subscription
) ;
return subscription ;
}
}
}