Compare commits

..

No commits in common. "555d7cb12671ffa8e3085d2b0bd28442ab5761af" and "c0d92ea66d09823d38d902c90fe3a8382de2e04f" have entirely different histories.

12 changed files with 56 additions and 44 deletions

View file

@ -1,7 +1,7 @@
// @ts-check
const {reg} = require("./src/matrix/read-registration")
const token = reg.ooye.discord_token
const config = require("./config")
const token = config.discordToken
const id = Buffer.from(token.split(".")[0], "base64").toString()
function addbot() {

View file

@ -1,3 +1,3 @@
#!/usr/bin/env sh
echo "Open this link to add the bot to a Discord server:"
echo "https://discord.com/oauth2/authorize?client_id=$(grep discord_token registration.yaml | sed -E 's!.*: ["'\'']([A-Za-z0-9+=/_-]*).*!\1!g' | base64 -d)&scope=bot&permissions=1610883072"
echo "https://discord.com/oauth2/authorize?client_id=$(grep discordToken config.js | sed -E 's!.*: ["'\'']([A-Za-z0-9+=/_-]*).*!\1!g' | base64 -d)&scope=bot&permissions=1610883072"

3
config.example.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
discordToken: "yes"
}

View file

@ -81,7 +81,11 @@ Follow these steps:
1. Install dependencies: `npm install`
1. Run `node scripts/seed.js` to check your setup and set the bot's initial state. It will prompt you for information. You only need to run this once ever.
1. Copy `config.example.js` to `config.js` and fill in Discord token.
1. Copy `registration.example.yaml` to `registration.yaml` and fill in bracketed values. You could generate each hex string with `dd if=/dev/urandom bs=32 count=1 2> /dev/null | basenc --base16 | dd conv=lcase 2> /dev/null`. Register the registration in Synapse's `homeserver.yaml` through the usual appservice installation process, then restart Synapse.
1. Run `node scripts/seed.js` to check your setup and set the bot's initial state. You only need to run this once ever.
1. Start the bridge: `node start.js`
@ -109,6 +113,7 @@ To get into the rooms on your Matrix account, either add yourself to `invite` in
* Run this to start the bridge:
├── start.js
* Runtime configuration, like tokens and user info:
├── config.js
├── registration.yaml
* The bridge's SQLite database is stored here:
├── db

View file

@ -10,6 +10,7 @@
*/
module.exports = async function(db) {
const id = require("../../../addbot").id
const config = require("../../../config")
const id = Buffer.from(config.discordToken.split(".")[0], "base64").toString()
db.prepare("UPDATE OR REPLACE sim SET user_id = ? WHERE user_id = '0'").run(id)
}

View file

@ -55,6 +55,7 @@ discord.snow.interaction.bulkOverwriteApplicationCommands(id, [{
async function dispatchInteraction(interaction) {
const interactionId = interaction.data.custom_id || interaction.data.name
try {
console.log(interaction)
if (interactionId === "Matrix info") {
await matrixInfo.interact(interaction)
} else if (interactionId === "invite") {

View file

@ -1073,7 +1073,7 @@ test("event2message: rich reply to a sim user", async t => {
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ " Slow news day."
+ "\nTesting this reply, ignore",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1225,7 +1225,7 @@ test("event2message: rich reply to an already-edited message will quote the new
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647><@111604486476181504>:"
+ " this is the new content. heya!"
+ "\nhiiiii....",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1278,7 +1278,7 @@ test("event2message: rich reply to a missing event will quote from formatted_bod
username: "cadence [they]",
content: "-# > But who sees the seashells she sells sitting..."
+ "\nWhat a tongue-bender...",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1327,7 +1327,7 @@ test("event2message: rich reply to a missing event without formatted_body will u
messagesToSend: [{
username: "cadence [they]",
content: "Testing this reply, ignore",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1378,7 +1378,7 @@ test("event2message: rich reply to a missing event and no reply fallback will no
messagesToSend: [{
username: "cadence [they]",
content: "Testing this reply, ignore.",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1430,7 +1430,7 @@ test("event2message: should avoid using blockquote contents as reply preview in
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ " that can't be true! there's no way :o"
+ "\nI agree!",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1568,7 +1568,7 @@ test("event2message: should include a reply preview when message ends with a blo
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜ_ooye_cookie**:"
+ " <https://tootsuite.net/Warp-Gate2.gif> tanget: @..."
+ "\naichmophobia",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1652,7 +1652,7 @@ test("event2message: should include a reply preview when replying to a descripti
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/497161350934560778/1162625810109317170 <@1109360903096369153>:"
+ " It looks like this queue has ended."
+ `\nso you're saying on matrix side I would have to edit ^this^ to add "Timed out" before the blockquote?`,
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -1705,7 +1705,7 @@ test("event2message: entities are not escaped in main message or reply preview",
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**Ⓜcadence [they]**:"
+ " Testing? \"':.`[]&things"
+ "\n_Testing?_ \"':.\\`\\[\\]&things",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2037,7 +2037,7 @@ test("event2message: editing a rich reply to a sim user", async t => {
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ " Slow news day."
+ "\nEditing this reply, which is also a test",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2093,7 +2093,7 @@ test("event2message: editing a plaintext body message", async t => {
message: {
username: "cadence [they]",
content: "well, I guess it's no longer brand new... it's existed for mere seconds...",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2148,7 +2148,7 @@ test("event2message: editing a plaintext message to be longer", async t => {
message: {
content: "aaaaaaaaa ".repeat(198) + "well, I guess it's",
username: "cadence [they]",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2157,7 +2157,7 @@ test("event2message: editing a plaintext message to be longer", async t => {
messagesToSend: [{
content: "no longer brand new... it's existed for mere seconds..." + ("aaaaaaaaa ".repeat(20)).slice(0, -1),
username: "cadence [they]",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2210,7 +2210,7 @@ test("event2message: editing a plaintext message to be shorter", async t => {
message: {
username: "cadence [they]",
content: "well, I guess it's no longer brand new... it's existed for mere seconds...",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2271,7 +2271,7 @@ test("event2message: editing a formatted body message", async t => {
message: {
username: "cadence [they]",
content: "**well, I guess it's no longer brand new... it's existed for mere seconds...**",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2328,7 +2328,7 @@ test("event2message: rich reply to a matrix user's long message with formatting"
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 **Ⓜcadence [they]**:"
+ " i should have a little happy test list bold em..."
+ "\n**no you can't!!!**",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2390,7 +2390,7 @@ test("event2message: rich reply to an image", async t => {
username: "cadence [they]",
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504> 🖼️"
+ "\nCaught in 8K UHD VR QLED Epic Edition",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2446,7 +2446,7 @@ test("event2message: rich reply to a spoiler should ensure the spoiler is hidden
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>:"
+ " [spoiler] cw crossword spoilers you'll never..."
+ "\nomg NO WAY!!",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2501,7 +2501,7 @@ test("event2message: with layered rich replies, the preview should only be the r
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 **Ⓜcadence [they]**:"
+ " two"
+ "\nthree",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2558,7 +2558,7 @@ test("event2message: if event is a reply and starts with a quote, they should be
+ " i have a feeling that clients are meant to strip..."
+ "\n"
+ "\n> To strip the fallback on the `body`, the client should iterate over each line of the string, removing any lines that start with the fallback prefix (\"> “, including the space, without quotes) and stopping when a line is encountered without the prefix. This prefix is known as the “fallback prefix sequence”.",
avatar_url: "https://bridge.example.org/download/matrix/syndicated.gay/ZkBUPXCiXTjdJvONpLJmcbKP",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/syndicated.gay/ZkBUPXCiXTjdJvONpLJmcbKP",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -2616,7 +2616,7 @@ test("event2message: rich reply to a deleted event", async t => {
username: "Ampflower 🌺",
content: "-# > <:L1:1144820033948762203><:L2:1144820084079087647>**ⓂAmpflower 🌺** (in reply to a deleted message)"
+ "\nHuh it did the same thing here too",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/PRfhXYBTOalvgQYtmCLeUXko",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/PRfhXYBTOalvgQYtmCLeUXko",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -3384,7 +3384,7 @@ test("event2message: caches the member if the member is not known", async t => {
messagesToSend: [{
username: "should_be_newly_cached",
content: "testing the member state cache",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/this_is_the_avatar",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/this_is_the_avatar",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -3548,7 +3548,7 @@ test("event2message: text attachments work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
attachments: [{id: "0", description: undefined, filename: "chiki-powerups.txt"}],
pendingFiles: [{name: "chiki-powerups.txt", mxc: "mxc://cadence.moe/zyThGlYQxvlvBVbVgKDDbiHH"}]
}]
@ -3584,7 +3584,7 @@ test("event2message: image attachments work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
attachments: [{id: "0", description: undefined, filename: "cool cat.png"}],
pendingFiles: [{name: "cool cat.png", mxc: "mxc://cadence.moe/IvxVJFLEuksCNnbojdSIeEvn"}]
}]
@ -3620,9 +3620,9 @@ test("event2message: image attachments can have a custom description", async t =
messagesToSend: [{
username: "cadence [they]",
content: "",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
attachments: [{id: "0", description: "Cat emoji surrounded by pink hearts", filename: "cool cat.png"}],
pendingFiles: [{name: "cool cat.png", mxc: "mxc://cadence.moe/IvxVJFLEuksCNnbojdSIeEvn"}]
pendingFiles: [{name: "cool cat.png", url: "mxc://cadence.moe/IvxVJFLEuksCNnbojdSIeEvn"}]
}]
}
)
@ -3670,7 +3670,7 @@ test("event2message: encrypted image attachments work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
attachments: [{id: "0", description: undefined, filename: "image.png"}],
pendingFiles: [{
name: "image.png",
@ -3715,7 +3715,7 @@ test("event2message: stickers work", async t => {
messagesToSend: [{
username: "cadence [they]",
content: "",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
attachments: [{id: "0", filename: "get_real2.gif"}],
pendingFiles: [{name: "get_real2.gif", mxc: "mxc://cadence.moe/NyMXQFAAdniImbHzsygScbmN"}]
}]
@ -3851,7 +3851,7 @@ test("event2message: emojis in other servers are reused if they have the same ti
messagesToSend: [{
username: "cadence [they]",
content: "<:hippo:230201364309868544>",
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
allowed_mentions: {
parse: ["users", "roles"]
}
@ -3910,7 +3910,7 @@ test("event2message: unknown emojis in the middle are linked", async t => {
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
content: "a [:ms_robot_grin:](https://bridge.example.org/download/matrix/cadence.moe/RLMgJGfgTPjIQtvvWZsYjhjy) b",
content: "a [:ms_robot_grin:](https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/RLMgJGfgTPjIQtvvWZsYjhjy) b",
avatar_url: undefined,
allowed_mentions: {
parse: ["users", "roles"]
@ -4333,7 +4333,7 @@ slow()("event2message: known and unknown emojis in the end are reuploaded as a s
fileContentStart: messages.messagesToSend[0].pendingFiles[0].buffer.subarray(0, 90).toString("base64")
}
t.deepEqual(testResult, {
content: "known unknown: <:hippo:230201364309868544> [:ms_robot_dress:](https://bridge.example.org/download/matrix/cadence.moe/wcouHVjbKJJYajkhJLsyeJAA) and known unknown:",
content: "known unknown: <:hippo:230201364309868544> [:ms_robot_dress:](https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/wcouHVjbKJJYajkhJLsyeJAA) and known unknown:",
fileName: "emojis.png",
fileContentStart: "iVBORw0KGgoAAAANSUhEUgAAAGAAAAAwCAYAAADuFn/PAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAeXRFWHRSYXcACklQVEMgcHJvZmlsZQogICAgICA0Ngoz"
})

View file

@ -3,12 +3,12 @@
const Ty = require("../types")
const assert = require("assert").strict
const fetch = require("node-fetch")
const passthrough = require("../passthrough")
const { discord, sync, db } = passthrough
/** @type {import("./mreq")} */
const mreq = sync.require("./mreq")
/** @type {import("./file")} */
const file = sync.require("./file")
/** @type {import("./txnid")} */
const makeTxnId = sync.require("./txnid")
const {reg} = require("./read-registration.js")

View file

@ -3,6 +3,7 @@
/**
* @typedef {Object} Passthrough
* @property {import("repl").REPLServer} repl
* @property {typeof import("./config")} config
* @property {import("./d2m/discord-client")} discord
* @property {import("heatsync").default} sync
* @property {import("better-sqlite3/lib/database")} db

View file

@ -5,7 +5,7 @@ const util = require("util")
const {addbot} = require("../addbot")
const passthrough = require("./passthrough")
const {discord, sync, db} = passthrough
const {discord, config, sync, db} = passthrough
const data = sync.require("../test/data")
const createSpace = sync.require("./d2m/actions/create-space")

View file

@ -4,18 +4,18 @@ const sqlite = require("better-sqlite3")
const migrate = require("./src/db/migrate")
const HeatSync = require("heatsync")
const {reg} = require("./src/matrix/read-registration")
const config = require("./config")
const passthrough = require("./src/passthrough")
const db = new sqlite("src/db/ooye.db")
/** @type {import("heatsync").default} */ // @ts-ignore
const sync = new HeatSync()
Object.assign(passthrough, {sync, db})
Object.assign(passthrough, {config, sync, db})
const DiscordClient = require("./src/d2m/discord-client")
const discord = new DiscordClient(reg.ooye.discord_token)
const discord = new DiscordClient(config.discordToken, "no")
passthrough.discord = discord
const {as} = require("./src/matrix/appservice")
@ -26,7 +26,7 @@ passthrough.from = orm.from
passthrough.select = orm.select
const power = require("./src/matrix/power.js")
sync.require("./src/m2d/event-dispatcher")
// sync.require("./src/m2d/event-dispatcher")
;(async () => {
await migrate.migrate(db)

View file

@ -13,6 +13,7 @@ const data = require("./data")
const fetch = require("node-fetch")
const {green} = require("colorette")
const config = require("../config")
const passthrough = require("../src/passthrough")
const db = new sqlite(":memory:")
@ -45,7 +46,7 @@ const discord = {
])
}
Object.assign(passthrough, { discord, sync, db })
Object.assign(passthrough, { discord, config, sync, db })
const orm = sync.require("../src/db/orm")
passthrough.from = orm.from