Start of rewrite
This commit is contained in:
commit
97e46f6447
12 changed files with 1448 additions and 0 deletions
14
.eslintignore
Normal file
14
.eslintignore
Normal file
|
@ -0,0 +1,14 @@
|
|||
pnpm-debug.log
|
||||
dist
|
||||
.cache
|
||||
.tern-port
|
||||
config.json
|
||||
package-lock.json
|
||||
README.html
|
||||
*~
|
||||
\#*\#
|
||||
node_modules
|
||||
yarn-error.log
|
||||
npm-error.log
|
||||
/.vscode
|
||||
/.idea
|
31
.eslintrc.js
Normal file
31
.eslintrc.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const OFF = 0;
|
||||
// const WARN = 1;
|
||||
const ERROR = 2;
|
||||
|
||||
module.exports = {
|
||||
extends: ["eslint:recommended"],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
},
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
rules: {
|
||||
indent: OFF,
|
||||
semi: ERROR,
|
||||
quotes: [ERROR, "double", {avoidEscape: true, allowTemplateLiterals: true}],
|
||||
"no-empty": ERROR,
|
||||
"array-callback-return": ERROR,
|
||||
"consistent-return": ERROR,
|
||||
eqeqeq: OFF,
|
||||
"prefer-const": ERROR,
|
||||
"no-unused-vars": [ERROR, {args: "none", varsIgnorePattern: "^_"}],
|
||||
"no-console": OFF,
|
||||
"no-debugger": OFF,
|
||||
"require-atomic-updates": OFF,
|
||||
},
|
||||
globals: {
|
||||
hf: true,
|
||||
},
|
||||
};
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
node_modules/
|
||||
|
||||
config.json
|
||||
config.prod.json
|
||||
config.testing.json
|
||||
apikeys.json
|
5
.prettierrc
Normal file
5
.prettierrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"semi": true,
|
||||
"bracketSpacing": false,
|
||||
"endOfLine": "lf"
|
||||
}
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# HiddenPhox
|
||||
**This is the rewrite branch. For the main branch go [here](https://gitlab.com/Cynosphere/HiddenPhox/-/tree/master)**
|
30
package.json
Normal file
30
package.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "hiddenphox",
|
||||
"version": "10.0.0",
|
||||
"description": "Discord bot",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://gitlab.com/Cynosphere/HiddenPhox.git"
|
||||
},
|
||||
"author": "Cynosphere",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/Cynosphere/HiddenPhox/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/Cynosphere/HiddenPhox#readme",
|
||||
"dependencies": {
|
||||
"colorcolor": "^1.1.1",
|
||||
"eris": "github:abalabahaha/eris#dev",
|
||||
"murmurhash": "^2.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"npmlog": "^4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.22.0",
|
||||
"prettier": "^2.2.1"
|
||||
}
|
||||
}
|
1001
pnpm-lock.yaml
Normal file
1001
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
66
src/index.js
Normal file
66
src/index.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
const Eris = require("eris");
|
||||
const logger = require("npmlog");
|
||||
const fs = require("fs");
|
||||
const {resolve} = require("path");
|
||||
|
||||
const config = require("../config.json");
|
||||
const Command = require("./lib/command.js");
|
||||
const CommandDispatcher = require("./lib/commandDispatcher.js");
|
||||
|
||||
const bot = new Eris(config.token, {
|
||||
defaultImageFormat: "png",
|
||||
defaultImageSize: 1024,
|
||||
});
|
||||
|
||||
const commands = new Eris.Collection();
|
||||
|
||||
function registerCommand(cmdObj) {
|
||||
if (cmdObj instanceof Command) {
|
||||
commands.set(cmdObj.name, cmdObj);
|
||||
const aliases = cmdObj.getAliases();
|
||||
logger.info(
|
||||
"hf:cmd",
|
||||
"Registered command '%s'%s",
|
||||
cmdObj.name,
|
||||
aliases.length > 0 ? ` (aliases: ${aliases.join(", ")})` : ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
global.hf = {
|
||||
bot,
|
||||
config,
|
||||
commands,
|
||||
registerCommand,
|
||||
};
|
||||
|
||||
for (const file of fs.readdirSync(resolve(__dirname, "modules"))) {
|
||||
require(resolve(__dirname, "modules", file));
|
||||
logger.info("hf:modules", "Loaded module: '%s'", file);
|
||||
}
|
||||
|
||||
bot.on("messageCreate", CommandDispatcher);
|
||||
bot.on("messageUpdate", (msg) => {
|
||||
const oneDay = Date.now() - 86400000;
|
||||
if (msg.timestamp > oneDay && !msg.hasRan) {
|
||||
CommandDispatcher(msg);
|
||||
}
|
||||
});
|
||||
|
||||
bot.on("ready", async () => {
|
||||
logger.info("hf:main", "Connected to Discord.");
|
||||
logger.info(
|
||||
"hf:main",
|
||||
"Logged in as: %s#%s (%s)",
|
||||
bot.user.username,
|
||||
bot.user.discriminator,
|
||||
bot.user.id
|
||||
);
|
||||
|
||||
const channel = await bot.getDMChannel(config.owner_id);
|
||||
if (channel) {
|
||||
channel.createMessage(":white_check_mark: Loaded HiddenPhox.");
|
||||
}
|
||||
});
|
||||
|
||||
bot.connect();
|
39
src/lib/command.js
Normal file
39
src/lib/command.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
const {Permissions} = require("eris/lib/Constants");
|
||||
|
||||
class Command {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this.aliases = [];
|
||||
this.permissions = {};
|
||||
this.helpText = "No description provided.";
|
||||
this.category = "unsorted";
|
||||
}
|
||||
|
||||
addAlias(alias) {
|
||||
this.aliases.push(alias);
|
||||
}
|
||||
getAliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
hasAlias(alias) {
|
||||
return this.aliases.includes(alias);
|
||||
}
|
||||
|
||||
addPermission(permission) {
|
||||
if (Permissions[permission]) {
|
||||
this.permissions[permission] = true;
|
||||
}
|
||||
}
|
||||
removePermission(permission) {
|
||||
delete this.permissions[permission];
|
||||
}
|
||||
getPermissions() {
|
||||
return this.permissions;
|
||||
}
|
||||
|
||||
callback() {
|
||||
return "Callback not overwritten.";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Command;
|
94
src/lib/commandDispatcher.js
Normal file
94
src/lib/commandDispatcher.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
const logger = require("npmlog");
|
||||
|
||||
function parseArguments(str) {
|
||||
return str.match(/\\?.|^$/g).reduce(
|
||||
(p, c) => {
|
||||
if (c === '"') {
|
||||
p.quote ^= 1;
|
||||
} else if (!p.quote && c === " ") {
|
||||
p.a.push("");
|
||||
} else {
|
||||
p.a[p.a.length - 1] += c.replace(/\\(.)/, "$1");
|
||||
}
|
||||
|
||||
return p;
|
||||
},
|
||||
{a: [""]}
|
||||
).a;
|
||||
}
|
||||
|
||||
function runCommand(msg, cmd, line, args) {
|
||||
let cmdObj = hf.commands.get(cmd);
|
||||
if (!cmdObj) {
|
||||
for (const c of hf.commands.values()) {
|
||||
if (c.hasAlias(cmd)) {
|
||||
cmdObj = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cmdObj) return null;
|
||||
|
||||
if (cmdObj.ownerOnly && msg.author.id != hf.config.owner_id) {
|
||||
return "No\n\nSent from my iPhone.";
|
||||
}
|
||||
|
||||
if (cmdObj.elevatedOnly && !hf.config.elevated.includes(msg.author.id)) {
|
||||
return "No\n\nSent from my iPhone.";
|
||||
}
|
||||
|
||||
try {
|
||||
return cmdObj.callback(msg, line, ...args);
|
||||
} catch (err) {
|
||||
logger.error("hf:cmd:" + cmd, err);
|
||||
return ":warning: An internal error occurred.";
|
||||
}
|
||||
}
|
||||
|
||||
function CommandDispatcher(msg) {
|
||||
let str = msg.content;
|
||||
let inCommand = false;
|
||||
|
||||
const prefix1 = hf.config.prefix;
|
||||
const prefix2 = `<@${hf.bot.user.id}> `;
|
||||
const prefix3 = `<@!${hf.bot.user.id}> `;
|
||||
|
||||
if (str.startsWith(prefix1)) {
|
||||
str = str.substring(prefix1.length);
|
||||
inCommand = true;
|
||||
} else if (str.startsWith(prefix2)) {
|
||||
str = str.substring(prefix2.length);
|
||||
inCommand = true;
|
||||
} else if (str.startsWith(prefix3)) {
|
||||
str = str.substring(prefix3.length);
|
||||
inCommand = true;
|
||||
}
|
||||
|
||||
if (inCommand) {
|
||||
let line = str.split(" ");
|
||||
let [cmd] = line.splice(0, 1);
|
||||
cmd = cmd.toLowerCase();
|
||||
line = line.join(" ");
|
||||
|
||||
const args = parseArguments(line);
|
||||
|
||||
const response = runCommand(msg, cmd, line, args);
|
||||
if (response) {
|
||||
msg.channel.createMessage(
|
||||
Object.assign(
|
||||
typeof response === "string" ? {content: response} : response,
|
||||
{
|
||||
allowedMentions: {
|
||||
repliedUser: false,
|
||||
},
|
||||
messageReferenceID: msg.id,
|
||||
}
|
||||
),
|
||||
response.file
|
||||
);
|
||||
}
|
||||
msg.hasRan = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CommandDispatcher;
|
25
src/lib/misc.js
Normal file
25
src/lib/misc.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
const {v3} = require("murmurhash");
|
||||
const colorcolor = require("colorcolor");
|
||||
|
||||
function pastelize(id) {
|
||||
const hue = v3(id) % 360;
|
||||
const hex = colorcolor(`hsl(${hue},75%,60%)`, "hex");
|
||||
return parseInt(hex.substring(1), 16);
|
||||
}
|
||||
|
||||
function getTopColor(msg, id, fallback = 0x7289da) {
|
||||
if (!msg.channel.guild) return fallback;
|
||||
|
||||
const roles = msg.channel.guild.members
|
||||
.get(id)
|
||||
.roles.map((role) => msg.channel.guild.roles.get(role))
|
||||
.filter((role) => role.color);
|
||||
roles.sort((a, b) => b.position - a.position);
|
||||
|
||||
return roles[0]?.color || fallback;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
pastelize,
|
||||
getTopColor,
|
||||
};
|
135
src/modules/general.js
Normal file
135
src/modules/general.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
const Command = require("../lib/command.js");
|
||||
const CATEGORY = "general";
|
||||
const {pastelize, getTopColor} = require("../lib/misc.js");
|
||||
|
||||
const help = new Command("help");
|
||||
help.category = CATEGORY;
|
||||
help.helpText = "Lists all commands";
|
||||
help.usage = "[command] or [--category]";
|
||||
help.callback = function (msg, line) {
|
||||
const color = getTopColor(msg, hf.bot.user.id, pastelize(hf.bot.user.id));
|
||||
const sorted = {};
|
||||
|
||||
for (const cmd of hf.commands.values()) {
|
||||
const cat = cmd.category.toLowerCase();
|
||||
if (!sorted[cat]) {
|
||||
sorted[cat] = [];
|
||||
}
|
||||
sorted[cat].push(cmd);
|
||||
}
|
||||
|
||||
if (line == "") {
|
||||
const embed = {
|
||||
title: "HiddenPhox Help",
|
||||
color,
|
||||
fields: [],
|
||||
};
|
||||
|
||||
for (const cat in sorted) {
|
||||
embed.fields.push({
|
||||
name: cat.toUpperCase().charAt(0) + cat.toLowerCase().substring(1),
|
||||
value: `${sorted[cat].length} Commands\n\`${
|
||||
hf.config.prefix
|
||||
}help --${cat.toLowerCase()}\``,
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
return {embed};
|
||||
} else if (line.startsWith("--")) {
|
||||
const cat = line.replace("--", "").toLowerCase().trim();
|
||||
|
||||
if (sorted[cat]) {
|
||||
const embed = {
|
||||
title: `HiddenPhox Help: Category > ${
|
||||
cat.toUpperCase().charAt(0) + cat.toLowerCase().substring(1)
|
||||
}`,
|
||||
color,
|
||||
fields: [],
|
||||
};
|
||||
|
||||
for (const cmd of sorted[cat]) {
|
||||
embed.fields.push({
|
||||
name: hf.config.prefix + cmd.name,
|
||||
value: cmd.helpText,
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
return {embed};
|
||||
} else {
|
||||
return "Category not found.";
|
||||
}
|
||||
} else {
|
||||
let cmd = hf.commands.get(line.toLowerCase().trim());
|
||||
if (!cmd) {
|
||||
for (const c of hf.commands.values()) {
|
||||
if (c.hasAlias(line.toLowerCase().trim())) {
|
||||
cmd = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd) {
|
||||
const aliases = cmd.getAliases();
|
||||
|
||||
const embed = {
|
||||
title: `HiddenPhox Help: Command > \`${hf.config.prefix}${cmd.name}\``,
|
||||
color,
|
||||
description: cmd.helpText,
|
||||
fields: [
|
||||
{
|
||||
name: "Category",
|
||||
value:
|
||||
cmd.category.toUpperCase().charAt(0) +
|
||||
cmd.category.toLowerCase().substring(1),
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (aliases.length > 0) {
|
||||
embed.fields.push({
|
||||
name: "Aliases",
|
||||
value: aliases.join(", "),
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
if (cmd.usage) {
|
||||
embed.fields.push({
|
||||
name: "Usage",
|
||||
value: `${hf.config.prefix}${cmd.name} ${cmd.usage}`,
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (cmd.description) {
|
||||
embed.fields.push({
|
||||
name: "Full Description",
|
||||
value: cmd.description,
|
||||
});
|
||||
}
|
||||
|
||||
return {embed};
|
||||
} else {
|
||||
return "Command not found.";
|
||||
}
|
||||
}
|
||||
};
|
||||
hf.registerCommand(help);
|
||||
|
||||
const ping = new Command("ping");
|
||||
ping.category = CATEGORY;
|
||||
ping.helpText = "Pong";
|
||||
ping.description = "Measures response times to Discord.";
|
||||
ping.addAlias("p");
|
||||
ping.callback = async function (msg) {
|
||||
const newMsg = await msg.channel.createMessage("Pong.");
|
||||
const rtt = Math.floor(newMsg.timestamp - msg.timestamp);
|
||||
const gateway = hf.bot.shards.get(
|
||||
hf.bot.guildShardMap[hf.bot.channelGuildMap[msg.channel.id]] || 0
|
||||
).latency;
|
||||
|
||||
newMsg.edit(`Pong. RTT: \`${rtt}ms\`, Gateway: \`${gateway}ms\``);
|
||||
};
|
||||
hf.registerCommand(ping);
|
Loading…
Reference in a new issue