Compare commits
10 Commits
d29db3959c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e996a349a | |||
| 84c9032891 | |||
| c7727474c9 | |||
| 29f6c0cca1 | |||
| 85f031c33a | |||
| 5b07182020 | |||
| fe0c937fb2 | |||
| dcea3ce294 | |||
| 0ca35deb6e | |||
| 96af757961 |
@@ -5,34 +5,45 @@ HelBot v5 introduces an improved background logic structure, streamlined integra
|
||||
### Database Structure:
|
||||
|
||||
**client.credentials**:
|
||||
- `_id`
|
||||
- `client_id`
|
||||
- `client_secret`
|
||||
- `token`
|
||||
- `service`
|
||||
- `mod_id`
|
||||
- `client_id` (twitch:discord)
|
||||
- `client_secret` (twitch:discord)
|
||||
- `token` (access_token:token)
|
||||
- `service` (twitch:discord)
|
||||
- `mod_id` (twitch only)
|
||||
|
||||
**shoutouts.#channel**:
|
||||
- `_id`
|
||||
- `user`
|
||||
- `created_at`
|
||||
|
||||
**guilds.id**:
|
||||
- `_id`
|
||||
- `settings`
|
||||
- `channels`
|
||||
- `event`
|
||||
- `channel`
|
||||
|
||||
**commands.channel**:
|
||||
- `name`
|
||||
- `enabled`
|
||||
|
||||
**settings.channel**:
|
||||
- `name`
|
||||
- `enabled`
|
||||
|
||||
### Chat Commands:
|
||||
|
||||
**Update Chat Mode** (Mods & Broadcaster only)
|
||||
- `$mode [on:off]`
|
||||
|
||||
**Get a Random Positive Reminder**
|
||||
**Get A Positive Reminder**
|
||||
- `$positivity`
|
||||
|
||||
**View Donothon/Charity Event Information**
|
||||
- `$donate`
|
||||
|
||||
**View / Manage Settings**
|
||||
- `$commands [enable:disable] [setting]`
|
||||
|
||||
**View / Manage Commands**
|
||||
- `$commands [enable:disable] [command]`
|
||||
|
||||
### Behaviour:
|
||||
|
||||
- Automatically protects the chat by enabling **follow-only**, **sub-only**, or **emote-only** modes when the stream goes offline.
|
||||
|
||||
@@ -54,6 +54,29 @@ async function getChannel(interaction) {
|
||||
}, 5000))
|
||||
}
|
||||
}
|
||||
async function unsetChannel(interaction) {
|
||||
const event = interaction.options.getString('event')
|
||||
const db = mClient.db('guilds')
|
||||
const coll = db.collection(interaction.guild.id)
|
||||
|
||||
try {
|
||||
await coll.deleteOne({
|
||||
event: event
|
||||
})
|
||||
|
||||
return interaction.editReply({
|
||||
content: `Channel for Event: ${event} has been unset`,
|
||||
flags: MessageFlags.Ephemeral
|
||||
})
|
||||
} catch (error) {
|
||||
return interaction.editReply({
|
||||
content: `**[ERROR]:** ${event} is currently not set to any channel`,
|
||||
flags: MessageFlags.Ephemeral
|
||||
}).then(setTimeout(() => {
|
||||
interaction.deleteReply()
|
||||
}, 5000))
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('channel')
|
||||
@@ -100,6 +123,24 @@ module.exports = {
|
||||
])
|
||||
.setRequired(true)
|
||||
)
|
||||
)
|
||||
.addSubcommand(s =>
|
||||
s
|
||||
.setName('unset')
|
||||
.setDescription('unset channel for certain events')
|
||||
.addStringOption(o =>
|
||||
o
|
||||
.setName('event')
|
||||
.setDescription('choose the event')
|
||||
.addChoices([
|
||||
{ "name": "When a user joins this server", "value": "GuildMemberAdd" },
|
||||
{ "name": "When a user left this server", "value": "GuildMemberRemove" },
|
||||
{ "name": "When it's a users birthday", "value": "Discord/Birthday" },
|
||||
{ "name": "When debug logs are sent", "value": "Discord/Logs" },
|
||||
{ "name": "When stream is live", "value": "Twitch/Online" }
|
||||
])
|
||||
.setRequired(true)
|
||||
)
|
||||
),
|
||||
async execute(interaction) {
|
||||
if (!interaction.member.permissions.has("ADMINISTRATOR")) {
|
||||
@@ -116,6 +157,9 @@ module.exports = {
|
||||
case "get":
|
||||
getChannel(interaction)
|
||||
break;
|
||||
case "unset":
|
||||
unsetChannel(interaction)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
// Event triggered by client connected to server
|
||||
|
||||
const { RWSConnect, RWSDisconnect } = require("../../functions")
|
||||
const { mClient, dClient } = require("../..");
|
||||
var { tClient } = require('../..')
|
||||
const { refreshAccessToken } = require("../../functions")
|
||||
const tmi = require('tmi.js')
|
||||
|
||||
module.exports = {
|
||||
name: 'Twitch/Disconnected',
|
||||
once: false,
|
||||
async execute(reason) {
|
||||
console.log('Twitch disconnected:', reason);
|
||||
try {
|
||||
RWSDisconnect()
|
||||
} catch (error) {
|
||||
console.error
|
||||
}
|
||||
|
||||
if (reason.includes('Login authentication failed')) {
|
||||
try {
|
||||
await refreshAccessToken();
|
||||
console.log('Reinitializing Twitch client after token refresh...');
|
||||
|
||||
try {
|
||||
await tClient.disconnect();
|
||||
} catch (err) {
|
||||
console.warn('Twitch client already disconnected:', err.message);
|
||||
}
|
||||
|
||||
const db = mClient.db("clients");
|
||||
const credentialCollection = db.collection('credentials');
|
||||
const tCreds = await credentialCollection.findOne({ service: 'twitch' });
|
||||
@@ -38,8 +28,8 @@ module.exports = {
|
||||
},
|
||||
channels: tClient.channels,
|
||||
});
|
||||
|
||||
await tClient.connect();
|
||||
const { address, port } = await tClient.connect()
|
||||
dClient.emit("Twitch/Connected", address, port)
|
||||
console.log('Twitch client reconnected successfully.');
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh token and reconnect:', error);
|
||||
|
||||
@@ -12,6 +12,7 @@ module.exports = {
|
||||
name: 'Twitch/EventSub',
|
||||
once: false,
|
||||
async execute() {
|
||||
console.log('Starting Event Subs...')
|
||||
const endpoint = `wss://eventsub.wss.twitch.tv/ws`
|
||||
|
||||
const db = mClient.db('clients')
|
||||
@@ -39,6 +40,9 @@ module.exports = {
|
||||
function onDisconnect(reason) {
|
||||
console.log(`Disconnecting due to reason`, reason)
|
||||
}
|
||||
function onError(error){
|
||||
console.log(error)
|
||||
}
|
||||
function connect() {
|
||||
connection = new ReconnectingWebSocket(endpoint, [], {
|
||||
WebSocket: WebSocket,
|
||||
@@ -48,6 +52,7 @@ module.exports = {
|
||||
return new Promise((resolve, reject) => {
|
||||
connection.onclose = ({ reason }) => onDisconnect(reason, reject)
|
||||
connection.onmessage = ({ data }) => onMessage(data, resolve)
|
||||
connection.onerror = ({ error }) => onError(error)
|
||||
})
|
||||
}
|
||||
function onMessage(data) {
|
||||
@@ -92,6 +97,7 @@ module.exports = {
|
||||
subscribedEvents[type] = listener
|
||||
return true
|
||||
}
|
||||
|
||||
connect(options)
|
||||
if (options.debug) {
|
||||
events.on(WebsocketEvents.CONNECTED, () => {
|
||||
@@ -105,7 +111,7 @@ module.exports = {
|
||||
|
||||
const conditions = [{
|
||||
broadcaster_user_id: String(await getIDByName("x__hel__x"))
|
||||
},{
|
||||
}, {
|
||||
broadcaster_user_id: String(await getIDByName("desq_blocki"))
|
||||
}]
|
||||
|
||||
|
||||
+12
-48
@@ -21,48 +21,6 @@ module.exports = {
|
||||
})
|
||||
}
|
||||
}
|
||||
async function sendPositivity() {
|
||||
// Function sends a random string of predetermined positivity, Donothon Top Donator Reward
|
||||
let positive_Messages = [
|
||||
"You are so very worthy of all the love and support that may come your way.",
|
||||
"There are many things which draw us together. In this time and place, that lovely subject is you, Hel.",
|
||||
"The happiness and joy you add to the world is worth more than most anything.",
|
||||
"You deserve every warm laugh, bright smile, and all the genuine kindness given to you.",
|
||||
"There are few things as precious as your time. Thank you for sharing with us.",
|
||||
"Your feelings are valid and you are not less than for having them.",
|
||||
"I've seen all the work you do and I'm so very proud of you.",
|
||||
"You are dearly cherished and I want to thank you for being so wonderfully you.",
|
||||
"You. Are. Worthy. Enough. And I will tell you as many times as it takes for you to believe it.",
|
||||
"Every day you give your best and that is so admirable. Don't let anyone tell you otherwise.",
|
||||
"Your light is like that of the full moon, brightening our lives even in our darkest moments.",
|
||||
"It's okay to take a moment to catch your breath. Even machines require maintenance from time to time.",
|
||||
"Watching you succeed and achieve your heart's desires gives me so much motivation and I am very grateful for it."
|
||||
]
|
||||
|
||||
let rdm = Math.floor(Math.random() * positive_Messages.length)
|
||||
return tClient.say(channel, positive_Messages[rdm])
|
||||
}
|
||||
async function sendDonationAd() {
|
||||
// Function to send static donate ad
|
||||
const links = [
|
||||
"https://bit.ly/heltwittergoals",
|
||||
"https://bit.ly/donatetohel",
|
||||
"http://bit.ly/donothon_goals"
|
||||
];
|
||||
|
||||
const messages = [
|
||||
"Hel is currently celebrating her birthday with a donathon!",
|
||||
`You can see goals and incentives here: ${links[0]}`,
|
||||
`You can donate here: ${links[1]}`,
|
||||
`Terms, conditions, rules and how rewards work are found here: ${links[2]}`,
|
||||
"All donations and gifts are greatly appreciated, but please do so responsibly!"
|
||||
];
|
||||
|
||||
for (const message of messages) {
|
||||
await tClient.say(channel, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (self) { return }
|
||||
if (knownBots.has(userstate.username)) { return }
|
||||
@@ -87,16 +45,22 @@ module.exports = {
|
||||
const cmd = args[0]
|
||||
switch (cmd) {
|
||||
case "mode":
|
||||
if (userstate.badges.moderator != 1 && userstate.badges.broadcaster != 1) { break } // return stops all further operations, so you should just break out of switch
|
||||
let regex = /^(on|off)$/
|
||||
if (!args[1].match(regex)) { break }
|
||||
updateChatMode(await getIDByName(channel.substring(1)), args[1])
|
||||
dClient.emit('Command/mode', channel, userstate, message, self, args[1])
|
||||
break;
|
||||
case "donate":
|
||||
sendDonationAd()
|
||||
dClient.emit('Command/donate', channel, userstate, message, self)
|
||||
break;
|
||||
case "positivity":
|
||||
sendPositivity()
|
||||
dClient.emit('Command/positivity', channel, userstate, message, self)
|
||||
break;
|
||||
case "commands":
|
||||
dClient.emit('Command/commands', channel, userstate, message, self, args[1], args[2])
|
||||
break;
|
||||
case "settings":
|
||||
dClient.emit('Command/settings', channel, userstate, message, self, args[1], args[2])
|
||||
break;
|
||||
case "so":
|
||||
dClient.emit('Command/so', channel, userstate, message, self, args[1])
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
+31
-44
@@ -7,15 +7,15 @@ module.exports = {
|
||||
once: false,
|
||||
async execute(stream) {
|
||||
const db = mClient.db('guilds')
|
||||
const res = await db.listCollections().toArray()
|
||||
const guilds = await db.listCollections().toArray()
|
||||
const streamer = stream.broadcaster_user_login
|
||||
console.log(`${streamer} went live!`)
|
||||
|
||||
res.forEach(async (guildColl) => {
|
||||
const guildId = guildColl.name
|
||||
guilds.forEach(async (guildData) => {
|
||||
const guildId = guildData.name
|
||||
const coll = db.collection(guildId)
|
||||
const res = await coll.findOne({ event: 'Twitch/Online' })
|
||||
if(!res){
|
||||
if (!res) {
|
||||
return // ignore if no live channel set
|
||||
}
|
||||
const guild = dClient.guilds.cache.get(guildId)
|
||||
@@ -23,47 +23,34 @@ module.exports = {
|
||||
|
||||
try {
|
||||
const streamData = await getStreams(streamer)
|
||||
|
||||
if (streamData?.data[0]) {
|
||||
let liveData = {
|
||||
streamer: streamData.data[0].user_name,
|
||||
game: streamData.data[0].game_name,
|
||||
title: streamData.data[0].title,
|
||||
thumbnail: streamData.data[0].thumbnail_url.replace('-{width}x{height}', ''),
|
||||
tags: streamData.data[0].tags
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${escapeMarkdown(liveData.streamer)} is live!`)
|
||||
.setDescription(`They're playing ${liveData.game}`)
|
||||
.addFields(
|
||||
{ name: '\u200B', value: `${liveData.title}` })
|
||||
.setImage(liveData.thumbnail)
|
||||
.setURL(`https://twitch.tv/${streamer}`)
|
||||
let footer = ""
|
||||
liveData.tags.forEach((tag) => {
|
||||
footer += `#${tag} `
|
||||
})
|
||||
embed.setFooter({
|
||||
text: footer
|
||||
})
|
||||
|
||||
return channel.send({
|
||||
embeds: [embed],
|
||||
flags: MessageFlags.Ephemeral
|
||||
}).then(message => setTimeout(() => {
|
||||
message.deleteReply()
|
||||
}, 60000))
|
||||
} else {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${escapeMarkdown(streamer)} is currently offline!`)
|
||||
.setImage('https://media.discordapp.net/attachments/1061304429724319794/1319800268770250883/no-signal-tv-descendant-network-rainbow-bars-abstract-background-vector.jpg?ex=67674748&is=6765f5c8&hm=d539944a67fccec461b0183a9f0300e19ac485deda7b23090165088567f2c84f&=&format=webp')
|
||||
.setURL(`https://twitch.tv/${streamer}`)
|
||||
return channel.send({
|
||||
embeds: [embed],
|
||||
flags: MessageFlags.Ephemeral
|
||||
})
|
||||
let liveData = {
|
||||
streamer: streamData.data[0].user_name,
|
||||
game: streamData.data[0].game_name,
|
||||
title: streamData.data[0].title,
|
||||
thumbnail: streamData.data[0].thumbnail_url.replace('-{width}x{height}', ''),
|
||||
tags: streamData.data[0].tags
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${escapeMarkdown(liveData.streamer)} is live!`)
|
||||
.setDescription(`They're playing ${liveData.game}`)
|
||||
.addFields(
|
||||
{ name: '\u200B', value: `${liveData.title}` })
|
||||
.setImage(liveData.thumbnail)
|
||||
.setURL(`https://twitch.tv/${streamer}`)
|
||||
let footer = ""
|
||||
liveData.tags.forEach((tag) => {
|
||||
footer += `#${tag} `
|
||||
})
|
||||
embed.setFooter({
|
||||
text: footer
|
||||
})
|
||||
|
||||
return channel.send({
|
||||
content: `@everyone ${escapeMarkdown(streamer)} is live`,
|
||||
embeds: [embed]
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
return console.error
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { tClient } = require("../..");
|
||||
const { tClient, mClient } = require("../..");
|
||||
const { getChannelInformation } = require("../../functions");
|
||||
|
||||
// Event triggered by Custom Shoutout emitted in Messages.js
|
||||
@@ -9,7 +9,21 @@ module.exports = {
|
||||
name: 'Twitch/Shoutout',
|
||||
once: false,
|
||||
async execute(reason, channel, username) {
|
||||
|
||||
// Check if shoutout is enabled
|
||||
const db = mClient.db('settings')
|
||||
const coll = db.collection(channel)
|
||||
const setting = await coll.findOne({ name: 'shoutout' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!setting) {
|
||||
await coll.insertOne({
|
||||
name: 'shoutout',
|
||||
enabled: false // default
|
||||
})
|
||||
}
|
||||
|
||||
if (!setting?.enabled && reason != 'command' ){ return }
|
||||
|
||||
// Function to perform shoutout (Nightbot or custom)
|
||||
async function doShoutouts(channel, user) {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
const { mClient, tClient } = require("../..");
|
||||
|
||||
module.exports = {
|
||||
name: 'Command/commands',
|
||||
once: false,
|
||||
async execute(channel, userstate, message, self, state, name) {
|
||||
const db = mClient.db('commands')
|
||||
const coll = db.collection(channel)
|
||||
const defaultCommands = await coll.find({ default: true}).toArray()
|
||||
var isDefault = false
|
||||
defaultCommands.forEach((command) => {
|
||||
if(command.default && command.name == name ){
|
||||
isDefault = true
|
||||
}
|
||||
})
|
||||
if (isDefault){
|
||||
return tClient.say(channel, `${name} can't be modified`)
|
||||
}
|
||||
const command = await coll.findOne({ name: 'commands' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!command) {
|
||||
await coll.insertOne({
|
||||
name: 'commands',
|
||||
enabled: true,
|
||||
default: true
|
||||
})
|
||||
}
|
||||
|
||||
// Default non-admin mode, give list of all enabled commands
|
||||
if (!name) {
|
||||
const commands = await coll.find({}).toArray()
|
||||
var commandList = []
|
||||
commands.forEach((command) => {
|
||||
if(userstate.badges.moderator != 1 && userstate.badges.broadcaster != 1){
|
||||
commandList.push(` ${command.name}`)
|
||||
} else {
|
||||
commandList.push(` ${command.name}(${command.enabled?'✅':'❌'})`)
|
||||
}
|
||||
|
||||
})
|
||||
if (commandList.length == 0) {
|
||||
return await tClient.say(channel, `No commands available in this channel`)
|
||||
}
|
||||
return await tClient.say(channel, `Command List: ${commandList.toString()}`)
|
||||
}
|
||||
|
||||
if (userstate.badges.moderator != 1 && userstate.badges.broadcaster != 1) { return }
|
||||
|
||||
if (!state) { return }
|
||||
|
||||
// Admin Mode & Additional Parameters were given
|
||||
|
||||
// Parameters are valid
|
||||
switch (state) {
|
||||
case 'enable':
|
||||
state = true
|
||||
break;
|
||||
case 'disable':
|
||||
state = false
|
||||
break;
|
||||
default:
|
||||
return tClient.say(channel, `invalid state, expecting 'enable' or 'disable'`)
|
||||
}
|
||||
|
||||
// command is valid
|
||||
|
||||
const findCommand = await coll.findOne({ name: name })
|
||||
if (!findCommand) { return await tClient.say(channel, `Command [${name}] not found. Try using it first if it exists`) }
|
||||
|
||||
|
||||
await coll.findOneAndUpdate({
|
||||
name: name
|
||||
}, {
|
||||
$set: { enabled: state }
|
||||
}, {
|
||||
upsert: true
|
||||
})
|
||||
|
||||
return await tClient.say(channel, `[${name}] has been set to [${state}]`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
const { mClient, tClient } = require("../..");
|
||||
|
||||
module.exports = {
|
||||
name: 'Command/donate',
|
||||
once: false,
|
||||
async execute(channel, userstate, message, self) {
|
||||
|
||||
const db = mClient.db('commands')
|
||||
const coll = db.collection(channel)
|
||||
const command = await coll.findOne({ name: 'donate' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!command) {
|
||||
await coll.insertOne({
|
||||
name: 'donate',
|
||||
enabled: false // default
|
||||
})
|
||||
}
|
||||
|
||||
if (!command?.enabled){ return tClient.say(channel, `This command is currently disabled `)}
|
||||
|
||||
async function sendDonationAd() {
|
||||
// Function to send static donate ad
|
||||
const links = [
|
||||
"https://bit.ly/heltwittergoals",
|
||||
"https://bit.ly/donatetohel",
|
||||
"http://bit.ly/donothon_goals"
|
||||
];
|
||||
|
||||
const messages = [
|
||||
"Hel is currently celebrating her birthday with a donathon!",
|
||||
`You can see goals and incentives here: ${links[0]}`,
|
||||
`You can donate here: ${links[1]}`,
|
||||
`Terms, conditions, rules and how rewards work are found here: ${links[2]}`,
|
||||
"All donations and gifts are greatly appreciated, but please do so responsibly!"
|
||||
];
|
||||
|
||||
for (const message of messages) {
|
||||
await tClient.say(channel, message);
|
||||
}
|
||||
}
|
||||
sendDonationAd()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
const { mClient, tClient } = require('../..')
|
||||
const { updateChatMode, getIDByName } = require('../../functions')
|
||||
module.exports = {
|
||||
name: 'Command/mode',
|
||||
once: false,
|
||||
async execute(channel, userstate, message, self, params) {
|
||||
const db = mClient.db('commands')
|
||||
const coll = db.collection(channel)
|
||||
const command = await coll.findOne({ name: 'mode' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!command) {
|
||||
await coll.insertOne({
|
||||
name: 'mode',
|
||||
enabled: false // default
|
||||
})
|
||||
}
|
||||
if (!command?.enabled){ return tClient.say(channel, `This command is currently disabled `) }
|
||||
|
||||
if (userstate.badges.moderator != 1 && userstate.badges.broadcaster != 1) { return }
|
||||
let regex = /^(on|off)$/
|
||||
if (!params.match(regex)) { return }
|
||||
updateChatMode(await getIDByName(channel.substring(1)), params)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
const { tClient, mClient } = require('../..')
|
||||
module.exports = {
|
||||
name: 'Command/positivity',
|
||||
once: false,
|
||||
async execute(channel, userstate, message, self) {
|
||||
const db = mClient.db('commands')
|
||||
const coll = db.collection(channel)
|
||||
const command = await coll.findOne({ name: 'positivity' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!command) {
|
||||
await coll.insertOne({
|
||||
name: 'positivity',
|
||||
enabled: false // default
|
||||
})
|
||||
}
|
||||
|
||||
if (!command?.enabled){ return tClient.say(channel, `This command is currently disabled `) }
|
||||
|
||||
async function sendPositivity() {
|
||||
// Function sends a random string of predetermined positivity, Donothon Top Donator Reward
|
||||
let positive_Messages = [
|
||||
"You are so very worthy of all the love and support that may come your way.",
|
||||
"There are many things which draw us together. In this time and place, that lovely subject is you, Hel.",
|
||||
"The happiness and joy you add to the world is worth more than most anything.",
|
||||
"You deserve every warm laugh, bright smile, and all the genuine kindness given to you.",
|
||||
"There are few things as precious as your time. Thank you for sharing with us.",
|
||||
"Your feelings are valid and you are not less than for having them.",
|
||||
"I've seen all the work you do and I'm so very proud of you.",
|
||||
"You are dearly cherished and I want to thank you for being so wonderfully you.",
|
||||
"You. Are. Worthy. Enough. And I will tell you as many times as it takes for you to believe it.",
|
||||
"Every day you give your best and that is so admirable. Don't let anyone tell you otherwise.",
|
||||
"Your light is like that of the full moon, brightening our lives even in our darkest moments.",
|
||||
"It's okay to take a moment to catch your breath. Even machines require maintenance from time to time.",
|
||||
"Watching you succeed and achieve your heart's desires gives me so much motivation and I am very grateful for it."
|
||||
]
|
||||
|
||||
let rdm = Math.floor(Math.random() * positive_Messages.length)
|
||||
return tClient.say(channel, positive_Messages[rdm])
|
||||
}
|
||||
sendPositivity()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
const { mClient, tClient } = require("../..");
|
||||
|
||||
module.exports = {
|
||||
name: 'Command/settings',
|
||||
once: false,
|
||||
async execute(channel, userstate, message, self, state, name) {
|
||||
if (userstate.badges.moderator != 1 && userstate.badges.broadcaster != 1) { return }
|
||||
const db = mClient.db('commands')
|
||||
const coll = db.collection(channel)
|
||||
const command = await coll.findOne({ name: 'settings' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!command) {
|
||||
await coll.insertOne({
|
||||
name: 'settings',
|
||||
enabled: true,
|
||||
default: true
|
||||
})
|
||||
}
|
||||
if (!command?.enabled) { return tClient.say(channel, `This command is currently disabled `) }
|
||||
|
||||
const db2 = mClient.db('settings')
|
||||
const coll2 = db2.collection(channel)
|
||||
|
||||
// Default non-admin mode, give list of all enabled commands
|
||||
if (!name) {
|
||||
const settings = await coll2.find({}).toArray()
|
||||
var settingsList = []
|
||||
console.log(settings)
|
||||
settings.forEach((setting) => {
|
||||
settingsList.push(` ${setting.name}(${setting.enabled?'✅':'❌'})`)
|
||||
})
|
||||
if (settingsList.length == 0) {
|
||||
return await tClient.say(channel, `No settings available in this channel`)
|
||||
}
|
||||
return await tClient.say(channel, `Settings List: ${settingsList.toString()}`)
|
||||
}
|
||||
|
||||
if (!state) { return }
|
||||
|
||||
// Parameters are valid
|
||||
switch (state) {
|
||||
case 'enable':
|
||||
state = true
|
||||
break;
|
||||
case 'disable':
|
||||
state = false
|
||||
break;
|
||||
default:
|
||||
return tClient.say(channel, `invalid state, expecting 'enable' or 'disable'`)
|
||||
}
|
||||
// command is valid
|
||||
|
||||
const findSetting = await coll2.findOne({ name: name })
|
||||
if (!findSetting) { return await tClient.say(channel, `Setting [${name}] not found.`) }
|
||||
|
||||
|
||||
await coll2.findOneAndUpdate({
|
||||
name: name
|
||||
}, {
|
||||
$set: { enabled: state }
|
||||
}, {
|
||||
upsert: true
|
||||
})
|
||||
|
||||
return await tClient.say(channel, `[${name}] has been set to [${state}]`)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
const { mClient, dClient, tClient } = require('../..')
|
||||
const { updateChatMode, getIDByName } = require('../../functions')
|
||||
module.exports = {
|
||||
name: 'Command/so',
|
||||
once: false,
|
||||
async execute(channel, userstate, message, self, name) {
|
||||
if (userstate.badges.moderator != 1 && userstate.badges.broadcaster != 1) { return }
|
||||
const db = mClient.db('commands')
|
||||
const coll = db.collection(channel)
|
||||
const command = await coll.findOne({ name: 'so' })
|
||||
|
||||
// create in disabled state if not exists
|
||||
if (!command) {
|
||||
await coll.insertOne({
|
||||
name: 'so',
|
||||
enabled: false // default
|
||||
})
|
||||
}
|
||||
if (!command?.enabled) { return tClient.say(channel, `This command is currently disabled `) }
|
||||
|
||||
dClient.emit('Twitch/Shoutout', 'command', channel, name)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
const axios = require("axios");
|
||||
const { mClient } = require(".");
|
||||
const ReconnectingWebSocket = require("reconnecting-websocket");
|
||||
const { WebSocket } = require("ws");
|
||||
const twitchEventSubWsUrl = 'wss://eventsub.wss.twitch.tv/ws';
|
||||
|
||||
// Delay function for pauses
|
||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
||||
|
||||
+1
-4
@@ -1,9 +1,6 @@
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path');
|
||||
var { dClient, mClient, tClient } = require('..');
|
||||
const { refreshAccessToken } = require('../functions');
|
||||
const tmi = require('tmi.js')
|
||||
|
||||
var { dClient, tClient } = require('..');
|
||||
const folderPath = path.join(__dirname, '../events')
|
||||
const eventFolders = fs.readdirSync(folderPath)
|
||||
|
||||
|
||||
Generated
+31
-31
@@ -21,15 +21,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.10.0.tgz",
|
||||
"integrity": "sha512-ikVZsZP+3shmVJ5S1oM+7SveUCK3L9fTyfA8aJ7uD9cNQlTqF+3Irbk2Y22KXTb3C3RNUahRkSInClJMkHrINg==",
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.10.1.tgz",
|
||||
"integrity": "sha512-OWo1fY4ztL1/M/DUyRPShB4d/EzVfuUvPTRRHRIt/YxBrUYSz0a+JicD5F5zHFoNs2oTuWavxCOVFV1UljHTng==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/formatters": "^0.6.0",
|
||||
"@discordjs/util": "^1.1.1",
|
||||
"@sapphire/shapeshift": "^4.0.0",
|
||||
"discord-api-types": "^0.37.114",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"ts-mixer": "^6.0.4",
|
||||
"tslib": "^2.6.3"
|
||||
@@ -66,9 +66,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/rest": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.2.tgz",
|
||||
"integrity": "sha512-9bOvXYLQd5IBg/kKGuEFq3cstVxAMJ6wMxO2U3wjrgO+lHv8oNCT+BBRpuzVQh7BoXKvk/gpajceGvQUiRoJ8g==",
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.3.tgz",
|
||||
"integrity": "sha512-+SO4RKvWsM+y8uFHgYQrcTl/3+cY02uQOH7/7bKbVZsTfrfpoE62o5p+mmV+s7FVhTX82/kQUGGbu4YlV60RtA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/collection": "^2.1.1",
|
||||
@@ -76,10 +76,10 @@
|
||||
"@sapphire/async-queue": "^1.5.3",
|
||||
"@sapphire/snowflake": "^3.5.3",
|
||||
"@vladfrangu/async_event_emitter": "^2.4.6",
|
||||
"discord-api-types": "^0.37.114",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.19.8"
|
||||
"undici": "6.21.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -113,18 +113,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/ws": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.0.tgz",
|
||||
"integrity": "sha512-QH5CAFe3wHDiedbO+EI3OOiyipwWd+Q6BdoFZUw/Wf2fw5Cv2fgU/9UEtJRmJa9RecI+TAhdGPadMaEIur5yJg==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.1.tgz",
|
||||
"integrity": "sha512-PBvenhZG56a6tMWF/f4P6f4GxZKJTBG95n7aiGSPTnodmz4N5g60t79rSIAq7ywMbv8A4jFtexMruH+oe51aQQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/collection": "^2.1.0",
|
||||
"@discordjs/rest": "^2.4.1",
|
||||
"@discordjs/rest": "^2.4.3",
|
||||
"@discordjs/util": "^1.1.0",
|
||||
"@sapphire/async-queue": "^1.5.2",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@vladfrangu/async_event_emitter": "^2.2.4",
|
||||
"discord-api-types": "^0.37.114",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"tslib": "^2.6.2",
|
||||
"ws": "^8.17.0"
|
||||
},
|
||||
@@ -148,9 +148,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mongodb-js/saslprep": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz",
|
||||
"integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz",
|
||||
"integrity": "sha512-+ywrb0AqkfaYuhHs6LxKWgqbh3I72EpEgESCw37o+9qPx9WTCkgDm2B+eMrwehGtHBWHFU4GXvnSCNiFhhausg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sparse-bitfield": "^3.0.3"
|
||||
@@ -494,23 +494,23 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/discord.js": {
|
||||
"version": "14.17.3",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.17.3.tgz",
|
||||
"integrity": "sha512-8/j8udc3CU7dz3Eqch64UaSHoJtUT6IXK4da5ixjbav4NAXJicloWswD/iwn1ImZEMoAV3LscsdO0zhBh6H+0Q==",
|
||||
"version": "14.18.0",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.18.0.tgz",
|
||||
"integrity": "sha512-SvU5kVUvwunQhN2/+0t55QW/1EHfB1lp0TtLZUSXVHDmyHTrdOj5LRKdR0zLcybaA15F+NtdWuWmGOX9lE+CAw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^1.10.0",
|
||||
"@discordjs/builders": "^1.10.1",
|
||||
"@discordjs/collection": "1.5.3",
|
||||
"@discordjs/formatters": "^0.6.0",
|
||||
"@discordjs/rest": "^2.4.2",
|
||||
"@discordjs/rest": "^2.4.3",
|
||||
"@discordjs/util": "^1.1.1",
|
||||
"@discordjs/ws": "^1.2.0",
|
||||
"@discordjs/ws": "^1.2.1",
|
||||
"@sapphire/snowflake": "3.5.3",
|
||||
"discord-api-types": "^0.37.114",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"lodash.snakecase": "4.1.1",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.19.8"
|
||||
"undici": "6.21.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -1335,9 +1335,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz",
|
||||
"integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==",
|
||||
"version": "6.21.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
|
||||
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
@@ -1365,9 +1365,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz",
|
||||
"integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==",
|
||||
"version": "14.1.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz",
|
||||
"integrity": "sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "^5.0.0",
|
||||
|
||||
Reference in New Issue
Block a user