Panel terminé + Refresh token auto
This commit is contained in:
25
app.js
25
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)
|
||||
|
||||
9
public/panel/arrow.svg
Normal file
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
BIN
public/panel/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
25
utils/checkChannel.js
Normal 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
25
utils/checkUser.js
Normal 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]
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
const mysql = require('mysql2/promise')
|
||||
require('dotenv').config()
|
||||
|
||||
module.exports = async function () {
|
||||
// Create a connection to the MySQL database
|
||||
|
||||
@@ -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) })
|
||||
|
||||
@@ -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) })
|
||||
}
|
||||
@@ -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) })
|
||||
}
|
||||
@@ -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) })
|
||||
}
|
||||
@@ -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
13
utils/refreshToken.js
Normal 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) })
|
||||
}
|
||||
@@ -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
13
utils/validateToken.js
Normal 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) })
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user