Compare commits
No commits in common. "multibot" and "master" have entirely different histories.
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,5 +2,3 @@
|
|||||||
node_modules
|
node_modules
|
||||||
.env
|
.env
|
||||||
memberlist.json
|
memberlist.json
|
||||||
members.json
|
|
||||||
accountpool.json
|
|
258
index.mjs
258
index.mjs
@ -1,8 +1,6 @@
|
|||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import {Bot, IncomingChatPreference, RichText} from "@skyware/bot";
|
import {Bot, IncomingChatPreference, RichText} from "@skyware/bot";
|
||||||
import fetchRetry from "fetch-retry";
|
import fetchRetry from "fetch-retry";
|
||||||
import serveHandler from 'serve-handler';
|
|
||||||
import { createServer } from "http";
|
|
||||||
import { appendFileSync, readFileSync, writeFileSync } from "fs";
|
import { appendFileSync, readFileSync, writeFileSync } from "fs";
|
||||||
|
|
||||||
var _fetch = fetchRetry(global.fetch);
|
var _fetch = fetchRetry(global.fetch);
|
||||||
@ -11,82 +9,42 @@ global.fetch = function fetch(url, options) {
|
|||||||
return _fetch(url, options);
|
return _fetch(url, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
var accountpool = JSON.parse(readFileSync("accountpool.json", "utf8"));
|
|
||||||
var members = new Map(JSON.parse(readFileSync("members.json", "utf8"))); // member did => bot identifier
|
|
||||||
|
|
||||||
function saveMembers() {
|
|
||||||
writeFileSync("members.json", JSON.stringify(Array.from(members)));
|
|
||||||
|
var memberlist = []; // list of conversation ids
|
||||||
|
try {
|
||||||
|
memberlist = JSON.parse(readFileSync("memberlist.json", "utf8"));
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
function saveMemberlist() {
|
||||||
|
writeFileSync("memberlist.json", JSON.stringify(memberlist));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addMember(did) {
|
|
||||||
if (members.has(did)) {
|
|
||||||
if (bots.has(did)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
let identifier = members.get(did);
|
|
||||||
let {password, service} = accountpool.find(x => x.identifier == identifier);
|
|
||||||
let bot = newbot(identifier, password, service);
|
|
||||||
bots.set(did, bot);
|
|
||||||
return bot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let bot = bots.get(did);
|
|
||||||
if (bot) {
|
|
||||||
var identifier = bot.profile.handle;
|
|
||||||
} else {
|
|
||||||
var takenIdentifiers = new Set([...members.values(), ...Array.from(bots.values()).map(bot => bot.profile.handle)]);
|
|
||||||
for (var {identifier, password, service} of accountpool) {
|
|
||||||
if (!takenIdentifiers.has(identifier)) break;
|
|
||||||
}
|
|
||||||
bot = await newbot(identifier, password, service);
|
|
||||||
bots.set(did, bot);
|
|
||||||
}
|
|
||||||
members.set(did, identifier);
|
|
||||||
saveMembers();
|
|
||||||
return bot;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeMember(did) {
|
|
||||||
members.delete(did);
|
|
||||||
saveMembers();
|
|
||||||
}
|
|
||||||
|
|
||||||
var bots = new Map(await Promise.all(Array.from(members).map(async ([memberdid, identifier]) => {
|
|
||||||
let {password, service} = accountpool.find(x => /*x.did == identifier ||*/ x.identifier == identifier);
|
|
||||||
let bot = await newbot(identifier, password, service);
|
|
||||||
return [memberdid, bot];
|
|
||||||
}))); // member did => Bot instance
|
|
||||||
|
|
||||||
|
|
||||||
async function newbot(identifier, password, service) {
|
|
||||||
let bot = new Bot({
|
var bot = new Bot({
|
||||||
emitEvents: false,
|
emitEvents: false,
|
||||||
emitChatEvents: true,
|
emitChatEvents: true
|
||||||
service
|
});
|
||||||
});
|
bot.on("error", error => {
|
||||||
bot.on("error", error => {
|
console.error("bot error", error);
|
||||||
console.error(`bot ${identifier} error`, error);
|
});
|
||||||
});
|
|
||||||
bot.on("message", messageHandler);
|
|
||||||
await bot.login({
|
|
||||||
identifier,
|
|
||||||
password
|
|
||||||
});
|
|
||||||
console.log(`logged in bot ${identifier}`);
|
|
||||||
await bot.setChatPreference(IncomingChatPreference.All);
|
|
||||||
return bot;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mainbot = await newbot("groupchatbot.bsky.social", process.env.PASSWORD);
|
await bot.login({
|
||||||
|
identifier: process.env.IDENTIFIER,
|
||||||
|
password: process.env.PASSWORD
|
||||||
|
});
|
||||||
|
await bot.setChatPreference(IncomingChatPreference.All);
|
||||||
|
|
||||||
|
|
||||||
|
bot.on("message", async message => {
|
||||||
async function messageHandler(message) {
|
console.debug(new Date().toISOString(), message.senderDid, message.text);
|
||||||
console.debug('m', new Date().toISOString(), message.bot.profile.did, message.senderDid, message.text);
|
|
||||||
try {
|
try {
|
||||||
var sender = await message.getSender();
|
var sender = await message.getSender();
|
||||||
//var conversation = await message.getConversation();
|
var conversation = await message.getConversation();
|
||||||
var respond = text => sender.sendMessage({text});
|
var respond = text => sendMessage({conversationId: conversation.id, text});
|
||||||
|
|
||||||
if (message.text.startsWith('/')) {
|
if (message.text.startsWith('/')) {
|
||||||
let args = message.text.split(' ');
|
let args = message.text.split(' ');
|
||||||
@ -97,52 +55,33 @@ async function messageHandler(message) {
|
|||||||
await respond("pong");
|
await respond("pong");
|
||||||
return;
|
return;
|
||||||
case "list":
|
case "list":
|
||||||
let m = members.keys();
|
let memberConversations = await Promise.all(memberlist.map(convoid => bot.getConversation(convoid)));
|
||||||
m = m.filter(x => bots.has(x));
|
await respond(`${memberConversations.length} members in group chat: ${memberConversations.map(c => {
|
||||||
m = await Promise.all(m.map(async memberdid => {
|
let handle = c.members.find(m => m.did != bot.profile.did).handle;
|
||||||
try {
|
if (handle != "missing.invalid") { // work around https://github.com/skyware-js/bot/issues/19
|
||||||
return await message.bot.getProfile(memberdid);
|
handle = `@${handle}`;
|
||||||
} catch(error) {}
|
|
||||||
return memberdid;
|
|
||||||
}));
|
|
||||||
let rt = new RichText();
|
|
||||||
rt.addText(`${m.length} members in group chat: `);
|
|
||||||
for (let p of m) {
|
|
||||||
rt.addMention(p.displayName || p.handle || p.did || p, p.did || p);
|
|
||||||
rt.addText(", ");
|
|
||||||
}
|
}
|
||||||
await respond(rt);
|
return handle;
|
||||||
|
}).join(', ')}`);
|
||||||
return;
|
return;
|
||||||
case "leave":
|
case "leave":
|
||||||
broadcast({text:new RichText().addMention(sender.displayName || sender.handle || message.senderDid, message.senderDid).addText(" left the group chat.")}).catch(console.error);
|
broadcast(new RichText().addMention(sender.displayName || sender.handle || message.senderDid, message.senderDid).addText(" left the group chat.")).catch(console.error);
|
||||||
removeMember(message.senderDid);
|
memberlist = memberlist.filter(convoid => convoid != conversation.id);
|
||||||
await respond(`You left the group chat. To join the group chat again, send /join to @groupchatbot.bsky.social.`);
|
saveMemberlist();
|
||||||
|
await respond(`You left the group chat. Rejoin at any time with /join`);
|
||||||
return;
|
return;
|
||||||
case "join":
|
case "join":
|
||||||
if (members.has(message.senderDid) && bots.has(message.senderDid)) {
|
if (memberlist.includes(conversation.id)) {
|
||||||
await (await bots.get(message.senderDid).getProfile(message.senderDid)).sendMessage({
|
await respond(`You're already in the group chat.`);
|
||||||
text: `Use this bot to access group chat.`
|
|
||||||
});
|
|
||||||
await respond(`You are already in the group chat, use @${bots.get(message.senderDid).profile.handle} to access it.`);
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
broadcast({text:new RichText().addMention(sender.displayName || sender.handle || message.senderDid, message.senderDid).addText(" joined the group chat.")}).catch(console.error);
|
broadcast(new RichText().addMention(sender.displayName || sender.handle || message.senderDid, message.senderDid).addText(" joined the group chat.")).catch(console.error);
|
||||||
let b = await addMember(message.senderDid);
|
memberlist.push(conversation.id);
|
||||||
let s = await b.getProfile(message.senderDid);
|
saveMemberlist();
|
||||||
await respond(`You shall receive a message from @${b.profile.handle}, use that bot to access the group chat.`);
|
await respond(`Welcome to the group chat; you are now chatting with ${memberlist.length} other people. Use /list to see them.`);
|
||||||
try {
|
|
||||||
await s.sendMessage({
|
|
||||||
text: `Welcome to the group chat; you are now chatting with ${members.size} other people. Use /list to see them.`
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
await respond(`The other groupchat bot failed to DM you. Please allow DMs from everyone or open a DM with @${b.profile.handle} to access the group chat.\n\n(${error.message}\n${error.cause})`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case "invite":
|
case "invite":
|
||||||
if (!members.has(message.senderDid)) {
|
if (!memberlist.includes(conversation.id)) {
|
||||||
await respond(`You are not allowed to invite people to the group chat when you are not in the group chat yourself. Use /join first.`);
|
await respond(`You are not allowed to invite people to the group chat when you are not in the group chat yourself. Use /join first.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -152,17 +91,9 @@ async function messageHandler(message) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handle = handle.replace('@','');
|
handle = handle.replace('@','');
|
||||||
let profile = await mainbot.getProfile(handle);
|
let profile = await bot.getProfile(handle);
|
||||||
if (members.has(profile.did)) {
|
|
||||||
await respond("They're already here!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//try {
|
|
||||||
await profile.sendMessage({text: `@${sender.handle} invited you to the group chat! Use /join to accept!`});
|
await profile.sendMessage({text: `@${sender.handle} invited you to the group chat! Use /join to accept!`});
|
||||||
//} catch (error) {
|
await broadcast(new RichText().addMention(sender.displayName || sender.handle || message.senderDid, message.senderDid).addText(" invited ").addMention(profile.displayName||profile.handle,profile.did).addText(" to the group chat."));
|
||||||
|
|
||||||
//}
|
|
||||||
await broadcast({text: new RichText().addMention(sender.displayName || sender.handle || message.senderDid, message.senderDid).addText(" invited ").addMention(profile.displayName||profile.handle,profile.did).addText(" to the group chat.")});
|
|
||||||
return;
|
return;
|
||||||
case "help":
|
case "help":
|
||||||
await respond(`Commands: ${commandList}`);
|
await respond(`Commands: ${commandList}`);
|
||||||
@ -173,20 +104,11 @@ async function messageHandler(message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!members.has(message.senderDid)) {
|
if (!memberlist.includes(conversation.id)) {
|
||||||
await respond("Use /join to join the group chat.");
|
await respond("Use /join to join the group chat.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bots.has(message.senderDid)) {
|
|
||||||
await addMember(message.senderDid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bots.get(message.senderDid) != message.bot) {
|
|
||||||
await respond(`Wrong bot. Use @${bots.get(message.senderDid).profile?.handle} to access the group chat.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var logline = `${message.sentAt.toISOString()},${message.senderDid},${sender.displayName},${sender.handle},${JSON.stringify(message.text)}`;
|
var logline = `${message.sentAt.toISOString()},${message.senderDid},${sender.displayName},${sender.handle},${JSON.stringify(message.text)}`;
|
||||||
console.log(logline);
|
console.log(logline);
|
||||||
appendFileSync(`chatlog.csv`, logline + '\n');
|
appendFileSync(`chatlog.csv`, logline + '\n');
|
||||||
@ -217,55 +139,81 @@ async function messageHandler(message) {
|
|||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
await broadcast({text, facets, embed: message.embed}, {resolveFacets: false}, [message.senderDid]);
|
var otherconvoids = memberlist.filter(x => x != conversation.id);
|
||||||
|
var messages = otherconvoids.map(conversationId => ({
|
||||||
|
conversationId,
|
||||||
|
text,
|
||||||
|
facets,
|
||||||
|
embed: message.embed
|
||||||
|
}));
|
||||||
|
await sendMessages(messages, {resolveFacets: false});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
sender.sendMessage({text: `${error.message}\ncause: ${error.cause?.message}`}).catch(error => console.error(error));
|
if (conversation) sendMessage({conversationId: conversation.id, text: `${error.message}\ncause: ${error.cause.message}`}).catch(error => console.error(error));
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function broadcast(message, options, excludeDids) {
|
async function broadcast(text) {
|
||||||
if (!excludeDids) {
|
var logline = `${new Date().toISOString()},,,,${JSON.stringify(text.text||text)}`;
|
||||||
var logline = `${new Date().toISOString()},,,,${JSON.stringify(message.text.text||message.text)}`;
|
|
||||||
console.log(logline);
|
console.log(logline);
|
||||||
appendFileSync(`chatlog.csv`, logline + '\n');
|
appendFileSync(`chatlog.csv`, logline + '\n');
|
||||||
}
|
var messages = memberlist.map(conversationId => ({
|
||||||
for (let [memberdid, bot] of bots) {
|
conversationId,
|
||||||
if (excludeDids?.includes(memberdid)) continue;
|
text
|
||||||
if (!members.has(memberdid)) continue;
|
}));
|
||||||
trySendMessageToDid(bot, memberdid, message, options);
|
await sendMessages(messages);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function trySendMessageToDid(bot, did, message, options) {
|
|
||||||
|
// presere order
|
||||||
|
var queue = [];
|
||||||
|
var ratelimited = false;
|
||||||
|
function sendMessages(messages, options) {
|
||||||
|
queue.push([messages, options]);
|
||||||
|
if (!ratelimited) return flushQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function flushQueue() {
|
||||||
|
if (!queue.length) return;
|
||||||
|
var [messages, options] = queue.shift();
|
||||||
try {
|
try {
|
||||||
let profile = await bot.getProfile(did);
|
await bot.sendMessages(messages, options);
|
||||||
await profile.sendMessage(message, options);
|
ratelimited = false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`@ ${did} ${error.message} ${error.cause?.message}`);
|
if (error.cause?.kind == "RateLimitExceeded") {
|
||||||
|
console.warn("ratelimited");
|
||||||
|
ratelimited = true;
|
||||||
|
queue.unshift([messages, options]);
|
||||||
|
} else throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(function flushQueueLoop() {
|
||||||
|
flushQueue().catch(console.error).then(() => {
|
||||||
|
setTimeout(flushQueueLoop, 10000);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
// no preserve order
|
||||||
|
async function sendMessage(message, options) {
|
||||||
|
try {
|
||||||
|
return await bot.sendMessage(message, options);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.cause?.kind == "RateLimitExceeded") {
|
||||||
|
console.warn("ratelimited");
|
||||||
|
await new Promise(r => setTimeout(r, 10000));
|
||||||
|
return await sendMessage(message, options);
|
||||||
|
} else throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
global.bot = bot;
|
||||||
|
|
||||||
|
|
||||||
createServer((req, res) => {
|
|
||||||
serveHandler(req, res, {
|
|
||||||
public: "public",
|
|
||||||
headers: [{
|
|
||||||
source: "*.csv",
|
|
||||||
headers: [{
|
|
||||||
key: "Content-Type",
|
|
||||||
value: "text/plain; charset=utf-8"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}).listen(2383);
|
|
||||||
|
100
package-lock.json
generated
100
package-lock.json
generated
@ -7,8 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@skyware/bot": "^0.3.7",
|
"@skyware/bot": "^0.3.7",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"fetch-retry": "^6.0.0",
|
"fetch-retry": "^6.0.0"
|
||||||
"serve-handler": "^6.1.6"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@atcute/base32": {
|
"node_modules/@atcute/base32": {
|
||||||
@ -134,41 +133,6 @@
|
|||||||
"partysocket": "^1.0.2"
|
"partysocket": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/balanced-match": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
|
||||||
},
|
|
||||||
"node_modules/brace-expansion": {
|
|
||||||
"version": "1.1.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/bytes": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
|
||||||
},
|
|
||||||
"node_modules/content-disposition": {
|
|
||||||
"version": "0.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
|
|
||||||
"integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dotenv": {
|
"node_modules/dotenv": {
|
||||||
"version": "16.4.5",
|
"version": "16.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||||
@ -198,36 +162,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-6.0.0.tgz",
|
||||||
"integrity": "sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag=="
|
"integrity": "sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag=="
|
||||||
},
|
},
|
||||||
"node_modules/mime-db": {
|
|
||||||
"version": "1.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
|
||||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mime-types": {
|
|
||||||
"version": "2.1.18",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
|
||||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"mime-db": "~1.33.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/minimatch": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^1.1.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/partysocket": {
|
"node_modules/partysocket": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.0.2.tgz",
|
||||||
@ -238,16 +172,6 @@
|
|||||||
"event-target-shim": "^6.0.2"
|
"event-target-shim": "^6.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/path-is-inside": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w=="
|
|
||||||
},
|
|
||||||
"node_modules/path-to-regexp": {
|
|
||||||
"version": "3.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz",
|
|
||||||
"integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw=="
|
|
||||||
},
|
|
||||||
"node_modules/quick-lru": {
|
"node_modules/quick-lru": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.0.0.tgz",
|
||||||
@ -260,14 +184,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/range-parser": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/rate-limit-threshold": {
|
"node_modules/rate-limit-threshold": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/rate-limit-threshold/-/rate-limit-threshold-0.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/rate-limit-threshold/-/rate-limit-threshold-0.1.5.tgz",
|
||||||
@ -277,20 +193,6 @@
|
|||||||
"node": "^14.13.1 || >=16.0.0"
|
"node": "^14.13.1 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/serve-handler": {
|
|
||||||
"version": "6.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz",
|
|
||||||
"integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"bytes": "3.0.0",
|
|
||||||
"content-disposition": "0.5.2",
|
|
||||||
"mime-types": "2.1.18",
|
|
||||||
"minimatch": "3.1.2",
|
|
||||||
"path-is-inside": "1.0.2",
|
|
||||||
"path-to-regexp": "3.3.0",
|
|
||||||
"range-parser": "1.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.18.0",
|
"version": "8.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@skyware/bot": "^0.3.7",
|
"@skyware/bot": "^0.3.7",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"fetch-retry": "^6.0.0",
|
"fetch-retry": "^6.0.0"
|
||||||
"serve-handler": "^6.1.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user