mirror of
https://github.com/liyunze-coding/rython-task-bot-v2.git
synced 2026-11-06 08:43:33 +00:00
1 line
No EOL
29 KiB
JavaScript
1 line
No EOL
29 KiB
JavaScript
var Streamerbot=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){"@babel/helpers - typeof";return t=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},t(e)}function n(e,n){if(t(e)!=`object`||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var i=r.call(e,n||`default`);if(t(i)!=`object`)return i;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(n===`string`?String:Number)(e)}function r(e){var r=n(e,`string`);return t(r)==`symbol`?r:r+``}function i(e,t,n){return(t=r(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}let a=new class{constructor(e={}){i(this,`level`,void 0),i(this,`customLogger`,void 0),i(this,`logLevels`,{verbose:0,debug:1,info:2,warn:3,error:4,none:5}),this.level=e.level||`info`,this.customLogger=e.customLogger}setLevel(e){this.level=e}setCustomLogger(e){this.customLogger=e}verbose(...e){this.log(`verbose`,...e)}debug(...e){this.log(`debug`,...e)}info(...e){this.log(`info`,...e)}warn(...e){this.log(`warn`,...e)}error(...e){this.log(`error`,...e)}log(e,...t){if(!(this.logLevels[e]<this.logLevels[this.level]))if(this.customLogger)this.customLogger(e,...t);else switch(e){default:case`verbose`:console.log(...t);break;case`debug`:console.debug(...t);break;case`info`:console.info(...t);break;case`warn`:console.warn(...t);break;case`error`:console.error(...t);break}}},o={General:[`Custom`],Twitch:`Follow.Cheer.Sub.ReSub.GiftSub.GiftBomb.Raid.HypeTrainStart.HypeTrainUpdate.HypeTrainLevelUp.HypeTrainEnd.RewardRedemption.RewardCreated.RewardUpdated.RewardDeleted.CommunityGoalContribution.CommunityGoalEnded.StreamUpdate.Whisper.FirstWord.SubCounterRollover.BroadcastUpdate.StreamUpdateGameOnConnect.PresentViewers.PollCreated.PollUpdated.PollCompleted.PredictionCreated.PredictionUpdated.PredictionCompleted.PredictionCanceled.PredictionLocked.ChatMessage.ChatMessageDeleted.UserTimedOut.UserBanned.Announcement.AdRun.BotWhisper.CharityDonation.CharityCompleted.CoinCheer.ShoutoutCreated.UserUntimedOut.CharityStarted.CharityProgress.GoalBegin.GoalProgress.GoalEnd.ShieldModeBegin.ShieldModeEnd.StreamOnline.StreamOffline.ShoutoutReceived.ChatCleared.RaidStart.RaidSend.RaidCancelled.PollTerminated.PyramidSuccess.PyramidBroken.ViewerCountUpdate.GuestStarSessionBegin.GuestStarSessionEnd.GuestStarGuestUpdate.GuestStarSlotUpdate.GuestStarSettingsUpdate.HypeChat.RewardRedemptionUpdated.HypeChatLevel.BroadcasterAuthenticated.BroadcasterChatConnected.BroadcasterChatDisconnected.BroadcasterEventSubConnected.BroadcasterEventSubDisconnected.SevenTVEmoteAdded.SevenTVEmoteRemoved.BetterTTVEmoteAdded.BetterTTVEmoteRemoved.BotEventSubConnected.BotEventSubDisconnected.UpcomingAd.ModeratorAdded.ModeratorRemoved.VipAdded.VipRemoved.UserUnbanned.UnbanRequestApproved.UnbanRequestDenied.AutomaticRewardRedemption.UnbanRequestCreated.PowerUp.ChatEmoteModeOn.ChatEmoteModeOff.ChatFollowerModeOn.ChatFollowerModeOff.ChatFollowerModeChanged.ChatSlowModeOn.ChatSlowModeOff.ChatSlowModeChanged.ChatSubscriberModeOn.ChatSubscriberModeOff.ChatUniqueModeOn.ChatUniqueModeOff.AutoModMessageHeld.AutoModMessageUpdate.BlockedTermsAdded.BlockedTermsDeleted.WarnedUser.SuspiciousUserUpdate.PermittedTermsAdded.PermittedTermsDeleted.WarningAcknowledged.WatchStreak.PollArchived.SharedChatSessionBegin.SharedChatSessionUpdate.SharedChatSessionEnd.PrimePaidUpgrade.PayItForward.GiftPaidUpgrade.BitsBadgeTier.SharedChatAnnouncement.SharedChatRaid.SharedChatPrimePaidUpgrade.SharedChatGiftPaidUpgrade.SharedChatPayItForward.SharedChatSub.SharedChatResub.SharedChatSubGift.SharedChatCommunitySubGift.SharedChatUserBanned.SharedChatUserUnbanned.SharedChatUserTimedout.SharedChatUserUntimedout.SharedChatMessageDeleted`.split(`.`),Streamlabs:[`Donation`,`Merchandise`,`Connected`,`Disconnected`,`CharityDonation`,`Authenticated`],SpeechToText:[`Dictation`,`Command`],Command:[`Triggered`,`Cooldown`],FileWatcher:[`Changed`,`Created`,`Deleted`,`Renamed`],FileTail:[`Changed`],Quote:[`Added`,`Show`],Misc:[`TimedAction`,`Test`,`ProcessStarted`,`ProcessStopped`,`ChatWindowAction`,`StreamerbotStarted`,`StreamerbotExiting`,`ToastActivation`,`GlobalVariableUpdated`,`UserGlobalVariableUpdated`,`GlobalVariableCreated`,`GlobalVariableDeleted`,`ApplicationImport`],Raw:[`Action`,`SubAction`,`ActionCompleted`],WebsocketClient:[`Open`,`Close`,`Message`],StreamElements:[`Tip`,`Merch`,`Connected`,`Disconnected`,`Authenticated`],WebsocketCustomServer:[`Open`,`Close`,`Message`],DonorDrive:[`Donation`,`ProfileUpdated`,`Incentive`],YouTube:`BroadcastStarted.BroadcastEnded.Message.MessageDeleted.UserBanned.SuperChat.SuperSticker.NewSponsor.MemberMileStone.NewSponsorOnlyStarted.NewSponsorOnlyEnded.StatisticsUpdated.BroadcastUpdated.MembershipGift.GiftMembershipReceived.FirstWords.PresentViewers.NewSubscriber.BroadcastMonitoringStarted.BroadcastMonitoringEnded.BroadcastAdded.BroadcastRemoved.SevenTVEmoteAdded.SevenTVEmoteRemoved.BetterTTVEmoteAdded.BetterTTVEmoteRemoved.PollClosed.PollStarted.PollUpdated`.split(`.`),Pulsoid:[`HeartRatePulse`],HypeRate:[`HeartRatePulse`,`TwitchClipCreated`,`Connected`,`Disconnected`],Kofi:[`Donation`,`Subscription`,`Resubscription`,`ShopOrder`,`Commission`],Patreon:[`FollowCreated`,`FollowDeleted`,`PledgeCreated`,`PledgeUpdated`,`PledgeDeleted`],Application:[`ActionAdded`,`ActionUpdated`,`ActionDeleted`,`CommandAdded`,`CommandUpdated`,`CommandDeleted`],TipeeeStream:[`Donation`],TreatStream:[`Treat`,`Authenticated`,`Connected`,`Disconnected`],Shopify:[`OrderCreated`,`OrderPaid`],Obs:[`Connected`,`Disconnected`,`Event`,`SceneChanged`,`StreamingStarted`,`StreamingStopped`,`RecordingStarted`,`RecordingStopped`,`VendorEvent`],Midi:[`Message`],Inputs:[`InputKeyPress`,`InputMouseClick`],StreamDeck:[`Action`,`Connected`,`Disconnected`,`Info`],Custom:[`Event`,`CodeEvent`],VTubeStudio:[`ModelLoaded`,`ModelUnloaded`,`BackgroundChanged`,`ModelConfigChanged`,`HotkeyTriggered`,`ModelAnimation`,`Connected`,`Disconnected`,`TrackingStatusChanged`,`ItemEvent`,`ModelClicked`],CrowdControl:[`GameSessionStart`,`GameSessionEnd`,`EffectRequest`,`EffectSuccess`,`EffectFailure`,`TimedEffectStarted`,`TimedEffectEnded`,`TimedEffectUpdated`,`CoinExchange`],Elgato:`WaveLinkOutputSwitched.WaveLinkOutputVolumeChanged.WaveLinkOutputMuteChanged.WaveLinkSelectedOutputChanged.WaveLinkInputVolumeChanged.WaveLinkInputMuteChanged.WaveLinkInputNameChanged.WaveLinkMicrophoneGainChanged.WaveLinkMicrophoneOutputVolumeChanged.WaveLinkMicrophoneBalanceChanged.WaveLinkMicrophoneMuteChanged.WaveLinkMicrophoneSettingChanged.WaveLinkFilterAdded.WaveLinkFilterChanged.WaveLinkFilterDeleted.WaveLinkFilterBypassStateChanged.WaveLinkConnected.WaveLinkDisconnected.WaveLinkInputLevelMeterChanged.WaveLinkOutputLevelMeterChanged.CameraHubConnected.CameraHubDisconnected.CameraHubWebcamConnected.CameraHubWebcamrDisconnected.CameraHubWebcamActivated.CameraHubWebcamDeactivated.CameraHubSelectedWebcamChanged.CameraHubWebcamMirrored.CameraHubWebcamFlipped.CameraHubWebcamDeviceOrientationChanged.CameraHubWebcamExposureAutoLockEnabled.CameraHubWebcamExposureAutoLockDisabled.CameraHubWebcamSnapshotTaken.CameraHubWebcamZoomChanged.CameraHubWebcamContrastChanged.CameraHubWebcamWhiteBalanceChanged.CameraHubWebcamAutoExposureEnabled.CameraHubWebcamAutoExposureDisabled.CameraHubWebcamAutoWhiteBalanceEnabled.CameraHubWebcamAutoWhiteBalanceDisabled.CameraHubWebcamNoiseReductionEnabled.CameraHubWebcamNoiseReductionDisabled.CameraHubWebcamISOChanged.CameraHubWebcamShutterSpeedChanged.CameraHubWebcamSharpnessChanged.CameraHubWebcamAntiFlickerChanged.CameraHubWebcamLensChanged.CameraHubWebcamARLensChanged.CameraHubWebcamBitrateChanged.CameraHubWebcamFlashEnabled.CameraHubWebcamFlashDisabled.CameraHubWebcamPanChanged.CameraHubTiltChanged.CameraHubWebcamOverscanChanged.CameraHubWebcamAutoFocusEnabled.CameraHubWebcamAutoFocusDisabled.CameraHubWebcamFocusChanged.CameraHubWebcamWhiteBalanceTintChanged.CameraHubWebcamBrightnessChanged.CameraHubWebcamSaturationChanged.CameraHubWebcamLiveISOChanged.CameraHubWebcamLiveShutterSpeedChanged.CameraHubWebcamLiveWhiteBalanceChanged.CameraHubWebcamLiveWhiteBalanceTintChanged.CameraHubPrompterConnected.CameraHubPrompterDisconnected.CameraHubPrompterModeChanged.CameraHubPrompterBrightnessChanged.CameraHubPrompterFontChanged.CameraHubPrompterFontSizeChanged.CameraHubPrompterAutoScrollEnabled.CameraHubPrompterAutoScrollDisabled.CameraHubPrompterAutoScrollChapterEnabled.CameraHubPrompterAutoScrollChapterDisabled.CameraHubPrompterScrollSpeedChanged.CameraHubPrompterOpacityChanged.CameraHubPrompterHorizontalMarginChanged.CameraHubPrompterVerticalMarginChanged.CameraHubPrompterLineSpacingChanged.CameraHubPrompterFontColorChanged.CameraHubPrompterBackgroundColorChanged.CameraHubPrompterSelectedChapterChanged.CameraHubPrompterChannelsChanged.CameraHubPrompterSelectedChannelChanged.CameraHubPrompterContrastChanged.CameraHubPrompterCrosshairEnabled.CameraHubPrompterCrosshairDisabled.CameraHubPrompterCrosshairImageChanged.CameraHubPrompterCrosshairColorChanged.CameraHubPrompterSelectedScriptChanged`.split(`.`),StreamlabsDesktop:[`Connected`,`Disconnected`,`SceneChanged`,`StreamingStarted`,`StreamingStopped`,`RecordingStarted`,`RecordingStopped`],SpeakerBot:[`Connected`,`Disconnected`],Fourthwall:[`ProductCreated`,`ProductUpdated`,`GiftPurchase`,`OrderPlaced`,`OrderUpdated`,`Donation`,`SubscriptionPurchased`,`SubscriptionExpired`,`SubscriptionChanged`,`ThankYouSent`,`NewsletterSubscribed`,`GiftDrawStarted`,`GiftDrawEnded`],Trovo:[`BroadcasterAuthenticated`,`BroadcasterChatConnected`,`BroadcasterChatDisconnected`,`FirstWords`,`PresentViewers`,`ChatMessage`,`Follow`,`SpellCast`,`CustomSpellCast`,`Raid`,`Subscription`,`Resubscription`,`GiftSubscription`,`MassGiftSubscription`,`StreamOnline`,`StreamOffline`],ThrowingSystem:[`Connected`,`WebsocketConnected`,`WebsocketDisconnected`,`EventsConnected`,`EventsDisconnected`,`ItemHit`,`TriggerActivated`,`TriggerEnded`],Pallygg:[`Connected`,`Disconnected`,`CampaignTip`],StreamerBotRemote:[`InstanceConnected`,`InstanceDisconnected`,`InstanceTrigger`,`InstanceSignal`],VoiceMod:[`Connected`,`Disconnected`,`VoiceLoaded`,`SoundboardChanged`],Group:[`Added`,`Removed`,`Cleared`,`UsersAdded`,`UsersRemoved`],MeldStudio:[`Connected`,`Disconnected`,`StreamingStarted`,`StreamingStopped`,`RecordingStarted`,`RecordingStopped`,`SceneChanged`,`LayerVisbilityChanged`,`LEffectEnabledStateChanged`,`TrackMonitoringStateChanged`,`TrackMustedStateChanged`,`Event`],StreamerBot:[`CustomWebook`],Kick:[`BroadcasterAuthenticated`,`BroadcasterChatConnected`,`BroadcasterChatDisconnected`,`FirstWords`,`PresentViewers`,`ChatMessage`,`Follow`,`StreamOnline`,`StreamOffline`,`Subscription`,`Resubscription`,`GiftSubscription`,`MassGiftSubscription`,`UserTimedOut`,`UserBanned`,`ChannelUpdate`,`SevenTVEmoteAdded`,`SevenTVEmoteRemoved`,`ViewerCountUpdate`],System:[`ClipboardChanged`]},s=globalThis.crypto,c=s.subtle,l=e=>s.getRandomValues(e);function u(e=`req`){return`sb:client:${e}:${Date.now()}-${l(new Uint32Array(12))[0]}`}function d(e){let t;return t=e.code==1e3?`Connection closed.`:e.code==1001?`Endpoint is "going away".`:e.code==1002?`Connection closed due to a protocol error.`:e.code==1003||e.code==1007||e.code==1008||e.code==1010?`Bad request.`:e.code==1004?`Reserved`:e.code==1005?`Missing status code.`:e.code==1006?`The connection was closed abnormally.`:e.code==1009?`Message size limit exceeded.`:e.code==1011?`Server terminated connection because due to unexpected condition.`:e.code==1015?`TLS handshake failure`:`Unknown error`,t}async function f(e,t){let{timeout:n,message:r=`Operation timed out.`,controller:i}=t,a;return await Promise.race([new Promise((e,o)=>{a=setTimeout(()=>(i.abort(),console.debug(`[withTimeout] timeout reached`,t),o(Error(r))),n),t.signal?.addEventListener(`abort`,()=>{clearTimeout(a),i?.abort(),o(Error(`Operation aborted.`))},{once:!0,signal:i.signal})}),e]).finally(()=>{clearTimeout(a),i.abort()})}async function p(e){let t=new TextEncoder().encode(e),n=await c.digest(`SHA-256`,t);return m(Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``))}function m(e){let t=new Uint8Array(e.match(/.{1,2}/g).map(e=>parseInt(e,16)));return btoa(String.fromCharCode.apply(null,Array.from(t)))}function h({timeout:e=1e4,addEventListener:t,removeEventListener:n}){let r=u(`res`),i=new AbortController,a=i.signal;return{responseId:r,promise:new Promise((o,s)=>{let c=e=>{let t=e?.data;t?.eventName===r&&(i.abort(),o(t?.args))};t(`Custom.Event`,c);let l=setTimeout(()=>{i.abort(),s(Error(`Timed out waiting for Custom Event`))},e);a.addEventListener(`abort`,()=>{clearTimeout(l),n(e=>e.events?.includes(`Custom.Event`)&&e.callback===c)},{once:!0})}),controller:i}}let g={scheme:`ws`,host:`127.0.0.1`,port:8080,endpoint:`/`,immediate:!0,autoReconnect:!0,retries:-1,subscribe:{},logger:a,logLevel:`info`};var _=class{constructor(e=g){i(this,`options`,void 0),i(this,`logger`,void 0),i(this,`socket`,void 0),i(this,`info`,void 0),i(this,`version`,void 0),i(this,`supportedEvents`,void 0),i(this,`_authEnabled`,!1),i(this,`_authenticated`,!1),i(this,`listeners`,[]),i(this,`subscriptions`,{}),i(this,`_explicitlyClosed`,!1),i(this,`_retried`,0),i(this,`_connectController`,new AbortController),i(this,`_reconnectTimeout`,void 0),this.options={...g,...e},this.logger=this.options.logger||null,this.logger&&this.options.logLevel&&this.logger.setLevel(this.options.logLevel),!0===this.options.immediate&&this.connect().catch(e=>this.logger?.warn(`Failed to connect:`,e))}get authenticated(){return!!this.socket&&this.socket.readyState===this.socket.OPEN&&this._authenticated}get ready(){return!this.socket||this.socket.readyState!==this.socket.OPEN||this._authEnabled&&!this._authenticated?!1:!!this.info&&!!this.version}async connect(e=1e4){if(this.socket?.readyState!==this.socket?.CLOSED)try{await this.disconnect()}catch(e){this.logger?.warn(`Unexpected error while calling disconnect():`,e)}this._explicitlyClosed=!1,this._connectController.abort(),this._connectController=new AbortController;let t=new AbortController,{signal:n}=t;return this._connectController.signal.addEventListener(`abort`,()=>t.abort(),{once:!0,signal:n}),await f(new Promise((e,t)=>{try{this.options.password&&(this._authEnabled=!0);let r=`${this.options.scheme}://${this.options.host}:${this.options.port}${this.options.endpoint}`;this.logger?.debug(`Connecting to Streamer.bot WebSocket server at`,r,this._authEnabled?`with authentication`:``),this.socket=new WebSocket(r),this.socket.onmessage=this.onMessage.bind(this),this.socket.onopen=this.onOpen.bind(this),this.socket.onclose=this.onClose.bind(this),this.socket.onerror=this.onError.bind(this),this.socket.addEventListener(`open`,()=>{if(!this.socket)return t(Error(`WebSocket not initialized`));e()},{once:!0,signal:n}),this.socket.addEventListener(`close`,()=>t(Error(`WebSocket closed`)),{once:!0,signal:n})}catch(e){this.disconnect().catch(e=>this.logger?.warn(`Unexpected error while calling disconnect():`,e)),this?.options?.onError?.(e),t(e)}}),{timeout:e,message:`WebSocket connection timeout exceeded`,controller:t,signal:this._connectController.signal})}async disconnect(e=1e3,t=1e3){if(this._explicitlyClosed=!0,this._connectController.abort(),this._reconnectTimeout&&clearTimeout(this._reconnectTimeout),!this.socket||this.socket.readyState===this.socket.CLOSED)return;let n=new AbortController,r=n.signal;return this._connectController.signal.addEventListener(`abort`,()=>n.abort(),{once:!0,signal:r}),await f(new Promise((t,n)=>{if(this.socket&&(this.socket.addEventListener(`close`,()=>{this.logger?.debug(`Disconnected from Streamer.bot WebSocket server`),t()},{signal:r}),this.socket.readyState!==this.socket.CLOSING))try{this.socket?.close(e)}catch(e){n(e)}}),{timeout:t,message:`Timeout exceeded while closing connection`,controller:n,signal:this._connectController.signal})}async handshake(){if(!this.socket)throw Error(`WebSocket not initialized`);let e=new AbortController,{signal:t}=e;this._connectController.signal.addEventListener(`abort`,()=>e.abort(),{once:!0,signal:t});let n=await f(new Promise((e,n)=>{this.socket&&this.socket.addEventListener(`message`,async t=>{if(!(`data`in t)||!t.data||typeof t.data!=`string`){this.logger?.debug(`Unknown message received :: ${typeof t}`);return}try{let n=JSON.parse(t.data);n&&`info`in n&&e(n)}catch(e){this.logger?.warn(`Invalid JSON payload received`,t.data),n(e)}},{signal:t})}),{timeout:5e3,message:`Handshake timeout exceeded`,controller:e,signal:this._connectController.signal});if(!n||!(`info`in n))throw Error(`Handshake failed (invalid payload)`);if(`request`in n&&n?.request===`Hello`&&n.authentication)return await this.authenticate(n);if(n.info&&!n.authentication){this.logger?.debug(`Connected to Streamer.bot WebSocket server`,n.info),this.info=n.info,this.version=n.info.version;return}throw Error(`Handshake failed (unknown)`)}async authenticate(e){if(!this._authEnabled||!this.options.password){if(this.logger?.debug(`No password provided for authentication. Checking if auth is enforced for all requests...`),(await this.getInfo()).status===`ok`){this._authenticated=!1,this.version=e.info.version,this.info=e.info;return}throw await this.disconnect(),Error(`Authentication required`)}if(!e.authentication)throw this.logger?.debug(`Missing authentication payload`),await this.disconnect(),Error(`Invalid authentication payload`);this.logger?.debug(`Authenticating with Streamer.bot WebSocket server...`);let{salt:t,challenge:n}=e.authentication,r=await p(`${await p(`${this.options.password}${t}`)}${n}`);if((await this.request({request:`Authenticate`,authentication:r})).status===`ok`)this._authenticated=!0,this.version=e.info.version,this.info=e.info;else throw await this.disconnect(),Error(`Authentication failed`)}async onOpen(){this._retried=0,this._reconnectTimeout&&clearTimeout(this._reconnectTimeout);try{this._authEnabled||this.getInfo().catch(()=>this.logger?.debug(`Failed to fetch Streamer.bot instance info`)),await this.handshake(),this.version&&this.info&&(this.logger?.debug(`Connected to Streamer.bot: v${this.version} (${this.info.name})`),await this.updateSupportedEvents(),this?.options?.onConnect?.(this.info))}catch(e){return this.logger?.warn(`Failed handshake with Streamer.bot`,e),this.options?.onError?.(e instanceof Error?e:Error(`Failed handshake with Streamer.bot`)),await this.disconnect()}try{if(this.options.subscribe===`*`||typeof this.options.subscribe==`object`&&!Array.isArray(this.options.subscribe)&&Object.keys(this.options.subscribe??{}).length)this.logger?.debug(`Subscribing to initial events from options:`,this.options.subscribe),await this.subscribe(this.options.subscribe);else if(typeof this.options.subscribe==`string`||Array.isArray(this.options.subscribe)){this.logger?.debug(`Subscribing to initial events from options:`,this.options.subscribe);let e=await this.getSubscriptionsFromEventStrings(this.options.subscribe);this.logger?.debug(`Parsed subscriptions from options:`,e),e&&await this.subscribe(e)}if(this.listeners.length){let e=await this.getSubscriptionsFromListeners();await this.subscribe(e)}this.logger?.verbose(`Subscribed to requested events`,this.subscriptions,this.listeners)}catch(e){this.logger?.warn(`Error subscribing to requested events`,e)}}onClose(e){this._connectController.abort();try{(e.type===`error`||!e.wasClean)&&this.options.onError&&this?.options?.onError(Error(d(e))),this?.options?.onDisconnect?.()}catch(e){this.logger?.warn(`Error invoking user-provided onDisconnect handler`,e)}if(this._explicitlyClosed||!this.options.autoReconnect)return this.logger?.debug(`Cleaning up...`),this.cleanup();this._retried+=1,typeof this.options.retries==`number`&&(this.options.retries<0||this._retried<this.options.retries)?(this._reconnectTimeout&&clearTimeout(this._reconnectTimeout),this._reconnectTimeout=setTimeout(async()=>{if(!(this.socket&&this.socket.readyState!==this.socket.CLOSED)){this.logger?.debug(`Reconnecting... (attempt ${this._retried})`);try{await this.connect(1e4)}catch(e){this._retried&&this.logger?.warn(`Failed to reconnect (attempt ${this._retried-1})`,e)}}},Math.min(3e4,this._retried*1e3))):(this.logger?.debug(`Auto-reconnect limit reached. Cleaning up...`),this.cleanup())}async onMessage(e){if(!e.data||typeof e.data!=`string`){this.logger?.debug(`Unknown message received`,e,e.data);return}let t;try{t=JSON.parse(e.data)}catch(t){this.logger?.warn(`Invalid JSON payload received`,e.data,t);return}this.logger?.verbose(`RECV`,t);try{this.options.onData&&this?.options?.onData(t)}catch(e){this.logger?.warn(`Error occurred within user-provided onData callback`,e)}if(t?.event?.source&&t?.event?.type){for(let e of this.listeners)if(e.events?.length&&e.events.find(e=>e===`*`||e===`${t?.event?.source}.${t?.event?.type}`||e.split(`.`,2)?.[1]===`*`&&e.split(`.`,2)?.[0]===t?.event?.source))try{e.callback(t)}catch(t){this.logger?.warn(`Error occurred within user-provided event callback (${e.events})`,t)}}}onError(e){this.logger?.debug(`WebSocket onError`,e),this.socket&&this.socket.readyState!==this.socket.OPEN&&this._connectController.abort();try{this?.options?.onError?.(Error(`WebSocket Error`))}catch(e){this.logger?.warn(`Error occurred within user-provided onError callback`,e)}}cleanup(){this.socket&&(this.socket.onopen=null,this.socket.onclose=null,this.socket.onerror=null,this.socket.onmessage=null,this.socket=void 0),this.listeners=[],this._retried=0,this._connectController.abort(),this._reconnectTimeout&&clearTimeout(this._reconnectTimeout)}send(e){this.socket?.send(JSON.stringify(e))}async request(e,t=``,n=1e4){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw Error(`WebSocket is not connected`);t||(t=u());let r=new AbortController,i=r.signal;this._connectController.signal.addEventListener(`abort`,()=>r.abort(),{once:!0,signal:i});let a=await f(new Promise((n,r)=>{this.socket&&(this.socket.addEventListener(`message`,i=>{if(!(`data`in i)||!i.data||typeof i.data!=`string`){this.logger?.debug(`Unknown message received`,i.data);return}try{let r=JSON.parse(i?.data);if(r?.id===t)return this.logger?.verbose(`RECV :: ${e.request}`,r),n(r)}catch(e){this.logger?.warn(`Invalid JSON payload received`,i.data),r(e)}},{signal:i}),this.logger?.verbose(`SEND :: ${e.request}`,{...e,id:t}),this.send({...e,id:t}))}),{timeout:n,message:`Request timed out`,controller:r,signal:this._connectController.signal});if(a?.status===`ok`){try{this.options.onData&&this?.options?.onData(a)}catch(e){this.logger?.warn(`Error invoking onData handler`,e)}return{event:{source:`Request`,type:e.request??`Unknown`},...a}}throw Error(`Request failed`)}async on(e,t){try{if(!e)return;let n={events:[e],callback:t};if(this.listeners.push(n),this.ready){let e=await this.getSubscriptionsFromListeners([n]);await this.subscribe(e)}this.logger?.debug(`LISTEN :: ${e}`)}catch(t){this.logger?.warn(`LISTEN :: ${e} :: Unexpected error while adding listener`,t)}}async updateSupportedEvents(){if(this.ready)try{let e=await this.getEvents();if(e.status!==`ok`||!e.events)throw Error(e.status);this.supportedEvents=e.events,this.logger?.debug(`Successfully fetched supported event types for Streamer.bot v${this.version}`)}catch(e){this.logger?.warn(`Failed to fetch supported events from Streamer.bot, falling back to stored events type.`,e),this.supportedEvents=o}}async getSupportedEvents(){return this.supportedEvents||(this.logger?.warn(`Supported event types not yet initialized, fetching from Streamer.bot instance...`),await this.updateSupportedEvents()),this.supportedEvents??o}getEventsFromListeners(e){return(e??this.listeners).reduce((e,t)=>(t.events.forEach(n=>{e[n]||(e[n]=[]),e[n].push(t.callback)}),e),{})}async getSubscriptionsFromListeners(e){let t=this.getEventsFromListeners(e);return this.getSubscriptionsFromEventStrings(Object.keys(t))}async getSubscriptionsFromEventStrings(e){let t={};typeof e==`string`&&(e=[e]);for(let n of e){let e=await this.parseEventString(n);if(e)for(let n of e){let{source:e,eventTypes:r}=n;t[e]=[...new Set([...t[e]??[],...r])]}}return t}async parseEventString(e){let t=await this.getSupportedEvents();if(!e||typeof e!=`string`){this.logger?.warn(`Invalid event subscription requested "${e}"`);return}if(e===`*`)return Object.keys(t).map(e=>{let n=e;return{source:n,eventTypes:t[n]??[]}});{let[n,r]=e.split(`.`,2);if(!n||!r||!(n in t)){this.logger?.warn(`Invalid event subscription requested "${e}"`);return}let i=n,a=r;if(a)return[{source:i,eventTypes:a===`*`?t[i]:[a]}];this.logger?.warn(`Invalid event type requested "${e}"`);return}}async subscribe(e){let t=await this.getSupportedEvents();e===`*`&&(e=t);for(let n in e){if(!n||n===`err`)continue;if(!(n in t)){this.logger?.warn(`Attempted to subscribe to empty or unknown event source: "${n}"`,Object.keys(e));continue}let r=n,i=e[r]??[];if(i&&i.length){let e=new Set([...this.subscriptions[r]??[],...i]);this.subscriptions[r]=[...e]}}return Object.keys(this.subscriptions).length===0?(this.logger?.warn(`No valid events to subscribe to. Please provide valid event sources and types.`),{id:`invalid`,status:`error`,error:`No valid events to subscribe to`}):await this.request({request:`Subscribe`,events:this.subscriptions})}async unsubscribe(e){let t=await this.getSupportedEvents();e===`*`&&(e=t);for(let n in e){if(n===void 0||!Object.keys(t).includes(n))continue;let r=n,i=e[r];if(i&&i.length)for(let e of i)e&&this.subscriptions[r]?.filter&&(this.subscriptions[r]=this.subscriptions[r])?.filter(t=>e!==t)}return await this.request({request:`UnSubscribe`,events:e})}async getEvents(){return await this.request({request:`GetEvents`})}async getActions(){return await this.request({request:`GetActions`})}async doAction(e,t,n){if(n?.customEventResponse)return this.doActionWithCustomEventResponse(e,t);let r,i;return typeof e==`string`?r=e:(r=e.id,i=e.name),await this.request({request:`DoAction`,action:{id:r,name:i},args:t})}async doActionWithCustomEventResponse(e,t={},n=1e4){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw Error(`WebSocket is not connected`);let{responseId:r,promise:i,controller:a}=h({timeout:n,addEventListener:(e,t)=>this.on(e,t),removeEventListener:e=>{this.listeners=this.listeners.filter(t=>!e(t))}}),o={...t,sbClientResponse:r};try{let t=await this.doAction(e,o),n=await i;return{...t,customEventResponseArgs:n}}catch(e){throw a.signal.aborted||a.abort(),e}}async getBroadcaster(){return await this.request({request:`GetBroadcaster`})}async getMonitoredYouTubeBroadcasts(){return await this.request({request:`GetMonitoredYouTubeBroadcasts`})}async getCredits(){return await this.request({request:`GetCredits`})}async testCredits(){return await this.request({request:`TestCredits`})}async clearCredits(){return await this.request({request:`ClearCredits`})}async getInfo(){return await this.request({request:`GetInfo`})}async getActiveViewers(){return await this.request({request:`GetActiveViewers`})}async executeCodeTrigger(e,t,n){return n?.customEventResponse?this.executeCodeTriggerWithCustomEventResponse(e,t):await this.request({request:`ExecuteCodeTrigger`,triggerName:e,args:t})}async executeCodeTriggerWithCustomEventResponse(e,t={},n=1e4){if(!this.socket||this.socket.readyState!==this.socket.OPEN)throw Error(`WebSocket is not connected`);let{responseId:r,promise:i,controller:a}=h({timeout:n,addEventListener:(e,t)=>this.on(e,t),removeEventListener:e=>{this.listeners=this.listeners.filter(t=>!e(t))}}),o={...t,sbClientResponse:r};try{let t=await this.executeCodeTrigger(e,o),n=await i;return{...t,customEventResponseArgs:n}}catch(e){throw a.signal.aborted||a.abort(),e}}async getCodeTriggers(){return await this.request({request:`GetCodeTriggers`})}async getCommands(){return await this.request({request:`GetCommands`})}async getEmotes(e){switch(e){case`twitch`:return await this.request({request:`TwitchGetEmotes`});case`youtube`:return await this.request({request:`YouTubeGetEmotes`});default:throw Error(`Invalid platform`)}}async getGlobals(e=!0){return await this.request({request:`GetGlobals`,persisted:e})}async getGlobal(e,t=!0){let n=await this.request({request:`GetGlobal`,variable:e,persisted:t});return n.status===`ok`?n.variables[e]?{id:n.id,status:n.status,variable:n.variables[e]}:{status:`error`,error:`Variable not found`}:n}async getUserGlobals(e,t=null,n=!0){let r={twitch:`TwitchGetUserGlobals`,youtube:`YouTubeGetUserGlobals`,trovo:`TrovoGetUserGlobals`,kick:`KickGetUserGlobals`}[e];if(!r)throw Error(`Invalid platform`);return await this.request({request:r,variable:t,persisted:n})}async getUserGlobal(e,t,n=null,r=!0){let i={twitch:`TwitchGetUserGlobal`,youtube:`YouTubeGetUserGlobal`,trovo:`TrovoGetUserGlobal`,kick:`KickGetUserGlobal`}[e];if(!i)throw Error(`Invalid platform`);let a=await this.request({request:i,userId:t,variable:n||null,persisted:r});if(a.status===`ok`&&t&&n){let e=a.variables.find(e=>e.name===n);return e?{id:a.id,status:a.status,variable:e}:{status:`error`,error:`Variable not found`}}return a}async sendMessage(e,t,{bot:n=!1,internal:r=!0,...i}={}){if(!this._authenticated)return{status:`error`,error:`Authentication required`};let a={platform:e,message:t,bot:n,internal:r};return[`twitch`,`kick`].includes(e)&&i.replyId&&Object.assign(a,{replyId:i.replyId}),[`youtube`].includes(e)&&i.broadcastId&&Object.assign(a,{broadcastId:i.broadcastId}),await this.request({...a,request:`SendMessage`})}async getUserPronouns(e,t){return await this.request({request:`GetUserPronouns`,platform:e,userLogin:t})}};return Object.assign(globalThis,{StreamerbotClient:_}),e.Client=_,e})({}); |