Correctif import + library Opus + Fix util Twitch
This commit is contained in:
@@ -3,9 +3,10 @@
|
|||||||
node_modules
|
node_modules
|
||||||
public/cracks
|
public/cracks
|
||||||
.dockerignore
|
.dockerignore
|
||||||
|
.env
|
||||||
.gitignore
|
.gitignore
|
||||||
Dockerfile
|
|
||||||
README.md
|
|
||||||
tsconfig.json
|
|
||||||
.ncurc.json
|
.ncurc.json
|
||||||
.env
|
Dockerfile
|
||||||
|
eslint.config.mjs
|
||||||
|
README.md
|
||||||
|
tsconfig.json
|
||||||
35
.vscode/launch.json
vendored
35
.vscode/launch.json
vendored
@@ -13,41 +13,6 @@
|
|||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"internalConsoleOptions": "neverOpen",
|
"internalConsoleOptions": "neverOpen",
|
||||||
"restart": true
|
"restart": true
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Nodemon Tamiseur",
|
|
||||||
"args": ["-r", "dotenv/config", "${workspaceFolder}/src/index.ts", "dotenv_config_path=${workspaceFolder}/.env1"],
|
|
||||||
"skipFiles": ["<node_internals>/**"],
|
|
||||||
"runtimeExecutable": "nodemon",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"internalConsoleOptions": "neverOpen",
|
|
||||||
"restart": true
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Nodemon Groove",
|
|
||||||
"args": ["-r", "dotenv/config", "${workspaceFolder}/src/index.ts", "dotenv_config_path=${workspaceFolder}/.env2"],
|
|
||||||
"skipFiles": ["<node_internals>/**"],
|
|
||||||
"runtimeExecutable": "nodemon",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"internalConsoleOptions": "neverOpen",
|
|
||||||
"restart": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Nodemon Funky",
|
|
||||||
"args": ["-r", "dotenv/config", "${workspaceFolder}/src/index.ts", "dotenv_config_path=${workspaceFolder}/.env3"],
|
|
||||||
"skipFiles": ["<node_internals>/**"],
|
|
||||||
"runtimeExecutable": "nodemon",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"internalConsoleOptions": "neverOpen",
|
|
||||||
"restart": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"docker.commands.build": "docker build --rm -f \"${dockerfile}\" --target tamiseur -t bot_tamiseur:tamiseur -t localhost:5000/bot_tamiseur:tamiseur \"${context}\" && docker push localhost:5000/bot_tamiseur:tamiseur && docker build --rm -f \"${dockerfile}\" --target funky -t bot_tamiseur:funky -t localhost:5000/bot_tamiseur:funky \"${context}\" && docker push localhost:5000/bot_tamiseur:funky && docker build --rm -f \"${dockerfile}\" --target groove -t bot_tamiseur:groove -t localhost:5000/bot_tamiseur:groove \"${context}\" && docker push localhost:5000/bot_tamiseur:groove"
|
"docker.commands.build": "docker build --rm -f \"${dockerfile}\" -t bot_tamiseur:latest -t localhost:5000/bot_tamiseur:latest \"${context}\" && docker push localhost:5000/bot_tamiseur:latest"
|
||||||
}
|
}
|
||||||
20
Dockerfile
20
Dockerfile
@@ -1,15 +1,19 @@
|
|||||||
FROM node:lts-alpine
|
FROM node:lts-alpine
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
WORKDIR /usr/src/app
|
|
||||||
|
|
||||||
COPY ["package.json", "package-lock.json*", "./"]
|
|
||||||
RUN apk add --no-cache ffmpeg python3 make g++
|
RUN apk add --no-cache ffmpeg python3 make g++
|
||||||
RUN npm install -g ts-node
|
RUN npm install -g ts-node
|
||||||
RUN npm install --production --verbose && mv node_modules ../
|
|
||||||
|
|
||||||
COPY . .
|
RUN mkdir -p /usr/src/app/node_modules
|
||||||
RUN chown -R node /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN chown -R node:node /usr/src/app
|
||||||
|
|
||||||
USER node
|
USER node
|
||||||
|
#ENV NODE_ENV=production
|
||||||
|
#RUN npm install --production --verbose
|
||||||
|
RUN npm install --verbose
|
||||||
|
|
||||||
CMD ["npm", "start"]
|
COPY --chown=node:node . .
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
||||||
|
#CMD ["npm", "run", "prod"]
|
||||||
1600
package-lock.json
generated
1600
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "bot_tamiseur",
|
"name": "bot_tamiseur",
|
||||||
"description": "Listen to music and use fun commands with your friends!",
|
"description": "Listen to music and use fun commands with your friends!",
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Zachary Guénot"
|
"name": "Zachary Guénot"
|
||||||
},
|
},
|
||||||
@@ -10,8 +10,9 @@
|
|||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"start": "ts-node src/index.ts",
|
"start": "ts-node src/index.ts",
|
||||||
"dev": "nodemon -e ts src/index.ts",
|
"dev": "nodemon -e ts src/index.ts",
|
||||||
"build": "tsc && terser ./dist -o ./dist",
|
"build": "tsc",
|
||||||
"lint": "eslint src/**/*.ts"
|
"lint": "eslint src/**/*.ts",
|
||||||
|
"prod": "node dist/index.js"
|
||||||
},
|
},
|
||||||
"//": [
|
"//": [
|
||||||
"Garder chalk à la version 4.1.2 pour éviter un bug ESM avec la version >=5.0.0"
|
"Garder chalk à la version 4.1.2 pour éviter un bug ESM avec la version >=5.0.0"
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
"@discord-player/equalizer": "^0.2.3",
|
"@discord-player/equalizer": "^0.2.3",
|
||||||
"@discord-player/extractor": "^4.5.0",
|
"@discord-player/extractor": "^4.5.0",
|
||||||
"@discordjs/voice": "^0.17.0",
|
"@discordjs/voice": "^0.17.0",
|
||||||
"@types/parse-torrent": "^5.8.7",
|
"@evan/opus": "^1.0.3",
|
||||||
"axios": "^1.7.3",
|
"axios": "^1.7.3",
|
||||||
"bufferutil": "^4.0.8",
|
"bufferutil": "^4.0.8",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
@@ -31,13 +32,11 @@
|
|||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"jsdom": "^24.1.1",
|
"jsdom": "^24.1.1",
|
||||||
"libsodium-wrappers": "^0.7.14",
|
"libsodium-wrappers": "^0.7.14",
|
||||||
"mariadb": "^3.3.1",
|
|
||||||
"mediaplex": "^0.0.9",
|
"mediaplex": "^0.0.9",
|
||||||
"mongoose": "^8.5.2",
|
"mongoose": "^8.5.2",
|
||||||
"parse-torrent": "^9.1.5",
|
"parse-torrent": "^9.1.5",
|
||||||
"require-all": "^3.0.0",
|
"require-all": "^3.0.0",
|
||||||
"rss-parser": "^3.13.0",
|
"rss-parser": "^3.13.0",
|
||||||
"sqlite3": "^5.1.7",
|
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"utf-8-validate": "^6.0.4",
|
"utf-8-validate": "^6.0.4",
|
||||||
"websocket": "^1.0.35"
|
"websocket": "^1.0.35"
|
||||||
@@ -47,12 +46,12 @@
|
|||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@swc/core": "^1.7.6",
|
"@swc/core": "^1.7.6",
|
||||||
"@types/node": "^22.1.0",
|
"@types/node": "^22.1.0",
|
||||||
|
"@types/parse-torrent": "^5.8.7",
|
||||||
"@types/websocket": "^1.0.10",
|
"@types/websocket": "^1.0.10",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
||||||
"@typescript-eslint/parser": "^8.0.1",
|
"@typescript-eslint/parser": "^8.0.1",
|
||||||
"eslint": "^9.8.0",
|
"eslint": "^9.8.0",
|
||||||
"nodemon": "^3.1.4",
|
"nodemon": "^3.1.4",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3"
|
||||||
"terser": "^5.31.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,17 +54,11 @@ export default {
|
|||||||
}, 30000)
|
}, 30000)
|
||||||
|
|
||||||
// TWITCH EVENTSUB
|
// TWITCH EVENTSUB
|
||||||
let dbData = guildProfile.get('guildTwitch')
|
|
||||||
if (!dbData?.enabled) return console.log(chalk.magenta(`[Twitch] Module is disabled for "${guild?.name}", please activate with \`/database edit guildTwitch.enabled True\` !`))
|
|
||||||
|
|
||||||
let client_id = process.env.TWITCH_APP_ID as string
|
let client_id = process.env.TWITCH_APP_ID as string
|
||||||
if (!client_id) return console.log(chalk.magenta('[Twitch] App ID is not defined !'))
|
|
||||||
|
|
||||||
let client_secret = process.env.TWITCH_APP_SECRET as string
|
let client_secret = process.env.TWITCH_APP_SECRET as string
|
||||||
if (!client_secret) return console.log(chalk.magenta('[Twitch] App Secret is not defined !'))
|
|
||||||
|
|
||||||
let twitch = new WebSocket.client().on('connect', async connection => {
|
let twitch = new WebSocket.client().on('connect', async connection => {
|
||||||
console.log(chalk.magenta('[Twitch] EventSub WebSocket Connected !'))
|
console.log(chalk.magenta(`[Twitch] {${guild.name}} EventSub WebSocket Connected !`))
|
||||||
|
|
||||||
connection.on('message', async message => { if (message.type === 'utf8') { try {
|
connection.on('message', async message => { if (message.type === 'utf8') { try {
|
||||||
let data = JSON.parse(message.utf8Data)
|
let data = JSON.parse(message.utf8Data)
|
||||||
@@ -75,7 +69,7 @@ export default {
|
|||||||
|
|
||||||
// Check if the channel access token is still valid before connecting
|
// Check if the channel access token is still valid before connecting
|
||||||
channel_access_token = await Twitch.checkChannel(client_id, client_secret, channel_access_token, guild) as string
|
channel_access_token = await Twitch.checkChannel(client_id, client_secret, channel_access_token, guild) as string
|
||||||
if (!channel_access_token) return console.log(chalk.magenta("[Twitch] Can't refresh channel access token !"))
|
if (!channel_access_token) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Can't refresh channel access token !`))
|
||||||
|
|
||||||
// Get broadcaster user id and reward id
|
// Get broadcaster user id and reward id
|
||||||
let broadcaster_user_id = await Twitch.getUserInfo(client_id, channel_access_token, 'id') as string
|
let broadcaster_user_id = await Twitch.getUserInfo(client_id, channel_access_token, 'id') as string
|
||||||
@@ -87,29 +81,31 @@ export default {
|
|||||||
|
|
||||||
// Subscribe to all events required
|
// Subscribe to all events required
|
||||||
for (let type in topics) {
|
for (let type in topics) {
|
||||||
console.log(chalk.magenta(`[Twitch] Creating ${type}...`))
|
console.log(chalk.magenta(`[Twitch] {${guild.name}} Creating ${type}...`))
|
||||||
let { version, condition } = topics[type]
|
let { version, condition } = topics[type]
|
||||||
|
|
||||||
let status = await Twitch.subscribeToEvents(client_id, channel_access_token, data.payload.session.id, type, version, condition)
|
let status = await Twitch.subscribeToEvents(client_id, channel_access_token, data.payload.session.id, type, version, condition)
|
||||||
if (!status) return console.error(chalk.magenta(`[Twitch] Failed to create ${type}`))
|
if (!status) return console.error(chalk.magenta(`[Twitch] {${guild.name}} Failed to create ${type}`))
|
||||||
else if (status.error) return console.log(chalk.magenta('[Twitch] Erreur de connexion EventSub, veuillez vous reconnecter !'))
|
else if (status.error) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Erreur de connexion EventSub, veuillez vous reconnecter !`))
|
||||||
else console.log(chalk.magenta(`[Twitch] Successfully created ${type}`))
|
else console.log(chalk.magenta(`[Twitch] {${guild.name}} Successfully created ${type}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle notification messages
|
// Handle notification messages
|
||||||
else if (data.metadata.message_type === 'notification') Twitch.notification(client_id, channel_access_token, data, guild)
|
else if (data.metadata.message_type === 'notification') Twitch.notification(client_id, channel_access_token, data, guild)
|
||||||
|
|
||||||
} catch (error) { console.error(chalk.magenta('[Twitch] ' + error)) } } })
|
} catch (error) { console.error(chalk.magenta(`[Twitch] {${guild.name}} ` + error)) } } })
|
||||||
.on('error', error => console.error(chalk.magenta('[Twitch] ' + error)))
|
.on('error', error => console.error(chalk.magenta(`[Twitch] {${guild.name}} ` + error)))
|
||||||
.on('close', () => {
|
.on('close', () => {
|
||||||
console.log(chalk.magenta('[Twitch] EventSub Connection Closed !'))
|
console.log(chalk.magenta('[Twitch] {${guild.name}} EventSub Connection Closed !'))
|
||||||
twitch.connect('wss://eventsub.wss.twitch.tv/ws')
|
twitch.connect('wss://eventsub.wss.twitch.tv/ws')
|
||||||
})
|
})
|
||||||
}).on('connectFailed', error => console.error(chalk.magenta('[Twitch] ' + error)))
|
}).on('connectFailed', error => console.error(chalk.magenta(`[Twitch] {${guild.name}} ` + error)))
|
||||||
|
|
||||||
// LAUNCH TWITCH EVENTSUB
|
let dbData = guildProfile.get('guildTwitch')
|
||||||
twitch.connect('wss://eventsub.wss.twitch.tv/ws')
|
if (!dbData?.enabled) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Module is disabled for "${guild?.name}", please activate with \`/database edit guildTwitch.enabled True\` !`))
|
||||||
|
else if (!client_id || !client_secret) return console.log(chalk.magenta(`[Twitch] {${guild.name}} App ID or Secret is not defined !`))
|
||||||
|
else twitch.connect('wss://eventsub.wss.twitch.tv/ws')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue, Track } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'audioTrackAdd',
|
name: 'audioTrackAdd',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue, Track } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'audioTracksAdd',
|
name: 'audioTracksAdd',
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
import dbGuild from '../../schemas/guild'
|
import dbGuild from '../../schemas/guild'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'disconnect',
|
name: 'disconnect',
|
||||||
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
|
async execute(queue: GuildQueue<PlayerMetadata>) {
|
||||||
// Emitted when the bot leaves the voice channel
|
// Emitted when the bot leaves the voice channel
|
||||||
queue.metadata.channel.send("J'ai quitté le vocal !")
|
queue.metadata.channel.send("J'ai quitté le vocal !")
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'emptyChannel',
|
name: 'emptyChannel',
|
||||||
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
|
async execute(queue: GuildQueue<PlayerMetadata>) {
|
||||||
// Emitted when the voice channel has been empty for the set threshold
|
// Emitted when the voice channel has been empty for the set threshold
|
||||||
// Bot will automatically leave the voice channel with this event
|
// Bot will automatically leave the voice channel with this event
|
||||||
queue.metadata.channel.send(`Je quitte le vocal car il est vide depuis trop longtemps.`)
|
queue.metadata.channel.send(`Je quitte le vocal car il est vide depuis trop longtemps.`)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'emptyQueue',
|
name: 'emptyQueue',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue, Track } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'playerSkip',
|
name: 'playerSkip',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GuildQueue, Track } from 'discord-player'
|
import { GuildQueue, Track } from 'discord-player'
|
||||||
import { PlayerMetadata } from '../../utilsPlayer/metadata'
|
import { PlayerMetadata } from '../../utils/player'
|
||||||
import dbGuild from '../../schemas/guild'
|
import dbGuild from '../../schemas/guild'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import axios from 'axios'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
interface Game {
|
export interface Game {
|
||||||
name: string
|
name: string
|
||||||
link: string
|
link: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Guild, TextChannel, EmbedBuilder } from 'discord.js'
|
import { Guild, TextChannel, EmbedBuilder, hyperlink } from 'discord.js'
|
||||||
import axios, { AxiosHeaderValue } from 'axios'
|
import axios, { AxiosHeaderValue } from 'axios'
|
||||||
import dbGuild from '../schemas/guild'
|
import dbGuild from '../schemas/guild'
|
||||||
|
import chalk from 'chalk'
|
||||||
|
|
||||||
interface NotificationData {
|
interface NotificationData {
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -26,14 +27,14 @@ interface Condition {
|
|||||||
|
|
||||||
export async function checkChannel (client_id: string, client_secret: string, channel_access_token: string, guild: Guild) {
|
export async function checkChannel (client_id: string, client_secret: string, channel_access_token: string, guild: Guild) {
|
||||||
let guildProfile = await dbGuild.findOne({ guildId: guild?.id })
|
let guildProfile = await dbGuild.findOne({ guildId: guild?.id })
|
||||||
if (!guildProfile) return console.log(`Database data for ${guild?.name} does not exist, please initialize with \`/database init\` !`)
|
if (!guildProfile) return console.log(chalk.magenta(`[Twitch] Database data for ${guild?.name} does not exist, please initialize with \`/database init\` !`))
|
||||||
|
|
||||||
let dbData = guildProfile.get('guildTwitch')
|
let dbData = guildProfile.get('guildTwitch')
|
||||||
if (!dbData?.enabled) return console.log(`Twitch module is disabled for "${guild?.name}", please activate with \`/database edit guildTwitch.enabled True\` !`)
|
if (!dbData?.enabled) return console.log(chalk.magenta(`[Twitch] module is disabled for "${guild?.name}", please activate with \`/database edit guildTwitch.enabled True\` !`))
|
||||||
|
|
||||||
if (!await validateToken(channel_access_token)) {
|
if (!await validateToken(channel_access_token)) {
|
||||||
let channel_refresh_token = dbData.channelRefreshToken
|
let channel_refresh_token = dbData.channelRefreshToken
|
||||||
if (!channel_refresh_token) return console.log('No refresh token found in database !')
|
if (!channel_refresh_token) return console.log(chalk.magenta('[Twitch] No refresh token found in database !'))
|
||||||
|
|
||||||
let GetAccessFromRefresh = await refreshToken(client_id, client_secret, channel_refresh_token)
|
let GetAccessFromRefresh = await refreshToken(client_id, client_secret, channel_refresh_token)
|
||||||
if (!GetAccessFromRefresh) return false;
|
if (!GetAccessFromRefresh) return false;
|
||||||
@@ -93,22 +94,25 @@ export async function getUserInfo (client_id: string, access_token: string, type
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function notification (client_id: string, channel_access_token: string, data: NotificationData, guild: Guild) {
|
export async function notification (client_id: string, channel_access_token: string, data: NotificationData, guild: Guild) {
|
||||||
|
if (!guild) return console.log(chalk.magenta('[Twitch] Can\'t find guild !'))
|
||||||
let { subscription, event } = data.payload
|
let { subscription, event } = data.payload
|
||||||
|
|
||||||
let guildProfile = await dbGuild.findOne({ guildId: guild?.id })
|
let guildProfile = await dbGuild.findOne({ guildId: guild.id })
|
||||||
if (!guildProfile) return console.log(`Database data for ${guild?.name} does not exist, please initialize with \`/database init\` !`)
|
if (!guildProfile) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Database data does not exist, please initialize with \`/database init\` !`))
|
||||||
|
|
||||||
let dbData = guildProfile.get('guildTwitch')
|
let dbData = guildProfile.get('guildTwitch')
|
||||||
if (!dbData?.enabled) return console.log(`Twitch module is disabled for "${guild?.name}", please activate with \`/database edit guildTwitch.enabled True\` !`)
|
if (!dbData?.enabled) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Module is disabled, please activate with \`/database edit guildTwitch.enabled True\` !`))
|
||||||
|
|
||||||
let liveChannelId = dbData.liveChannelId
|
let liveChannelId = dbData.liveChannelId
|
||||||
if (!liveChannelId) return console.log('No live channel id found in database !')
|
if (!liveChannelId) return console.log(chalk.magenta(`[Twitch] {${guild.name}} No live channel id found in database !`))
|
||||||
|
|
||||||
let liveChannel = guild.channels.cache.get(liveChannelId) as TextChannel
|
let liveChannel = guild.channels.cache.get(liveChannelId) as TextChannel
|
||||||
if (!liveChannel) return console.log(`\u001b[1;35m Can't find channel with id ${liveChannelId}`)
|
if (!liveChannel) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Can't find channel with id ${liveChannelId}`))
|
||||||
|
|
||||||
|
let liveMessageInterval
|
||||||
|
|
||||||
if (subscription.type === 'stream.online') {
|
if (subscription.type === 'stream.online') {
|
||||||
console.log(`\u001b[1;35m Stream from ${event.broadcaster_user_name} is now online, sending Discord message...`)
|
console.log(chalk.magenta(`[Twitch] {${guild.name}} Stream from ${event.broadcaster_user_name} is now online, sending Discord message...`))
|
||||||
|
|
||||||
let stream_data = await getStreams(client_id, channel_access_token, event.broadcaster_user_login)
|
let stream_data = await getStreams(client_id, channel_access_token, event.broadcaster_user_login)
|
||||||
let user_profile_image_url = await getUserInfo(client_id, channel_access_token, 'profile_image_url')
|
let user_profile_image_url = await getUserInfo(client_id, channel_access_token, 'profile_image_url')
|
||||||
@@ -116,39 +120,51 @@ export async function notification (client_id: string, channel_access_token: str
|
|||||||
let embed = new EmbedBuilder()
|
let embed = new EmbedBuilder()
|
||||||
.setColor('#6441a5')
|
.setColor('#6441a5')
|
||||||
.setTitle(stream_data.title)
|
.setTitle(stream_data.title)
|
||||||
.setURL(`https://twitch.tv/laytho_`)
|
.setURL(`https://twitch.tv/${event.broadcaster_user_login}`)
|
||||||
.setAuthor({ name: `${event.broadcaster_user_login.toUpperCase()} EST ACTUELLEMENT EN LIVE !`, iconURL: user_profile_image_url })
|
.setAuthor({ name: `🔴 ${event.broadcaster_user_name.toUpperCase()} EST ACTUELLEMENT EN LIVE ! 🎥`, iconURL: user_profile_image_url })
|
||||||
.setDescription(`Joue à ${stream_data.game_name} avec ${stream_data.viewer_count} viewers`)
|
.setDescription(`Joue à ${stream_data.game_name} avec ${stream_data.viewer_count} viewers`)
|
||||||
.setImage(stream_data.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080'))
|
.setImage(stream_data.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080'))
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
let message = await liveChannel.send({ content: `Hey @everyone ! <@${dbData.liveBroadcasterId}> démarre son live sur **Twitch** !`, embeds: [embed] })
|
let hidden = hyperlink('démarre un live', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&pp=ygUJcmljayByb2xs')
|
||||||
|
let message = await liveChannel.send({ content: `Hey ! <@${dbData.liveBroadcasterId}> ${hidden} sur **Twitch**, venez !`, embeds: [embed] })
|
||||||
|
|
||||||
dbData.liveMessageId = message.id
|
dbData.liveMessageId = message.id
|
||||||
guildProfile.set('guildTwitch', dbData)
|
guildProfile.set('guildTwitch', dbData)
|
||||||
guildProfile.markModified('guildTwitch')
|
guildProfile.markModified('guildTwitch')
|
||||||
await guildProfile.save().catch(console.error)
|
await guildProfile.save().catch(console.error)
|
||||||
|
|
||||||
|
liveMessageInterval = setInterval(async () => {
|
||||||
|
let stream_data = await getStreams(client_id, channel_access_token, event.broadcaster_user_login)
|
||||||
|
if (!stream_data) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Can't find stream data for ${event.broadcaster_user_name}`))
|
||||||
|
embed.setTitle(stream_data.title)
|
||||||
|
.setDescription(`Joue à ${stream_data.game_name} avec ${stream_data.viewer_count} viewers`)
|
||||||
|
.setImage(stream_data.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080'))
|
||||||
|
.setTimestamp()
|
||||||
|
message.edit({ content: `Hey @everyone !\n<@${dbData.liveBroadcasterId}> est en live sur **Twitch**, venez !`, embeds: [embed] }).catch(console.error)
|
||||||
|
}, 60000)
|
||||||
}
|
}
|
||||||
else if (subscription.type === 'stream.offline') {
|
else if (subscription.type === 'stream.offline') {
|
||||||
console.log(`\u001b[1;35m Stream from laytho_ is now offline, editing Discord message...`)
|
console.log(chalk.magenta(`[Twitch] {${guild.name}} Stream from ${event.broadcaster_user_name} is now offline, editing Discord message...`))
|
||||||
|
|
||||||
let message = liveChannel.messages.cache.find(message => message.id === dbData.liveMessageId)
|
let message = await liveChannel.messages.fetch(dbData.liveMessageId as string)
|
||||||
if (!message) return console.log(`\u001b[1;35m Can't find message with id ${dbData.liveMessageId}`)
|
if (!message) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Can't find message with id ${dbData.liveMessageId}`))
|
||||||
if (!message.embeds[0]) return console.log(`\u001b[1;35m Can't find embed in message with id ${dbData.liveMessageId}`)
|
if (!message.embeds[0]) return console.log(chalk.magenta(`[Twitch] {${guild.name}} Can't find embed in message with id ${dbData.liveMessageId}`))
|
||||||
|
|
||||||
let duration = new Date().getTime() - new Date(message.embeds[0].data.timestamp ?? 0).getTime()
|
let duration = new Date().getTime() - new Date(message.embeds[0].data.timestamp ?? 0).getTime()
|
||||||
let seconds = Math.floor(duration / 1000)
|
let seconds = Math.floor(duration / 1000)
|
||||||
let minutes = Math.floor(seconds / 60)
|
let minutes = Math.floor(seconds / 60)
|
||||||
let hours = Math.floor(minutes / 60)
|
let hours = Math.floor(minutes / 60)
|
||||||
let duration_string = `${hours ? hours + 'H' : ''} ${minutes % 60 ? minutes % 60 + 'M' : ''} ${seconds % 60 ? seconds % 60 + 'S' : ''}`
|
let duration_string = `${hours ? hours + 'H ' : ''}${minutes % 60 ? minutes % 60 + 'M ' : ''}${seconds % 60 ? seconds % 60 + 'S' : ''}`
|
||||||
|
|
||||||
let user_profile_image_url = await getUserInfo(client_id, channel_access_token, 'profile_image_url')
|
let user_profile_image_url = await getUserInfo(client_id, channel_access_token, 'profile_image_url')
|
||||||
|
|
||||||
let embed = new EmbedBuilder()
|
let embed = new EmbedBuilder()
|
||||||
.setColor('#6441a5')
|
.setColor('#6441a5')
|
||||||
.setAuthor({ name: `C'EST FINI, LE LIVE A DURÉ ${duration_string} !`, iconURL: user_profile_image_url })
|
.setAuthor({ name: `⚫ C'EST FINI, LE LIVE A DURÉ ${duration_string} ! 📼`, iconURL: user_profile_image_url })
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
|
|
||||||
message.edit({ content: `Re @everyone ! <@${dbData.liveBroadcasterId}> a terminé son live sur **Twitch** !`, embeds: [embed] })
|
message.edit({ content: `Re !\n<@${dbData.liveBroadcasterId}> a terminé son live sur **Twitch** !`, embeds: [embed] }).catch(console.error)
|
||||||
|
clearInterval(liveMessageInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user