Start of rewrite

This commit is contained in:
Cynthia Foxwell 2021-03-14 19:41:40 -06:00
commit 97e46f6447
12 changed files with 1448 additions and 0 deletions

14
.eslintignore Normal file
View 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
View 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
View file

@ -0,0 +1,6 @@
node_modules/
config.json
config.prod.json
config.testing.json
apikeys.json

5
.prettierrc Normal file
View file

@ -0,0 +1,5 @@
{
"semi": true,
"bracketSpacing": false,
"endOfLine": "lf"
}

2
README.md Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

66
src/index.js Normal file
View 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
View 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;

View 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
View 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
View 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);