commit be73cd765d7e2a43426d28e32bcacfef50369c1a Author: Zachary Guénot Date: Mon May 8 04:47:30 2023 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e762de3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.env +/node_modules +/package-lock.json \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..d08bb92 --- /dev/null +++ b/app.js @@ -0,0 +1,57 @@ +// PACKAGES +const tmi = require('tmi.js') +const WebSocketClient = require('websocket').client +const axios = require('axios') +require('dotenv').config() + +// UTILS +const getAccessToken = require('./utils/getAccessToken') +const subscribeToEvent = require('./utils/subscribeToEvent') + +// CHATBOT +const chatBotC = new tmi.Client({ + options: { debug: true }, + identity: { + username: process.env.TWITCH_USERNAME, + password: `oauth:${process.env.TWITCH_TOKEN}` + }, + channels: [ process.env.TWITCH_CHANNEL ] +}) + +chatBotC.on('message', async (channel, tags, message, self) => { + if (self) return + if (message.toLowerCase() === '!hello') { + console.log('Command "hello" was triggered in channel: ' + channel) + chatBotC.say(channel, `@${tags.username}, heya!`) + } +}) + +//chatBotC.connect() + +// EVENTSUB +const eventSubC = new WebSocketClient() + +eventSubC.on('connect', async connection => { + console.log('WebSocket eventSub Connected') + connection.sendUTF('CAP REQ :twitch.tv/membership twitch.tv/tags twitch.tv/commands') + connection.sendUTF(`PASS oauth:${process.env.TWITCH_APP_SECRET}`) + connection.sendUTF('NICK bot_Laytho') + connection.sendUTF('JOIN #liveAngels') + + connection.on('message', async message => { + if (message.type === 'utf8') { + console.log("Received: '" + message.utf8Data + "'") + try { + let data = JSON.parse(message.utf8Data) + console.log(data) + if (data.metadata.message_type === 'session_welcome') { + let access_token = await getAccessToken(process.env.TWITCH_APP_ID, process.env.TWITCH_APP_SECRET) + await subscribeToEvent(access_token, data.payload.session.id, process.env.TWITCH_APP_ID) + } + } catch (e) { console.log(e) } + } }) + .on('error', error => { console.log("Connection Error: " + error.toString()) }) + .on('close', () => { console.log('echo-protocol Connection Closed') }) +}).on('connectFailed', error => { console.log('Connect Error: ' + error.toString()) }) + +eventSubC.connect('wss://eventsub.wss.twitch.tv/ws') diff --git a/package.json b/package.json new file mode 100644 index 0000000..437f709 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "axios": "^1.4.0", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "open": "^9.1.0", + "tmi.js": "^1.8.5", + "websocket": "^1.0.34" + } +} diff --git a/utils/getAccessToken.js b/utils/getAccessToken.js new file mode 100644 index 0000000..bb90771 --- /dev/null +++ b/utils/getAccessToken.js @@ -0,0 +1,50 @@ +const axios = require('axios') +const express = require('express') +//const open = require('open') +const open = (...args) => import('open').then(({default: open}) => open(...args)) + +module.exports = async (client_id, client_secret) => { + /* + return await axios.post('https://id.twitch.tv/oauth2/token', { + client_id, + client_secret, + grant_type: 'client_credentials', + scope: 'channel:manage:redemptions' + }).then(response => { + console.log(response.data) + if (response.data.token_type === 'bearer') return response.data.access_token + }).catch(error => { console.log(error) }) + */ + + // Listen on port 3000 for twitch to send us the access token + const app = express() + const port = 3000 + + app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) + + // Open the browser to the twitch login page + await open(`https://id.twitch.tv/oauth2/authorize?client_id=${client_id}&redirect_uri=http://localhost:3000&response_type=code&scope=channel:manage:redemptions`) + + // Wait for the access token to be sent to us + let code = await new Promise((resolve, reject) => { + app.get('/', (req, res) => { + console.log(req.query) + res.send('Hello World!') + resolve(req.query.code) + }) + }) + + // Use the access token to get the oauth token + return await axios.post('https://id.twitch.tv/oauth2/token', { + client_id, + client_secret, + code, + grant_type: 'authorization_code', + redirect_uri: 'http://localhost:3000' + }).then(response => { + console.log(response.data) + if (response.data.token_type === 'bearer') return response.data.access_token + }).catch(error => { console.log(error) }) + + +} \ No newline at end of file diff --git a/utils/subscribeToEvent.js b/utils/subscribeToEvent.js new file mode 100644 index 0000000..e0c1fa0 --- /dev/null +++ b/utils/subscribeToEvent.js @@ -0,0 +1,24 @@ +const axios = require('axios') + +module.exports = async (access_token, session_id, client_id) => { + await axios.post('https://api.twitch.tv/helix/eventsub/subscriptions', { + type: 'channel.channel_points_custom_reward_redemption.add', + version: '1', + condition: { + broadcaster_user_id: '1337', + reward_id: 'abcf127c-7326-4483-a52b-b0da0be61c01' + }, + transport: { + method: 'websocket', + session_id + } + }, { + headers: { + 'Authorization': `Bearer ${access_token}`, + 'Client-Id': client_id, + 'Content-Type': 'application/json' + } + }).then(response => { + console.log(response.data) + }).catch(error => { console.log(error) }) +} \ No newline at end of file