Compare commits

..

38 Commits

Author SHA1 Message Date
lamp 0121a48063 :/ 2026-03-18 03:16:05 -04:00
lamp 525346ddcf change getOwnParticipant()._id to user._id 2026-03-18 03:10:12 -04:00
lamp dff251d33d ignore bot name change 2026-03-18 03:00:04 -04:00
lamp 7e64c4379e add cheez 2026-03-18 02:59:56 -04:00
lamp f3f8a35107 fucking bruh moment 2026-03-18 02:18:39 -04:00
lamp 39adc796d0 up max reconnect interval to 60s 2026-03-18 01:47:48 -04:00
lamp 5ac9604504 updated mppclone uri 2026-03-18 01:43:54 -04:00
lamp 2527a331a7 too much error overload webhook 2025-09-19 01:12:55 -04:00
lamp 17052a9ffe update user-agent 2025-09-19 01:10:22 -04:00
lamp e0dea9ebf4 stop print [object Object] 2025-09-19 01:07:12 -04:00
lamp 4a40060439 no more tag 2025-09-19 00:46:41 -04:00
lamp b507813f0a update deps 2025-09-19 00:44:23 -04:00
lamp 5476ecf714 disable name change msg in dev room 2024-12-05 17:07:41 -06:00
lamp ef4ccb8bc0 update deps 2023-10-10 18:29:16 -05:00
lamp 995ac6d96f delete unused prbridge and screenshotter 2023-10-10 16:17:16 -07:00
lamp e21a264ed0 normalize indents 2023-10-10 16:14:42 -07:00
lamp 1af74e957d ignore unknown participant bye 2023-10-10 18:04:19 -05:00
lamp 8bfd16a41f fix useless error 2023-10-10 17:58:11 -05:00
lamp a86466efdb fix bug in sendEmbed 2023-10-10 17:54:34 -05:00
lamp 999e71c5cc update opid 2023-10-10 17:47:26 -05:00
lamp 6b29918703 fix 403 2023-10-09 14:59:31 -05:00
lamp 41a1f0533f add lobby2, test/awkward 2023-10-06 16:06:50 -05:00
lamp 48b7791ae3 add new official server lobby 2023-10-06 15:22:52 -05:00
lamp fe0c0bbe61 disable prbridge 2023-03-05 18:36:19 -06:00
lamp 7b934bf762 remove ced mpp 2023-03-05 18:34:39 -06:00
lamp 44cd2cabb4 update bridges.json 2022-04-07 15:21:20 -05:00
lamp 9775aef89a stop spam error log with 502 2022-02-24 17:03:50 -06:00
lamp aabebc7d74 change ced uri 2022-01-07 21:56:01 -06:00
lamp 1fda5903d0 bch 2022-01-05 18:15:28 -08:00
lamp 35d1299897 i try new discord sender 2022-01-05 18:12:13 -08:00
lamp fa1c39790a ass 2022-01-04 16:30:07 -08:00
lamp 14c8c8fba3 Fuck 'cannot send an empty message' 2022-01-04 16:28:12 -08:00
lamp 198a8ceb3a rewrite data collector
maybe it will work
2022-01-04 16:01:27 -08:00
lamp e8b4334e3a fix bruhs 2022-01-03 23:00:36 -08:00
lamp 7fe2b0fa12 revert new thing 2022-01-03 22:57:17 -08:00
lamp 3ef1bccb7a add slash command 2022-01-03 22:45:28 -08:00
lamp fb0c39b5c8 paste my eval/exec code 2022-01-03 22:26:27 -08:00
lamp da4e033760 delete commands 2022-01-03 22:24:25 -08:00
21 changed files with 862 additions and 2283 deletions
+10 -10
View File
@@ -1,13 +1,13 @@
[ [
{ "room": "lobby", "channel": "339609383644168195", "uri": "wss://mppclone.com:8443" }, { "room": "lobby", "channel": "1159943041692471488", "uri": "wss://game.multiplayerpiano.com:443" },
{ "room": "lobby2", "channel": "350006891948277770", "uri": "wss://mppclone.com:8443" }, { "room": "lobby2", "channel": "1159954805146529823", "uri": "wss://game.multiplayerpiano.com:443" },
{ "room": "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧", "channel": "698736467559710740", "uri": "wss://mppclone.com:8443" }, { "room": "test/awkward", "channel": "1159954847542546513", "uri": "wss://game.multiplayerpiano.com:443" },
{ "room": "test/awkward", "channel": "360556775860076544", "uri": "wss://mppclone.com:8443" },
{ "room": "test/fishing", "channel": "339613702472859659", "uri": "wss://mppclone.com:8443" },
{ "room": "the-dev-channel", "channel": "925129849457233970", "uri": "wss://mppclone.com:8443" },
{ "room": "lobby", "channel": "430226348901007360", "uri": "wss://mppws.cf" }, { "room": "lobby", "channel": "339609383644168195", "uri": "wss://backend.multiplayerpiano.net" },
{ "room": "lobby", "channel": "339904195719200768", "uri": "wss://piano.ourworldofpixels.com" }, { "room": "lobby2", "channel": "350006891948277770", "uri": "wss://backend.multiplayerpiano.net" },
{ "room": "lobby", "channel": "559898407511261219", "uri": "ws://104.237.150.24:8513/" }, { "room": "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧", "channel": "698736467559710740", "uri": "wss://backend.multiplayerpiano.net" },
{ "room": "lobby", "channel": "927720571201028187", "uri": "wss://beta-mpp.cedms.jp" } { "room": "test/awkward", "channel": "360556775860076544", "uri": "wss://backend.multiplayerpiano.net" },
{ "room": "test/fishing", "channel": "339613702472859659", "uri": "wss://backend.multiplayerpiano.net" },
{ "room": "lobby", "channel": "339904195719200768", "uri": "wss://piano.ourworldofpixels.com" }
] ]
+15 -141
View File
@@ -1,147 +1,21 @@
global.commands = { global.commands = [
"help": { {
usage: "[command]", name: "list",
aliases: ["commands"], description: "Show the members on the other side of an MPP bridge",
exec: async function (msg) { exec: i => {
if (msg.args[1]) { let bridge = bridges.find(x => x.channel == i.channel.id);
var commandName = msg.args[1]; if (!bridge) return i.reply({ephemeral: true, content: "Not available in this channel"});
var command = commands[commandName]; let ppl_list = Object.values(bridge.client.ppl).map(m => `\`${m._id}\` ${m.name}`);
if (!command) i.reply({content: `__**${ppl_list.length} people are playing**__\n${ppl_list.join("\n")}`});
for (let cmdNme in commands) {
let cmd = commands[cmdNme];
if (cmd.aliases && cmd.aliases.includes(commandName)) {command = cmd; break;}
}
if (!command) return msg.react('❓');
var str = '`'+`!${commandName} ${command.usage || ''}`.trim()+'`\n';
if (command.hasOwnProperty('aliases')) str += `**Aliases:** \`!${command.aliases.join(', !')}\`\n`;
if (command.hasOwnProperty('description')) str += `\n${command.description}`;
msg.channel.send({embed:{
description: str
}});
} else {
var cmdArr = [];
for (var command in commands) {
if (!commands[command].op) cmdArr.push(`!${command}`);
}
var embed = {
title: "Commands",
description: cmdArr.join(', '),
footer: {text: "Use `!help <command>` for more info on a command."}
};
msg.channel.send({embed});
} }
} }
}, ];
'delete': {
usage: "[channel]",
aliases: ['archive'],
hidden: true,
description: "Archives a channel that you have permission to delete.",
exec: async function (msg) {
if (msg.args[1]) {
var channel = msg.mentions.channels.first();
if (!channel) {
msg.react(``);
return;
}
} else {
var channel = msg.channel;
}
if (!channel.permissionsFor(msg.member).has('MANAGE_CHANNELS')) return msg.react('🚫');
await channel.setParent(config.channels.deleted_channels);
await new Promise(resolve => setTimeout(resolve, 500));
await channel.lockPermissions();
msg.react('🆗');
}
},
"eval": { dClient.on("interactionCreate", interaction => {
op: true, commands.find(x => x.name == interaction.commandName)?.exec?.(interaction);
description: "Evaluate javascript",
usage: "<code>",
aliases: ['>'],
exec: async function (message) {
var msg = message, m = message,
guild = message.guild,
channel = message.channel,
member = message.member,
client = dClient,
send = function(){
channel.send.apply(channel, arguments);
},
say = send;
try {
var out = eval(message.content.substr(2));
} catch (error) {
var out = error;
} finally {
message.channel.send('`'+out+'`', {split:{char:''}});
}
}
},
"exec": {
op: true,
description: "Run a shell command",
usage: "<command>",
aliases: ["$"],
exec: async function (msg) {
require("child_process").exec(msg.txt(1), function(error, stdout, stderr){
if (error) msg.channel.send(error, {split:{char:'',maxLength:2000}});
if (stdout) msg.channel.send(stdout, {split:{char:'',maxLength:2000}});
if (stderr) msg.channel.send(stderr, {split:{char:'',maxLength:2000}});
})
}
},
}
dClient.on('messageCreate', async message => {
if (!message.content.startsWith('!')) return;
if (message.author.id === dClient.user.id) return;
var args = message.content.split(' ');
var cmd = args[0].slice(1).toLowerCase();
var txt = function(i){return args.slice(i).join(' ').trim()};
message.args = args;
message.cmd = cmd;
message.txt = function(i){return this.args.slice(i).join(' ')};
if (!message.guild) message.guild = dClient.guilds.resolve(config.guildID);
if (!message.member) message.member = dClient.guilds.resolve(config.guildID).members.resolve(message.author.id);
Object.keys(commands).forEach(commandName => {
var command = commands[commandName];
if (!(commandName === cmd || (command.aliases && command.aliases.includes(cmd)))) return;
if (command.op && !config.opIDs.includes(message.author.id)) return message.react('🚫');
command.exec(message, args, txt).then(
(res) => {
switch (res) {
case "ENOTBRIDGE":
message.channel.send(random([
`This is not a bridged channel.`,
`You can only use this command in a bridged channel.`
]));
break;
case "EBADUSG":
message.channel.send(`**Usage:** \`!${commandName} ${command.usage}\``);
break;
}
},
(err) => {
message.reply(`:warning: An error occured: \`\`\`\n${err.stack}\n\`\`\`<@281134216115257344>`);
handleError(err);
}
)
}); });
dClient.once("ready", () => {
dClient.guilds.resolve(config.guildID)?.commands.set(commands);
}); });
+1 -2
View File
@@ -11,8 +11,7 @@ module.exports = {
"pinboard": process.env.WEBHOOK_PINBOARD "pinboard": process.env.WEBHOOK_PINBOARD
}, },
"opID": "707359017252683896", "opID": "330499035419115522",
"opIDs": ["707359017252683896", "330499035419115522"], //TODO i dont need multiple ops anymore
"guildID": testmode ? "467473467634089985" : "321819041348190249", "guildID": testmode ? "467473467634089985" : "321819041348190249",
"channels": { // includes voice channels & category channels "channels": { // includes voice channels & category channels
-42
View File
@@ -1,42 +0,0 @@
var os = require('os');
var zlib = require('zlib');
// WebSocket message data collector. Returns a function for inputting websocket messages.
// Collects inputted messages to a file and gzips them every time it reaches 8mb,
// and sends it to the output callback function.
// For recording websocket data to a discord channel.
module.exports = function createWSMessageCollector(output) { // output func must be async
var filepath = os.tmpdir() + "/" + Math.random().toString(36).substring(2);
var size = 0;
var startDate = new Date();
// gzip the data & send to output callback
async function save(callback){
fs.readFile(filepath, (err, file) => {
if (err) return handleError(err);
zlib.gzip(file, async function(err, data){
if (err) return handleError(err);
var thisStartDate = startDate, thisEndDate = new Date();
fs.writeFileSync(filepath, '');
size = 0;
startDate = new Date();
await output(data, thisStartDate, thisEndDate);
if (callback) callback();
});
});
}
// save on exit
exitHook(callback => {
save(()=>callback());
});
return function input(message) { // input for websocket messages
message = message.data || message;
if (message instanceof ArrayBuffer) message = Buffer.from(message).toString('base64');
var line = `${Date.now()} ${message}\n`;
size += line.length;
fs.appendFileSync(filepath, line);
if (size > 8000000) {save(); size = 0;}
};
}
+4 -4
View File
@@ -1,14 +1,14 @@
var WebSocket = require('ws'); var WebSocket = require('ws');
var Discord = require('discord.js'); var Discord = require('discord.js');
var createWsMessageCollector = require('./datacollector'); var WebSocketMessageCollector = require('./lib/datacollector');
var webhook = new Discord.WebhookClient({url: config.webhooks.ddp, allowedMentions: {parse: []}}); var webhook = new Discord.WebhookClient({url: config.webhooks.ddp}, {allowedMentions: {parse: []}});
var ws; var ws;
var wasConnected = false; var wasConnected = false;
//var myId; //var myId;
var collectWsMessage = createWsMessageCollector(async function(data, startDate, endDate){ var wsc = new WebSocketMessageCollector(async function(data, startDate, endDate){
await webhook.send({files:[{ await webhook.send({files:[{
attachment: data, attachment: data,
name: `daydun piano main raw data recording from ${startDate.toISOString()} to ${endDate.toISOString()} .txt.gz` name: `daydun piano main raw data recording from ${startDate.toISOString()} to ${endDate.toISOString()} .txt.gz`
@@ -22,7 +22,7 @@ var collectWsMessage = createWsMessageCollector(async function(data, startDate,
wasConnected = true; wasConnected = true;
}); });
ws.on("message", message => { ws.on("message", message => {
collectWsMessage(message); wsc.collect(message);
if (typeof message != 'string') return; if (typeof message != 'string') return;
var transmission = JSON.parse(message); var transmission = JSON.parse(message);
if (transmission.type == 'chat') { if (transmission.type == 'chat') {
+37
View File
@@ -0,0 +1,37 @@
dClient.on("messageCreate", async function (message) {
if (message.author.id != config.opID) return;
if (message.content.startsWith("!>")) {
with (message) {
try {
var x = await eval(message.content.substr(2).trim());
} catch(e) {
var x = e.message;
}
}
if (typeof x == "undefined") return void await message.react(config.eval_undefined_emoji);
let t = typeof x == 'string' ? 'txt' : 'js';
if (typeof x != 'string' && typeof x != "function") x = require('util').inspect(x, {depth: 1});
let cb = `\`\`\`${t}\n${x}\`\`\``;
if (cb.length <= 2000)
message.channel.send(cb);
else
message.channel.send({files:[{
attachment: Buffer.from(x),
name: `output.${t}`
}]});
}
else if (message.content.startsWith("!$")) {
let cp = require("child_process").spawn("bash", ["-c", message.content.substr(2).trim()]);
function ondat(a) {
try {
var split = Discord.Util.splitMessage(a.toString(), {split:{char:'\n',length:2000}});
} catch(x) {
var split = Discord.Util.splitMessage(a.toString(), {split:{char:'',length:2000}});
}
split.forEach(message.channel.send.bind(message.channel));
}
cp.stdout.on("data", ondat);
cp.stderr.on("data", ondat);
}
});
+7 -8
View File
@@ -74,14 +74,13 @@ Client.prototype.connect = function() {
return; return;
this.emit("status", "Connecting..."); this.emit("status", "Connecting...");
if(typeof module !== "undefined") { if(typeof module !== "undefined") {
let headers = {
"origin": `https://${new URL(this.uri).host}`,
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
};
if (this.uri.includes("multiplayerpiano.com")) headers["X-Forwarded-For"] = `${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`;
// nodejsicle // nodejsicle
require('https').get('https://app_legacy.multiplayerpiano.com').on("error", () => {}); this.ws = new WebSocket(this.uri, {headers});
this.ws = new WebSocket(this.uri, {
headers: {
"origin": "https://multiplayerpiano.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"
}
});
} else { } else {
// browseroni // browseroni
this.ws = new WebSocket(this.uri); this.ws = new WebSocket(this.uri);
@@ -106,7 +105,7 @@ Client.prototype.connect = function() {
} else { } else {
++self.connectionAttempts; ++self.connectionAttempts;
} }
var ms_lut = [50, 2950, 7000, 10000]; var ms_lut = [50, 2950, 7000, 10000, 30000, 60000];
var idx = self.connectionAttempts; var idx = self.connectionAttempts;
if(idx >= ms_lut.length) idx = ms_lut.length - 1; if(idx >= ms_lut.length) idx = ms_lut.length - 1;
var ms = ms_lut[idx]; var ms = ms_lut[idx];
+39
View File
@@ -0,0 +1,39 @@
module.exports = class DiscordMessageSender {
constructor(channel) {
this.channel = channel;
this.interval = setInterval(this.flush.bind(this), 3000);
}
//async init() {
// var webhooks = await this.channel.fetchWebhooks();
// this.webhook = webhooks.filter(w => w.token).first() || await this.channel.createWebhook("sdfadffg");
// this.interval = setInterval(this.flush.bind(this), 3000);
//}
send(text) {
this.pp ||= {content: ""};
this.pp.content += text + '\n';
}
sendEmbed(embed) {
this.pp ||= {};
this.pp.embeds = [embed];
this.flush();
}
flush() {
if (!this.pp) return;
var pp = this.pp;
delete this.pp;
if (pp.content?.length > 2000) {
pp.files = [{name: "message.txt", attachment: Buffer.from(pp.content)}];
delete pp.content;
}
//this.webhook.send(pp).catch(error => {
//handleError(error, "webhook");
this.channel.send(pp);
//});
}
}
+28
View File
@@ -0,0 +1,28 @@
var gzip = require("util").promisify(require("zlib").gzip);
module.exports = class WebSocketMessageCollector {
constructor(dispatchFunction) {
this.maxSize = 8000000;
this.data = "";
this.startDate = new Date();
this.dispatchFunction = dispatchFunction;
exitHook(cb => {
this.package().then(cb);
});
}
collect(message) {
message = message.data || message;
if (message instanceof ArrayBuffer) message = Buffer.from(message).toString('base64');
var line = `${Date.now()} ${message}\n`;
this.data += line;
if (this.data.length > this.maxSize) this.package();
}
async package() {
var data = this.data, startDate = this.startDate, endDate = new Date();
this.data = "", this.startDate = new Date();
data = await gzip(data);
await this.dispatchFunction(data, startDate, endDate);
}
}
+6 -7
View File
@@ -13,12 +13,12 @@ global.dClient = new Discord.Client({
// error handling // error handling
{ {
let webhook = new Discord.WebhookClient({url: config.webhooks.error, allowedMentions: {parse: []}}); let webhook = new Discord.WebhookClient({url: config.webhooks.error}, {allowedMentions: {parse: []}});
global.handleError = function logError(error, title) { global.handleError = function logError(error, title) {
let msg = error && (error.stack || error.message || error); let msg = error && (error.stack || error.message || error);
console.error(title + ':\n' + msg); console.error(title + ':\n' + msg);
try { try {
webhook.send(`${title ? `**${title}:**` : ""}\`\`\`\n${msg}\n\`\`\``).catch(()=>{}); //webhook.send(`${title ? `**${title}:**` : ""}\`\`\`\n${msg}\n\`\`\``).catch(()=>{});
} catch(e) {} } catch(e) {}
} }
process.on('unhandledRejection', error => handleError(error, "Unhandled Rejection")); process.on('unhandledRejection', error => handleError(error, "Unhandled Rejection"));
@@ -30,13 +30,12 @@ global.dClient = new Discord.Client({
dClient.login(config.DISCORD_TOKEN); dClient.login(config.DISCORD_TOKEN);
dClient.once('ready', () => { dClient.on('ready', () => {
console.log('Discord Client Ready'); console.log('Discord Client Ready');
});
require('./commands'); require('./eval-exec');
require("./commands");
require('./mppbridger'); require('./mppbridger');
require('./misc'); require('./misc');
require('./ddpbridge'); require('./ddpbridge');
require('./prbridge');
});
+3 -13
View File
@@ -1,6 +1,6 @@
// join/leave // join/leave
(async function(){ (async function(){
var webhook = new Discord.WebhookClient({url: config.webhooks.welcome, allowedMentions: {parse: []}}); var webhook = new Discord.WebhookClient({url: config.webhooks.welcome}, {allowedMentions: {parse: []}});
dClient.on('guildMemberAdd', async member => { dClient.on('guildMemberAdd', async member => {
if (member.guild.id != config.guildID) return; if (member.guild.id != config.guildID) return;
let username = member.user.username.toLowerCase().includes('clyde') ? member.user.username.replace(/C/g,'Q').replace(/c/g,'q') : member.user.username; let username = member.user.username.toLowerCase().includes('clyde') ? member.user.username.replace(/C/g,'Q').replace(/c/g,'q') : member.user.username;
@@ -9,7 +9,7 @@
dClient.on('guildMemberRemove', async member => { dClient.on('guildMemberRemove', async member => {
if (member.guild.id != config.guildID) return; if (member.guild.id != config.guildID) return;
let username = member.user.username.toLowerCase().includes('clyde') ? member.user.username.replace(/C/g,'Q').replace(/c/g,'q') : member.user.username; let username = member.user.username.toLowerCase().includes('clyde') ? member.user.username.replace(/C/g,'Q').replace(/c/g,'q') : member.user.username;
webhook.send({content: `${member.user.tag} left.`, username, avatarURL: member.user.displayAvatarURL({format:'png',size:2048})}); webhook.send({content: `${member.user.username} left.`, username, avatarURL: member.user.displayAvatarURL({format:'png',size:2048})});
}); });
})(); })();
@@ -67,17 +67,7 @@ dClient.on("emojiDelete", async emoji => {
// allow anyone to pin a message via reaction // allow anyone to pin a message via reaction
// todo need enable partials for it to work on old messages // todo need enable partials for it to work on old messages
dClient.on("messageReactionAdd", async (messageReaction) => { dClient.on("messageReactionAdd", async (messageReaction) => {
if (messageReaction.guild.id != config.guildID) return; if (messageReaction.guild?.id != config.guildID) return;
if (messageReaction.emoji.name == "📌" || messageReaction.emoji.name == "📍") if (messageReaction.emoji.name == "📌" || messageReaction.emoji.name == "📍")
await messageReaction.message.pin(); await messageReaction.message.pin();
}); });
+46 -59
View File
@@ -1,32 +1,13 @@
var Client = require('./lib/Client.js'); var Client = require('./lib/Client.js');
var WebSocketMessageCollector = require("./lib/datacollector");
var DiscordMessageSender = require("./lib/DiscordMessageSender");
global.createMPPbridge = async function createMPPbridge({room, channel, uri}) { global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
channel = dClient.channels.resolve(channel); channel = dClient.channels.resolve(channel);
var webhooks = await channel.fetchWebhooks(); var d = new DiscordMessageSender(channel);
var webhook = webhooks.filter(w => w.token).first() || await channel.createWebhook("sdfadffg");
//todo figure out new way to buffer
function dSend(msg, options = {}) {
if (msg) options.content = msg;
if (options.content?.length > 2000) {
options.attachments ||= [];
options.attachments.push(new Discord.MessageAttachment(Buffer.from(options.content), "message.txt"));
delete options.content;
}
let username = gClient.channel && gClient.channel._id || room;
if (username.length > 80) username = username.substr(0,79) + '…';
webhook.send(Object.assign(options, {username})).catch(error => {
handleError(error, `webhook fail in ${channel.id}`);
channel.send(options).catch(error => handleError(error, `send fail in ${channel.id} after webhook send fail`));
});
}
const gClient = new Client(uri); const gClient = new Client(uri);
if (uri == "wss://mppclone.com:8443") gClient.token = config.mpc_token; //todo hmm if (uri == "wss://backend.multiplayerpiano.net") gClient.token = config.mpc_token; //todo hmm
gClient.setChannel(room, {visible:false}); gClient.setChannel(room, {visible:false});
gClient.start(); gClient.start();
@@ -41,16 +22,16 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
let lastError; let lastError;
gClient.on("error", error => { gClient.on("error", error => {
handleError(error, `[${uri}][${room}]`); handleError(error, `[${uri}][${room}]`);
error = error.toString(); error = error.message || JSON.stringify(error);
if (lastError != error) { if (lastError != error) {
dSend(`**${error.toString()}**`); d.send(`**${error}**`);
lastError = error; lastError = error;
} }
}); });
var isConnected = false; // TODO use gClient.isConnected() ? var isConnected = false; // TODO use gClient.isConnected() ?
gClient.on('connect', () => { gClient.on('connect', () => {
console.log(`[${uri}][${room}] Connected to server`); console.log(`[${uri}][${room}] Connected to server`);
dSend(`**Connected to server; joining channel…**`); d.send(`**Connected to server; joining channel…**`);
isConnected = true; isConnected = true;
lastError = undefined; lastError = undefined;
}); });
@@ -64,7 +45,7 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
gClient.on('disconnect', () => { gClient.on('disconnect', () => {
if (isConnected) { if (isConnected) {
console.log(`[${uri}][${room}] Disconnected from server`); console.log(`[${uri}][${room}] Disconnected from server`);
dSend(`**Disconnected from server**`); d.send(`**Disconnected from server**`);
isConnected = false; isConnected = false;
} }
}); });
@@ -80,12 +61,12 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
gClient.on('ch', async msg => { gClient.on('ch', async msg => {
// announce channel join // announce channel join
if (!lastCh) { if (!lastCh) {
dSend(`**Joined channel \`${msg.ch._id}\`**`); d.send(`**Joined channel \`${msg.ch._id}\`**`);
console.log(`[${uri}][${room}] Joined channel ${msg.ch._id}`); console.log(`[${uri}][${room}] Joined channel ${msg.ch._id}`);
} }
// announce channel change // announce channel change
else if (msg.ch._id !== lastCh) { else if (msg.ch._id !== lastCh) {
dSend(`**Channel changed from \`${lastCh}\` to \`${msg.ch._id}\`**`); d.send(`**Channel changed from \`${lastCh}\` to \`${msg.ch._id}\`**`);
console.log(`[${uri}][${room}] Channel changed from ${lastCh} to ${msg.ch._id}`); console.log(`[${uri}][${room}] Channel changed from ${lastCh} to ${msg.ch._id}`);
} }
lastCh = msg.ch._id; lastCh = msg.ch._id;
@@ -97,35 +78,38 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
// MPP to Discord // MPP to Discord
gClient.on('a', async msg => { gClient.on('a', async msg => {
if (msg.p._id == gClient.user._id) return;
var id = msg.p._id.substr(0,6); var id = msg.p._id.substr(0,6);
var name = sanitizeName(msg.p.name); var name = sanitizeName(msg.p.name);
var content = msg.a; var content = msg.a;
var str = `\`${id}\` **${name}:** ${content}`; var str = `\`${id}\` **${name}:** ${content}`;
dSend(str); d.send(str);
}); });
// Discord to MPP // Discord to MPP
{ {
//let msgQueue = []; let msgQueue = [];
dClient.on('message', async message => { dClient.on('message', async message => {
if (message.channel.id !== channel.id || message.author.id == dClient.user.id || !message.member /*|| message.content.startsWith('!')*/) return; if (message.channel.id !== channel.id || message.author.id == dClient.user.id || !message.member /*|| message.content.startsWith('!')*/) return;
var str = message.cleanContent; var str = message.cleanContent;
var aname = message.author.tag; var aname = message.author.tag;
//if (str.startsWith('/') || str.startsWith('\\')) if (str.startsWith('/') || str.startsWith('\\'))
// msgQueue.push(`⤹ ${aname}`); msgQueue.push(`${aname}`);
//else else
str = `${aname}: ${str}`; str = `${aname}: ${str}`;
//if (str.startsWith('\\')) str = str.slice(1); if (str.startsWith('\\')) str = str.slice(1);
if (message.attachments.size > 0) str += ' ' + message.attachments.map(a => a.url).join(' '); if (message.attachments.size > 0) str += ' ' + message.attachments.map(a => a.url).join(' ');
if (str.length > 512) str = str.substr(0,511) + '…'; if (str.length > 512) {
//msgQueue.push(str); str = str.substr(0,511) + '…';
gClient.sendArray([{m:'a', message: str}]); message.react('');
if (gClient.isConnected()) message.delete(); }
msgQueue.push(str);
}); });
//setInterval(()=>{ setInterval(()=>{
// let message = msgQueue.shift(); let message = msgQueue.shift();
// if (message) gClient.sendArray([{m:'a', message}]); if (message) gClient.sendArray([{m:'a', message}]);
//}, 1600); // just about fastest without exceeding quota; I figured quota is 4 messages per 6 seconds in lobbies //todo wait moment to see if message got through then react warning if didnt
}, 1600); // just about fastest without exceeding quota; I figured quota is 4 messages per 6 seconds in lobbies
} }
@@ -135,15 +119,17 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
gClient.prependListener("p", async participant => { gClient.prependListener("p", async participant => {
if (gClient.ppl[participant.id]) { // is update if (gClient.ppl[participant.id]) { // is update
let oldName = gClient.ppl[participant.id].name, newName = participant.name; let oldName = gClient.ppl[participant.id].name, newName = participant.name;
if (newName != oldName) let isBot = gClient.ppl[participant.id].tag?.text == "BOT";
dSend(`\`${participant._id.substr(0,6)}\` ___**${sanitizeName(oldName)}** changed their name to **${sanitizeName(newName)}**___`); if (newName != oldName && !isBot)
d.send(`\`${participant._id.substr(0,6)}\` ___**${sanitizeName(oldName)}** changed their name to **${sanitizeName(newName)}**___`);
} else { // is join } else { // is join
dSend(`\`${participant._id.substr(0,6)}\` ___**${sanitizeName(participant.name)}** entered the room.___`); d.send(`\`${participant._id.substr(0,6)}\` ___**${sanitizeName(participant.name)}** entered the room.___`);
} }
}); });
gClient.prependListener("bye", async msg => { gClient.prependListener("bye", async msg => {
var participant = gClient.ppl[msg.p]; var participant = gClient.ppl[msg.p];
dSend(`\`${participant._id.substr(0,6)}\` ___**${sanitizeName(participant.name)}** left the room.___`); if (!participant) return;
d.send(`\`${participant._id.substr(0,6)}\` ___**${sanitizeName(participant.name)}** left the room.___`);
}); });
@@ -151,10 +137,10 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
// on notifications // on notifications
gClient.on('notification', async msg => { gClient.on('notification', async msg => {
// show notification // show notification
dSend(undefined, {embeds:[{ d.sendEmbed({
title: msg.title, title: msg.title,
description: msg.text || msg.html description: msg.text || msg.html
}]}); });
// handle bans // handle bans
if (msg.text && (msg.text.startsWith('Banned from "'+room+'"') || msg.text.startsWith('Currently banned from "'+room+'"'))) { if (msg.text && (msg.text.startsWith('Banned from "'+room+'"') || msg.text.startsWith('Currently banned from "'+room+'"'))) {
@@ -169,7 +155,7 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
gClient.setChannel(room); gClient.setChannel(room);
gClient.start(); gClient.start();
}, minutes*60*1000+3000); }, minutes*60*1000+3000);
dSend(`**Attempting to rejoin in ${minutes} minutes.**`); d.send(`**Attempting to rejoin in ${minutes} minutes.**`);
} }
}); });
@@ -187,14 +173,15 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
// addons // addons
{ var wsc = new WebSocketMessageCollector(async function(data, startDate, endDate) {
// record raw data
let createWSMessageCollector = require("./datacollector")
gClient.on("message", createWSMessageCollector(async function(data, startDate, endDate){
var attachmentName = `${uri} ${room} raw data recording from ${startDate.toISOString()} to ${endDate.toISOString()} .txt.gz`; var attachmentName = `${uri} ${room} raw data recording from ${startDate.toISOString()} to ${endDate.toISOString()} .txt.gz`;
await channel.send(new Discord.MessageAttachment(data, attachmentName)); await channel.send({files:[{
})); attachment: data,
} name: attachmentName
}]});
});
gClient.on("message", wsc.collect.bind(wsc));
return gClient; return gClient;
}; };
@@ -202,7 +189,7 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
// start // start
(async function () { dClient.once("ready", async function () {
global.bridges = require("./bridges"); global.bridges = require("./bridges");
for (let bridge of bridges) { for (let bridge of bridges) {
try { try {
@@ -211,4 +198,4 @@ global.createMPPbridge = async function createMPPbridge({room, channel, uri}) {
handleError(error, JSON.stringify(bridge)); handleError(error, JSON.stringify(bridge));
} }
} }
})(); });
+523 -412
View File
File diff suppressed because it is too large Load Diff
+3 -4
View File
@@ -1,9 +1,8 @@
{ {
"dependencies": { "dependencies": {
"async-exit-hook": "^2.0.1", "async-exit-hook": "^2.0.1",
"discord.js": "^13.5.0", "discord.js": "^13.17.1",
"dotenv": "^8.2.0", "dotenv": "^8.6.0",
"socketcluster-client": "^14.2.2", "ws": "^8.18.3"
"ws": "^3.3.2"
} }
} }
-48
View File
@@ -1,48 +0,0 @@
const socketCluster = require("socketcluster-client")
const EventEmitter = require("events").EventEmitter;
class PRClient extends EventEmitter {
constructor(credentials, options) {
super()
EventEmitter.call(this);
this.options = options;
this.socket;
this.channels = {};
this.credentials = credentials
}
connect() {
if (!this.options) {
this.options = {
path: "/socketcluster/",
hostname: "www.pianorhythm.me",
port: 443,
secure: true,
autoReconnect: true,
}
}
// Initiate the connection to the server
this.socket = socketCluster.connect(this.options);
this.socket.connect();
this.socket.on("error", (msg) => {
handleError(msg, "pr socket");
})
this.socket.on("connect", () => {
console.log("Connected!")
this.socket.emit("enableAuthLogin", {
enable: true,
roomName: this.credentials.roomName
});
this.socket.emit("enableCursor", {
enable: true
});
this.socket.emit("login", {
password: this.credentials.password,
roomName: this.credentials.roomName,
username: this.credentials.username
});
this.socket.emit("getPlayerStats", {
"username": this.credentials.username
})
})
}
}
module.exports = PRClient;
-54
View File
@@ -1,54 +0,0 @@
const PRClient = require("./PRClient.js");
let client = new PRClient({// account stuff
username: "Discord",
password: config.pr_password,
roomName: 'lobby'
});
global.prClient = client;
client.connect();
client.socket.on("setRoom", function (data, callback) {
client.roomID = data.roomID;
try {
if (client.channels.chatChannel && client.roomID) {
client.socket.destroyChannel(client.roomID);
}
} catch (err) {}
client.channels.chatChannel = client.socket.subscribe(data.roomID);
client.channels.chatChannel.watch(messagehandle);
})
async function messagehandle(data) {
if (data && data.type) {
switch (data.type) {
case "chat":
if (data && data.message) {
let name = data.name || "";
let effect = data.effect || "";
let roomName = data.roomName;
let color = data.color;
let id = data.sID || data.socketID || data.id;
if (id == client.socket.id) return;
let c = dClient.channels.resolve("593943518351982603");
let msg;
(!name && (data.message.startsWith("[i]"))) ? msg = `*${data.message.split("[i]")[1]}*` : msg = `**${sanitizeName(name)}:** ${data.message}`;
if (c) c.send(msg);
}
break;
}
}
}
dClient.on("messageCreate", async message => {
if (message.channel.id != "593943518351982603" || message.author.id == dClient.user.id) return;
if (!client.roomID) return;
client.socket.publish(client.roomID, {
"type": "chat",
"message": `${message.member && message.member.displayName || message.author.username}#${message.author.discriminator}: ${message.cleanContent + (message.attachments.size > 0 && message.attachments.map(x => x.url).join(' ') || '')}`,
"value": false,
"socketID": "[discord.gg/k44Eqha]",
"uuid": "[discord.gg/k44Eqha]",
"color": "#8012ed",
"name": "[discord.gg/k44Eqha]"
});
});
-5
View File
@@ -1,5 +0,0 @@
FROM buildkite/puppeteer
ADD . /app
WORKDIR /app
RUN npm ci
CMD ["node", "screenshotter.js"]
-1255
View File
File diff suppressed because it is too large Load Diff
-7
View File
@@ -1,7 +0,0 @@
{
"dependencies": {
"discord.js": "^12.5.3",
"dotenv": "^10.0.0",
"puppeteer": "^10.2.0"
}
}
-72
View File
@@ -1,72 +0,0 @@
require("dotenv").config();
var Discord = require("discord.js");
var puppeteer = require('puppeteer');
var wh_hmpps = new Discord.WebhookClient(process.env.WH_HMPPS_ID, process.env.WH_HMPPS_TOKEN);
var wh_hrprs = new Discord.WebhookClient(process.env.WH_HRPRS_ID, process.env.WH_HRPRS_TOKEN);
var wh_howps = new Discord.WebhookClient(process.env.WH_HOWPS_ID, process.env.WH_HOWPS_TOKEN);
global.screenshotter = {
capture: async function () {
console.log('Starting screen captures');
try {
var browser = await puppeteer.launch(/*{ args: ['--no-sandbox'] }*/);
var page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900 });
try {
await page.goto('https://www.multiplayerpiano.com/');
try {await page.evaluate(function () {
document.getElementById('modal').click();
//MPP.client.uri = "wss://mpp_proxy.qonq.gq";
});} catch(e) {console.error(e.message)}
await new Promise(resolve => setTimeout(resolve, 5000));
let screenshot = await page.screenshot({ type: 'png' });
let filename = `Screenshot of www.multiplayerpiano.com @ ${new Date().toISOString()}.png`;
let attachment = new Discord.MessageAttachment(screenshot, filename);
await wh_hmpps.send(attachment);
} catch (error) {
await wh_hmpps.send(`:warning: ${error.stack}`);
}
try {
await page.evaluate(function () {
MPP.client.setChannel("✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧");
});
await new Promise(resolve => setTimeout(resolve, 5000));
let screenshot = await page.screenshot({ type: 'png' });
let filename = `Screenshot of www.multiplayerpiano.com/✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧ @ ${new Date().toISOString()}.png`;
let attachment = new Discord.MessageAttachment(screenshot, filename);
await wh_hrprs.send(attachment);
} catch(error) {
await wh_hrprs.send(`:warning: ${error.stack}`);
}
try {
await page.goto('http://ourworldofpixels.com');
await page.evaluate(function (owopcaptcha) {
localStorage.owopcaptcha = owopcaptcha;
OWOP.camera.zoom = 1;
}, process.env.OWOP_CAPTCHA_PASSWORD);
await new Promise(resolve => setTimeout(resolve, 2000));
await page.evaluate(function () {
for (let butt of document.getElementsByTagName('button')) {
if (butt.innerText == 'OK') {butt.click();break}
}
});
await new Promise(resolve => setTimeout(resolve, 13000));
let screenshot = await page.screenshot({ type: 'png' });
let filename = `Screenshot of ourworldofpixels.com/main @ ${new Date().toISOString()}.png`;
let attachment = new Discord.MessageAttachment(screenshot, filename);
await wh_howps.send(attachment);
} catch (error) {
await wh_howps.send(`:warning: ${error.stack}`);
}
} catch(error) {
console.error(`Error occured with screen capture:\n${error.stack}`)
} finally {
if (browser) await browser.close();
console.log('Finished screen captures');
}
},
interval: setInterval(() => { screenshotter.capture(); }, 1000 * 60 * 60)
};
screenshotter.capture();