507 lines
11 KiB
TypeScript
507 lines
11 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { DatePipe } from '@angular/common';
|
|
import { HermesSocketService } from './hermes-socket.service';
|
|
import EventService from './shared/services/EventService';
|
|
import { filter, map, Observable } from 'rxjs';
|
|
|
|
export interface Message {
|
|
d: object,
|
|
t: object,
|
|
o: object
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class HermesClientService {
|
|
private readonly pipe = new DatePipe('en-US');
|
|
session_id: string | undefined;
|
|
connected: boolean;
|
|
logged_in: boolean;
|
|
api_key: string | undefined;
|
|
|
|
constructor(private socket: HermesSocketService, private events: EventService) {
|
|
this.connected = false;
|
|
this.logged_in = false;
|
|
}
|
|
|
|
public connect() {
|
|
if (this.connected)
|
|
return;
|
|
|
|
this.socket.connect();
|
|
this.connected = true;
|
|
return this.listen();
|
|
}
|
|
|
|
public disconnect(impersonated: boolean = false) {
|
|
if (!this.connected)
|
|
return;
|
|
|
|
this.connected = false;
|
|
this.logged_in = false;
|
|
this.session_id = undefined;
|
|
this.api_key = undefined;
|
|
this.socket.close();
|
|
this.events.emit('tts_logoff', impersonated);
|
|
}
|
|
|
|
public filter(predicate: (data: any) => boolean): Observable<any> | undefined {
|
|
return this.socket.get$()?.pipe(
|
|
filter(predicate),
|
|
map(d => d.d)
|
|
);
|
|
}
|
|
|
|
public filterByRequestType(requestName: string): Observable<any> | undefined {
|
|
return this.socket.get$()?.pipe(
|
|
filter(d => d.op == 4 && d.d.request.type === requestName),
|
|
map(d => d.d)
|
|
);
|
|
}
|
|
|
|
public first(predicate: (data: any) => boolean): Observable<any> {
|
|
return this.socket.first(predicate);
|
|
}
|
|
|
|
private send(op: number, data: any) {
|
|
if (op != 0)
|
|
console.log("TX:", data);
|
|
|
|
this.socket.sendMessage({
|
|
d: data,
|
|
op
|
|
});
|
|
}
|
|
|
|
public login(api_key: string) {
|
|
if (!this.connected)
|
|
this.connect();
|
|
if (this.logged_in)
|
|
return;
|
|
|
|
this.api_key = api_key;
|
|
|
|
this.send(1, {
|
|
api_key,
|
|
web_login: true,
|
|
major_version: 0,
|
|
minor_version: 4
|
|
});
|
|
}
|
|
|
|
public createConnection(name: string, type: string, client_id: string, access_token: string, grant_type: string, scope: string, expiration: Date) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_connection",
|
|
data: { name, type, client_id, access_token, grant_type, scope, expiration },
|
|
});
|
|
}
|
|
|
|
public createConnectionState(name: string, type: string, client_id: string, grant_type: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_connection_state",
|
|
data: { name, type, client_id, grant_type },
|
|
});
|
|
}
|
|
|
|
public createGroup(name: string, priority: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_group",
|
|
data: { name, priority },
|
|
});
|
|
}
|
|
|
|
public createGroupChatter(groupId: string, chatterId: string, chatterLabel: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_group_chatter",
|
|
data: { group: groupId, chatter: chatterId, label: chatterLabel },
|
|
});
|
|
}
|
|
|
|
public createGroupPermission(groupId: string, path: string, allow: boolean | null) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_group_permission",
|
|
data: { group: groupId, path, allow },
|
|
});
|
|
}
|
|
|
|
public createPolicy(groupId: string, path: string, usage: number, timespan: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_policy",
|
|
data: { groupId, path, count: usage, span: timespan },
|
|
});
|
|
}
|
|
|
|
public createRedeemableAction(name: string, type: string, d: { [key: string]: any }) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_redeemable_action",
|
|
data: { name, type, data: d },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public createRedemption(twitchRedemptionId: string, actionName: string, order: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_redemption",
|
|
data: { redemption: twitchRedemptionId, action: actionName, order },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public createTTSFilter(search: string, replace: string, flag: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "create_tts_filter",
|
|
data: { search, replace, flag },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public deleteConnection(name: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_connection",
|
|
data: { name },
|
|
});
|
|
}
|
|
|
|
public deleteConnectionState(name: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_connection_state",
|
|
data: { name },
|
|
});
|
|
}
|
|
|
|
public deleteGroup(id: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_group",
|
|
data: { id },
|
|
});
|
|
}
|
|
|
|
public deleteGroupChatter(groupId: string, chatterId: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_group_chatter",
|
|
data: { group: groupId, chatter: chatterId },
|
|
});
|
|
}
|
|
|
|
public deleteGroupPermission(id: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_group_permission",
|
|
data: { id },
|
|
});
|
|
}
|
|
|
|
public deletePolicy(id: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_policy",
|
|
data: { id },
|
|
});
|
|
}
|
|
|
|
public deleteRedeemableAction(name: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_redeemable_action",
|
|
data: { name },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public deleteRedemption(id: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_redemption",
|
|
data: { id },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public deleteTTSFilter(id: string) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "delete_tts_filter",
|
|
data: { id },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public fetchConnections() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_connections",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchConnectionStates() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_connection_states",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchFilters() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_tts_word_filters",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchGroups() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_groups",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchPermissions() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_group_permissions",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchPolicies() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_policies",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchRedeemableActions() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_redeemable_actions",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public fetchRedemptions() {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "get_redemptions",
|
|
data: null,
|
|
});
|
|
}
|
|
|
|
public heartbeat() {
|
|
const date = new Date()
|
|
this.send(0, {
|
|
date_time: this.pipe.transform(date.getTime() + date.getUTCDate(), "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
|
|
});
|
|
}
|
|
|
|
public subscribe(code: number, next: (data: any) => void) {
|
|
return this.socket.subscribe({
|
|
next: (message: any) => {
|
|
if (message.op == code)
|
|
next(message.d);
|
|
}
|
|
});
|
|
}
|
|
|
|
public subscribeToRequests(requestType: string, action: (data: any) => void) {
|
|
return this.subscribe(4, (data) => {
|
|
const type = data.request.type;
|
|
if (type == requestType)
|
|
action(data);
|
|
});
|
|
}
|
|
|
|
public updateGroup(id: string, name: string, priority: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "update_group",
|
|
data: { id, name, priority },
|
|
});
|
|
}
|
|
|
|
public updateGroupPermission(id: string, groupId: string, path: string, allow: boolean | null) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "update_group_permission",
|
|
data: { id, group: groupId, path, allow },
|
|
});
|
|
}
|
|
|
|
public updatePolicy(id: string, groupId: string, path: string, usage: number, timespan: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "update_policy",
|
|
data: { id, groupId, path, count: usage, span: timespan },
|
|
});
|
|
}
|
|
|
|
public updateRedeemableAction(name: string, type: string, d: { [key: string]: any }) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "update_redeemable_action",
|
|
data: { name, type, data: d },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public updateRedemption(id: string, twitchRedemptionId: string, actionName: string, order: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "update_redemption",
|
|
data: { id, redemption: twitchRedemptionId, action: actionName, order, state: true },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
public updateTTSFilter(id: string, search: string, replace: string, flag: number) {
|
|
if (!this.logged_in)
|
|
return;
|
|
|
|
this.send(3, {
|
|
request_id: null,
|
|
type: "update_tts_filter",
|
|
data: { id, search, replace, flag },
|
|
nounce: this.session_id,
|
|
});
|
|
}
|
|
|
|
private listen() {
|
|
return this.socket.subscribe({
|
|
next: (message: any) => {
|
|
console.log("RX:", message);
|
|
switch (message.op) {
|
|
case 0: // Heartbeat
|
|
console.log("TTS Heartbeat received. Potential connection problem?");
|
|
break;
|
|
case 2: // Login Ack
|
|
if (message.d.another_client) {
|
|
return;
|
|
}
|
|
console.log("TTS Login successful.");
|
|
this.logged_in = true;
|
|
this.session_id = message.d.session_id;
|
|
this.events.emit('tts_login_ack', message.d);
|
|
break;
|
|
}
|
|
},
|
|
error: (err: any) => {
|
|
console.error('Websocket error', err);
|
|
if (err.type == 'close') {
|
|
this.disconnect();
|
|
}
|
|
},
|
|
complete: () => { console.log('Websocket disconnected.'); this.disconnect(); }
|
|
});
|
|
}
|
|
}
|