Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { v4 as uuidv4 } from "uuid";
- import * as WebSocket from "ws";
- /**
- * Created by Durss
- *
- * https://durss.ninja
- */
- export default class VoicemodWebSocket {
- public static ACTION_REGISTER_PLUGIN: string = "registerPlugin";
- public static ACTION_GET_VOICES: string = "getVoices";
- public static ACTION_GET_MEMES: string = "getMemes";
- public static ACTION_SELECT_VOICE: string = "selectVoice";
- public static ACTION_PLAY_MEME: string = "playMeme";
- public static ACTION_STOP_ALL_MEME_SOUNDS: string = "stopAllMemeSounds";
- public static ACTION_BEEP_SOUND_ON_OFF: string = "beepSound_OnOff";
- //Bellow events are captured but nothing is done with it so far
- public static EVENT_TOGGLE_MUTE: string = "toggleMute";
- public static EVENT_TOGGLE_VOICE_CHANGER: string = "toggleVoiceChanger";
- public static EVENT_TOGGLE_BACKGROUND: string = "toggleBackground";
- public static EVENT_TOGGLE_HEAR_MY_VOICE: string = "toggleHearMyVoice";
- public static EVENT_VOICE_CHANGED_EVENT: string = "voiceChangedEvent";
- //Bellow actions are not implemented
- public static ACTION_GET_BITMAP: string = "getBitmap";
- public static ACTION_SELECT_RANDOM_VOICE: string = "selectRandomVoice";
- public static ACTION_VOICE_CHANGER_ON_OFF: string = "voiceChanger_OnOff";
- public static ACTION_HEAR_MY_VOICE_ON_OFF: string = "hearMyVoice_OnOff";
- public static ACTION_BACKGROUND_ON_OFF: string = "background_OnOff";
- public static ACTION_GET_HEAR_MYSELF_STATUS: string = "getHearMyselfStatus";
- public static ACTION_GET_VOICE_CHANGER_STATUS: string = "getVoiceChangerStatus";
- public static ACTION_GET_MUTE_MIC_STATUS: string = "getMuteMicStatus";
- public static ACTION_GET_BACKGROUND_EFFECT_STATUS: string = "getBackgroundEffectStatus";
- public static ACTION_DATA_STOP_ALL_SOUNDS: string = "stopAllSounds";
- private _initResolver: Function;
- private _socket: WebSocket;
- private _voicesList: VoicemodTypes.Voice[];
- private _memesList: VoicemodTypes.Meme[];
- private _currentVoiceEffect: VoicemodTypes.Voice;
- constructor() {
- }
- /********************
- * GETTER / SETTERS *
- ********************/
- /**
- * Get all the available voice effects
- */
- public get voices():VoicemodTypes.Voice[] {
- return JSON.parse(JSON.stringify(this._voicesList));
- }
- /**
- * Get all the available memes list
- */
- public get memes():VoicemodTypes.Meme[] {
- return JSON.parse(JSON.stringify(this._memesList));
- }
- /**
- * Get all the available memes list
- */
- public get currentVoiceEffect():VoicemodTypes.Voice {
- return this._currentVoiceEffect;
- }
- /******************
- * PUBLIC METHODS *
- ******************/
- public connect(ip:string="127.0.0.1", port:number=59129): Promise<void> {
- return new Promise((resolve, reject) => {
- this._initResolver = resolve;
- this._socket = new WebSocket(`ws://${ip}:${port}/vmsd/`);
- this._socket.onopen = () => {
- console.log('Connected to Voicemod APP');
- console.log('Voicemod connection succeed');
- };
- this._socket.onmessage = (event:VoicemodTypes.SocketEvent) => this.onSocketMessage(event);
- this._socket.onerror = (error) => {
- console.log('Voicemod connection lost');
- setTimeout(_=> {
- this.connect();
- }, 1000);
- reject();
- }
- });
- }
- /**
- * Activate a voice effect by its name.
- * There's a tolerence on the name matching.
- * If the actual voice effect name is "Game Over", you can activate
- * it with "gameover".
- *
- * @param name the name of the voice effect to activate
- * @param id (optional) The ID of the voice effect to activate
- */
- public enableVoiceEffect(name:string, id?:string): void {
- let voice:VoicemodTypes.Voice;
- let rawName = name;
- name = name.trim().toLowerCase().replace(/[^\w\s]/g, '')
- //Search for a voice effect with the requested name
- for (let i = 0; i < this._voicesList.length; i++) {
- if(id) {
- if (id === this._voicesList[i].voiceID) {
- voice = this._voicesList[i];
- break;
- }
- }else{
- let nameRef = this._voicesList[i].friendlyName;
- //Check if the requested name is exactly the same
- if(rawName == nameRef) {
- voice = this._voicesList[i];
- //As this exactly matches the requested name, we can stop searching
- break;
- }
- //Check if requested name is more or less the same
- if (nameRef.trim().toLowerCase().replace(/[^\w\s]/g, '') === name) {
- voice = this._voicesList[i];
- }
- }
- }
- if(!voice) {
- console.log("Voicemod: voice effect "+id? id : name+" not found");
- }else{
- this._currentVoiceEffect = voice;
- this.send(VoicemodWebSocket.ACTION_SELECT_VOICE, {voiceID:voice.voiceID});
- }
- }
- /**
- * Disables the current voice effect
- */
- public disableVoiceEffect():void {
- this.enableVoiceEffect("clean");
- this._currentVoiceEffect = null;
- }
- /**
- * Makes a beep sound
- * If a duration is specified the beep will be stoped after this amoutn of milliseconds.
- *
- * @param duration beep duration. Set to 0 if you don't want it to stop automatically.
- * @param forcedState set to 1 to force it to beep, or 0 to force it to not beep
- */
- public beep(duration:number = 500, forcedState:1|0 = null):void {
- let data = {badLanguage:forcedState != null? forcedState : 1};
- this.send(VoicemodWebSocket.ACTION_BEEP_SOUND_ON_OFF, data);
- //If asked to beep for a specific duration,
- //stop the beep sound after that duration
- if(duration > 0) {
- setTimeout(_=> {
- data.badLanguage = 0;
- this.send(VoicemodWebSocket.ACTION_BEEP_SOUND_ON_OFF, data);
- }, duration);
- }
- }
- /**
- * Activate a meme sound by its name.
- * There's a tolerence on the name matching.
- * If the actual meme name is "Game Over", you can activate
- * it with "gameover".
- *
- * @param name the name of the meme sound to activate
- * @param id (optional) The "FileName" of the meme to activate
- */
- public playMeme(name:string, id?:string):void {
- let fileID = "";
- let rawName = name;
- name = name.trim().toLowerCase().replace(/[^\w\s]/g, '')
- //Search for a voice effect with the requested name
- for (let i = 0; i < this._memesList.length; i++) {
- if(id) {
- if (id === this._memesList[i].FileName) {
- fileID = this._memesList[i].FileName;
- break;
- }
- }else{
- let nameRef = this._memesList[i].Name;
- //Check if the requested name is exactly the same
- if(rawName == nameRef) {
- fileID = this._memesList[i].FileName;
- //As this exactly matches the requested name, we can stop searching
- break;
- }
- //Check if requested name is more or less the same
- if (nameRef.trim().toLowerCase().replace(/[^\w\s]/g, '') === name) {
- fileID = this._memesList[i].FileName;
- }
- }
- }
- if(!fileID) {
- console.log("Voicemod: meme sound "+id? id : name+" not found");
- }else{
- this.send(VoicemodWebSocket.ACTION_PLAY_MEME, {FileName:fileID, IsKeyDown:true});
- }
- }
- /**
- * Stops any playing meme sound
- */
- public stopMeme():void {
- this.send(VoicemodWebSocket.ACTION_STOP_ALL_MEME_SOUNDS);
- }
- /*******************
- * PRIVATE METHODS *
- *******************/
- /**
- * Sends a data to Voicemod
- */
- private send(actionType: string, data?:any):void {
- let uuid = uuidv4();
- let json:any = {
- "actionID": uuid,
- "actionType": actionType,
- "context": "request:" + uuid,
- "pluginVersion": "2.0.0",
- };
- if(data) {
- json.actionObject = data;
- }
- this._socket.send( JSON.stringify(json) );
- }
- /**
- * Called when a message is received from Voicemod app
- */
- private onSocketMessage(event:VoicemodTypes.SocketEvent):void {
- let json:VoicemodTypes.SocketData = JSON.parse(event.data);
- if (json.server) {
- this.send(VoicemodWebSocket.ACTION_REGISTER_PLUGIN);
- return;
- }
- switch(json.actionType) {
- case VoicemodWebSocket.ACTION_REGISTER_PLUGIN:
- //Request all available voice effect list
- this.send(VoicemodWebSocket.ACTION_GET_VOICES);
- //Request all available meme sound list
- this.send(VoicemodWebSocket.ACTION_GET_MEMES);
- //Request all available bitmaps
- this.send(VoicemodWebSocket.ACTION_GET_BITMAP);
- break;
- case VoicemodWebSocket.ACTION_GET_VOICES:
- this._voicesList = json.actionObject.allVoices;
- this.checkInitComplete();
- break;
- case VoicemodWebSocket.ACTION_GET_MEMES:
- this._memesList = json.actionObject.listOfMemes;
- this.checkInitComplete();
- break;
- case VoicemodWebSocket.ACTION_GET_BITMAP:
- //JSON contains nothing much interesting
- //No idea what those bitmaps are supposed to be...
- break;
- case VoicemodWebSocket.EVENT_TOGGLE_MUTE:
- //TODO
- break;
- case VoicemodWebSocket.EVENT_TOGGLE_BACKGROUND:
- //TODO
- break;
- case VoicemodWebSocket.EVENT_TOGGLE_HEAR_MY_VOICE:
- //TODO
- break;
- case VoicemodWebSocket.EVENT_VOICE_CHANGED_EVENT:
- //TODO
- break;
- case VoicemodWebSocket.EVENT_TOGGLE_VOICE_CHANGER:
- //TODO
- break;
- default:
- console.log("Voicemod: unhandled actionType "+json.actionType);
- // console.log(json);
- }
- }
- /**
- * Check if voices and memes list are laoded and resolves the
- * connect promise.
- */
- private checkInitComplete():void {
- if(this._voicesList && this._memesList) {
- this._initResolver();
- }
- }
- }
- declare module VoicemodTypes {
- export interface SocketEvent {
- target:WebSocket;
- type:string;
- data:string;
- }
- export interface SocketData {
- actionType: string;
- appVersion: string;
- actionID?: any;
- actionObject: ActionObject;
- context: string;
- server?: string;
- }
- export interface ActionObject {
- allVoices?: Voice[];
- listOfMemes?: Meme[];
- favoriteVoices?: Voice[];
- customVoices?: Voice[];
- selectedVoice?: string;
- result?: Result;
- }
- export interface Voice {
- voiceID: string;
- friendlyName: string;
- }
- export interface Meme {
- FileName:string;
- Profile:string;
- Name:string;
- Type:string;
- Image:string;
- IsCore:boolean;
- }
- export interface Result {
- default: string;
- }
- }
Add Comment
Please, Sign In to add comment