woah is that a refactor???

This commit is contained in:
Ashley Graves 2024-10-15 09:30:27 +02:00
parent c94fbfec4e
commit 7218b22b2b
27 changed files with 482 additions and 379 deletions

View file

@ -1,41 +0,0 @@
var meows = [
"mreow",
"miau",
"mewo",
"maow",
"mrow",
"mrao",
"meow",
"mew",
"nya",
];
var emoticons = [
":3",
"^w^",
"=^w^=",
"-w-",
":333"
];
async function execute(client, event) {
var reply = "";
for(let i = 0;i < Math.random() * 15; i++)
reply += " " + meows.random();
reply += "!".repeat(Math.random() * 5);
if(Math.random() > 0.5) {
reply += " " + emoticons.random();
}
await client.reply(event, reply);
}
export default {
command: "catgpt",
name: "catgpt",
usage: "[prompt]",
desc: "advanced NAI-based language meowdel",
execute
}

View file

@ -1,25 +0,0 @@
import { xxh64 } from "@node-rs/xxhash";
import { encode } from "html-entities";
import { JSDOM } from "jsdom";
import util from "util";
import fs from "fs";
function execute(client, event, args) {
var c = "";
try {
var result = eval(args);
c = util.format(result).replaceAll(process.env.ACCESS_TOKEN, "*".repeat(process.env.ACCESS_TOKEN.length));
} catch(err) {
c = util.format(err);
}
client.reply(event, c, `<pre><code>${encode(c)}</code></pre>`);
}
export default {
command: "eval",
name: "eval",
usage: "<code>",
owner: true,
desc: "run JS code and reply with the result",
execute
}

View file

@ -1,55 +0,0 @@
import { encode } from "html-entities";
function execute(client, event, args) {
var name = args.toLowerCase();
var command = client.commands.filter(c=>(c.name.toLowerCase()==name || c.command.toLowerCase()==name))[0];
var module = client.modules.filter(m=>m.name.toLowerCase()==name)[0];
var specific = command ?? module ?? false;
if(args != "") {
if(!command && !module) {
client.reply(event, `section "${args}" not found.\nrun "${process.env.PREFIX}help" for a list of commands and modules.`);
return;
}
if(module) {
var reply = module.name + "\n";
reply += module.desc;
var replyHTML = `<b>${encode(module.name)}</b><br>` +
`<i>${encode(module.desc)}</i>`;
client.reply(event, reply, replyHTML);
return;
}
var reply = command.name + "\n" +
command.desc + "\n\n" +
command.usage;
var replyHTML = `<b>${encode(command.name)}</b><br>` +
`<i>${encode(command.desc)}</i>` +
`<br><code>${encode(command.usage)}</code>`;
client.reply(event, reply, replyHTML);
return;
}
var reply = `commands: ${client.commands.map(m => m.name).join(", ")}\n` +
`modules: ${client.modules.map(m => m.name).join(", ")}\n` +
`run ${process.env.PREFIX}help <module/command> for more information.`;
var replyHTML = `commands: <code>${client.commands.map(m => encode(m.name)).join("</code>, <code>")}</code><br>` +
`modules: <code>${client.modules.map(m => encode(m.name)).join("</code>, <code>")}</code><br>` +
encode(`run ${process.env.PREFIX}help <module/command> for more information.`);
client.reply(event, reply, replyHTML);
}
export default {
command: "help",
name: "help",
desc: "show list of commands and modules",
execute
}

View file

@ -1,16 +0,0 @@
function execute(client, event, args) {
var info = `source code: https://git.lgbt/root/possumbot\n`;
info += `commands: ${client.commands.length}\n`;
info += `modules: ${client.modules.length}\n`;
info += `prefix: ${process.env.PREFIX} (you can also mention the bot!)\n`;
info += `owner: ${process.env.OWNER_ID}`;
client.reply(event, info);
}
export default {
command: "info",
name: "info",
desc: "show general info about the bot",
execute
}

View file

@ -1,13 +0,0 @@
import { exec } from "node:child_process";
function execute(client, event, args) {
client.joinRoom(args);
}
export default {
command: "join",
name: "join",
owner: true,
desc: "join a room",
execute
}

View file

@ -1,13 +0,0 @@
import { exec } from "node:child_process";
function execute(client, event, args) {
process.exit(255);
}
export default {
command: "restart",
name: "restart",
owner: true,
desc: "restarts the bot",
execute
}

View file

@ -1,47 +0,0 @@
import { encode } from "html-entities";
function execute(client, event, args) {
var name = args.toLowerCase();
var command = client.commands.filter(c=>(c.name.toLowerCase()==name || c.command.toLowerCase()==name))[0];
var module = client.modules.filter(m=>m.name.toLowerCase()==name)[0];
var specific = command ?? module ?? false;
var config = client.config.get(event.sender.roomId);
if(args != "") {
if(!module) {
client.reply(event, `Module "${args}" not found.\nRun "${process.env.PREFIX}help" for a list of commands and modules.`);
return;
}
config.set(module.name, !(config.get(module.name) ?? true));
var state = (config.get(module.name) ? "En" : "Dis") + "abled";
var reply = state + " " + module.name;
var replyHTML = `<b>${state}</b> <code>${encode(module.name)}</code>`;
client.reply(event, reply, replyHTML);
return;
}
var modules = client.modules.map(m=>m.name);
var enabled = modules.filter(m=>config.get(m)!==false);
var reply = `enabled modules:\n${enabled.join(", ")}`;
var replyHTML = `enabled modules:<br><code>${enabled.join("</code>, <code>")}</code>`;
reply += `\navailable modules:\n${modules.join(", ")}`;
replyHTML += `<br>available modules:<br><code>${modules.join("</code>, <code>")}</code>`;
client.reply(event, reply, replyHTML);
}
export default {
command: "toggle",
name: "toggle",
usage: "<module>",
minPwr: 50,
desc: "toggle a module on or off in current channel",
execute
}

View file

@ -1,81 +0,0 @@
import fedimbed from "../lib/fedimbed.js";
import { encode } from "html-entities";
import { JSDOM } from "jsdom";
import util from "util";
async function onMessage(client, event) {
const embed = await fedimbed(event.getContent().body);
if(!embed) return;
const dom = new JSDOM("<!DOCTYPE html><body></body>");
const document = dom.window.document;
var quote = document.createElement("blockquote");
if(!embed.embeds) {
var c = util.format(embed);
client.reply(event, c, `<pre><code>${encode(c)}</code></pre>`);
return;
}
for(const emb of embed.embeds) {
var link = document.createElement("a");
link.href = emb.url;
if(emb.thumbnail && emb.thumbnail.url) {
var avatar = document.createElement("img");
avatar.src = await client.uploadMedia(emb.thumbnail.url);
avatar.height = "16";
link.appendChild(avatar);
}
var linkText = document.createElement("span");
linkText.innerHTML = ((emb.thumbnail?.url) ? "&nbsp" : "") + emb.title;
link.appendChild(linkText);
quote.appendChild(link);
var text = document.createElement("p");
text.innerHTML = emb.description;
for(const emote of embed.emotes) {
console.log(text.innerHTML);
var img = document.createElement("img");
img.src = await client.uploadMedia(emote.url);
img.height = "16";
img.alt = emote.name;
text.innerHTML = text.innerHTML.replaceAll(emote.name, img.outerHTML);
}
quote.appendChild(text);
}
for(const file of embed.files) {
var media;
switch(file.type.split("/")[0]) {
case "audio":
media = document.createElement("audio");
break;
case "video":
media = document.createElement("video");
break;
case "image":
media = document.createElement("img");
break;
}
media.src = await client.uploadMedia(file.url);
media.alt = media.title = file.desc ?? "";
quote.appendChild(media);
}
document.body.appendChild(quote);
let x = document.createElement("small");
x.innerHTML = "Powered by <a href=\"https://gitdab.com/Cynosphere/HiddenPhox/src/branch/rewrite/src/modules/fedimbed.js\">HF Fedimbed</a>";
document.body.appendChild(x);
client.reply(event, "This message uses HTML, which your client does not support.", document.body.outerHTML);
}
export default {
name: "fedimbed",
desc: "embed fediverse post contents",
hooks: {
message: onMessage
}
}

View file

@ -1,49 +0,0 @@
var meows = [
"mreow",
"miau",
"mewo",
"maow",
"mrow",
"mrao",
"meow",
"mew",
"nya",
];
var re = new RegExp("\\b(n+y+a+n*?|m+[re]*([yiaou]+[wu]+|w+))(ing|er|s)?\\b", "gi");
var emoticons = [
":3",
"^w^",
"=^w^=",
"-w-",
":333"
];
async function onMessage(client, event) {
var content = event.getContent();
if(content["m.new_content"] != null) return;
for(const meow of meows) {
if(re.test(content.body.toLowerCase())) {
var reply = meows.random();
reply += "!".repeat(Math.random()*5)
if(Math.random() > 0.5) {
reply += " " + emoticons.random();
}
client.reply(event, reply);
break;
}
}
}
export default {
name: "meow",
desc: ":33",
hooks: {
message: onMessage
}
}

View file

@ -3,11 +3,11 @@
"type": "module",
"version": "0.0.0",
"description": "General purpose Matrix bot",
"main": "index.js",
"main": "src/index.js",
"author": "Ashley Graves",
"license": "GPL-v3",
"scripts": {
"login": "node login.js"
"login": "node src/login.js"
},
"dependencies": {
"@matrix-org/olm": "^3.2.15",

45
src/commands/catgpt.js Normal file
View file

@ -0,0 +1,45 @@
import BaseCommand from "../lib/base/command.js";
var meows = [
"mreow",
"miau",
"mewo",
"maow",
"mrow",
"mrao",
"meow",
"mew",
"nya",
];
var emoticons = [
":3",
"^w^",
"=^w^=",
"-w-",
":333"
];
class CatGPTCommand extends BaseCommand {
command = "catgpt";
name = "catgpt";
usage = "[prompt]";
description = "advanced NAI-based language meowdel";
/** @type {BaseCommand['execute']} */
async execute(client, event) {
var reply = "";
for (let i = 0; i < Math.random() * 15; i++)
reply += " " + meows.random();
reply += "!".repeat(Math.random() * 5);
if (Math.random() > 0.5) {
reply += " " + emoticons.random();
}
await client.reply(event, reply);
}
}
export default new CatGPTCommand();

29
src/commands/eval.js Normal file
View file

@ -0,0 +1,29 @@
import BaseCommand from "../lib/base/command.js";
import { xxh64 } from "@node-rs/xxhash";
import { encode } from "html-entities";
import { JSDOM } from "jsdom";
import util from "util";
import fs from "fs";
class EvalCommand extends BaseCommand {
name = "eval";
command = "eval";
usage = "<code>";
ownerOnly = true;
description = "run JS code and reply with the result";
/** @type {BaseCommand['execute']} */
async execute(client, event, args) {
var c = "";
try {
var result = eval(args);
c = util.format(result).replaceAll(process.env.ACCESS_TOKEN, "*".repeat(process.env.ACCESS_TOKEN.length));
} catch (err) {
c = util.format(err);
}
await client.reply(event, c, `<pre><code>${encode(c)}</code></pre>`);
}
}
export default new EvalCommand();

62
src/commands/help.js Normal file
View file

@ -0,0 +1,62 @@
import { encode } from "html-entities";
import BaseCommand from "../lib/base/command.js";
class HelpCommand extends BaseCommand {
command = "help";
name = "help";
desc = "show list of commands and modules";
/** @type {BaseCommand['execute']} */
async execute(client, event, args) {
var name = args.toLowerCase();
var command = client.commands.filter(c => (c.name.toLowerCase() == name || c.command.toLowerCase() == name))[0];
var module = client.modules.filter(m => m.name.toLowerCase() == name)[0];
if (args != "") {
if (!command && !module) {
client.reply(event, `section "${args}" not found.\nrun "${process.env.PREFIX}help" for a list of commands and modules.`);
return;
}
if (module) {
module.desc = module.desc ?? module.description;
var reply = module.name + "\n";
reply += module.desc;
var replyHTML = `<b>${encode(module.name)}</b><br>` +
`<i>${encode(module.desc)}</i>`;
client.reply(event, reply, replyHTML);
return;
}
command.desc = command.desc ?? command.description;
var reply = command.name + "\n" +
command.desc + "\n\n" +
command.usage;
var replyHTML = `<b>${encode(command.name)}</b><br>` +
`<i>${encode(command.desc)}</i>` +
`<br><code>${encode(command.usage)}</code>`;
client.reply(event, reply, replyHTML);
return;
}
var reply = `commands: ${client.commands.map(m => m.name).join(", ")}\n` +
`modules: ${client.modules.map(m => m.name).join(", ")}\n` +
`run ${process.env.PREFIX}help <module/command> for more information.`;
var replyHTML = `commands: <code>${client.commands.map(m => encode(m.name)).join("</code>, <code>")}</code><br>` +
`modules: <code>${client.modules.map(m => encode(m.name)).join("</code>, <code>")}</code><br>` +
encode(`run ${process.env.PREFIX}help <module/command> for more information.`);
client.reply(event, reply, replyHTML);
}
}
export default new HelpCommand();

20
src/commands/info.js Normal file
View file

@ -0,0 +1,20 @@
import BaseCommand from "../lib/base/command.js";
class InfoCommand extends BaseCommand {
command = "info";
name = "info";
desc = "show general info about the bot";
/** @type {BaseCommand['execute']} */
async execute(client, event, args) {
var info = `source code: https://git.lgbt/root/possumbot\n`;
info += `commands: ${client.commands.length}\n`;
info += `modules: ${client.modules.length}\n`;
info += `prefix: ${process.env.PREFIX} (you can also mention the bot!)\n`;
info += `owner: ${process.env.OWNER_ID}`;
await client.reply(event, info);
}
}
export default new InfoCommand();

16
src/commands/join.js Normal file
View file

@ -0,0 +1,16 @@
import { exec } from "node:child_process";
import BaseCommand from "../lib/base/command.js";
class JoinCommand extends BaseCommand {
command = "join";
name = "join";
ownerOnly = true;
description = "join a room";
/** @type {BaseCommand['execute']} */
async execute(client, event, args) {
client.joinRoom(args);
}
}
export default new JoinCommand();

16
src/commands/restart.js Normal file
View file

@ -0,0 +1,16 @@
import BaseCommand from "../lib/base/command.js";
class RestartCommand extends BaseCommand {
name = "restart";
command = "restart";
description = "restarts the bot";
ownerOnly = true;
/** @type {BaseCommand['execute']} */
async execute(client, event, args) {
await client.reply(event, "Restarting, please wait...");
process.exit(255);
}
}
export default new RestartCommand();

50
src/commands/toggle.js Normal file
View file

@ -0,0 +1,50 @@
import { encode } from "html-entities";
import BaseCommand from "../lib/base/command.js";
class ToggleCommand extends BaseCommand {
command = "toggle";
name = "toggle";
usage = "<module>";
minPowerLevel = 50;
description = "toggle a module on or off in current channel";
/** @type {BaseCommand['execute']} */
async execute(client, event, args) {
var name = args.toLowerCase();
var command = client.commands.filter(c => (c.name.toLowerCase() == name || c.command.toLowerCase() == name))[0];
var module = client.modules.filter(m => m.name.toLowerCase() == name)[0];
var specific = command ?? module ?? false;
var config = client.config.get(event.sender.roomId);
if (args != "") {
if (!module) {
client.reply(event, `Module "${args}" not found.\nRun "${process.env.PREFIX}help" for a list of commands and modules.`);
return;
}
config.set(module.name, !(config.get(module.name) ?? true));
var state = (config.get(module.name) ? "En" : "Dis") + "abled";
var reply = state + " " + module.name;
var replyHTML = `<b>${state}</b> <code>${encode(module.name)}</code>`;
client.reply(event, reply, replyHTML);
return;
}
var modules = client.modules.map(m => m.name);
var enabled = modules.filter(m => config.get(m) !== false);
var reply = `enabled modules:\n${enabled.join(", ")}`;
var replyHTML = `enabled modules:<br><code>${enabled.join("</code>, <code>")}</code>`;
reply += `\navailable modules:\n${modules.join(", ")}`;
replyHTML += `<br>available modules:<br><code>${modules.join("</code>, <code>")}</code>`;
client.reply(event, reply, replyHTML);
}
}
export default new ToggleCommand();

View file

@ -6,6 +6,9 @@ import sdkExt from "./lib/ext.js";
import { resolve } from "node:path";
import fs from "node:fs";
import { LocalStorage } from 'node-localstorage';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
global.__dirname = dirname(fileURLToPath(import.meta.url));
import fetch from "node-fetch";
global.fetch = fetch;
@ -14,6 +17,8 @@ import Olm from "@matrix-org/olm";
global.Olm = Olm;
import env from "dotenv";
import BaseCommand from "./lib/base/command.js";
import { format } from "node:util";
env.config();
const localStorage = new LocalStorage("./data/localstorage");
@ -49,10 +54,11 @@ client.initialized = false;
client.modules = [];
client.commands = [];
for (const file of fs.readdirSync(resolve("modules"))) {
var modulesDir = resolve(__dirname, "modules");
for (const file of fs.readdirSync(modulesDir)) {
try {
if (file.startsWith(".")) continue;
var module = (await import(resolve("modules", file))).default;
var module = (await import(resolve(modulesDir, file))).default;
client.modules.push(module);
client.log("[load:modules]", `loaded ${module.name}`);
} catch (err) {
@ -60,10 +66,11 @@ for (const file of fs.readdirSync(resolve("modules"))) {
}
}
for (const file of fs.readdirSync(resolve("commands"))) {
var commandsDir = resolve(__dirname, "commands");
for (const file of fs.readdirSync(commandsDir)) {
try {
if (file.startsWith(".")) continue;
var command = (await import(resolve("commands", file))).default;
var command = (await import(resolve(commandsDir, file))).default;
command.usage = process.env.PREFIX + command.command + (command.usage ? " " + command.usage : '');
client.commands.push(command);
client.log("[load:commands]", `loaded ${command.name}`);
@ -74,27 +81,36 @@ for (const file of fs.readdirSync(resolve("commands"))) {
function doModule(client, event) {
client.modules.forEach(m => {
if (!m) return;
if (!m.onMessage) return;
var config = client.config.get(event.sender.roomId);
if (config.get(m.name) === false) return;
try {
m.hooks?.message(client, event);
m.onMessage(client, event);
} catch (err) {
client.log("[hook]", err);
}
});
}
/**
* @param {MatrixClient} client
* @param {MatrixEvent} event
* @param {string} cmd
* @param {string} args
* @returns {Boolean} Success?
*/
function doCommand(client, event, cmd, args) {
var command;
command = client.commands.filter(c => c.command == cmd)[0];
/**
* @type {BaseCommand}
*/
var command = client.commands.filter(c => c.command == cmd)[0];
if (!command)
return false;
if ((command.owner && event.sender.userId != process.env.OWNER_ID) || (command.minPwr && event.sender.powerLevel < command.minPwr && event.sender.userId != process.env.OWNER_ID)) {
var addl = command.minPwr ? `this command requires a power level of ${command.minPwr}\nyour power level is ${event.sender.powerLevel}` : "this command is owner-only.";
if ((command.ownerOnly && event.sender.userId != process.env.OWNER_ID) || (command.minPowerLevel > 0 && event.sender.powerLevel < command.minPowerLevel && event.sender.userId != process.env.OWNER_ID)) {
var addl = command.minPowerLevel ? `this command requires a power level of ${command.minPowerLevel}\nyour power level is ${event.sender.powerLevel}` : "this command is owner-only.";
client.reply(event, addl, '<img src="mxc://nyx.ftp.sh/2kAXPyosdaz1M6Fv8t2V9SyxcJZEscdR" alt="nuh uh" /><br>' + addl.replaceAll("\n", "<br>"));
return true;
}
@ -107,35 +123,57 @@ function doCommand(client, event, cmd, args) {
return true;
}
async function verifyCallback(request) {
/** @param {import("matrix-js-sdk/lib/crypto-api.js").VerificationRequest} request */
client.verifyCallback = async function (request) {
console.log("### VERIFICATION ### Starting for " + request.otherUserId);
if (!request.initiatedByMe) {
await request.accept();
var verifier = await request.startVerification(VerificationMethod.Sas);
verifier.on(VerifierEvent.ShowSas, async function () {
console.log("### VERIFICATION ### Confirming");
await verifier.getShowSasCallbacks().confirm();
});
try {
var verifier = await request.startVerification(VerificationMethod.Sas);
verifier.on(VerifierEvent.ShowSas, async function () {
console.log("### VERIFICATION ### Confirming");
await verifier.getShowSasCallbacks().confirm();
});
verifier.on(VerifierEvent.Cancel, async function (e) {
console.log("### VERIFICATION ### ", e);
await client.sendMessage(request.roomId, {
body: format(e),
msgtype: sdk.MsgType.Text
})
});
} catch (err) {
client.sendMessage(request.roomId, {
body: err,
msgtype: sdk.MsgType.Notice
})
}
}
request.on(VerificationRequestEvent.Change, async function () {
switch (request.phase) {
case 3:
break;
case 4:
var verifier = await request.startVerification(VerificationMethod.Sas);
verifier.on(VerifierEvent.ShowSas, async function () {
console.log("### VERIFICATION ### Confirming");
await verifier.getShowSasCallbacks().confirm();
});
case 5:
console.log("### VERIFICATION ### Cancelled!");
case 6:
console.log("### VERIFICATION ### Done!");
break;
default:
console.log("### VERIFICATION ### " + request.phase);
break;
try {
switch (request.phase) {
case 3:
case 4:
var verifier = await request.startVerification(VerificationMethod.Sas);
verifier.on(VerifierEvent.ShowSas, async function () {
console.log("### VERIFICATION ### Confirming");
await verifier.getShowSasCallbacks().confirm();
});
case 5:
console.log("### VERIFICATION ### Cancelled!");
case 6:
console.log("### VERIFICATION ### Done!");
break;
default:
console.log("### VERIFICATION ### " + request.phase);
break;
}
} catch (err) {
client.sendMessage(request.roomId, {
body: err,
msgtype: sdk.MsgType.Notice
})
}
});
}
@ -149,15 +187,14 @@ client.once("sync", async function (state, prevState, data) {
prefixes.push(client.name + " ");
client.initialized = true;
while (!await client.getCrypto().isCrossSigningReady()) { }
var status = await client.getCrypto().getDeviceVerificationStatus(client.getUserId(), client.getDeviceId());
if (!status || Object.keys(status).map(v => status[v]).includes(false)) {
const request = await client.getCrypto().requestOwnUserVerification();
verifyCallback(request);
client.verifyCallback(request);
}
});
client.on(sdk.CryptoEvent.VerificationRequestReceived, verifyCallback);
client.on(sdk.CryptoEvent.VerificationRequestReceived, client.verifyCallback);
client.on(sdk.RoomEvent.Timeline, async function (event, room, toStartOfTimeline) {
await client.decryptEventIfNeeded(event);
@ -184,7 +221,7 @@ client.on(sdk.RoomEvent.Timeline, async function (event, room, toStartOfTimeline
}
if (!isCommand) {
doModule(client, event);
doModule(client, event)
} else {
var args = content.split(/\s/g);
var cmd = args.shift();

19
src/lib/base/command.js Normal file
View file

@ -0,0 +1,19 @@
import { MatrixClient, MatrixEvent } from "matrix-js-sdk";
import BaseEvent from "./event.js";
export default class BaseCommand extends BaseEvent {
command = "";
usage = "";
minPowerLevel = 0;
ownerOnly = false;
/**
* @param {MatrixClient} client
* @param {MatrixEvent} event
* @param {string} args
* @returns {Boolean} Success?
*/
async execute(client, event, args) {
throw new Error("Not implemented.");
}
}

7
src/lib/base/event.js Normal file
View file

@ -0,0 +1,7 @@
import { MatrixClient, MatrixEvent } from "matrix-js-sdk";
export default class BaseEvent {
name = "";
description = "";
hooks = {};
}

15
src/lib/base/module.js Normal file
View file

@ -0,0 +1,15 @@
import BaseEvent from "./event.js";
export default class BaseModule extends BaseEvent {
name = "";
description = "";
/**
* @param {MatrixClient} client
* @param {MatrixEvent} event
* @returns {Boolean} Success?
*/
async onMessage(client, event) {
}
}

79
src/modules/fedimbed.js Normal file
View file

@ -0,0 +1,79 @@
import fedimbed from "../lib/fedimbed.js";
import { encode } from "html-entities";
import { JSDOM } from "jsdom";
import util from "util";
import BaseModule from "../lib/base/module.js";
export default class FedimbedModule extends BaseModule {
name = "fedimbed";
description = "embed fediverse post contents";
async onMessage(client, event) {
const embed = await fedimbed(event.getContent().body);
if (!embed) return;
const dom = new JSDOM("<!DOCTYPE html><body></body>");
const document = dom.window.document;
var quote = document.createElement("blockquote");
if (!embed.embeds) {
var c = util.format(embed);
client.reply(event, c, `<pre><code>${encode(c)}</code></pre>`);
return;
}
for (const emb of embed.embeds) {
var link = document.createElement("a");
link.href = emb.url;
if (emb.thumbnail && emb.thumbnail.url) {
var avatar = document.createElement("img");
avatar.src = await client.uploadMedia(emb.thumbnail.url);
avatar.height = "16";
link.appendChild(avatar);
}
var linkText = document.createElement("span");
linkText.innerHTML = ((emb.thumbnail?.url) ? "&nbsp" : "") + emb.title;
link.appendChild(linkText);
quote.appendChild(link);
var text = document.createElement("p");
text.innerHTML = emb.description;
for (const emote of embed.emotes) {
console.log(text.innerHTML);
var img = document.createElement("img");
img.src = await client.uploadMedia(emote.url);
img.height = "16";
img.alt = emote.name;
text.innerHTML = text.innerHTML.replaceAll(emote.name, img.outerHTML);
}
quote.appendChild(text);
}
for (const file of embed.files) {
var media;
switch (file.type.split("/")[0]) {
case "audio":
media = document.createElement("audio");
break;
case "video":
media = document.createElement("video");
break;
case "image":
media = document.createElement("img");
break;
}
media.src = await client.uploadMedia(file.url);
media.alt = media.title = file.desc ?? "";
quote.appendChild(media);
}
document.body.appendChild(quote);
let x = document.createElement("small");
x.innerHTML = "Powered by <a href=\"https://gitdab.com/Cynosphere/HiddenPhox/src/branch/rewrite/src/modules/fedimbed.js\">HF Fedimbed</a>";
document.body.appendChild(x);
client.reply(event, "This message uses HTML, which your client does not support.", document.body.outerHTML);
}
}

48
src/modules/meow.js Normal file
View file

@ -0,0 +1,48 @@
import BaseModule from "../lib/base/module.js";
var meows = [
"mreow",
"miau",
"mewo",
"maow",
"mrow",
"mrao",
"meow",
"mew",
"nya",
];
var re = new RegExp("\\b(n+y+a+n*?|m+[re]*([yiaou]+[wu]+|w+))(ing|er|s)?\\b", "gi");
var emoticons = [
":3",
"^w^",
"=^w^=",
"-w-",
":333"
];
export default class MeowModule extends BaseModule {
name = "meow";
description = ":33";
async onMessage(client, event) {
var content = event.getContent();
if (content["m.new_content"] != null) return;
for (const meow of meows) {
if (re.test(content.body.toLowerCase())) {
var reply = meows.random();
reply += "!".repeat(Math.random() * 5)
if (Math.random() > 0.5) {
reply += " " + emoticons.random();
}
client.reply(event, reply);
break;
}
}
}
}