MCBot/main.js

275 lines
7.9 KiB
JavaScript
Raw Normal View History

2024-07-15 19:08:38 -06:00
const fs = require('fs')
const axios = require('axios')
const mineflayer = require('mineflayer')
const { EventEmitter } = require('events')
2024-07-15 14:24:50 -06:00
const { EmbedBuilder, hyperlink, WebhookClient } = require('discord.js');
2024-07-15 19:08:38 -06:00
const { registerFont, createCanvas } = require('canvas');
2024-07-15 14:24:50 -06:00
2024-07-15 19:08:38 -06:00
function stripChatColors(txt) {
const formattingRegex = /§[0-9a-fklmnor]+|[\[\]:]+/g;
return txt.replace(formattingRegex, '');
}
class GuildMessageSender {
constructor(rawUsername, rawHypixelRank, rawGuildRank) {
this.rawUsername = rawUsername
this.rawHypixelRank = rawHypixelRank
this.rawGuildRank = rawGuildRank
}
getCleanUsername() { return stripChatColors(this.rawUsername) }
getCleanHypixelRank() { return stripChatColors(this.rawHypixelRank) }
getCleanGuildRank() { return stripChatColors(this.rawGuildRank) }
}
2024-07-15 14:24:50 -06:00
2024-07-15 19:08:38 -06:00
class GuildMessage {
constructor(message, sender) {
this.message = message
this.sender = sender
}
2024-07-15 14:24:50 -06:00
}
2024-07-15 19:08:38 -06:00
class OfficerMessage {
constructor(message, sender) {
this.message = message
this.sender = sender
}
}
function parseGuildMessage(jsonMsg) {
const message_details = jsonMsg.json.extra
let message_prefix = message_details[0].text
let hypixel_rank = null
let username = null
let guild_rank = null
let eventType = 'null'
let sender_contents = null
if (message_prefix.includes('§2Guild >')) { eventType = 'guildmsg'; sender_contents = message_prefix.replace('§2Guild >', '') }
else if (message_prefix.includes('§3Officer >')) { eventType = 'officermsg'; sender_contents = message_prefix.replace('§3Officer >', '') }
let message_arr = sender_contents.trim().split(' ')
// Parse guild member details (with hypixel rank)
if (message_arr[0].includes('[')) { hypixel_rank = message_arr[0]; username = message_arr[1]; guild_rank = message_arr[2].replace(':', '') }
// Parse guild member details (nons)
else { hypixel_rank = ''; username = message_arr[0]; guild_rank = message_arr[1].replace(':', '') }
// Skip messages sent by the bot
if (stripChatColors(username) === bot.username) { return }
const sender = new GuildMessageSender(username, hypixel_rank, guild_rank)
let guildMessage = null
if (eventType === 'guildmsg') { guildMessage = new GuildMessage(message_details[1].text, sender) }
else if (eventType === 'officermsg') { guildMessage = new OfficerMessage(message_details[1].text, sender) }
else { console.error('Error parsing guild message: unknown event type'); return }
// Emit GuildMessage event
chatEvents.emit(eventType, guildMessage)
}
2024-07-15 20:03:41 -06:00
function getHexFromIdentifyer(identifyer) {
let fillStyle;
switch (identifyer) {
case '0':
fillStyle = '#000000' // Black
break
case '1':
fillStyle = '#0000AA' // Dark Blue
break
case '2':
fillStyle = '#00AA00' // Dark Green
break
case '3':
fillStyle = '#00AAAA' // Dark Aqua
break
case '4':
fillStyle = '#AA0000' // Dark Red
break
case '5':
fillStyle = '#AA00AA' // Dark Purple
break
case '6':
fillStyle = '#FFAA00' // Gold
break
case '7':
fillStyle = '#AAAAAA' // Gray
break
case '8':
fillStyle = '#555555' // Dark Gray
break
case '9':
fillStyle = '#5555FF' // Blue
break
case 'a':
fillStyle = '#55FF55' // Green
break
case 'b':
fillStyle = '#55FFFF' // Aqua
break
case 'c':
fillStyle = '#FF5555' // Red
break
case 'd':
fillStyle = '#FF55FF' // Light Purple
break
case 'e':
fillStyle = '#FFFF55' // Yellow
break
case 'f':
fillStyle = '#FFFFFF' // White
break
default:
fillStyle = '#000000' // Default to Black if no match
}
return fillStyle
}
2024-07-15 19:08:38 -06:00
async function sendWebhookMessage(guildMsg) {
2024-07-15 20:03:41 -06:00
const canvas = createCanvas(800, 45)
2024-07-15 19:08:38 -06:00
const context = canvas.getContext('2d')
2024-07-15 20:03:41 -06:00
context.font = '28px minecraft'
2024-07-15 19:08:38 -06:00
const username = guildMsg.sender.rawUsername
const hypixelRank = guildMsg.sender.rawHypixelRank
const guildRank = guildMsg.sender.rawGuildRank
const message = guildMsg.message
2024-07-15 20:03:41 -06:00
let x = 28
2024-07-15 19:08:38 -06:00
let y = 50
// Draw text with colors
2024-07-15 20:03:41 -06:00
let string_to_build = `${hypixelRank} ${username}`
let index = 0
let fillStyle = '#AAAAAA'
while (index < string_to_build.length) {
if (string_to_build.charAt(index) === '§') {
fillStyle = getHexFromIdentifyer(string_to_build.charAt(index + 1))
index++
index++
}
context.fillStyle = fillStyle
context.fillText(string_to_build.charAt(index), x, y)
x += context.measureText(string_to_build.charAt(index)).width // + 10
index++
}
context.fillStyle = '#ffffff'
context.fillText(`: ${message}`, x, y)
2024-07-15 19:08:38 -06:00
const buffer = canvas.toBuffer('image/png')
const form = new FormData()
form.append('file', new Blob([Buffer.from(buffer)]), 'message.png')
await axios.post(webhookUrl, form, {})
2024-07-15 14:24:50 -06:00
}
2024-07-15 19:08:38 -06:00
class ProudCircleBot {
constructor(username) {
this.username = username
this.auth = 'microsoft'
this.host = 'play.hypixel.net'
this.version = '1.8.9'
this.shouldReconnect = true
this.initBot()
}
initBot() {
this.bot = mineflayer.createBot({
"username": this.username,
"auth": 'microsoft',
"host": 'play.hypixel.net',
"version": this.version
})
this.initEvents()
this.bot.emit('startup')
this.listenToUserInput()
}
listenToUserInput() {}
initEvents() {
// Bot Startup
this.bot.on('startup', async () => { console.log('Starting bot...') })
// Server login
this.bot.on('login', async () => {
let sock = this.bot._client.socket
console.log(`Logged into ${sock.server ? sock.server : sock._host}`)
})
// Disconnect from server
this.bot.on('end', async (cause) => {
console.log(`Disconnected from server: ${cause}`)
if (reason === 'disconnect.quitting') { return }
else { console.error('Unknown cause of disconnecting!') }
// Auto Reconnect
if (this.shouldReconnect) {
console.log('Attempting to reconnect...')
setTimeout(() => this.initBot(), 5000)
}
})
// Chat Message
this.bot.on('message', async (jsonMsg, position) => {
// Avoid hypixel cancer
if (jsonMsg['extra'] && jsonMsg['extra'].length === 100) { return }
let rawText = jsonMsg.toString()
if (rawText === "Woah there, slow down!") { console.error("Server issued message spam warning") }
if (!jsonMsg?.json?.extra || jsonMsg.json.extra.length === 0 || !jsonMsg.json.extra[0]) { return }
// Check for guild messages
// Guild/Officer chat/member join/member leave
let extra_prefix = jsonMsg.json.extra[0].text
if (extra_prefix.startsWith('§2Guild >') || extra_prefix.startsWith('§3Officer >')) {
parseGuildMessage(jsonMsg)
}
})
// Custom Guild Message Event
chatEvents.on('guildmsg', async (guildMsg) => {
console.log(`Guild: ${guildMsg.sender.getCleanUsername()} ${guildMsg.message}`)
await sendWebhookMessage(guildMsg)
})
// Custom Officer Message Event
chatEvents.on('officermsg', (officerMsg) => {
console.log(`Officer: ${officerMsg.sender.getCleanUsername()} ${officerMsg.message}`)
})
}
2024-07-15 14:24:50 -06:00
}
2024-07-15 19:08:38 -06:00
registerFont('fonts/Minecraftia-Regular.ttf', {family: 'Minecraft'})
const webhookUrl = 'https://discord.com/api/webhooks/1262482329671176232/yAHgxkP2JSBPpdjmz6mdABu5yRkXxatXcbzI91iAjy0jM0z1kRzE1HZqzK5OGXCmkqPk'
const webhookClient = new WebhookClient({ url: webhookUrl });
2024-07-15 20:03:41 -06:00
// const chatEvents = new EventEmitter()
// const bot = new ProudCircleBot('ProudCircle')
const test_str = '§b[MVP§0++§b] illyum §e[STAFF]'
const guildMsgSender = new GuildMessageSender('illyum', '§b[MVP§0++§b]', '§e[STAFF]')
const guildMessage = new GuildMessage('This is a test!', guildMsgSender)
async function main() {
try {
await sendWebhookMessage(guildMessage);
// Additional async calls can be made here
} catch (error) {
console.error(error);
}
}
2024-07-15 19:08:38 -06:00
2024-07-15 20:03:41 -06:00
main();