From 8846299424bed3b2c6770b8b03a46601d50523ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zachary=20Gu=C3=A9not?= Date: Thu, 11 May 2023 00:37:16 +0200 Subject: [PATCH] =?UTF-8?q?Panel=20termin=C3=A9=20+=20Refresh=20token=20au?= =?UTF-8?q?to?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 25 +++++--- public/panel/arrow.svg | 9 +++ public/panel/background.png | Bin 0 -> 44876 bytes public/panel/panel.css | 115 +++++++++++++++++++++++++++++++++--- public/panel/panel.html | 37 +++++++----- public/panel/script.js | 12 +++- utils/checkChannel.js | 25 ++++++++ utils/checkUser.js | 25 ++++++++ utils/getRewardData.js | 1 + utils/getRewardID.js | 1 + utils/getUserAccessToken.js | 4 +- utils/getUserID.js | 13 ---- utils/getUserName.js | 13 ---- utils/oauthGen.js | 2 +- utils/refreshToken.js | 13 ++++ utils/subscribeToEvents.js | 1 + utils/validateToken.js | 13 ++++ utils/writeEnv.js | 6 +- 18 files changed, 251 insertions(+), 64 deletions(-) create mode 100644 public/panel/arrow.svg create mode 100644 public/panel/background.png create mode 100644 utils/checkChannel.js create mode 100644 utils/checkUser.js delete mode 100644 utils/getUserID.js delete mode 100644 utils/getUserName.js create mode 100644 utils/refreshToken.js create mode 100644 utils/validateToken.js diff --git a/app.js b/app.js index 17d74cc..a26e8c1 100644 --- a/app.js +++ b/app.js @@ -5,12 +5,12 @@ require('dotenv').config() // UTILS +const checkUser = require('./utils/checkUser') +const checkChannel = require('./utils/checkChannel') const getRewardData = require('./utils/getRewardData') const getRewardID = require('./utils/getRewardID') const getUserAccessToken = require('./utils/getUserAccessToken') -const getUserID = require('./utils/getUserID') const getUserInfo = require('./utils/getUserInfo') -const getUserName = require('./utils/getUserName') const oauthGen = require('./utils/oauthGen') const parseMessage = require('./utils/parseMessage') const rewardRedemption = require('./utils/rewardRedemption') @@ -54,19 +54,21 @@ app.get('/twitch/oauth/login/:type', async (req, res) => { let type = req.params.type if (type === 'user') { - user_access_token = await getUserAccessToken(client_id, client_secret, req.query.code, redirect_uri + type) + [ user_access_token, user_refresh_token ] = await getUserAccessToken(client_id, client_secret, req.query.code, redirect_uri + type) writeEnv('TWITCH_USER_ACCESS_TOKEN', user_access_token) + writeEnv('TWITCH_USER_REFRESH_TOKEN', user_refresh_token) - user_name = await getUserName(client_id, user_access_token).login + user_name = await getUserInfo(client_id, user_access_token).login writeEnv('TWITCH_USER_USERNAME', user_name) clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') } else if (type === 'channel') { - channel_access_token = await getUserAccessToken(client_id, client_secret, req.query.code, redirect_uri + type) + [ channel_access_token, channel_refresh_token ] = await getUserAccessToken(client_id, client_secret, req.query.code, redirect_uri + type) writeEnv('TWITCH_CHANNEL_ACCESS_TOKEN', channel_access_token) + writeEnv('TWITCH_CHANNEL_REFRESH_TOKEN', channel_refresh_token) - channel_name = await getUserName(client_id, channel_access_token).login + channel_name = await getUserInfo(client_id, channel_access_token).login writeEnv('TWITCH_CHANNEL_USERNAME', channel_name) clientEventSub.connect('wss://eventsub.wss.twitch.tv/ws') @@ -102,9 +104,13 @@ const clientChatBot = new WebSocketClient() let connectionChatBot clientChatBot.on('connect', async connection => { - console.log('Twitch ChatBot WebSocket Connected !') connectionChatBot = connection + console.log('Twitch ChatBot WebSocket Connected !') + + // Check if the user access token is still valid + //[user_access_token, user_name] = await checkUser(user_access_token) + // Authenticate to Twitch IRC and join channel connection.sendUTF('CAP REQ :twitch.tv/commands twitch.tv/membership twitch.tv/tags') connection.sendUTF(`PASS oauth:${user_access_token}`) @@ -151,6 +157,9 @@ clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') const clientEventSub = new WebSocketClient().on('connect', async connection => { console.log('Twitch EventSub WebSocket Connected !') + // Check if the channel access token is still valid + //[channel_access_token, channel_name] = await checkChannel(channel_access_token) + connection.on('message', async message => { if (message.type === 'utf8') { try { @@ -160,7 +169,7 @@ const clientEventSub = new WebSocketClient().on('connect', async connection => { if (data.metadata.message_type === 'session_welcome') { // Get broadcaster user id and reward id - let broadcaster_user_id = await getUserID(client_id, channel_access_token) + let broadcaster_user_id = await getUserInfo(client_id, channel_access_token).id writeEnv('TWITCH_CHANNEL_BROADCASTER_ID', broadcaster_user_id) let reward_id = await getRewardID(client_id, channel_access_token, broadcaster_user_id, channel_reward_name) writeEnv('TWITCH_CHANNEL_REWARD_ID', reward_id) diff --git a/public/panel/arrow.svg b/public/panel/arrow.svg new file mode 100644 index 0000000..c06756a --- /dev/null +++ b/public/panel/arrow.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/panel/background.png b/public/panel/background.png new file mode 100644 index 0000000000000000000000000000000000000000..a277494ec0bcfd02d6ec473fa5ef944b7d03e684 GIT binary patch literal 44876 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 MD$il1N@l_T2NEziqW}N^ literal 0 HcmV?d00001 diff --git a/public/panel/panel.css b/public/panel/panel.css index ce59694..bbe85d9 100644 --- a/public/panel/panel.css +++ b/public/panel/panel.css @@ -1,16 +1,113 @@ -p { - color: white; - text-align: center; +@import url('https://fonts.googleapis.com/css2?family=Annie+Use+Your+Telescope&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Advent+Pro&display=swap'); + +body { + /* background-color: #B9F1FD; */ + background: url(https://angels-dev.fr/twitch/panel/background.png); + background-repeat: no-repeat; + /* border: 2px solid black; */ + font-family: 'Advent Pro', sans-serif; + font-weight: 400; + color: black; } + +.div__title { + width: 205px; + height: 34px; + border-radius: 15px; + border-bottom: 1px solid #205E8B; + background-color: #5FB5F4; + justify-content: center; + margin: auto; + margin-bottom: 15px; +} + +.title { + color: black; + text-align: center; + font-family: 'Annie Use Your Telescope', cursive; + font-size: 24px; + font-weight: 600; +} + +.table { + margin: auto; + border-collapse : separate; + border-spacing: 4px; +} + +.table__body { + overflow-y: scroll; + scrollbar-width: thin; /* "auto" or "thin" */ + scrollbar-color: #24AEEA #7A7979; /* scroll thumb and track */ +} + +.table__rank { + background-color: #5FB6F4; + width: 30px; + height: 20px; + border-radius: 5px; + font-size: 12px; + font-weight: 600; +} + +.table__pseudos { + background-color: #5FB6F4; + width: 200px; + height: 20px; + border-radius: 5px; + text-align: left; + padding-left: 5px; + font-size: 12px; + font-weight: 600; +} + +.table__arrows { + background-color: #5FB6F4; + width: 54px; + height: 20px; + border-radius: 5px; + font-size: 12px; + font-weight: 600; +} + +.row__rank { + background-color: #99CFEE; + width: 30px; + height: 20px; + border-radius: 5px; + font-size: 12px; + font-weight: 800; +} + +.row__pseudos { + background-color: #99CFEE; + width: 200px; + height: 20px; + border-radius: 5px; + text-align: left; + padding-left: 5px; + font-size: 16px; + font-weight: 400; +} + +.row__arrows { + background-color: #99CFEE; + width: 54px; + height: 20px; + border-radius: 5px; + font-size: 14px; + font-weight: 400; +} + +.row__arrows::after { + content: url(https://angels-dev.fr/twitch/panel/arrow.svg); + margin-left: 7.5px; +} + th { - color: white; text-align: center; } td { - color: white; text-align: center; } -table .center { - margin-left: auto; - margin-right: auto; -} \ No newline at end of file diff --git a/public/panel/panel.html b/public/panel/panel.html index 9c6fe81..1a53276 100644 --- a/public/panel/panel.html +++ b/public/panel/panel.html @@ -1,16 +1,25 @@ - - - + + + + + + -Panel Laytho -

Classement des Daily Arrows

- - - - - - - - -
PseudoDaily Arrows
\ No newline at end of file + Laytho Panel + + +
+

Stand de tir à l'arc

+
+ + + + + + + + + +
RankPseudoCarquois
+ \ No newline at end of file diff --git a/public/panel/script.js b/public/panel/script.js index def9cbf..cdfe5b0 100644 --- a/public/panel/script.js +++ b/public/panel/script.js @@ -8,10 +8,20 @@ xhr.onload = () => { let tbodyRef = document.getElementById('table').getElementsByTagName('tbody')[0] - for (let entry of data.scoreboard) { + for (entry of data.scoreboard) { let row = tbodyRef.insertRow() + + row.insertCell().appendChild(document.createTextNode(data.scoreboard.indexOf(entry) + 1)) row.insertCell().appendChild(document.createTextNode(entry.user_name)) row.insertCell().appendChild(document.createTextNode(entry.count)) + + let i = 0 + for (cell of row.cells) { + i++ + if (i === 1) cell.className = "row__rank" + if (i === 2) cell.className = "row__pseudos" + if (i === 3) cell.className = "row__arrows" + } } } else console.error('Error:', xhr.statusText) } diff --git a/utils/checkChannel.js b/utils/checkChannel.js new file mode 100644 index 0000000..f0eaeae --- /dev/null +++ b/utils/checkChannel.js @@ -0,0 +1,25 @@ +require('dotenv').config() + +const validateToken = require('./validateToken') +const refreshToken = require('./refreshToken') +const writeEnv = require('./writeEnv') + +let client_id = process.env.TWITCH_APP_ID +let client_secret = process.env.TWITCH_APP_SECRET + +module.exports = async function (channel_access_token) { + let channel_refresh_token = '' + + // Check if channel_access_token is valid + if (!await validateToken(channel_access_token)) { + + // If not, refresh it + [channel_access_token, channel_refresh_token] = await refreshToken(client_id, client_secret, channel_access_token) + writeEnv('TWITCH_CHANNEL_ACCESS_TOKEN', channel_access_token) + writeEnv('TWITCH_CHANNEL_REFRESH_TOKEN', channel_refresh_token) + + let channel_name = await getUserInfo(client_id, channel_access_token).login + writeEnv('TWITCH_CHANNEL_USERNAME', channel_name) + } + return [channel_access_token, channel_name] +} \ No newline at end of file diff --git a/utils/checkUser.js b/utils/checkUser.js new file mode 100644 index 0000000..8eaeb34 --- /dev/null +++ b/utils/checkUser.js @@ -0,0 +1,25 @@ +require('dotenv').config() + +const validateToken = require('./validateToken') +const refreshToken = require('./refreshToken') +const writeEnv = require('./writeEnv') + +let client_id = process.env.TWITCH_APP_ID +let client_secret = process.env.TWITCH_APP_SECRET + +module.exports = async function (user_access_token) { + let user_refresh_token = '' + + // Check if user_access_token is valid + if (!await validateToken(user_access_token)) { + + // If not, refresh it + [user_access_token, user_refresh_token ] = await refreshToken(client_id, client_secret, user_access_token) + writeEnv('TWITCH_USER_ACCESS_TOKEN', user_access_token) + writeEnv('TWITCH_USER_REFRESH_TOKEN', user_refresh_token) + + let user_name = await getUserInfo(client_id, user_access_token).login + writeEnv('TWITCH_USER_USERNAME', user_name) + } + return [user_access_token, user_name] +} \ No newline at end of file diff --git a/utils/getRewardData.js b/utils/getRewardData.js index 9d70f7e..2eb9dd3 100644 --- a/utils/getRewardData.js +++ b/utils/getRewardData.js @@ -1,4 +1,5 @@ const mysql = require('mysql2/promise') +require('dotenv').config() module.exports = async function () { // Create a connection to the MySQL database diff --git a/utils/getRewardID.js b/utils/getRewardID.js index 10bb1fa..bc14613 100644 --- a/utils/getRewardID.js +++ b/utils/getRewardID.js @@ -7,6 +7,7 @@ module.exports = async function (client_id, access_token, broadcaster_id, reward 'Client-Id': client_id } }).then(response => { + //console.log(response.data) let reward = response.data.data.find(reward => reward.title === reward_name) return reward.id }).catch(error => { console.log(error.response.data) }) diff --git a/utils/getUserAccessToken.js b/utils/getUserAccessToken.js index 203247b..cc19003 100644 --- a/utils/getUserAccessToken.js +++ b/utils/getUserAccessToken.js @@ -8,7 +8,7 @@ module.exports = async function (client_id, client_secret, code, redirect_uri) { redirect_uri, grant_type: 'authorization_code' }).then(response => { - console.log(response.data) - if (response.data.token_type === 'bearer') return response.data.access_token + //console.log(response.data) + if (response.data.token_type === 'bearer') return [response.data.access_token, response.data.refresh_token] }).catch(error => { console.log(error.response.data) }) } \ No newline at end of file diff --git a/utils/getUserID.js b/utils/getUserID.js deleted file mode 100644 index 2d37d81..0000000 --- a/utils/getUserID.js +++ /dev/null @@ -1,13 +0,0 @@ -const axios = require('axios') - -module.exports = async function (client_id, access_token) { - return await axios.get(`https://api.twitch.tv/helix/users`, { - headers: { - 'Authorization': `Bearer ${access_token}`, - 'Client-Id': client_id - } - }).then(response => { - //console.log(response.data) - return response.data.data[0].id - }).catch(error => { console.log(error.response.data) }) -} \ No newline at end of file diff --git a/utils/getUserName.js b/utils/getUserName.js deleted file mode 100644 index 83e5e2f..0000000 --- a/utils/getUserName.js +++ /dev/null @@ -1,13 +0,0 @@ -const axios = require('axios') - -module.exports = async function (client_id, access_token) { - return await axios.get(`https://api.twitch.tv/helix/users`, { - headers: { - 'Authorization': `Bearer ${access_token}`, - 'Client-Id': client_id - } - }).then(response => { - //console.log(response.data) - return response.data.data[0].login - }).catch(error => { console.log(error.response.data) }) -} \ No newline at end of file diff --git a/utils/oauthGen.js b/utils/oauthGen.js index b5dba34..515cfae 100644 --- a/utils/oauthGen.js +++ b/utils/oauthGen.js @@ -1,7 +1,7 @@ module.exports = async function (client_id, redirect_uri, scope) { console.log(scope) let queries = { - response_type: 'code', + response_type: 'code', client_id, redirect_uri, scope: scope.join('+') diff --git a/utils/refreshToken.js b/utils/refreshToken.js new file mode 100644 index 0000000..3305da4 --- /dev/null +++ b/utils/refreshToken.js @@ -0,0 +1,13 @@ +const axios = require('axios') + +module.exports = async function (client_id, client_secret, refresh_token) { + return await axios.post('https://id.twitch.tv/oauth2/token', { + client_id, + client_secret, + refresh_token, + grant_type: 'refresh_token' + }).then(response => { + //console.log(response.data) + if (response.data.token_type === 'bearer') return [response.data.access_token, response.data.refresh_token] + }).catch(error => { console.log(error.response.data) }) +} \ No newline at end of file diff --git a/utils/subscribeToEvents.js b/utils/subscribeToEvents.js index 96c8c8b..1bac78e 100644 --- a/utils/subscribeToEvents.js +++ b/utils/subscribeToEvents.js @@ -16,6 +16,7 @@ module.exports = async function (client_id, access_token, session_id, type, vers 'Content-Type': 'application/json' } }).then(response => { + //console.log(response.data) return response.data.data[0].status }).catch(error => { return error.response.data }) } \ No newline at end of file diff --git a/utils/validateToken.js b/utils/validateToken.js new file mode 100644 index 0000000..cd9ae37 --- /dev/null +++ b/utils/validateToken.js @@ -0,0 +1,13 @@ +const axios = require('axios') + +module.exports = async function (access_token) { + return await axios.get('https://id.twitch.tv/oauth2/validate', { + headers: { + 'Authorization': `OAuth ${access_token}`, + } + }).then(response => { + //console.log(response.data) + if (response.data.status === '401') return false + else return true + }).catch(error => { console.log(error.response.data) }) +} \ No newline at end of file diff --git a/utils/writeEnv.js b/utils/writeEnv.js index f56bdb0..bf256ab 100644 --- a/utils/writeEnv.js +++ b/utils/writeEnv.js @@ -1,7 +1,7 @@ const fs = require('fs') module.exports = function (variable, value) { - let parsedFile = fs.readFileSync('./.env', 'utf8') - parsedFile = parsedFile.replace(new RegExp(`${variable}=.*`, 'g'), `${variable}=${value}`) - fs.writeFileSync('./.env', parsedFile) + let parsedFile = fs.readFileSync('./.env', 'utf8') + parsedFile = parsedFile.replace(new RegExp(`${variable}=.*`, 'g'), `${variable}=${value}`) + fs.writeFileSync('./.env', parsedFile) } \ No newline at end of file