diff --git a/commands/catgpt.js b/commands/catgpt.js deleted file mode 100644 index b8f27e1..0000000 --- a/commands/catgpt.js +++ /dev/null @@ -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 -} diff --git a/commands/eval.js b/commands/eval.js deleted file mode 100644 index d2b99af..0000000 --- a/commands/eval.js +++ /dev/null @@ -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, `
${encode(c)}
`);
-}
-
-export default {
- command: "eval",
- name: "eval",
- usage: "",
- owner: true,
- desc: "run JS code and reply with the result",
- execute
-}
diff --git a/commands/help.js b/commands/help.js
deleted file mode 100644
index 5dc7ee7..0000000
--- a/commands/help.js
+++ /dev/null
@@ -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 = `${encode(module.name)}
` +
- `${encode(module.desc)}`;
-
- client.reply(event, reply, replyHTML);
- return;
- }
-
- var reply = command.name + "\n" +
- command.desc + "\n\n" +
- command.usage;
-
- var replyHTML = `${encode(command.name)}
` +
- `${encode(command.desc)}` +
- `
${encode(command.usage)}
`;
-
- 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 for more information.`;
-
- var replyHTML = `commands: ${client.commands.map(m => encode(m.name)).join("
, ")}
` +
- `modules: ${client.modules.map(m => encode(m.name)).join("
, ")}
` +
- encode(`run ${process.env.PREFIX}help for more information.`);
-
- client.reply(event, reply, replyHTML);
-}
-
-export default {
- command: "help",
- name: "help",
- desc: "show list of commands and modules",
- execute
-}
diff --git a/commands/info.js b/commands/info.js
deleted file mode 100644
index 8caed69..0000000
--- a/commands/info.js
+++ /dev/null
@@ -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
-}
diff --git a/commands/join.js b/commands/join.js
deleted file mode 100644
index beec0e8..0000000
--- a/commands/join.js
+++ /dev/null
@@ -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
-}
diff --git a/commands/restart.js b/commands/restart.js
deleted file mode 100644
index 491d7f3..0000000
--- a/commands/restart.js
+++ /dev/null
@@ -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
-}
diff --git a/commands/toggle.js b/commands/toggle.js
deleted file mode 100644
index 05b79a5..0000000
--- a/commands/toggle.js
+++ /dev/null
@@ -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 = `${state} ${encode(module.name)}
`;
-
- 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:
${enabled.join("
, ")}
`;
-
- reply += `\navailable modules:\n${modules.join(", ")}`;
- replyHTML += `
available modules:
${modules.join("
, ")}
`;
-
- client.reply(event, reply, replyHTML);
-}
-
-export default {
- command: "toggle",
- name: "toggle",
- usage: "",
- minPwr: 50,
- desc: "toggle a module on or off in current channel",
- execute
-}
diff --git a/modules/fedimbed.js b/modules/fedimbed.js
deleted file mode 100644
index 13dc91c..0000000
--- a/modules/fedimbed.js
+++ /dev/null
@@ -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("");
- const document = dom.window.document;
- var quote = document.createElement("blockquote");
- if(!embed.embeds) {
- var c = util.format(embed);
- client.reply(event, c, `${encode(c)}
`);
- 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) ? " " : "") + 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 HF Fedimbed";
- 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
- }
-}
diff --git a/modules/meow.js b/modules/meow.js
deleted file mode 100644
index f16439f..0000000
--- a/modules/meow.js
+++ /dev/null
@@ -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
- }
-}
diff --git a/package.json b/package.json
index 3160e8d..426a0c2 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/auth-fetch.js b/src/auth-fetch.js
similarity index 100%
rename from auth-fetch.js
rename to src/auth-fetch.js
diff --git a/src/commands/catgpt.js b/src/commands/catgpt.js
new file mode 100644
index 0000000..fd82da9
--- /dev/null
+++ b/src/commands/catgpt.js
@@ -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();
\ No newline at end of file
diff --git a/src/commands/eval.js b/src/commands/eval.js
new file mode 100644
index 0000000..7d33cb9
--- /dev/null
+++ b/src/commands/eval.js
@@ -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 = "";
+ 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, `${encode(c)}
`);
+ }
+}
+
+export default new EvalCommand();
\ No newline at end of file
diff --git a/src/commands/help.js b/src/commands/help.js
new file mode 100644
index 0000000..a8e8ff1
--- /dev/null
+++ b/src/commands/help.js
@@ -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 = `${encode(module.name)}
` +
+ `${encode(module.desc)}`;
+
+ 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 = `${encode(command.name)}
` +
+ `${encode(command.desc)}` +
+ `
${encode(command.usage)}
`;
+
+ 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 for more information.`;
+
+ var replyHTML = `commands: ${client.commands.map(m => encode(m.name)).join("
, ")}
` +
+ `modules: ${client.modules.map(m => encode(m.name)).join("
, ")}
` +
+ encode(`run ${process.env.PREFIX}help for more information.`);
+
+ client.reply(event, reply, replyHTML);
+ }
+}
+
+export default new HelpCommand();
\ No newline at end of file
diff --git a/src/commands/info.js b/src/commands/info.js
new file mode 100644
index 0000000..4c6a178
--- /dev/null
+++ b/src/commands/info.js
@@ -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();
\ No newline at end of file
diff --git a/src/commands/join.js b/src/commands/join.js
new file mode 100644
index 0000000..c60dc84
--- /dev/null
+++ b/src/commands/join.js
@@ -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();
\ No newline at end of file
diff --git a/src/commands/restart.js b/src/commands/restart.js
new file mode 100644
index 0000000..bcac3dc
--- /dev/null
+++ b/src/commands/restart.js
@@ -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();
\ No newline at end of file
diff --git a/src/commands/toggle.js b/src/commands/toggle.js
new file mode 100644
index 0000000..966e2d2
--- /dev/null
+++ b/src/commands/toggle.js
@@ -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 = "";
+ 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 = `${state} ${encode(module.name)}
`;
+
+ 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:
${enabled.join("
, ")}
`;
+
+ reply += `\navailable modules:\n${modules.join(", ")}`;
+ replyHTML += `
available modules:
${modules.join("
, ")}
`;
+
+ client.reply(event, reply, replyHTML);
+ }
+}
+
+export default new ToggleCommand();
\ No newline at end of file
diff --git a/index.js b/src/index.js
similarity index 60%
rename from index.js
rename to src/index.js
index c181b3b..cae8913 100644
--- a/index.js
+++ b/src/index.js
@@ -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, '
' + addl.replaceAll("\n", "
"));
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();
diff --git a/src/lib/base/command.js b/src/lib/base/command.js
new file mode 100644
index 0000000..4a8f675
--- /dev/null
+++ b/src/lib/base/command.js
@@ -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.");
+ }
+}
\ No newline at end of file
diff --git a/src/lib/base/event.js b/src/lib/base/event.js
new file mode 100644
index 0000000..e80fde5
--- /dev/null
+++ b/src/lib/base/event.js
@@ -0,0 +1,7 @@
+import { MatrixClient, MatrixEvent } from "matrix-js-sdk";
+
+export default class BaseEvent {
+ name = "";
+ description = "";
+ hooks = {};
+}
\ No newline at end of file
diff --git a/src/lib/base/module.js b/src/lib/base/module.js
new file mode 100644
index 0000000..bf1abd9
--- /dev/null
+++ b/src/lib/base/module.js
@@ -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) {
+
+ }
+}
\ No newline at end of file
diff --git a/lib/ext.js b/src/lib/ext.js
similarity index 100%
rename from lib/ext.js
rename to src/lib/ext.js
diff --git a/lib/fedimbed.js b/src/lib/fedimbed.js
similarity index 100%
rename from lib/fedimbed.js
rename to src/lib/fedimbed.js
diff --git a/login.js b/src/login.js
similarity index 100%
rename from login.js
rename to src/login.js
diff --git a/src/modules/fedimbed.js b/src/modules/fedimbed.js
new file mode 100644
index 0000000..0e9e99f
--- /dev/null
+++ b/src/modules/fedimbed.js
@@ -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("");
+ const document = dom.window.document;
+ var quote = document.createElement("blockquote");
+ if (!embed.embeds) {
+ var c = util.format(embed);
+ client.reply(event, c, `${encode(c)}
`);
+ 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) ? " " : "") + 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 HF Fedimbed";
+ document.body.appendChild(x);
+
+ client.reply(event, "This message uses HTML, which your client does not support.", document.body.outerHTML);
+ }
+}
\ No newline at end of file
diff --git a/src/modules/meow.js b/src/modules/meow.js
new file mode 100644
index 0000000..aa06962
--- /dev/null
+++ b/src/modules/meow.js
@@ -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;
+ }
+ }
+ }
+}
\ No newline at end of file