initial commit
This commit is contained in:
commit
eaec14f4fb
14 changed files with 1987 additions and 0 deletions
7
.env.example
Normal file
7
.env.example
Normal file
|
@ -0,0 +1,7 @@
|
|||
PREFIX=!
|
||||
BASE_URL=https://example.com
|
||||
OWNER_ID=@root:example.com
|
||||
USER_ID=@bot:example.com
|
||||
ACCESS_TOKEN=1234567890
|
||||
DEVICE_ID=Bot-Device
|
||||
LOG_CHANNEL=!1234567890:example.com
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.env
|
||||
node_modules
|
||||
data/*
|
41
commands/catgpt.js
Normal file
41
commands/catgpt.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
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
|
||||
}
|
22
commands/eval.js
Normal file
22
commands/eval.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { encode } from "html-entities";
|
||||
import util from "util";
|
||||
|
||||
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
|
||||
}
|
55
commands/help.js
Normal file
55
commands/help.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
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
|
||||
}
|
16
commands/info.js
Normal file
16
commands/info.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
function execute(client, event, args) {
|
||||
var info = `${client.name}\n\n`;
|
||||
info += `Commands: ${client.commands.length}\n`;
|
||||
info += `Modules: ${client.commands.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
|
||||
}
|
13
commands/restart.js
Normal file
13
commands/restart.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { exec } from "node:child_process";
|
||||
|
||||
function execute(client, event, args) {
|
||||
exec("systemctl --user restart possumbot");
|
||||
}
|
||||
|
||||
export default {
|
||||
command: "restart",
|
||||
name: "restart",
|
||||
owner: true,
|
||||
desc: "restarts the bot",
|
||||
execute
|
||||
}
|
126
index.js
Normal file
126
index.js
Normal file
|
@ -0,0 +1,126 @@
|
|||
import { encode } from "html-entities";
|
||||
import * as sdk from "matrix-js-sdk";
|
||||
import sdkExt from "./lib/ext.js";
|
||||
import { resolve } from "node:path";
|
||||
import fs from "node:fs";
|
||||
import util from "util";
|
||||
|
||||
import fetch from "node-fetch";
|
||||
global.fetch = fetch;
|
||||
|
||||
import Olm from "@matrix-org/olm";
|
||||
global.Olm = Olm;
|
||||
|
||||
import env from "dotenv";
|
||||
env.config();
|
||||
|
||||
const client = sdk.createClient({
|
||||
baseUrl: process.env.BASE_URL,
|
||||
accessToken: process.env.ACCESS_TOKEN,
|
||||
deviceId: process.env.DEVICE_ID,
|
||||
userId: process.env.USER_ID
|
||||
});
|
||||
|
||||
sdkExt(client);
|
||||
|
||||
var prefixes = [process.env.PREFIX];
|
||||
client.initialized = false;
|
||||
|
||||
client.modules = [];
|
||||
client.commands = [];
|
||||
|
||||
for (const file of fs.readdirSync(resolve("modules"))) {
|
||||
try {
|
||||
if(file.startsWith(".")) continue;
|
||||
var module = (await import(resolve("modules", file))).default;
|
||||
client.modules.push(module);
|
||||
client.log("[load:modules]", `loaded ${module.name}`);
|
||||
} catch (err) {
|
||||
client.error("[load:modules]", `failed to load "${file}":\n`, err);
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of fs.readdirSync(resolve("commands"))) {
|
||||
try {
|
||||
if(file.startsWith(".")) continue;
|
||||
var command = (await import(resolve("commands", file))).default;
|
||||
command.usage = process.env.PREFIX + command.command + (command.usage ? " " + command.usage : '');
|
||||
client.commands.push(command);
|
||||
client.log("[load:commands]", `loaded ${command.name}`);
|
||||
} catch (err) {
|
||||
client.error("[load:commands]", `failed to load "${file}":`, err);
|
||||
}
|
||||
}
|
||||
|
||||
function doModule(client, event) {
|
||||
client.modules.forEach(m => {
|
||||
if(!m) return;
|
||||
m.hooks?.message(client, event);
|
||||
});
|
||||
}
|
||||
|
||||
function doCommand(client, event, cmd, args) {
|
||||
var command;
|
||||
command = client.commands.filter(c=>c.command==cmd)[0];
|
||||
if(!command)
|
||||
return false;
|
||||
|
||||
if(command.owner && event.sender.userId != process.env.OWNER_ID) {
|
||||
client.reply(event, "nuh uh", '<img src="mxc://possum.city/cu5mPRM1ITiJZQRgAyzJXDz22jN6TBo9" alt="nuh uh" />');
|
||||
return true;
|
||||
}
|
||||
|
||||
command.execute(client, event, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
client.once("sync", async function (state, prevState, data) {
|
||||
switch (state) {
|
||||
case "PREPARED":
|
||||
client.name = client._store.users[client.credentials.userId].displayName;
|
||||
client.log("[sdk:sync]", "connected:", client.name);
|
||||
prefixes.push(client.name + ": ");
|
||||
prefixes.push(client.name + " ");
|
||||
client.initialized = true;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
client.on(sdk.RoomEvent.Timeline, async function (event, room, toStartOfTimeline) {
|
||||
if (!client.initialized || toStartOfTimeline || event.getType() !== "m.room.message" || event.sender.userId == client.credentials.userId) {
|
||||
return;
|
||||
}
|
||||
if(event.event.content["m.relates_to"] != null)
|
||||
event.event.content.body = event.event.content.body.substring(event.event.content.body.indexOf("\n\n") + 2);
|
||||
|
||||
var content = event.event.content.body;
|
||||
var isCommand = false;
|
||||
for(const prefix of prefixes) {
|
||||
if(content.startsWith(prefix)) {
|
||||
isCommand = true;
|
||||
content = content.substring(prefix.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!isCommand) {
|
||||
doModule(client, event);
|
||||
} else {
|
||||
var args = content.split(/\s/g);
|
||||
var cmd = args.shift();
|
||||
args = content.substring(cmd.length + 1);
|
||||
if(!doCommand(client, event, cmd, args)) {
|
||||
client.reply(event, `Command "${cmd}" not found.\nRun "${process.env.PREFIX}help" for a list of commands.`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.on("Room.myMembership", function (room, membership, prevMembership) {
|
||||
if (membership === "invite") {
|
||||
client.joinRoom(room.roomId).then(function () {
|
||||
client.log("[client:autojoin] joined %s", room.roomId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//await client.initCrypto();
|
||||
await client.startClient();
|
107
lib/ext.js
Normal file
107
lib/ext.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
import { encode } from "html-entities";
|
||||
import forceSync from 'sync-rpc';
|
||||
import { JSDOM } from "jsdom";
|
||||
import util from "util";
|
||||
import fs from "fs";
|
||||
|
||||
Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)]}
|
||||
|
||||
var cache = {};
|
||||
var log = null;
|
||||
|
||||
export default function(client) {
|
||||
client.logEvent = null;
|
||||
|
||||
client.cache = {
|
||||
get: (key) => {
|
||||
return cache[key] ?? null;
|
||||
},
|
||||
set: (key, value) => {
|
||||
cache[key] = value;
|
||||
fs.writeFileSync("data/cache.json", JSON.stringify(cache));
|
||||
}
|
||||
}
|
||||
|
||||
client.reply = function(event, text, html) {
|
||||
var mcontent = {
|
||||
body: "> <" + event.sender.userId + "> " + event.event.content.body.split("\n")[0] + "\n\n" + text.trim(),
|
||||
msgtype: "m.notice",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": event.event.event_id
|
||||
}
|
||||
}
|
||||
};
|
||||
if(html) {
|
||||
mcontent = {
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "<mx-reply><blockquote><a href=\"https://m.posm.gay/#/" + event.event.room_id + "/" + event.event.event_id + "?via=possum.city\">In reply to</a> <a href=\"https://m.posm.gay/#/" + event.sender.userId + "\">" + event.sender.userId + "</a><br>" + encode(event.event.content.body.split("\n")[0]) + "</blockquote></mx-reply>" + html.trim(),
|
||||
...mcontent
|
||||
}
|
||||
}
|
||||
client.sendEvent(event.event.room_id, "m.room.message", mcontent, "", (err, res) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
client.logData = [];
|
||||
client.startup = new Date();
|
||||
|
||||
client.updateLog = async function() {
|
||||
if(log && (log.body == client.logData.join("\n") || log["m.new_content"]?.body == client.logData.join("\n"))) {
|
||||
setTimeout(client.updateLog, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
var mcontent = {
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: `<pre><code>[client:logger] started: ${client.startup}\n${encode(client.logData.join("\n"))}</code></pre>`,
|
||||
body: client.logData.join("\n"),
|
||||
msgtype: "m.notice"
|
||||
}
|
||||
|
||||
if(!client.logEvent) {
|
||||
log = mcontent;
|
||||
} else {
|
||||
log["m.new_content"] = mcontent;
|
||||
log["m.relates_to"] = {
|
||||
rel_type: "m.replace",
|
||||
event_id: client.logEvent
|
||||
}
|
||||
}
|
||||
|
||||
var x = await client.sendEvent(process.env.LOG_CHANNEL, "m.room.message", log, "", (err, res) => {
|
||||
console.log("[client:log]", res);
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
client.logEvent = client.logEvent ?? x.event_id;
|
||||
|
||||
setTimeout(client.updateLog, 1000);
|
||||
}
|
||||
|
||||
client.log = function() {
|
||||
var data = util.format.apply(null, arguments);
|
||||
client.logData.push(data);
|
||||
console.log(data);
|
||||
}
|
||||
|
||||
client.error = client.log;
|
||||
|
||||
if(fs.existsSync("data/cache.json")) {
|
||||
var data = fs.readFileSync("data/cache.json");
|
||||
|
||||
try {
|
||||
cache = JSON.parse(data);
|
||||
client.log("[sdkext:cache]", 'loaded', Object.keys(cache).length, 'cache entries!');
|
||||
} catch(err) {
|
||||
client.error("[sdkext:cache]", err);
|
||||
}
|
||||
}
|
||||
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.error('[core:err]', err);
|
||||
});
|
||||
|
||||
client.updateLog();
|
||||
}
|
597
lib/fedimbed.js
Normal file
597
lib/fedimbed.js
Normal file
|
@ -0,0 +1,597 @@
|
|||
import httpSignature from "@peertube/http-signature";
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
|
||||
const FRIENDLY_USERAGENT = "PossumBot/1.0 (+https://bot.possum.city/)";
|
||||
|
||||
const URLS_REGEX = /(?:\s|^|\]\()(\|\|\s*)?(https?:\/\/[^\s<]+[^<.,:;"'\]|)\s])(\s*\)?\|\||\s*[\S]*?\))?/g;
|
||||
|
||||
const PATH_REGEX = {
|
||||
mastodon: /^\/@(.+?)\/(\d+)\/?/,
|
||||
mastodon2: /^\/(.+?)\/statuses\/\d+\/?/,
|
||||
pleroma: /^\/objects\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/?/,
|
||||
pleroma2: /^\/notice\/[A-Za-z0-9]+\/?/,
|
||||
misskey: /^\/notes\/[a-z0-9]+\/?/,
|
||||
gotosocial: /^\/@(.+?)\/statuses\/[0-9A-Z]+\/?/,
|
||||
lemmy: /^\/post\/\d+\/?/,
|
||||
honk: /^\/u\/(.+?)\/h\/(.+?)\/?/,
|
||||
cohost: /^\/[A-Za-z0-9]+\/post\/\d+-[A-Za-z0-9-]+\/?/,
|
||||
};
|
||||
|
||||
const PLATFORM_COLORS = {
|
||||
mastodon: 0x2791da,
|
||||
pleroma: 0xfba457,
|
||||
akkoma: 0x593196,
|
||||
misskey: 0x99c203,
|
||||
calckey: 0x31748f,
|
||||
firefish: 0xf07a5b, // YCbCr interpolated from the two logo colors
|
||||
gotosocial: 0xff853e,
|
||||
lemmy: 0x14854f,
|
||||
birdsitelive: 0x1da1f2,
|
||||
iceshrimp: 0x8e82f9, // YCbCr interpolated as the accent color is a gradient
|
||||
cohost: 0x83254f,
|
||||
};
|
||||
|
||||
const domainCache = new Map();
|
||||
domainCache.set("cohost.org", "cohost"); // no nodeinfo
|
||||
|
||||
async function resolvePlatform(url) {
|
||||
const urlObj = new URL(url);
|
||||
if(domainCache.has(urlObj.hostname)) return domainCache.get(urlObj.hostname);
|
||||
|
||||
const res = await fetch(urlObj.origin + "/.well-known/nodeinfo", {
|
||||
headers: {"User-Agent": FRIENDLY_USERAGENT},
|
||||
}).then((res) => res.text());
|
||||
|
||||
if(!res.startsWith("{")) {
|
||||
console.error("[fedimbed]", `No nodeinfo for "${urlObj.hostname}"???`);
|
||||
domainCache.set(urlObj.hostname, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
const probe = JSON.parse(res);
|
||||
|
||||
if(!probe?.links) {
|
||||
console.error("[fedimbed]", `No nodeinfo for "${urlObj.hostname}"???`);
|
||||
domainCache.set(urlObj.hostname, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
const nodeinfo = await fetch(probe.links[probe.links.length - 1].href, {
|
||||
headers: {"User-Agent": FRIENDLY_USERAGENT},
|
||||
}).then((res) => res.json());
|
||||
|
||||
if(!nodeinfo?.software?.name) {
|
||||
console.error("[fedimbed]", `Got nodeinfo for "${urlObj.hostname}", but missing software name.`);
|
||||
domainCache.set(urlObj.hostname, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
domainCache.set(urlObj.hostname, nodeinfo.software.name);
|
||||
return nodeinfo.software.name;
|
||||
}
|
||||
|
||||
const keyId = "https://bot.possum.city/actor#main-key";
|
||||
const privKey = fs.readFileSync("data/private.pem");
|
||||
async function signedFetch(url, options) {
|
||||
const urlObj = new URL(url);
|
||||
|
||||
const headers = {
|
||||
host: urlObj.host,
|
||||
date: new Date().toUTCString(),
|
||||
};
|
||||
|
||||
const headerNames = ["(request-target)", "host", "date"];
|
||||
|
||||
httpSignature.sign(
|
||||
{
|
||||
getHeader: (name) => headers[name.toLowerCase()],
|
||||
setHeader: (name, value) => (headers[name] = value),
|
||||
method: options.method ?? "GET",
|
||||
path: urlObj.pathname,
|
||||
},
|
||||
{
|
||||
keyId,
|
||||
key: privKey,
|
||||
headers: headerNames,
|
||||
authorizationHeaderName: "signature",
|
||||
}
|
||||
);
|
||||
|
||||
options.headers = Object.assign(headers, options.headers ?? {});
|
||||
|
||||
return await fetch(url, options);
|
||||
}
|
||||
|
||||
async function processUrl(url) {
|
||||
let spoiler = false;
|
||||
let invalidUrl = false;
|
||||
let urlObj;
|
||||
try {
|
||||
urlObj = new URL(url);
|
||||
} catch(err) {
|
||||
console.error("[fedimbed]", err);
|
||||
invalidUrl = true;
|
||||
}
|
||||
|
||||
if(invalidUrl) return {};
|
||||
|
||||
// some lemmy instances have old reddit frontend subdomains
|
||||
// but these frontends are just frontends and dont actually expose the API
|
||||
if(urlObj.hostname.startsWith("old.")) {
|
||||
urlObj.hostname = urlObj.hostname.replace("old.", "");
|
||||
url = urlObj.href;
|
||||
}
|
||||
|
||||
let platform = (await resolvePlatform(url)) ?? "<no nodeinfo>";
|
||||
let color = PLATFORM_COLORS[platform];
|
||||
let platformName = platform
|
||||
.replace("gotosocial", "GoToSocial")
|
||||
.replace("birdsitelive", '"Twitter" (BirdsiteLive)')
|
||||
.replace(/^(.)/, (_, c) => c.toUpperCase())
|
||||
.replace("Cohost", "cohost");
|
||||
|
||||
const files = [];
|
||||
let content,
|
||||
cw,
|
||||
author,
|
||||
timestamp,
|
||||
title,
|
||||
poll,
|
||||
emotes = [],
|
||||
sensitive = false;
|
||||
|
||||
// Fetch post
|
||||
let rawPostData;
|
||||
try {
|
||||
rawPostData = await signedFetch(url, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
},
|
||||
}).then((res) => res.text());
|
||||
} catch (err) {
|
||||
console.error("[fedimbed]", `Failed to signed fetch "${url}", retrying unsigned: ${err}`);
|
||||
}
|
||||
if(!rawPostData) {
|
||||
try {
|
||||
rawPostData = await fetch(url, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
},
|
||||
}).then((res) => res.text());
|
||||
} catch (err) {
|
||||
console.error("[fedimbed]", `Failed to fetch "${url}": ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
let postData;
|
||||
if(rawPostData?.startsWith("{")) {
|
||||
try {
|
||||
postData = JSON.parse(rawPostData);
|
||||
} catch (err) {
|
||||
console.error("[fedimbed]", `Failed to decode JSON for "${url}": ${err}\n "${rawPostData}"`);
|
||||
}
|
||||
} else {
|
||||
console.warn("[fedimbed]", `Got non-JSON for "${url}": ${rawPostData}`);
|
||||
}
|
||||
|
||||
if(postData?.error) {
|
||||
console.error("[fedimbed]", `Received error for "${url}": ${postData.error}`);
|
||||
console.error("[fedimbed]", postData);
|
||||
return postData;
|
||||
}
|
||||
|
||||
if(!postData) {
|
||||
// We failed to get post.
|
||||
// Assume it was due to AFM or forced HTTP signatures and use MastoAPI
|
||||
|
||||
// Follow redirect from /object since we need the ID from /notice
|
||||
if(PATH_REGEX.pleroma.test(urlObj.pathname)) {
|
||||
url = await signedFetch(url, {
|
||||
method: "HEAD",
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
},
|
||||
redirect: "manual",
|
||||
}).then((res) => res.headers.get("location"));
|
||||
if(url.startsWith("/")) {
|
||||
url = urlObj.origin + url;
|
||||
}
|
||||
urlObj = new URL(url);
|
||||
}
|
||||
|
||||
let redirUrl;
|
||||
const options = {};
|
||||
const headers = {};
|
||||
if(PATH_REGEX.pleroma2.test(urlObj.pathname)) {
|
||||
redirUrl = url.replace("notice", "api/v1/statuses");
|
||||
} else if(PATH_REGEX.mastodon.test(urlObj.pathname)) {
|
||||
const postId = urlObj.pathname.match(PATH_REGEX.mastodon)?.[2];
|
||||
redirUrl = urlObj.origin + "/api/v1/statuses/" + postId;
|
||||
} else if(PATH_REGEX.mastodon2.test(urlObj.pathname)) {
|
||||
redirUrl = url.replace(/^\/(.+?)\/statuses/, "/api/v1/statuses");
|
||||
} else if(PATH_REGEX.misskey.test(urlObj.pathname)) {
|
||||
let noteId = url.split("/notes/")[1];
|
||||
if(noteId.indexOf("/") > -1) {
|
||||
noteId = noteId.split("/")[0];
|
||||
} else if(noteId.indexOf("?") > -1) {
|
||||
noteId = noteId.split("?")[0];
|
||||
} else if(noteId.indexOf("#") > -1) {
|
||||
noteId = noteId.split("#")[0];
|
||||
}
|
||||
console.log("[fedimbed]", "Misskey post ID: " + noteId);
|
||||
redirUrl = urlObj.origin + "/api/notes/show/";
|
||||
options.method = "POST";
|
||||
options.body = JSON.stringify({noteId});
|
||||
headers["Content-Type"] = "application/json";
|
||||
} else {
|
||||
console.error("[fedimbed]", `Missing MastoAPI replacement for "${platform}"`);
|
||||
}
|
||||
|
||||
if(redirUrl) {
|
||||
console.log(
|
||||
"[fedimbed]",
|
||||
`Redirecting "${url}" to "${redirUrl}": ${JSON.stringify(options)}, ${JSON.stringify(headers)}`
|
||||
);
|
||||
let rawPostData2;
|
||||
try {
|
||||
rawPostData2 = await signedFetch(
|
||||
redirUrl,
|
||||
Object.assign(options, {
|
||||
headers: Object.assign(headers, {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
}),
|
||||
})
|
||||
).then((res) => res.text());
|
||||
} catch (err) {
|
||||
console.error("[fedimbed]", `Failed to signed fetch "${url}" via MastoAPI, retrying unsigned: ${err}`);
|
||||
}
|
||||
if(!rawPostData2) {
|
||||
try {
|
||||
rawPostData2 = await signedFetch(
|
||||
redirUrl,
|
||||
Object.assign(options, {
|
||||
headers: Object.assign(headers, {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
}),
|
||||
})
|
||||
).then((res) => res.text());
|
||||
} catch (err) {
|
||||
console.error("[fedimbed]", `Failed to fetch "${url}" via MastoAPI: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
let postData2;
|
||||
if(rawPostData2?.startsWith("{")) {
|
||||
postData2 = JSON.parse(rawPostData2);
|
||||
} else {
|
||||
console.warn("[fedimbed]", `Got non-JSON for "${url}" via MastoAPI: ${rawPostData2}`);
|
||||
}
|
||||
|
||||
if(!postData2) {
|
||||
console.warn("[fedimbed]", `Bailing trying to re-embed "${url}": Failed to get post from normal and MastoAPI.`);
|
||||
} else if(postData2.error) {
|
||||
console.error(
|
||||
"[fedimbed]",
|
||||
`Bailing trying to re-embed "${url}", MastoAPI gave us error: ${JSON.stringify(postData2.error)}`
|
||||
);
|
||||
} else {
|
||||
cw = postData2.spoiler_warning ?? postData2.spoiler_text ?? postData2.cw;
|
||||
content =
|
||||
postData2.akkoma?.source?.content ??
|
||||
postData2.pleroma?.content?.["text/plain"] ??
|
||||
postData2.text ??
|
||||
postData2.content;
|
||||
author = {
|
||||
name:
|
||||
postData2.account?.display_name ??
|
||||
postData2.account?.username ??
|
||||
postData2.user?.name ??
|
||||
postData2.user?.username,
|
||||
handle:
|
||||
postData2.account?.fqn ?? `${postData2.account?.username ?? postData2.user?.username}@${urlObj.hostname}`,
|
||||
url: postData2.account?.url ?? `${urlObj.origin}/@${postData2.account?.username ?? postData2.user?.username}`,
|
||||
avatar: postData2.account?.avatar ?? postData2.user?.avatarUrl,
|
||||
};
|
||||
timestamp = postData2.created_at ?? postData2.createdAt;
|
||||
emotes = postData2.emojis.filter((x) => !x.name.endsWith("@.")).map((x) => ({name: `:${x.name}:`, url: x.url}));
|
||||
sensitive = postData2.sensitive;
|
||||
|
||||
const attachments = postData2.media_attachments ?? postData2.files;
|
||||
if(attachments) {
|
||||
for(const attachment of attachments) {
|
||||
const contentType = await fetch(attachment.url, {
|
||||
method: "HEAD",
|
||||
}).then((res) => res.headers.get("Content-Type"));
|
||||
|
||||
if(contentType) {
|
||||
if(contentType.startsWith("image/") || contentType.startsWith("video/") || contentType.startsWith("audio/")) {
|
||||
files.push({
|
||||
url: attachment.url,
|
||||
desc: attachment.description ?? attachment.comment,
|
||||
type: contentType,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const type = attachment.type?.toLowerCase();
|
||||
|
||||
const fileType =
|
||||
attachment.pleroma?.mime_type ?? type.indexOf("/") > -1
|
||||
? type
|
||||
: type +
|
||||
"/" +
|
||||
(url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? type == "image"
|
||||
? "png"
|
||||
: type == "video"
|
||||
? "mp4"
|
||||
: "mpeg");
|
||||
if(type.startsWith("image") || type.startsWith("video") || type.startsWith("audio")) {
|
||||
files.push({
|
||||
url: attachment.url,
|
||||
desc: attachment.description ?? attachment.comment,
|
||||
type: fileType,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(postData2.sensitive && attachments.length > 0) {
|
||||
spoiler = true;
|
||||
}
|
||||
|
||||
if(postData2.poll) {
|
||||
poll = {
|
||||
end: new Date(postData2.poll.expires_at),
|
||||
total: postData2.poll.votes_count,
|
||||
options: postData2.poll.options.map((o) => ({
|
||||
name: o.title,
|
||||
count: o.votes_count,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(postData.id) {
|
||||
const realUrlObj = new URL(postData.id);
|
||||
if(realUrlObj.origin != urlObj.origin) {
|
||||
platform = await resolvePlatform(postData.id);
|
||||
color = PLATFORM_COLORS[platform];
|
||||
platformName = platform.replace("gotosocial", "GoToSocial").replace(/^(.)/, (_, c) => c.toUpperCase());
|
||||
url = postData.id;
|
||||
}
|
||||
}
|
||||
|
||||
content = postData._misskey_content ?? postData.source?.content ?? postData.content;
|
||||
cw = postData.summary;
|
||||
timestamp = postData.published;
|
||||
sensitive = postData.sensitive;
|
||||
|
||||
if(postData.tag) {
|
||||
let tag = postData.tag;
|
||||
// gts moment
|
||||
if(!Array.isArray(tag)) tag = [tag];
|
||||
emotes = tag.filter((x) => !!x.icon).map((x) => ({name: x.name, url: x.icon.url}));
|
||||
}
|
||||
|
||||
// NB: gts doesnt send singular attachments as array
|
||||
const attachments = Array.isArray(postData.attachment) ? postData.attachment : [postData.attachment];
|
||||
for(const attachment of attachments) {
|
||||
if(!attachment) continue;
|
||||
if(attachment.mediaType) {
|
||||
if(attachment.mediaType.startsWith("video/") || attachment.mediaType.startsWith("image/") || attachment.mediaType.startsWith("audio/")) {
|
||||
files.push({
|
||||
url: attachment.url,
|
||||
desc: attachment.name ?? attachment.description ?? attachment.comment,
|
||||
type: attachment.mediaType,
|
||||
});
|
||||
}
|
||||
} else if(attachment.url) {
|
||||
const contentType = await fetch(attachment.url, {
|
||||
method: "HEAD",
|
||||
}).then((res) => res.headers.get("Content-Type"));
|
||||
|
||||
if(contentType) {
|
||||
if(contentType.startsWith("image/") || contentType.startsWith("video/") || contentType.startsWith("audio/")) {
|
||||
files.push({
|
||||
url: attachment.url,
|
||||
desc: attachment.name ?? attachment.description ?? attachment.comment,
|
||||
type: contentType,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const type = attachment.type?.toLowerCase();
|
||||
|
||||
const fileType =
|
||||
type.indexOf("/") > -1
|
||||
? type
|
||||
: type +
|
||||
"/" +
|
||||
(url.match(/\.([a-z0-9]{3,4})$/)?.[0] ?? type == "image" ? "png" : type == "video" ? "mp4" : "mpeg");
|
||||
if(type.startsWith("image") || type.startsWith("video") || type.startsWith("audio")) {
|
||||
files.push({
|
||||
url: attachment.url,
|
||||
desc: attachment.name ?? attachment.description ?? attachment.comment,
|
||||
type: fileType,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn("[fedimbed]", `Unhandled attachment structure! ${JSON.stringify(attachment)}`);
|
||||
}
|
||||
}
|
||||
|
||||
if(postData.sensitive && attachments.length > 0) {
|
||||
spoiler = true;
|
||||
}
|
||||
|
||||
if(postData.image?.url) {
|
||||
const imageUrl = new URL(postData.image.url);
|
||||
const contentType = await fetch(postData.image.url, {
|
||||
method: "HEAD",
|
||||
}).then((res) => res.headers.get("Content-Type"));
|
||||
files.push({
|
||||
url: postData.image.url,
|
||||
desc: "",
|
||||
type: contentType ?? "image/" + imageUrl.pathname.substring(imageUrl.pathname.lastIndexOf(".") + 1),
|
||||
});
|
||||
}
|
||||
|
||||
if(postData.name) title = postData.name;
|
||||
|
||||
// Author data is not sent with the post with AS2
|
||||
const authorData = await signedFetch(postData.actor ?? postData.attributedTo, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.catch((err) => {
|
||||
// only posts can be activity+json right now, reduce log spam
|
||||
if(platform !== "cohost") console.error("[fedimbed]", `Failed to get author for "${url}": ${err}`);
|
||||
});
|
||||
|
||||
if(authorData) {
|
||||
const authorUrlObj = new URL(authorData.url ?? authorData.id);
|
||||
author = {
|
||||
name: authorData.name,
|
||||
handle: `${authorData.preferredUsername}@${authorUrlObj.hostname}`,
|
||||
url: authorData.url,
|
||||
avatar: authorData.icon?.url,
|
||||
};
|
||||
} else {
|
||||
// bootleg author, mainly for cohost
|
||||
const authorUrl = postData.actor ?? postData.attributedTo;
|
||||
const authorUrlObj = new URL(authorUrl);
|
||||
const name = authorUrlObj.pathname.substring(authorUrlObj.pathname.lastIndexOf("/") + 1);
|
||||
author = {
|
||||
name,
|
||||
handle: `${name}@${authorUrlObj.hostname}`,
|
||||
url: authorUrl,
|
||||
};
|
||||
}
|
||||
|
||||
if(postData.endTime && postData.oneOf && postData.votersCount) {
|
||||
poll = {
|
||||
end: new Date(postData.endTime),
|
||||
total: postData.votersCount,
|
||||
options: postData.oneOf.map((o) => ({
|
||||
name: o.name,
|
||||
count: o.replies.totalItems,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// We could just continue without author but it'd look ugly and be confusing.
|
||||
if(!author) {
|
||||
console.warn("[fedimbed]", `Bailing trying to re-embed "${url}": Failed to get author.`);
|
||||
return {};
|
||||
}
|
||||
|
||||
// Start constructing embed
|
||||
content = content ?? "";
|
||||
cw = cw ?? "";
|
||||
|
||||
//content = htmlToMarkdown(content);
|
||||
for(const emote of emotes) {
|
||||
//content = content.replaceAll(emote.name, `[${emote.name}](${emote.url})`);
|
||||
content = content.replaceAll(emote.name, `<img src="${emote.url}" alt="${emote.name}" />`);
|
||||
}
|
||||
|
||||
//cw = htmlToMarkdown(cw);
|
||||
|
||||
let desc = cw;
|
||||
if((cw != "" || sensitive) && files.length) {
|
||||
desc += "<span data-mx-spoiler>" + content + "</span>";
|
||||
} else {
|
||||
desc = content;
|
||||
}
|
||||
|
||||
const user = author.name ? `${author.name} (${author.handle})` : author.handle;
|
||||
|
||||
const baseEmbed = {
|
||||
color,
|
||||
url,
|
||||
timestamp,
|
||||
description: desc,
|
||||
title: title ?? user,
|
||||
author: title
|
||||
? {
|
||||
name: user,
|
||||
url: author.url,
|
||||
}
|
||||
: null,
|
||||
footer: {
|
||||
text: platformName,
|
||||
},
|
||||
thumbnail: {
|
||||
url: author.avatar,
|
||||
},
|
||||
fields: [],
|
||||
};
|
||||
|
||||
if(poll) {
|
||||
baseEmbed.fields.push({
|
||||
name: "Poll",
|
||||
value:
|
||||
poll.options
|
||||
.map((o) => {
|
||||
const percent = o.count / poll.total;
|
||||
const bar = Math.round(percent * 30);
|
||||
|
||||
return `**${o.name}** (${o.count}, ${Math.round(percent * 100)}%)\n\`[${"=".repeat(bar)}${" ".repeat(
|
||||
30 - bar
|
||||
)}]\``;
|
||||
})
|
||||
.join("\n\n") + `\n\n${poll.total} votes \u2022 Ends <t:${Math.floor(poll.end.getTime() / 1000)}:R>`,
|
||||
});
|
||||
}
|
||||
|
||||
const embeds = [baseEmbed];
|
||||
|
||||
return {
|
||||
content:
|
||||
cw != "" && (files.length > 0)
|
||||
? `:warning: ${cw} <span data-mx-spoiler>${url}</span>`
|
||||
: spoiler
|
||||
? `<span data-mx-spoiler>${url}</span>`
|
||||
: "",
|
||||
embeds,
|
||||
files
|
||||
};
|
||||
}
|
||||
|
||||
async function fedimbed(msg) {
|
||||
if(URLS_REGEX.test(msg)) {
|
||||
const urls = msg.match(URLS_REGEX);
|
||||
for(let url of urls) {
|
||||
let urlObj;
|
||||
try {
|
||||
urlObj = new URL(url);
|
||||
} catch {
|
||||
console.error("[fedimbed]", `Invalid URL "${url}"`);
|
||||
// noop
|
||||
}
|
||||
for(const service of Object.keys(PATH_REGEX)) {
|
||||
const regex = PATH_REGEX[service];
|
||||
if(urlObj && regex.test(urlObj.pathname)) {
|
||||
console.log("[fedimbed]", `Hit "${service}" for "${url}", processing now.`);
|
||||
try {
|
||||
const response = await processUrl(url);
|
||||
return response;
|
||||
} catch (err) {
|
||||
console.error("[fedimbed]", `Error processing "${url}":\n` + err.stack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default fedimbed;
|
92
modules/fedimbed.js
Normal file
92
modules/fedimbed.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
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.event.content.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");
|
||||
var matrixUrl = client.cache.get("fedimbed_" + emb.thumbnail.url);
|
||||
if(!matrixUrl) {
|
||||
const buffer = await fetch(emb.thumbnail.url, {
|
||||
headers: {
|
||||
"User-Agent": "PossumBot/1.0 (+https://bot.possum.city/)",
|
||||
},
|
||||
}).then((res) => res.arrayBuffer()).then((buf) => Buffer.from(buf));
|
||||
const uploadResponse = await client.uploadContent(buffer, { rawResponse: false });
|
||||
matrixUrl = uploadResponse.content_uri;
|
||||
client.cache.set("fedimbed_" + emb.thumbnail.url, matrixUrl);
|
||||
}
|
||||
avatar.src = matrixUrl;
|
||||
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;
|
||||
quote.appendChild(text);
|
||||
}
|
||||
for(const file of embed.files) {
|
||||
var matrixUrl = client.cache.get("fedimbed_" + file.url);
|
||||
if(!matrixUrl) {
|
||||
const buffer = await fetch(file.url, {
|
||||
headers: {
|
||||
"User-Agent": "PossumBot/1.0 (+https://bot.possum.city/)",
|
||||
},
|
||||
}).then((res) => res.arrayBuffer()).then((buf) => Buffer.from(buf));
|
||||
const uploadResponse = await client.uploadContent(buffer, { rawResponse: false });
|
||||
matrixUrl = uploadResponse.content_uri;
|
||||
client.cache.set("fedimbed_" + file.url, matrixUrl);
|
||||
}
|
||||
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 = matrixUrl;
|
||||
media.alt = 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
|
||||
}
|
||||
}
|
45
modules/meow.js
Normal file
45
modules/meow.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
var meows = [
|
||||
"mreow",
|
||||
"miau",
|
||||
"mewo",
|
||||
"maow",
|
||||
"mrow",
|
||||
"mrao",
|
||||
"meow",
|
||||
"mew",
|
||||
"nya",
|
||||
];
|
||||
|
||||
var emoticons = [
|
||||
":3",
|
||||
"^w^",
|
||||
"=^w^=",
|
||||
"-w-",
|
||||
":333"
|
||||
];
|
||||
|
||||
async function onMessage(client, event) {
|
||||
if(event.event.content["m.new_content"] != null) return;
|
||||
|
||||
for(const meow of meows) {
|
||||
if(event.event.content.body.toLowerCase().includes(meow)) {
|
||||
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
|
||||
}
|
||||
}
|
20
package.json
Normal file
20
package.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "possumbot",
|
||||
"type": "module",
|
||||
"version": "0.0.0",
|
||||
"description": "General purpose Matrix bot",
|
||||
"main": "index.js",
|
||||
"author": "Ashley Graves",
|
||||
"license": "GPL-v3",
|
||||
"dependencies": {
|
||||
"@matrix-org/olm": "^3.2.15",
|
||||
"@peertube/http-signature": "^1.7.0",
|
||||
"cli-color": "^2.0.4",
|
||||
"dotenv": "^16.4.5",
|
||||
"html-entities": "^2.5.2",
|
||||
"jsdom": "^24.1.1",
|
||||
"matrix-js-sdk": "^32.0.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"sync-rpc": "^1.3.6"
|
||||
}
|
||||
}
|
843
pnpm-lock.yaml
Normal file
843
pnpm-lock.yaml
Normal file
|
@ -0,0 +1,843 @@
|
|||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@matrix-org/olm':
|
||||
specifier: ^3.2.15
|
||||
version: 3.2.15
|
||||
'@peertube/http-signature':
|
||||
specifier: ^1.7.0
|
||||
version: 1.7.0
|
||||
cli-color:
|
||||
specifier: ^2.0.4
|
||||
version: 2.0.4
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.4.5
|
||||
html-entities:
|
||||
specifier: ^2.5.2
|
||||
version: 2.5.2
|
||||
jsdom:
|
||||
specifier: ^24.1.1
|
||||
version: 24.1.1
|
||||
matrix-js-sdk:
|
||||
specifier: ^32.0.0
|
||||
version: 32.4.0
|
||||
node-fetch:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2
|
||||
sync-rpc:
|
||||
specifier: ^1.3.6
|
||||
version: 1.3.6
|
||||
|
||||
packages:
|
||||
|
||||
'@babel/runtime@7.25.0':
|
||||
resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@matrix-org/matrix-sdk-crypto-wasm@4.10.0':
|
||||
resolution: {integrity: sha512-zOqKVAYPfzs6Hav/Km9F5xWwoQ0bxDuoUU0/121m03Fg2VnfcHk43TjKImZolFc7IlgXwVGoda9Pp9Z/eTVKJA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@matrix-org/olm@3.2.15':
|
||||
resolution: {integrity: sha512-S7lOrndAK9/8qOtaTq/WhttJC/o4GAzdfK0MUPpo8ApzsJEC0QjtwrkC3KBXdFP1cD1MXi/mlKR7aaoVMKgs6Q==}
|
||||
|
||||
'@peertube/http-signature@1.7.0':
|
||||
resolution: {integrity: sha512-aGQIwo6/sWtyyqhVK4e1MtxYz4N1X8CNt6SOtCc+Wnczs5S5ONaLHDDR8LYaGn0MgOwvGgXyuZ5sJIfd7iyoUw==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
'@types/events@3.0.3':
|
||||
resolution: {integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==}
|
||||
|
||||
'@types/retry@0.12.0':
|
||||
resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
|
||||
|
||||
agent-base@7.1.1:
|
||||
resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
another-json@0.2.0:
|
||||
resolution: {integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==}
|
||||
|
||||
asn1@0.2.6:
|
||||
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
|
||||
|
||||
assert-plus@1.0.0:
|
||||
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
base-x@4.0.0:
|
||||
resolution: {integrity: sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==}
|
||||
|
||||
bcrypt-pbkdf@1.0.2:
|
||||
resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
|
||||
|
||||
bs58@5.0.0:
|
||||
resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==}
|
||||
|
||||
cli-color@2.0.4:
|
||||
resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
content-type@1.0.5:
|
||||
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
core-util-is@1.0.2:
|
||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||
|
||||
cssstyle@4.0.1:
|
||||
resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
d@1.0.2:
|
||||
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
dashdash@1.14.1:
|
||||
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
data-uri-to-buffer@4.0.1:
|
||||
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
data-urls@5.0.0:
|
||||
resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
debug@4.3.6:
|
||||
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
decimal.js@10.4.3:
|
||||
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
dotenv@16.4.5:
|
||||
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ecc-jsbn@0.1.2:
|
||||
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
||||
|
||||
entities@4.5.0:
|
||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
es6-weak-map@2.0.3:
|
||||
resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==}
|
||||
|
||||
esniff@2.0.1:
|
||||
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
|
||||
|
||||
events@3.3.0:
|
||||
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
|
||||
engines: {node: '>=0.8.x'}
|
||||
|
||||
ext@1.7.0:
|
||||
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
|
||||
|
||||
extsprintf@1.3.0:
|
||||
resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
|
||||
fetch-blob@3.2.0:
|
||||
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||
engines: {node: ^12.20 || >= 14.13}
|
||||
|
||||
form-data@4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
formdata-polyfill@4.0.10:
|
||||
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
|
||||
get-port@3.2.0:
|
||||
resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
getpass@0.1.7:
|
||||
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
|
||||
|
||||
html-encoding-sniffer@4.0.0:
|
||||
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
html-entities@2.5.2:
|
||||
resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==}
|
||||
|
||||
http-proxy-agent@7.0.2:
|
||||
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
https-proxy-agent@7.0.5:
|
||||
resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-potential-custom-element-name@1.0.1:
|
||||
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
|
||||
|
||||
is-promise@2.2.2:
|
||||
resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
|
||||
|
||||
jsbn@0.1.1:
|
||||
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
|
||||
|
||||
jsdom@24.1.1:
|
||||
resolution: {integrity: sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
canvas: ^2.11.2
|
||||
peerDependenciesMeta:
|
||||
canvas:
|
||||
optional: true
|
||||
|
||||
json-schema@0.4.0:
|
||||
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
|
||||
|
||||
jsprim@1.4.2:
|
||||
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
|
||||
engines: {node: '>=0.6.0'}
|
||||
|
||||
jwt-decode@4.0.0:
|
||||
resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
loglevel@1.9.1:
|
||||
resolution: {integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
lru-queue@0.1.0:
|
||||
resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==}
|
||||
|
||||
matrix-events-sdk@0.0.1:
|
||||
resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==}
|
||||
|
||||
matrix-js-sdk@32.4.0:
|
||||
resolution: {integrity: sha512-mzWfF4rJaTFLDfkedqP2jh/i1v5pv6xRHPkAQLn1ytXi72TFKLlKQmjaNUXfQYkmriIYnGYYQwBXQeJgwaT8SQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
matrix-widget-api@1.8.2:
|
||||
resolution: {integrity: sha512-kdmks3CvFNPIYN669Y4rO13KrazDvX8KHC7i6jOzJs8uZ8s54FNkuRVVyiQHeVCSZG5ixUqW9UuCj9lf03qxTQ==}
|
||||
|
||||
memoizee@0.4.17:
|
||||
resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
next-tick@1.1.0:
|
||||
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
|
||||
|
||||
node-domexception@1.0.0:
|
||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||
engines: {node: '>=10.5.0'}
|
||||
|
||||
node-fetch@3.3.2:
|
||||
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
nwsapi@2.2.12:
|
||||
resolution: {integrity: sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==}
|
||||
|
||||
oidc-client-ts@3.0.1:
|
||||
resolution: {integrity: sha512-xX8unZNtmtw3sOz4FPSqDhkLFnxCDsdo2qhFEH2opgWnF/iXMFoYdBQzkwCxAZVgt3FT3DnuBY3k80EZHT0RYg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
p-retry@4.6.2:
|
||||
resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
parse5@7.1.2:
|
||||
resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
|
||||
|
||||
psl@1.9.0:
|
||||
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
||||
|
||||
punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
querystringify@2.2.0:
|
||||
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
||||
|
||||
regenerator-runtime@0.14.1:
|
||||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
||||
|
||||
requires-port@1.0.0:
|
||||
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
|
||||
|
||||
retry@0.13.1:
|
||||
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
rrweb-cssom@0.6.0:
|
||||
resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
|
||||
|
||||
rrweb-cssom@0.7.1:
|
||||
resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==}
|
||||
|
||||
safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
|
||||
saxes@6.0.0:
|
||||
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
||||
engines: {node: '>=v12.22.7'}
|
||||
|
||||
sdp-transform@2.14.2:
|
||||
resolution: {integrity: sha512-icY6jVao7MfKCieyo1AyxFYm1baiM+fA00qW/KrNNVlkxHAd34riEKuEkUe4bBb3gJwLJZM+xT60Yj1QL8rHiA==}
|
||||
hasBin: true
|
||||
|
||||
sshpk@1.18.0:
|
||||
resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
hasBin: true
|
||||
|
||||
symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
|
||||
sync-rpc@1.3.6:
|
||||
resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==}
|
||||
|
||||
timers-ext@0.1.8:
|
||||
resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
tough-cookie@4.1.4:
|
||||
resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
tr46@5.0.0:
|
||||
resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tweetnacl@0.14.5:
|
||||
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
|
||||
|
||||
type@2.7.3:
|
||||
resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
|
||||
|
||||
unhomoglyph@1.0.6:
|
||||
resolution: {integrity: sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==}
|
||||
|
||||
universalify@0.2.0:
|
||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
url-parse@1.5.10:
|
||||
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
|
||||
|
||||
uuid@9.0.1:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
|
||||
verror@1.10.0:
|
||||
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
|
||||
w3c-xmlserializer@5.0.0:
|
||||
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
web-streams-polyfill@3.3.3:
|
||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
webidl-conversions@7.0.0:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
whatwg-encoding@3.1.1:
|
||||
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
whatwg-mimetype@4.0.0:
|
||||
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
whatwg-url@14.0.0:
|
||||
resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
ws@8.18.0:
|
||||
resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
xml-name-validator@5.0.0:
|
||||
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
xmlchars@2.2.0:
|
||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||
|
||||
snapshots:
|
||||
|
||||
'@babel/runtime@7.25.0':
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@matrix-org/matrix-sdk-crypto-wasm@4.10.0': {}
|
||||
|
||||
'@matrix-org/olm@3.2.15': {}
|
||||
|
||||
'@peertube/http-signature@1.7.0':
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
jsprim: 1.4.2
|
||||
sshpk: 1.18.0
|
||||
|
||||
'@types/events@3.0.3': {}
|
||||
|
||||
'@types/retry@0.12.0': {}
|
||||
|
||||
agent-base@7.1.1:
|
||||
dependencies:
|
||||
debug: 4.3.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
another-json@0.2.0: {}
|
||||
|
||||
asn1@0.2.6:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
assert-plus@1.0.0: {}
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
base-x@4.0.0: {}
|
||||
|
||||
bcrypt-pbkdf@1.0.2:
|
||||
dependencies:
|
||||
tweetnacl: 0.14.5
|
||||
|
||||
bs58@5.0.0:
|
||||
dependencies:
|
||||
base-x: 4.0.0
|
||||
|
||||
cli-color@2.0.4:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-iterator: 2.0.3
|
||||
memoizee: 0.4.17
|
||||
timers-ext: 0.1.8
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
content-type@1.0.5: {}
|
||||
|
||||
core-util-is@1.0.2: {}
|
||||
|
||||
cssstyle@4.0.1:
|
||||
dependencies:
|
||||
rrweb-cssom: 0.6.0
|
||||
|
||||
d@1.0.2:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
type: 2.7.3
|
||||
|
||||
dashdash@1.14.1:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
|
||||
data-uri-to-buffer@4.0.1: {}
|
||||
|
||||
data-urls@5.0.0:
|
||||
dependencies:
|
||||
whatwg-mimetype: 4.0.0
|
||||
whatwg-url: 14.0.0
|
||||
|
||||
debug@4.3.6:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
|
||||
decimal.js@10.4.3: {}
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
dotenv@16.4.5: {}
|
||||
|
||||
ecc-jsbn@0.1.2:
|
||||
dependencies:
|
||||
jsbn: 0.1.1
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
entities@4.5.0: {}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
dependencies:
|
||||
es6-iterator: 2.0.3
|
||||
es6-symbol: 3.1.4
|
||||
esniff: 2.0.1
|
||||
next-tick: 1.1.0
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-symbol: 3.1.4
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
ext: 1.7.0
|
||||
|
||||
es6-weak-map@2.0.3:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-iterator: 2.0.3
|
||||
es6-symbol: 3.1.4
|
||||
|
||||
esniff@2.0.1:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
event-emitter: 0.3.5
|
||||
type: 2.7.3
|
||||
|
||||
event-emitter@0.3.5:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
|
||||
events@3.3.0: {}
|
||||
|
||||
ext@1.7.0:
|
||||
dependencies:
|
||||
type: 2.7.3
|
||||
|
||||
extsprintf@1.3.0: {}
|
||||
|
||||
fetch-blob@3.2.0:
|
||||
dependencies:
|
||||
node-domexception: 1.0.0
|
||||
web-streams-polyfill: 3.3.3
|
||||
|
||||
form-data@4.0.0:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
|
||||
formdata-polyfill@4.0.10:
|
||||
dependencies:
|
||||
fetch-blob: 3.2.0
|
||||
|
||||
get-port@3.2.0: {}
|
||||
|
||||
getpass@0.1.7:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
|
||||
html-encoding-sniffer@4.0.0:
|
||||
dependencies:
|
||||
whatwg-encoding: 3.1.1
|
||||
|
||||
html-entities@2.5.2: {}
|
||||
|
||||
http-proxy-agent@7.0.2:
|
||||
dependencies:
|
||||
agent-base: 7.1.1
|
||||
debug: 4.3.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
https-proxy-agent@7.0.5:
|
||||
dependencies:
|
||||
agent-base: 7.1.1
|
||||
debug: 4.3.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
is-potential-custom-element-name@1.0.1: {}
|
||||
|
||||
is-promise@2.2.2: {}
|
||||
|
||||
jsbn@0.1.1: {}
|
||||
|
||||
jsdom@24.1.1:
|
||||
dependencies:
|
||||
cssstyle: 4.0.1
|
||||
data-urls: 5.0.0
|
||||
decimal.js: 10.4.3
|
||||
form-data: 4.0.0
|
||||
html-encoding-sniffer: 4.0.0
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.5
|
||||
is-potential-custom-element-name: 1.0.1
|
||||
nwsapi: 2.2.12
|
||||
parse5: 7.1.2
|
||||
rrweb-cssom: 0.7.1
|
||||
saxes: 6.0.0
|
||||
symbol-tree: 3.2.4
|
||||
tough-cookie: 4.1.4
|
||||
w3c-xmlserializer: 5.0.0
|
||||
webidl-conversions: 7.0.0
|
||||
whatwg-encoding: 3.1.1
|
||||
whatwg-mimetype: 4.0.0
|
||||
whatwg-url: 14.0.0
|
||||
ws: 8.18.0
|
||||
xml-name-validator: 5.0.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
json-schema@0.4.0: {}
|
||||
|
||||
jsprim@1.4.2:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
extsprintf: 1.3.0
|
||||
json-schema: 0.4.0
|
||||
verror: 1.10.0
|
||||
|
||||
jwt-decode@4.0.0: {}
|
||||
|
||||
loglevel@1.9.1: {}
|
||||
|
||||
lru-queue@0.1.0:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
|
||||
matrix-events-sdk@0.0.1: {}
|
||||
|
||||
matrix-js-sdk@32.4.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@matrix-org/matrix-sdk-crypto-wasm': 4.10.0
|
||||
another-json: 0.2.0
|
||||
bs58: 5.0.0
|
||||
content-type: 1.0.5
|
||||
jwt-decode: 4.0.0
|
||||
loglevel: 1.9.1
|
||||
matrix-events-sdk: 0.0.1
|
||||
matrix-widget-api: 1.8.2
|
||||
oidc-client-ts: 3.0.1
|
||||
p-retry: 4.6.2
|
||||
sdp-transform: 2.14.2
|
||||
unhomoglyph: 1.0.6
|
||||
uuid: 9.0.1
|
||||
|
||||
matrix-widget-api@1.8.2:
|
||||
dependencies:
|
||||
'@types/events': 3.0.3
|
||||
events: 3.3.0
|
||||
|
||||
memoizee@0.4.17:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-weak-map: 2.0.3
|
||||
event-emitter: 0.3.5
|
||||
is-promise: 2.2.2
|
||||
lru-queue: 0.1.0
|
||||
next-tick: 1.1.0
|
||||
timers-ext: 0.1.8
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-types@2.1.35:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
|
||||
ms@2.1.2: {}
|
||||
|
||||
next-tick@1.1.0: {}
|
||||
|
||||
node-domexception@1.0.0: {}
|
||||
|
||||
node-fetch@3.3.2:
|
||||
dependencies:
|
||||
data-uri-to-buffer: 4.0.1
|
||||
fetch-blob: 3.2.0
|
||||
formdata-polyfill: 4.0.10
|
||||
|
||||
nwsapi@2.2.12: {}
|
||||
|
||||
oidc-client-ts@3.0.1:
|
||||
dependencies:
|
||||
jwt-decode: 4.0.0
|
||||
|
||||
p-retry@4.6.2:
|
||||
dependencies:
|
||||
'@types/retry': 0.12.0
|
||||
retry: 0.13.1
|
||||
|
||||
parse5@7.1.2:
|
||||
dependencies:
|
||||
entities: 4.5.0
|
||||
|
||||
psl@1.9.0: {}
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
querystringify@2.2.0: {}
|
||||
|
||||
regenerator-runtime@0.14.1: {}
|
||||
|
||||
requires-port@1.0.0: {}
|
||||
|
||||
retry@0.13.1: {}
|
||||
|
||||
rrweb-cssom@0.6.0: {}
|
||||
|
||||
rrweb-cssom@0.7.1: {}
|
||||
|
||||
safer-buffer@2.1.2: {}
|
||||
|
||||
saxes@6.0.0:
|
||||
dependencies:
|
||||
xmlchars: 2.2.0
|
||||
|
||||
sdp-transform@2.14.2: {}
|
||||
|
||||
sshpk@1.18.0:
|
||||
dependencies:
|
||||
asn1: 0.2.6
|
||||
assert-plus: 1.0.0
|
||||
bcrypt-pbkdf: 1.0.2
|
||||
dashdash: 1.14.1
|
||||
ecc-jsbn: 0.1.2
|
||||
getpass: 0.1.7
|
||||
jsbn: 0.1.1
|
||||
safer-buffer: 2.1.2
|
||||
tweetnacl: 0.14.5
|
||||
|
||||
symbol-tree@3.2.4: {}
|
||||
|
||||
sync-rpc@1.3.6:
|
||||
dependencies:
|
||||
get-port: 3.2.0
|
||||
|
||||
timers-ext@0.1.8:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
next-tick: 1.1.0
|
||||
|
||||
tough-cookie@4.1.4:
|
||||
dependencies:
|
||||
psl: 1.9.0
|
||||
punycode: 2.3.1
|
||||
universalify: 0.2.0
|
||||
url-parse: 1.5.10
|
||||
|
||||
tr46@5.0.0:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
tweetnacl@0.14.5: {}
|
||||
|
||||
type@2.7.3: {}
|
||||
|
||||
unhomoglyph@1.0.6: {}
|
||||
|
||||
universalify@0.2.0: {}
|
||||
|
||||
url-parse@1.5.10:
|
||||
dependencies:
|
||||
querystringify: 2.2.0
|
||||
requires-port: 1.0.0
|
||||
|
||||
uuid@9.0.1: {}
|
||||
|
||||
verror@1.10.0:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
core-util-is: 1.0.2
|
||||
extsprintf: 1.3.0
|
||||
|
||||
w3c-xmlserializer@5.0.0:
|
||||
dependencies:
|
||||
xml-name-validator: 5.0.0
|
||||
|
||||
web-streams-polyfill@3.3.3: {}
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
whatwg-encoding@3.1.1:
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
|
||||
whatwg-mimetype@4.0.0: {}
|
||||
|
||||
whatwg-url@14.0.0:
|
||||
dependencies:
|
||||
tr46: 5.0.0
|
||||
webidl-conversions: 7.0.0
|
||||
|
||||
ws@8.18.0: {}
|
||||
|
||||
xml-name-validator@5.0.0: {}
|
||||
|
||||
xmlchars@2.2.0: {}
|
Loading…
Reference in a new issue