From 343ea2e2e943dd7e428ff2769f1c9d650f958147 Mon Sep 17 00:00:00 2001 From: sugoidogo Date: Sun, 9 Feb 2025 04:01:11 +0000 Subject: [PATCH] pubsub depreciation --- .gitignore | 1 + index.html | 2 +- js/script.js | 320 ++++++++++---------------------------- package-lock.json | 385 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 + 5 files changed, 472 insertions(+), 243 deletions(-) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/index.html b/index.html index 16dc2da..77b62db 100644 --- a/index.html +++ b/index.html @@ -21,6 +21,6 @@ integrity="sha256-yr4fRk/GU1ehYJPAs8P4JlTgu0Hdsp4ZKrx8bDEDC3I=" crossorigin="anonymous"> - + \ No newline at end of file diff --git a/js/script.js b/js/script.js index 0b2340c..b490ff8 100644 --- a/js/script.js +++ b/js/script.js @@ -1,27 +1,20 @@ -import('https://cdn.jsdelivr.net/npm/@sentry/browser@8/+esm').then(sentry=>{ - sentry.init({ - dsn:'https://f5fe0dec9f2f42dc80153b67e7e00dd0@app.glitchtip.com/8359', - environment:location.hostname, - release:"1.1.0" - }) -}).catch(e=>{ - console.warn('automatic error reporting failed to load',e) -}) +import AuthProvider from 'https://ebs.sugoidogo.com/SugoiAuthProvider.mjs' +import WebStorage from 'https://ebs.sugoidogo.com/WebStorage.mjs' +import { ApiClient } from 'https://cdn.jsdelivr.net/npm/@twurple/api@7/+esm' +import { EventSubWsListener } from 'https://cdn.jsdelivr.net/npm/@twurple/eventsub-ws@7/+esm' -try{ - if(window.location.search.includes('remotejs')){ - const channel=new URLSearchParams(window.location.search).get('remotejs') - const script=document.createElement('script') - script.src='https://remotejs.com/agent/agent.js' - script.setAttribute("data-consolejs-channel",channel) - document.head.appendChild(script) - } -}catch(e){ - console.warn('remotejs load failed',e) -} +const client_id = 'ib2n7v7mur7ab2mcxv7rjju2ctsyoi' -const client_id='ib2n7v7mur7ab2mcxv7rjju2ctsyoi' -const message_ids=[] +/** @type {import('../node_modules/twitch-cloud-ebs/static/SugoiAuthProvider.mjs').default} */ +const authProvider = new AuthProvider(client_id) +/** @type {import('../node_modules/twitch-cloud-ebs/static/WebStorage.mjs').default} */ +const webStorage = new WebStorage(authProvider) +/** @type {import('@twurple/api').ApiClient} */ +const apiClient = new ApiClient({ authProvider }) +/** @type {import('@twurple/eventsub-ws').EventSubWsListener} */ +const eventSub = new EventSubWsListener({ apiClient }) + +const message_ids = [] const timer=document.querySelector('#timeText') let tba,tokens,pubsub,ping_tid,pong_tid,eventsub,sse,time_started,time_passed,time_total,config,localforage,streamelements /** @type WebSocket */ @@ -31,31 +24,9 @@ window.onanimationend=function(event){ event.target.remove() } -window.onload=async function(){ - // init localforage - localforage=(await import('https://cdn.jsdelivr.net/npm/localforage/+esm')).default - localforage=localforage.createInstance({name:'sugoi-subathon-countdown'}) - // init timer display - time_started=await localforage.getItem('time_started') - time_passed=await localforage.getItem('time_passed') - time_total=await localforage.getItem('time_total') - updateTime() - // init twitch api tokens - tba=await import('https://tba.sugoidogo.com/tba.mjs') - tokens=await tba.get_tokens(client_id) - // load user config - await load_config() - // init event sources - init_irc() - init_pubsub() - init_eventsub() - if('streamelements-token' in config){ - init_streamelements() - } -} - -function handle_event(event_name,event_amount=1){ - if(!config[event_name+'-time-enabled']){ +function handle_event(event_name, event_amount = 1) { + console.debug(event_name,event_amount) + if (!config[event_name + '-time-enabled']) { return false } add_time(parseReadableTimeIntoMilliseconds(config[event_name+'-time'])*event_amount) @@ -72,7 +43,7 @@ function reset(){ } function load_config(){ - return fetch('https://ts.sugoidogo.com/config.json',{headers:tokens.auth_headers}) + return webStorage.fetch('config.json',{headers:tokens.auth_headers}) .then(response=>response.json()) .then(json=>{ config=json @@ -184,71 +155,9 @@ function updateTime(){ requestAnimationFrame(updateTime) } -function init_pubsub(){ - if(pong_tid){ - clearTimeout(pong_tid) - pong_tid=null - } - if(ping_tid){ - clearTimeout(ping_tid) - ping_tid=null - } - if(pubsub){ - pubsub.close() - } - pubsub=new WebSocket('wss://pubsub-edge.twitch.tv') - pubsub.onopen=function(){ - pubsub.send(JSON.stringify({ - "type":"LISTEN", - "data":{ - "auth_token":tokens.access_token, - "topics":[ - "channel-bits-events-v2."+tokens.user_id, - "channel-subscribe-events-v1."+tokens.user_id - ] - } - })) - } - pubsub.onmessage=function(event){ - let message=JSON.parse(event.data) - console.debug(message) - switch(message.type){ - case 'RESPONSE':{ - if(message.error){ - throw message.error - } - pubsub_ping() - break - } - case 'PONG':{ - clearTimeout(pong_tid) - pong_tid=null - break - } - case 'RECONNECT':{ - init_pubsub() - break - } - case 'AUTH_REVOKED':{ - location.reload() - break - } - case 'MESSAGE':{ - message=JSON.parse(message.data.message) - console.debug(message) - if('sub_plan' in message){ - handle_event('sub'+message.sub_plan) - break - } - message=message.data - console.debug(message) - if('bits_used' in message){ - handle_event('bit',message.bits_used) - break - } - } - } - } +function init_pubsub() { + eventSub.onChannelSubscription(tokens.user_id, event => handle_event('sub' + event.tier)) + eventSub.onChannelCheer(tokens.user_id, event => handle_event('bit ', event.bits)) } function pubsub_ping(){ @@ -258,84 +167,10 @@ function pubsub_ping(){ pong_tid=setTimeout(init_pubsub,20000) } -function init_eventsub(){ - eventsub=new WebSocket('wss://eventsub.wss.twitch.tv/ws') - eventsub.onmessage=function(event){ - let message=JSON.parse(event.data) - console.debug(message) - if(message.metadata.message_id in message_ids){ - return - }else{ - message_ids.push(message.metadata.message_id) - } - switch(message.metadata.message_type){ - case 'session_welcome':{ - let session_id=message.payload.session.id - const headers={'content-type':'application/json'} - Object.assign(headers,tokens.auth_headers) - const url=new URL('https://api.twitch.tv/helix/eventsub/subscriptions') - subscriptions=[ - { - "type": "channel.follow", - "version": "2", - "condition": { - "broadcaster_user_id": tokens.user_id, - "moderator_user_id": tokens.user_id - }, - "transport": { - "method": "websocket", - "session_id": session_id, - } - }, - { - "type": "channel.raid", - "version": "1", - "condition": { - "to_broadcaster_user_id": tokens.user_id - }, - "transport": { - "method": "websocket", - "session_id": session_id, - } - }, - { - "type": "channel.charity_campaign.donate", - "version": "1", - "condition": { - "broadcaster_user_id": tokens.user_id - }, - "transport": { - "method": "websocket", - "session_id": session_id, - } - } - ] - for(const subscription of subscriptions){ - fetch(url,{ - headers:headers, - method:"POST", - body:JSON.stringify(subscription) - }) - } - break - } - case 'notification':{ - switch(message.metadata.subscription_type){ - case 'channel.follow':{ - handle_event('follow') - break - } - case 'channel.raid':{ - handle_event('raid') - break - } - case 'channel.charity_campaign.donate':{ - handle_event('charity',message.event.amount.value) - } - } - } - } - } +function init_eventsub() { + eventSub.onChannelFollow(tokens.user_id, tokens.user_id, event => handle_event('follow')) + eventSub.onChannelRaidFrom(tokens.user_id, event => handle_event('raid')) + eventSub.onChannelCharityDonation(tokens.user_id, event => handle_event('charity', event.amount.value)) } function ircSend(message){ @@ -343,62 +178,32 @@ function ircSend(message){ irc.send(message) } -async function init_irc(){ - if(irc){ - irc.onclose=null - irc.close() - } - irc=new WebSocket('wss://irc-ws.chat.twitch.tv:443') - irc.onclose=init_irc - irc.onerror=init_irc - irc.onopen=function(){ - ircSend('CAP REQ twitch.tv/tags') - ircSend('PASS oauth:'+tokens.access_token) - ircSend('NICK '+tokens.login) - ircSend('JOIN #'+tokens.login) - //ircSend('PRIVMSG #'+tokens.login+' :SugoiSubathon connected') - } - irc.onmessage=function(event){ - console.debug(event) - for(let data of event.data.split('\r\n')){ - console.debug('> '+data) - /** @type string */ - data=data.split(':') - const tags=data.shift() - const type=data.shift() - const message=data.join(':') - console.debug(tags,type,message) - if(!message){ - continue +async function init_irc() { + eventSub.onChannelChatMessage(tokens.user_id, tokens.user_id, event => { + console.debug('> ' + event.messageText) + const command = event.messageText.split(' ') + if ((command.shift()!='!subathon') || event.chatterId !== tokens.user_id && (!mods.includes(event.chatterId))) { + return + } + switch(command.shift()){ + case 'start':{ + start() + break } - if(!(tags.includes('broadcaster') || tags.includes('moderator'))){ - continue + case 'pause':{ + pause() + break } - const command=message.split(' ') - console.debug(command) - if(command.shift()!='!subathon'){ - continue + case 'reset':{ + reset() + break } - switch(command.shift()){ - case 'start':{ - start() - break - } - case 'pause':{ - pause() - break - } - case 'reset':{ - reset() - break - } - case 'add':{ - add_time(parseReadableTimeIntoMilliseconds(command.shift())) - break - } + case 'add':{ + add_time(parseReadableTimeIntoMilliseconds(command.shift())) + break } } - } + }) } function init_streamelements(){ @@ -421,3 +226,34 @@ function init_streamelements(){ streamelements.on('event:update', onEvent); streamelements.on('event:reset', onEvent); } + +// init localforage +localforage = (await import('https://cdn.jsdelivr.net/npm/localforage/+esm')).default +localforage = localforage.createInstance({ name: 'sugoi-subathon-countdown' }) +// init timer display +time_started = await localforage.getItem('time_started') +time_passed = await localforage.getItem('time_passed') +time_total = await localforage.getItem('time_total') +updateTime() +// migrate to WebStorage +if(time_started){ + +} +// init twitch api tokens +tokens = await authProvider.getAccessTokenForUser(null) +await apiClient.getTokenInfo().then(info => tokens.user_id = info.userId) +// load user config +await load_config() +// create real time mod list +const mods = await apiClient.moderation.getModeratorsPaginated(tokens.user_id).getAll() +eventSub.onChannelModeratorAdd(tokens.user_id, event => mods.push(event.userId)) +eventSub.onChannelModeratorRemove(tokens.user_id, event => mods.slice(mods.indexOf(event.userId), 1)) +// init event sources +init_irc() +init_pubsub() +init_eventsub() +if ('streamelements-token' in config) { + init_streamelements() +} +eventSub.start() +console.debug('load complete') \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..751ea97 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,385 @@ +{ + "name": "twitch-subathon-countdown", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@twurple/api": "^7.2.1", + "@twurple/eventsub-ws": "^7.2.1", + "twitch-cloud-ebs": "github:sugoidogo/twitch-cloud-ebs" + } + }, + "node_modules/@d-fischer/cache-decorators": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@d-fischer/cache-decorators/-/cache-decorators-4.0.1.tgz", + "integrity": "sha512-HNYLBLWs/t28GFZZeqdIBqq8f37mqDIFO6xNPof94VjpKvuP6ROqCZGafx88dk5zZUlBfViV9jD8iNNlXfc4CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/shared-utils": "^3.6.3", + "tslib": "^2.6.2" + } + }, + "node_modules/@d-fischer/connection": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@d-fischer/connection/-/connection-9.0.0.tgz", + "integrity": "sha512-Mljp/EbaE+eYWfsFXUOk+RfpbHgrWGL/60JkAvjYixw6KREfi5r17XdUiXe54ByAQox6jwgdN2vebdmW1BT+nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/isomorphic-ws": "^7.0.0", + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.5.0", + "@d-fischer/typed-event-emitter": "^3.3.0", + "@types/ws": "^8.5.4", + "tslib": "^2.4.1", + "ws": "^8.11.0" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/cross-fetch": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@d-fischer/cross-fetch/-/cross-fetch-5.0.5.tgz", + "integrity": "sha512-symjDUPInTrkfIsZc2n2mo9hiAJLcTJsZkNICjZajEWnWpJ3s3zn50/FY8xpNUAf5w3eFuQii2wxztTGpvG1Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/@d-fischer/detect-node": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@d-fischer/detect-node/-/detect-node-3.0.1.tgz", + "integrity": "sha512-0Rf3XwTzuTh8+oPZW9SfxTIiL+26RRJ0BRPwj5oVjZFyFKmsj9RGfN2zuTRjOuA3FCK/jYm06HOhwNK+8Pfv8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@d-fischer/isomorphic-ws": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@d-fischer/isomorphic-ws/-/isomorphic-ws-7.0.2.tgz", + "integrity": "sha512-xK+qIJUF0ne3dsjq5Y3BviQ4M+gx9dzkN+dPP7abBMje4YRfow+X9jBgeEoTe5e+Q6+8hI9R0b37Okkk8Vf0hQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ws": "^8.2.0" + } + }, + "node_modules/@d-fischer/logger": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@d-fischer/logger/-/logger-4.2.3.tgz", + "integrity": "sha512-mJUx9OgjrNVLQa4od/+bqnmD164VTCKnK5B4WOW8TX5y/3w2i58p+PMRE45gUuFjk2BVtOZUg55JQM3d619fdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/detect-node": "^3.0.1", + "@d-fischer/shared-utils": "^3.2.0", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/qs": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@d-fischer/qs/-/qs-7.0.2.tgz", + "integrity": "sha512-yAu3xDooiL+ef84Jo8nLjDjWBRk7RXk163Y6aTvRB7FauYd3spQD/dWvgT7R4CrN54Juhrrc3dMY7mc+jZGurQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/rate-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@d-fischer/rate-limiter/-/rate-limiter-1.0.1.tgz", + "integrity": "sha512-Mq+0pAJsx92hP83cjmsrXQZVQJ+/+u1JFT6fjH8pj3yfUrbT3eDBsA+6J63eat+QaC+Mci78HdiBfpsdBkdwog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/logger": "^4.2.3", + "@d-fischer/shared-utils": "^3.6.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/shared-utils": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@d-fischer/shared-utils/-/shared-utils-3.6.4.tgz", + "integrity": "sha512-BPkVLHfn2Lbyo/ENDBwtEB8JVQ+9OzkjJhUunLaxkw4k59YFlQxUUwlDBejVSFcpQT0t+D3CQlX+ySZnQj0wxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.1" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@d-fischer/typed-event-emitter": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@d-fischer/typed-event-emitter/-/typed-event-emitter-3.3.3.tgz", + "integrity": "sha512-OvSEOa8icfdWDqcRtjSEZtgJTFOFNgTjje7zaL0+nAtu2/kZtRCSK5wUMrI/aXtCH8o0Qz2vA8UqkhWUTARFQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/api": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@twurple/api/-/api-7.2.1.tgz", + "integrity": "sha512-fqoX87GyHRL4pSmgloF5Mfj2XDJMx8fWBbcl4JGG7bgF2jvH5X9p3nzH169zqwSU/etfUdfytyoQ7/r2R+G3cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/cache-decorators": "^4.0.0", + "@d-fischer/cross-fetch": "^5.0.1", + "@d-fischer/detect-node": "^3.0.1", + "@d-fischer/logger": "^4.2.1", + "@d-fischer/rate-limiter": "^1.0.0", + "@d-fischer/shared-utils": "^3.6.1", + "@d-fischer/typed-event-emitter": "^3.3.1", + "@twurple/api-call": "7.2.1", + "@twurple/common": "7.2.1", + "retry": "^0.13.1", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "@twurple/auth": "7.2.1" + } + }, + "node_modules/@twurple/api-call": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@twurple/api-call/-/api-call-7.2.1.tgz", + "integrity": "sha512-x+p6fMleFA/pJHVu8tFpkDkARGGt30EAUA+cLc+dEtU1EpH1mv7nv5LLHh9NW9vdZpYp0jk5TyY/TSbHdj7Ggw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/cross-fetch": "^5.0.1", + "@d-fischer/qs": "^7.0.2", + "@d-fischer/shared-utils": "^3.6.1", + "@twurple/common": "7.2.1", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/auth": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@twurple/auth/-/auth-7.2.1.tgz", + "integrity": "sha512-IGHsJ/g0RblRSBC59XKA9277rE5w1dAKdhCPQz1QwkWnt6fsUyVoD1ut+qZvjuh7ssX1SBtNzFqohydfmWZytg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.6.1", + "@d-fischer/typed-event-emitter": "^3.3.1", + "@twurple/api-call": "7.2.1", + "@twurple/common": "7.2.1", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/common": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@twurple/common/-/common-7.2.1.tgz", + "integrity": "sha512-veLY5laA00dPuekAcpHN6GDvnr6s1uH7yBDebLC1NhpcLkQgiAlGA50RdNS5YeA3xz7kfE2MOcYSi2S6Qoc7EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/shared-utils": "^3.6.1", + "klona": "^2.0.4", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/eventsub-base": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@twurple/eventsub-base/-/eventsub-base-7.2.1.tgz", + "integrity": "sha512-QDhYFetOXCaX2HGOe6GpVBKtddSZ7uLwo+N8r08gc33TAz+xUwLQY5MhixA2v+KNyEoWih4xMemOKRDo6lIm5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.6.1", + "@d-fischer/typed-event-emitter": "^3.3.0", + "@twurple/api": "7.2.1", + "@twurple/auth": "7.2.1", + "@twurple/common": "7.2.1", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@twurple/eventsub-ws": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@twurple/eventsub-ws/-/eventsub-ws-7.2.1.tgz", + "integrity": "sha512-hGOn0EWnO+x9/K0eC2nVYgtbbuWdIc9yedaucuNNf8qxGe7SaHj509nKiLJQ+8PKsD6sK6PTfuHhU4G2PpsUSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@d-fischer/connection": "^9.0.0", + "@d-fischer/logger": "^4.2.1", + "@d-fischer/shared-utils": "^3.6.1", + "@d-fischer/typed-event-emitter": "^3.3.0", + "@twurple/auth": "7.2.1", + "@twurple/common": "7.2.1", + "@twurple/eventsub-base": "7.2.1", + "tslib": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "@twurple/api": "7.2.1" + } + }, + "node_modules/@types/node": { + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/ws": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", + "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/twitch-cloud-ebs": { + "version": "1.0.0", + "resolved": "git+ssh://git@github.com/sugoidogo/twitch-cloud-ebs.git#e2adb054a1a1cdf1649a520bbff146161520b2cd", + "dev": true + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..27c1753 --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "devDependencies": { + "@twurple/api": "^7.2.1", + "@twurple/eventsub-ws": "^7.2.1", + "twitch-cloud-ebs": "github:sugoidogo/twitch-cloud-ebs" + } +}