Panel terminé + Refresh token auto

This commit is contained in:
Zachary Guénot
2023-05-11 00:37:16 +02:00
parent de01c981f8
commit 8846299424
18 changed files with 251 additions and 64 deletions

25
app.js
View File

@@ -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)

9
public/panel/arrow.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 39 KiB

BIN
public/panel/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -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;
}

View File

@@ -1,16 +1,25 @@
<!DOCTYPE HTML>
<script src="https://extension-files.twitch.tv/helper/v1/twitch-ext.min.js"></script>
<script src="https://angels-dev.fr/twitch/panel/script.js"></script>
<link rel="stylesheet" href="https://angels-dev.fr/twitch/panel/panel.css">
<html lang="en">
<head>
<script src="https://extension-files.twitch.tv/helper/v1/twitch-ext.min.js"></script>
<script src="https://angels-dev.fr/twitch/panel/script.js"></script>
<link rel="stylesheet" href="https://angels-dev.fr/twitch/panel/panel.css">
<link rel="image/svg" href="https://angels-dev.fr/twitch/panel/arrow.svg">
<title>Panel Laytho</title>
<p>Classement des Daily Arrows</p>
<table id="table" class="center">
<thead>
<tr>
<th scope="col">Pseudo</th>
<th scope="col">Daily Arrows</th>
</tr>
</thead>
<tbody></tbody>
</table>
<title>Laytho Panel</title>
</head>
<body>
<div class="div__title">
<h2 class="title">Stand de tir à l'arc</h2>
</div>
<table id="table" class="table">
<thead>
<tr class="table__names">
<th scope="col" class="table__rank">Rank</th>
<th scope="col" class="table__pseudos">Pseudo</th>
<th scope="col" class="table__arrows">Carquois</th>
</tr>
</thead>
<tbody class="table__body"></tbody>
</table>
</html>

View File

@@ -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)
}

25
utils/checkChannel.js Normal file
View File

@@ -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]
}

25
utils/checkUser.js Normal file
View File

@@ -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]
}

View File

@@ -1,4 +1,5 @@
const mysql = require('mysql2/promise')
require('dotenv').config()
module.exports = async function () {
// Create a connection to the MySQL database

View File

@@ -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) })

View File

@@ -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) })
}

View File

@@ -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) })
}

View File

@@ -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) })
}

View File

@@ -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('+')

13
utils/refreshToken.js Normal file
View File

@@ -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) })
}

View File

@@ -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 })
}

13
utils/validateToken.js Normal file
View File

@@ -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) })
}

View File

@@ -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)
}