diff --git a/app.js b/app.js index fad7c92..f969d05 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,7 @@ // PACKAGES const WebSocketClient = require('websocket').client const express = require('express') +const getUserID = require('./utils/getUserID') require('dotenv').config() require('require-all')(__dirname + '/utils/') @@ -9,16 +10,20 @@ require('require-all')(__dirname + '/utils/') let client_id = process.env.TWITCH_APP_ID let client_secret = process.env.TWITCH_APP_SECRET -let user_name = process.env.TWITCH_USER_USERNAME -let channel_name = process.env.TWITCH_CHANNEL_USERNAME +let user_name = process.env.TWITCH_USER_NAME +let channel_name = process.env.TWITCH_CHANNEL_NAME let channel_reward_name = process.env.TWITCH_CHANNEL_REWARD_NAME +let bot_prefix = process.env.TWITCH_BOT_PREFIX +let bot_coubeh = process.env.TWITCH_BOT_COUBEH +let bot_mention = process.env.TWITCH_BOT_MENTION + const user_scope = ['chat:read', 'chat:edit', 'channel:moderate'] const channel_scope = ['channel:manage:redemptions'] -const uri = 'https://angels-dev.fr/twitch/' -const redirect_uri = uri + 'oauth/login/' -const chatBeginMsg = `PRIVMSG #${channel_name}` +const redirect_uri = 'https://angels-dev.fr/twitch/oauth/login/' +const chatBeginMsg = `PRIVMSG #${channel_name} :` +const chatReplyMsg = (id) => `@reply-parent-msg-id=${id} ${chatBeginMsg}` // EXPRESS @@ -29,31 +34,34 @@ app.use(express.static('public')) // Twitch OAuth app.get('/twitch/oauth/:type', async (req, res) => { + console.log(`${new Date().toLocaleString()} - ${req.method} ${req._parsedUrl.pathname} from ${req.socket.remoteAddress}`) let type = req.params.type let url = await oauthGen(client_id, redirect_uri + type, type === 'user' ? user_scope : type === 'channel' ? channel_scope : []) return res.redirect(url) }) + app.get('/twitch/oauth/login/:type', async (req, res) => { + console.log(`${new Date().toLocaleString()} - ${req.method} ${req._parsedUrl.pathname} from ${req.socket.remoteAddress}`) let type = req.params.type if (type === 'user') { - [ user_access_token, user_refresh_token ] = await getUserAccessToken(client_id, client_secret, req.query.code, redirect_uri + type) + let [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 getUserInfo(client_id, user_access_token).login - writeEnv('TWITCH_USER_USERNAME', user_name) + user_name = await getUserInfo(client_id, user_access_token, 'login') + writeEnv('TWITCH_USER_NAME', user_name) clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') } else if (type === 'channel') { - [ channel_access_token, channel_refresh_token ] = await getUserAccessToken(client_id, client_secret, req.query.code, redirect_uri + type) + let [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 getUserInfo(client_id, channel_access_token).login - writeEnv('TWITCH_CHANNEL_USERNAME', channel_name) + channel_name = await getUserInfo(client_id, channel_access_token, 'login') + writeEnv('TWITCH_CHANNEL_NAME', channel_name) clientEventSub.connect('wss://eventsub.wss.twitch.tv/ws') } @@ -62,25 +70,21 @@ app.get('/twitch/oauth/login/:type', async (req, res) => { // Twitch Panel app.get('/twitch/panel/:file', async (req, res) => { + console.log(req.socket) + console.log(`${new Date().toLocaleString()} - ${req.method} ${req._parsedUrl.pathname} from ${req.socket.remoteAddress}`) let file = req.params.file if (file === 'data') { - //let { panel_user_id } = req.query - let panel_user_id = '44322889' - - //let event_user_id = '55833896' - //let event_user_name = 'angelskimi' - //await rewardRedemption(event_user_id, event_user_name) - let panel_data = await getRewardData() - let response = { scoreboard: panel_data, user: panel_data.find(entry => entry.user_id === panel_user_id) } + //let response = { scoreboard: panel_data, viewer: panel_data.find(entry => entry.viewer_id === panel_viewer_id) } + let response = { scoreboard: panel_data } return res.json(response) } else return res.sendFile(__dirname + '/public/panel/' + file) }) -app.listen(port, () => { console.log(`Express listening at port ${port} !`) }) +app.listen(port, () => { console.log(`[SYS] Express listening at port ${port} !`) }) // CHATBOT @@ -89,8 +93,7 @@ let connectionChatBot clientChatBot.on('connect', async connection => { connectionChatBot = connection - - console.log('Twitch ChatBot WebSocket Connected !') + console.log('[SYS] Twitch ChatBot WebSocket Connected !') // Check if the user access token is still valid let [user_access_token, user_name] = await checkUser(process.env.TWITCH_USER_ACCESS_TOKEN) @@ -101,108 +104,159 @@ clientChatBot.on('connect', async connection => { connection.sendUTF(`PASS oauth:${user_access_token}`) connection.sendUTF(`NICK ${user_name}`) connection.sendUTF(`JOIN #${channel_name}`) - connection.sendUTF(`PRIVMSG #${channel_name} :Salut tout le monde !`) + connection.sendUTF(`${chatBeginMsg} Salut tout le monde !`) - connection.on('message', async message => { - if (message.type === 'utf8') { - try { - let data = parseMessage(message.utf8Data) + connection.on('message', async message => { if (message.type === 'utf8') { try { + let data = parseMessage(message.utf8Data) + //console.log(data) - // Handle incoming messages - if (data.command.command === 'PRIVMSG') { - let message = data.parameters.split('\r\n')[0] - console.log(`${data.source.nick}: ${message}`) + // Handle incoming messages + if (data.command.command === 'PRIVMSG') { + let message = data.parameters.split('\r\n')[0] + console.log(`${data.source.nick}: ${message}`) - if (message.includes('@Bot_Laytho')) { - connection.sendUTF(`@reply-parent-msg-id=${data.tags.id} ${chatBeginMsg} :Kestuveu @${data.tags['display-name']} ?`) - connection.sendUTF(`${chatBeginMsg} :/timeout ${data.tags['display-name']} 60 T'as pas à me parler comme ça !`) - } - else if (message.toLowerCase().includes('quoi')) { - connection.sendUTF(`@reply-parent-msg-id=${data.tags.id} ${chatBeginMsg} :@${data.tags['display-name']} Coubeh !`) - connection.sendUTF(`${chatBeginMsg} :/timeout ${data.tags['display-name']} 60 T'as pas à me parler comme ça !`) - } - else if (message === '!ping') { - connection.sendUTF(`@reply-parent-msg-id=${data.tags.id} ${chatBeginMsg} :Pong !`) - } - } else if (data.command.command === 'NOTICE') { - if (data.parameters.includes('Login authentication failed')) { - console.log('Erreur de connexion ChatBot, veuillez vous reconnecter !\nhttps://angels-dev.fr/twitch/oauth/user') - } + if (message.slice(0, 2) === bot_prefix) { + if (data.tags.badges.moderator !== '1') return connection.sendUTF(`${chatReplyMsg(data.tags.id)} Oh lache ça, t'es fou toi !`) + + let command = message.split(bot_prefix)[1].split(' ')[0] + let args = message.split(' ').slice(1) + + if (command === 'ping') connection.sendUTF(`${chatReplyMsg(data.tags.id)} Pong !`) + else if (command === 'coubeh') { + if (bot_coubeh === 'true') { bot_coubeh = 'false' + connection.sendUTF(`${chatReplyMsg(data.tags.id)} Ok j'arrête de flop les viewers...`) } + else { bot_coubeh = 'true' + connection.sendUTF(`${chatReplyMsg(data.tags.id)} Aller c'est parti pour faire flop du monde :)))`) } + writeEnv('BOT_COUBEH', bot_coubeh) } - } catch (error) { } // catch (error) { console.error(error) } - } }) + else if (command === 'mention') { + if (bot_mention === 'true') { bot_mention = 'false' + connection.sendUTF(`${chatReplyMsg(data.tags.id)} Ah tu veux plus que je te répondes ? Ok dac`) } + else { bot_mention = 'true' + connection.sendUTF(`${chatReplyMsg(data.tags.id)} Maintenant vous allez arrêter de me parler :(((`) } + writeEnv('BOT_MENTION', bot_mention) + } + else if (command === 'arrow') { + if ((args.length < 2 || args.length > 4) + || !args[1].split('@')[1] + || (args.length === 2 && args[0] !== 'get') + || (args.length >= 3 && ( + (args[0] !== 'add' && args[0] !== 'remove' && args[0] !== 'set') + || !parseInt(args[2]) + )) + || (args.length === 4 && (args[3] !== 'current' && args[3] !== 'permanent')) + ) return connection.sendUTF(`${chatReplyMsg(data.tags.id)} Syntaxe: J/arrow <@viewer> | <@viewer> [current|permanent]`) + + let action = args[0] + let viewer_login = args[1].split('@')[1].toLowerCase() + let viewer_id = await getUserID(client_id, user_access_token, viewer_login) + let quantity = parseInt(args[2]) + let type = args[3] + if (quantity < 0) return connection.sendUTF(`${chatReplyMsg(data.tags.id)} Tu veux spawn un trou noir dans le stand ou quoi ?!`) + + let result = await modifyReward(viewer_id, viewer_login, action, quantity, type) + if (result.status === 'get_entry') connection.sendUTF(`${chatReplyMsg(data.tags.id)} ${args[1]} a ${result.count} flèche(s) dans son carquois et ${result.current_count} flèche(s) permanente(s) !`) + else if (result.status === 'insert_entry') connection.sendUTF(`${chatReplyMsg(data.tags.id)} ${args[1]} a été ajouté au stand avec ${quantity} flèche(s) !`) + else if (result.status === 'update_entry') connection.sendUTF(`${chatReplyMsg(data.tags.id)} ${quantity} flèche(s) ajoutée(s) à ${args[1]} !`) + else if (result.status === 'no_get_entry') connection.sendUTF(`${chatReplyMsg(data.tags.id)} ${args[1]} ne dispose d'aucune flèche, il n'est même pas dans le stand !`) + else if (result.status === 'no_delete_entry') connection.sendUTF(`${chatReplyMsg(data.tags.id)} Impossble de retirer des flèches à ${args[1]}, il n'en a aucune !`) + else if (result.status === 'not_enough_count') connection.sendUTF(`${chatReplyMsg(data.tags.id)} ${args[1]} n'a pas assez de flèches permanentes pour lui en enlever ${quantity} !`) + else if (result.status === 'not_enough_current_count') connection.sendUTF(`${chatReplyMsg(data.tags.id)} ${args[1]} n'a pas assez de flèches dans son carquois pour lui en enlever ${quantity} !`) + } + else connection.sendUTF(`${chatReplyMsg(data.tags.id)} Commande inconnue !`) + } + else if (message.includes('@Bot_Laytho') && bot_mention === 'true') { + connection.sendUTF(`${chatReplyMsg(data.tags.id)} Kestuveu @${data.tags['display-name']} ?`) + //connection.sendUTF(`${chatBeginMsg} /timeout ${data.tags['display-name']} 60 T'as pas à me parler comme ça !`) + } + else if (message.toLowerCase().includes('quoi') && bot_coubeh === 'true') { + connection.sendUTF(`${chatReplyMsg(data.tags.id)} @${data.tags['display-name']} Coubeh !`) + //connection.sendUTF(`${chatBeginMsg} /timeout ${data.tags['display-name']} 60 T'as pas à me parler comme ça !`) + } + } else if (data.command.command === 'NOTICE' && data.parameters.includes('Login authentication failed')) { + console.log('[SYS] Erreur de connexion ChatBot, veuillez vous reconnecter !\nhttps://angels-dev.fr/twitch/oauth/user') + } + } catch (error) { } } }) .on('error', error => { console.error(error) }) - .on('close', () => { console.log('Twitch ChatBot Connection Closed !') }) + .on('close', () => { + console.log('[SYS] Twitch ChatBot Connection Closed !') + if (connectionEventSub.state === 'open') clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') + }) }).on('connectFailed', error => { console.error(error) }) clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') // EVENTSUB -const clientEventSub = new WebSocketClient().on('connect', async connection => { - console.log('Twitch EventSub WebSocket Connected !') +const clientEventSub = new WebSocketClient() +let connectionEventSub - // Check if the channel access token is still valid - let [channel_access_token, channel_name] = await checkChannel(process.env.TWITCH_CHANNEL_ACCESS_TOKEN) - if (channel_access_token === 'no_refresh') return console.log("Can't refresh channel access token: ", channel_name) +clientEventSub.on('connect', async connection => { + connectionEventSub = connection + console.log('[SYS] Twitch EventSub WebSocket Connected !') - connection.on('message', async message => { - if (message.type === 'utf8') { - try { - let data = JSON.parse(message.utf8Data) - - // Check when Twitch asks to login - if (data.metadata.message_type === 'session_welcome') { + connection.on('message', async message => { if (message.type === 'utf8') { try { + let data = JSON.parse(message.utf8Data) - // Get broadcaster user id and reward id - 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) - let topics = { - 'channel.channel_points_custom_reward_redemption.add': { version: '1', condition: { broadcaster_user_id, reward_id } }, - 'stream.online': { version: '1', condition: { broadcaster_user_id } } - } + // Check when Twitch asks to login + if (data.metadata.message_type === 'session_welcome') { + + // Check if the channel access token is still valid before connecting + let [channel_access_token, channel_name] = await checkChannel(process.env.TWITCH_CHANNEL_ACCESS_TOKEN) + if (channel_access_token === 'no_refresh') return console.log("[SYS] Can't refresh channel access token: ", channel_name) + + // Get broadcaster user id and reward id + 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) + + let topics = { + 'channel.channel_points_custom_reward_redemption.add': { version: '1', condition: { broadcaster_user_id, reward_id } }, + 'stream.online': { version: '1', condition: { broadcaster_user_id } } + } - // Subscribe to all events required - for (let type in topics) { - console.log(`Creating ${type}...`) - let { version, condition } = topics[type] + // Subscribe to all events required + for (let type in topics) { + console.log(`[SYS] Creating ${type}...`) + let { version, condition } = topics[type] - let status = await subscribeToEvents(client_id, channel_access_token, data.payload.session.id, type, version, condition) - if (!status) return console.error(`Failed to create ${type}`) + let status = await subscribeToEvents(client_id, channel_access_token, data.payload.session.id, type, version, condition) + if (!status) return console.error(`[SYS] Failed to create ${type}`) + else if (status.error) return console.log('[SYS] Erreur de connexion EventSub, veuillez vous reconnecter !') + else console.log(`[SYS] Successfully created ${type}`) + } + } - else if (status.error) { - console.error(status) - console.log('Erreur de connexion EventSub, veuillez vous reconnecter !\nhttps://angels-dev.fr/twitch/oauth/channel') - return connection.sendUTF(`${chatBeginMsg} :@${channel_name} Erreur de connexion EventSub, veuillez vous reconnecter !\nhttps://angels-dev.fr/twitch/oauth/channel`) - } else console.log(`Successfully created ${type}`) - } - } + // Handle notification messages for reward redemption + else if (data.metadata.message_type === 'notification') { + let { subscription, event } = data.payload - // Handle notification messages for reward redemption - else if (data.metadata.message_type === 'notification') { - let { subscription, event } = data.payload + if (subscription.type === 'channel.channel_points_custom_reward_redemption.add') { + let viewer_id = event.user_id + let viewer_name = event.user_name + console.log(`[SYS] Viewer ${viewer_name} claimed reward ${event.reward.title} !`) - if (subscription.type === 'channel.channel_points_custom_reward_redemption.add') { - console.log(`User ${{ user_name } = event} claimed reward ${event.reward.title} !`) - await rewardRedemption({ user_id, user_name } = event) - } - else if (subscription.type === 'stream.online') { - console.log(`Stream from ${event.broadcaster_user_name} is now online, connecting to chat...`) - clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') - } - } + let result = await rewardRedemption(viewer_id, viewer_name) + + if (result.status === 'insert_entry') connectionChatBot.sendUTF(`${chatReplyMsg(viewer_id)} a récupéré sa première ${event.reward.title}, GG !`) + else if (result.status === 'update_entry') connectionChatBot.sendUTF(`${chatReplyMsg(viewer_id)} a récupéré sa ${event.reward.title}, t'en as ${result.current_count} dans ton carquois et récupéré ${result.count} depuis le début !`) + } + else if (subscription.type === 'stream.online') { + console.log(`[SYS] Stream from ${event.broadcaster_user_name} is now online, connecting to chat...`) + clientChatBot.connect('wss://irc-ws.chat.twitch.tv:443') + } + } - // Don't log ping/pong messages - else if (data.metadata.message_type === 'session_keepalive') return + // Don't log ping/pong messages + else if (data.metadata.message_type === 'session_keepalive') return - // Log unknown messages - else console.log(data) - } catch (error) { console.error(error) } - } }) + // Log unknown messages + else console.log(data) + + } catch (error) { console.error(error) } } }) .on('error', error => { console.error(error) }) - .on('close', () => { console.log('Twitch EventSub Connection Closed !') }) + .on('close', () => { console.log('[SYS] Twitch EventSub Connection Closed !') }) }).on('connectFailed', error => { console.error(error) }) clientEventSub.connect('wss://eventsub.wss.twitch.tv/ws') \ No newline at end of file diff --git a/public/panel/config.html b/public/panel/config.html new file mode 100644 index 0000000..db4f8de --- /dev/null +++ b/public/panel/config.html @@ -0,0 +1,14 @@ + + + + + + + Panel Laytho Config + + +
+

Configuration

+
+

Work in Progress !

+ \ No newline at end of file diff --git a/public/panel/panel.html b/public/panel/panel.html index 1a53276..3ec01a3 100644 --- a/public/panel/panel.html +++ b/public/panel/panel.html @@ -6,7 +6,7 @@ - Laytho Panel + Panel Laytho
diff --git a/public/panel/script.js b/public/panel/script.js index cdfe5b0..e20e852 100644 --- a/public/panel/script.js +++ b/public/panel/script.js @@ -1,7 +1,6 @@ const xhr = new XMLHttpRequest() -const url = 'https://angels-dev.fr/twitch/panel/data' -xhr.open('GET', url, true) +xhr.open('GET', 'https://angels-dev.fr/twitch/panel/data', true) xhr.onload = () => { if (xhr.status === 200) { let data = JSON.parse(xhr.responseText) @@ -12,7 +11,7 @@ xhr.onload = () => { 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.viewer_name)) row.insertCell().appendChild(document.createTextNode(entry.count)) let i = 0 diff --git a/utils/checkChannel.js b/utils/checkChannel.js index 0d7fc19..8cb3503 100644 --- a/utils/checkChannel.js +++ b/utils/checkChannel.js @@ -7,21 +7,26 @@ const writeEnv = require('./writeEnv') let client_id = process.env.TWITCH_APP_ID let client_secret = process.env.TWITCH_APP_SECRET -module.exports = checkChannel = (async (access_token) => { +module.exports = checkChannel = (async (channel_access_token) => { + let result = [channel_access_token, ''] // Check if channel_access_token is valid - if (!await validateToken(access_token)) { - - // If not, refresh it - let result = await refreshToken(client_id, client_secret, process.env.TWITCH_CHANNEL_REFRESH_TOKEN) + if (!await validateToken(channel_access_token)) { + result = await refreshToken(client_id, client_secret, process.env.TWITCH_CHANNEL_REFRESH_TOKEN) + if (result.status) return result = ['no_refresh', result.message] + else { + let [channel_access_token, channel_refresh_token] = result + writeEnv('TWITCH_CHANNEL_ACCESS_TOKEN', channel_access_token) + writeEnv('TWITCH_CHANNEL_REFRESH_TOKEN', channel_refresh_token) - let [channel_access_token, channel_refresh_token] = result - 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) + let channel_name = await getUserInfo(client_id, channel_access_token, 'login') + writeEnv('TWITCH_CHANNEL_NAME', channel_name) + } + } else { + let channel_name = await getUserInfo(client_id, channel_access_token, 'login') + result = [channel_access_token, channel_name] + writeEnv('TWITCH_CHANNEL_NAME', channel_name) } return result }) \ No newline at end of file diff --git a/utils/checkUser.js b/utils/checkUser.js index e739b6a..daad505 100644 --- a/utils/checkUser.js +++ b/utils/checkUser.js @@ -7,21 +7,26 @@ const writeEnv = require('./writeEnv') let client_id = process.env.TWITCH_APP_ID let client_secret = process.env.TWITCH_APP_SECRET -module.exports = checkUser = (async (access_token) => { +module.exports = checkUser = (async (user_access_token) => { + let result = [user_access_token, ''] // Check if user_access_token is valid - if (!await validateToken(access_token)) { + if (!await validateToken(user_access_token)) { + result = await refreshToken(client_id, client_secret, process.env.TWITCH_USER_REFRESH_TOKEN) - // If not, refresh it - let result = await refreshToken(client_id, client_secret, process.env.TWITCH_USER_REFRESH_TOKEN) if (result.status) return result = ['no_refresh', result.message] + else { + let [user_access_token, user_refresh_token] = result + writeEnv('TWITCH_USER_ACCESS_TOKEN', user_access_token) + writeEnv('TWITCH_USER_REFRESH_TOKEN', user_refresh_token) - let [user_access_token, user_refresh_token] = result - 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) + let user_name = await getUserInfo(client_id, user_access_token, 'login') + writeEnv('TWITCH_USER_NAME', user_name) + } + } else { + let user_name = await getUserInfo(client_id, user_access_token, 'login') + result = [user_access_token, user_name] + writeEnv('TWITCH_USER_NAME', user_name) } return result }) \ No newline at end of file diff --git a/utils/getRewardData.js b/utils/getRewardData.js index b15de21..cb262bc 100644 --- a/utils/getRewardData.js +++ b/utils/getRewardData.js @@ -11,7 +11,7 @@ module.exports = getRewardData = (async () => { database: process.env.MYSQL_DATABASE }) - // Retrieve the count of rewards claimed by each user, sorted by count + // Retrieve the count of rewards claimed by each viewer, sorted by count let results = await connection.execute('SELECT * FROM rewards ORDER BY count DESC') .then(async ([rows, fields]) => { return rows }) .catch(error => { console.error(error) }) diff --git a/utils/getUserAccessToken.js b/utils/getUserAccessToken.js index 9ff6047..e81ade2 100644 --- a/utils/getUserAccessToken.js +++ b/utils/getUserAccessToken.js @@ -8,7 +8,7 @@ module.exports = getUserAccessToken = (async (client_id, client_secret, code, re redirect_uri, grant_type: 'authorization_code' }).then(response => { - //console.log(response.data) + 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 new file mode 100644 index 0000000..70d83e6 --- /dev/null +++ b/utils/getUserID.js @@ -0,0 +1,13 @@ +const axios = require('axios') + +module.exports = getUserID = (async (client_id, access_token, login) => { + return await axios.get(`https://api.twitch.tv/helix/users?login=${login}`, { + 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/getUserInfo.js b/utils/getUserInfo.js index 9481e42..a6bb8d4 100644 --- a/utils/getUserInfo.js +++ b/utils/getUserInfo.js @@ -1,13 +1,14 @@ const axios = require('axios') -module.exports = getUserInfo = (async (client_id, access_token) => { - return await axios.get(`https://api.twitch.tv/helix/users`, { +module.exports = getUserInfo = (async (client_id, access_token, type) => { + 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] + if (type === 'login') return response.data.data[0].login + if (type === 'id') return response.data.data[0].id }).catch(error => { console.log(error.response.data) }) }) \ No newline at end of file diff --git a/utils/modifyReward.js b/utils/modifyReward.js new file mode 100644 index 0000000..748d855 --- /dev/null +++ b/utils/modifyReward.js @@ -0,0 +1,72 @@ +const mysql = require('mysql2/promise') +require('dotenv').config() + +module.exports = modifyReward = (async (viewer_id, viewer_name, action, quantity, type) => { + // Create a connection to the MySQL database + const connection = await mysql.createConnection({ + host: process.env.MYSQL_HOST, + port: process.env.MYSQL_PORT, + user: process.env.MYSQL_USER, + password: process.env.MYSQL_PASSWORD, + database: process.env.MYSQL_DATABASE + }) + + const result = {} + let sql_data = {} + + // Check if the viewer already exists in the rewards table + await connection.query('SELECT * FROM rewards WHERE viewer_id = ?', [viewer_id]) + .then(async ([rows, fields]) => { + console.log(rows) + + if (rows.length === 0) { + // Viewer doesn't exist, insert a new row + sql_data = { viewer_id, viewer_name } + + if (action === 'add' || action === 'set') { // Add or set the viewer with the quantity + if (type === 'permanent') sql_data.count = quantity + else if (type === 'current') sql_data.current_count = quantity + else { sql_data.count = quantity; sql_data.current_count = quantity } + + await connection.query('INSERT INTO rewards SET ?', sql_data) .catch(error => { console.error(error) }) + return result.status = 'insert_entry' + } + else if (action === 'get') return result.status = 'no_get_entry' // Can't get a viewer that doesn't exist + else if (action === 'remove') return result.status = 'no_delete_entry' // Can't remove a viewer that doesn't exist + } else { + // Viewer exists, update the count + result.count = rows[0].count + result.current_count = rows[0].current_count + + if (action === 'get') return result.status = 'get_entry' + + else if (action === 'add') { // Add the quantity + if (type === 'permanent') sql_data.count = rows[0].count + quantity + else if (type === 'current') sql_data.current_count = rows[0].current_count + quantity + else { sql_data.count = rows[0].count + quantity; sql_data.current_count = rows[0].current_count + quantity } + } + else if (action === 'remove') { // Remove the quantity + if (type === 'permanent') sql_data.count = rows[0].count - quantity + else if (type === 'current') sql_data.current_count = rows[0].current_count - quantity + else { sql_data.count = rows[0].count - quantity; sql_data.current_count = rows[0].current_count - quantity } + + if (sql_data.count < 0) return result.status = 'not_enough_count' // Can't delete more than the count + if (sql_data.current_count < 0) return result.status = 'not_enough_current_count' // Can't delete more than the current_count + } + else if (action === 'set') { // Set the quantity + if (type === 'permanent') sql_data.count = quantity + else if (type === 'current') sql_data.current_count = quantity + else { sql_data.count = quantity; sql_data.current_count = quantity } + } + + await connection.query('UPDATE rewards SET ? WHERE viewer_id = ?', [sql_data, viewer_id]).catch(error => { console.error(error) }) + return result.status = 'update_entry' + } + }).catch(error => { console.error(error) }) + + // Terminate the connection to the database + await connection.end() + + result.sql_data = sql_data + return result +}) \ No newline at end of file diff --git a/utils/rewardRedemption.js b/utils/rewardRedemption.js index 2398c1b..7c16f33 100644 --- a/utils/rewardRedemption.js +++ b/utils/rewardRedemption.js @@ -1,6 +1,7 @@ const mysql = require('mysql2/promise') +require('dotenv').config() -module.exports = rewardRedemption = (async (user_id, user_name) => { +module.exports = rewardRedemption = (async (viewer_id, viewer_name) => { // Create a connection to the MySQL database const connection = await mysql.createConnection({ host: process.env.MYSQL_HOST, @@ -10,21 +11,33 @@ module.exports = rewardRedemption = (async (user_id, user_name) => { database: process.env.MYSQL_DATABASE }) - // Check if the user already exists in the rewards table - await connection.query('SELECT * FROM rewards WHERE user_id = ?', [user_id]) + const result = {} + + // Check if the viewer already exists in the rewards table + await connection.query('SELECT * FROM rewards WHERE viewer_id = ?', [viewer_id]) .then(async ([rows, fields]) => { if (rows.length === 0) { - // User doesn't exist, insert a new row - await connection.query('INSERT INTO rewards SET ?', { user_id, user_name, count: 1, current_count: 1 }) - .catch(error => { console.error(error) }) + // Viewer doesn't exist, insert a new row + + let sql_data = { viewer_id, viewer_name, count: 1, current_count: 1 } + + await connection.query('INSERT INTO rewards SET ?', sql_data).catch(error => { console.error(error) }) + return result.status = 'insert_entry' } else { - // User exists, update the count - const newRow = { count: rows[0].count + 1, current_count: rows[0].current_count + 1 } - await connection.query('UPDATE rewards SET ? WHERE user_id = ?', [newRow, user_id]) - .catch(error => { console.error(error) }) + // Viewer exists, update the count + result.count = rows[0].count + 1 + result.current_count = rows[0].current_count + 1 + + let sql_data = { count: result.count, current_count: result.current_count } + + await connection.query('UPDATE rewards SET ? WHERE viewer_id = ?', [sql_data, viewer_id]).catch(error => { console.error(error) }) + return result.status = 'update_entry' } }).catch(error => { console.error(error) }) // Terminate the connection to the database await connection.end() + + //return [newRow.current_count, newRow.count] + return result }) \ No newline at end of file diff --git a/utils/validateToken.js b/utils/validateToken.js index a7a6bfc..f48a005 100644 --- a/utils/validateToken.js +++ b/utils/validateToken.js @@ -7,7 +7,6 @@ module.exports = validateToken = (async (access_token) => { } }).then(response => { //console.log(response.data) - if (response.data.status === '401') return false - else return true + return true }).catch(error => { console.log(error.response.data) }) }) \ No newline at end of file