hermes-web-angular/src/app/hermes-client.service.ts

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(); }
});
}
}