You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
5.6 KiB
TypeScript

/**
* Rocket.Chat RealTime API
*/
import {
webSocket,
WebSocketSubject,
WebSocketSubjectConfig
} from "rxjs/webSocket";
import { filter, buffer, flatMap, merge, map, tap } from "rxjs/operators";
import { v4 as uuid } from "uuid";
import { SHA256 } from "crypto-js";
export class RealTimeAPI {
public webSocket: WebSocketSubject<any>;
constructor(param: string | WebSocketSubjectConfig<any>) {
this.webSocket = webSocket(param);
}
/**
* Returns the Observable to the RealTime API Socket
*/
public getObservable() {
return this.webSocket;
}
/**
* 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: any): void {
this.webSocket.next(messageObject);
}
/**
* getObservableFilteredByMessageType
*/
public getObservableFilteredByMessageType(messageType: string) {
return this.getObservable().pipe(
filter((message: any) => message.msg === messageType)
);
}
/**
* getObservableFilteredByID
*/
public getObservableFilteredByID(id: string) {
return this.getObservable().pipe(
filter((message: any) => message.id === id)
);
}
/**
* connectToServer
*/
public connectToServer() {
this.sendMessage({
msg: "connect",
version: "1",
support: ["1", "pre2", "pre1"]
});
return this.getObservableFilteredByMessageType("connected");
}
/**
* Returns an Observable to subscribe to keepAlive, Ping and Pong to the Rocket.Chat Server to Keep the Connection Alive.
*/
public keepAlive() {
return this.getObservableFilteredByMessageType("ping").pipe(
tap(() => this.sendMessage({ msg: "pong" }))
);
}
/**
* Login with Username and Password
*/
public login(username: string, password: string) {
let id = uuid();
let usernameType = username.indexOf("@") !== -1 ? "email" : "username";
this.sendMessage({
msg: "method",
method: "login",
id: id,
params: [
{
user: { [usernameType]: username },
password: {
digest: SHA256(password).toString(),
algorithm: "sha-256"
}
}
]
});
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().pipe(
buffer(
resultObservable.pipe(
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.
merge(resultObservable) //Merging "result" and "added" messages.
);
return addedObservable;
}
/**
* 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(
() => ({
msg: "sub",
id: id,
name: streamName,
params: [streamParam, addEvent]
}),
() => ({
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;
}
}