1
0
Fork 0
;)
Find a file
2023-09-06 12:04:15 +12:00
.vscode changing spaces to tabs 2023-08-21 21:04:41 +12:00
d2m no longer invite me to created rooms 2023-09-06 09:38:07 +12:00
db code coverage 2023-08-30 13:29:38 +12:00
m2d add readme 2023-09-06 12:00:39 +12:00
matrix add readme 2023-09-06 12:00:39 +12:00
scripts add migration process for stuff already bridged 2023-09-05 00:59:10 +12:00
test allow migrating from old to new bridge 2023-09-04 01:38:30 +12:00
.gitignore avoid committing the database 2023-08-26 23:29:08 +12:00
config.example.js initial with Discord 2022-12-06 17:10:31 -07:00
index.js add readme 2023-09-06 12:00:39 +12:00
notes.md m->d avoid using blockquote as reply preview 2023-09-03 16:42:17 +12:00
package-lock.json add readme 2023-09-06 12:00:39 +12:00
package.json add readme 2023-09-06 12:00:39 +12:00
passthrough.js add appservice listener 2023-06-29 08:08:17 +12:00
readme.md elaborate on features in readme 2023-09-06 12:04:15 +12:00
registration.example.yaml add readme 2023-09-06 12:00:39 +12:00
reply-line.svg add readme 2023-09-06 12:00:39 +12:00
seed.js make hardcoded "cadence.moe" configurable 2023-08-23 13:02:32 +12:00
stdin.js test on a member that has no member props 2023-08-25 11:44:58 +12:00
types.d.ts fix display_name -> displayname 2023-09-04 01:43:12 +12:00
types.js m2d reactions (untested) 2023-07-04 17:19:17 +12:00

Out Of Your Element

Modern Matrix-to-Discord appservice bridge.

Why a new bridge?

  • Modern: Supports new Discord features like replies, threads and stickers, and new Matrix features like edits, spaces and space membership.
  • Reliable: Any errors on either side are notified on Matrix and can be retried.
  • Tested: A test suite and code coverage make sure all the core logic works.
  • Simple development: No build step (it's JavaScript, not TypeScript), minimal/lightweight dependencies, and abstraction only where necessary so that less background knowledge is required. No need to learn about Intents or library functions.

What works?

Most features you'd expect in both directions, plus a little extra spice:

  • Messages
  • Edits
  • Deletions
  • Text formatting, including spoilers
  • Reactions
  • Mentions
  • Replies
  • Theads
  • Stickers
  • Attachments
  • Spoiler attachments
  • Guild-Space details syncing
  • Channel-Room details syncing
  • Custom room names/avatars can be applied on Matrix-side
  • Larger files from Discord are linked instead of reuploaded to Matrix

Caveats

  • Custom emojis don't fully work yet.
  • Embeds don't work yet.
  • Some aspects of this bridge are customised for my homeserver. I'm working over time to make it more general. Please please reach out to @cadence:cadence.moe if you would like to run this, and I'll work with you to get it running!

Development information

You will need

  • Discord bot
  • Access to the homeserver's configuration
  • (For now) Help and support from @cadence:cadence.moe. Message me and tell me you're interested in OOYE!
  • The L1 and L2 emojis

Initial setup

Node.js version 18 or later is required: https://nodejs.org/en/download/releases (the matrix-appservice dependency demands 18)

Install dependencies: npm install --save-dev

Copy config.example.js to config.js and fill in Discord token.

Copy registration.example.yaml to registration.yaml and fill in bracketed values. Register it in Synapse's homeserver.yaml through the usual appservice installation process, then restart Synapse.

If developing on a different computer to the one running the homeserver, use SSH port forwarding so that Synapse can connect on its localhost:6693 to reach the running bridge on your computer. Example: ssh -T -v -R 6693:localhost:6693 username@matrix.cadence.moe

Make sure the tests work: npm t

I recommend developing in Visual Studio Code so that the JSDoc x TypeScript annotations work. I don't know what other editors or language servers support annotations and type inference.

Repository structure

.
* Entrypoint:
├── index.js
* Runtime configuration, like tokens and user info:
├── config.js
├── registration.yaml
* The bridge's SQLite database is stored here:
├── db
│   └── *.sql, *.db
* Discord-to-Matrix bridging:
├── d2m
│   * Execute actions through the whole flow, like sending a Discord message to Matrix:
│   ├── actions
│   │   └── *.js
│   * Convert data from one form to another without depending on bridge state. Called by actions:
│   ├── converters
│   │   └── *.js
│   * Making Discord work:
│   ├── discord-*.js
│   * Listening to events from Discord and dispatching them to the correct `action`:
│   └── event-dispatcher.js
* Matrix-to-Discord bridging:
├── m2d
│   * Execute actions through the whole flow, like sending a Matrix message to Discord:
│   ├── actions
│   │   ├── *.js
│   ├── converters
│   │   └── *.js
│   └── event-dispatcher.js
* We aren't using the matrix-js-sdk, so here's all the stuff we need to call the Matrix CS API:
├── matrix
│   └── *.js
* Various files you can run once if you need them. Hopefully you won't need them.
├── scripts
│   └── *.js
* First time running a new bridge? Run this file to plant a seed, which will flourish into state for the bridge:
├── seed.js
* You are here :)
└── readme.md

Dependency justification

(transitive dependency count) dependency name: explanation

  • (0) @chriscdn/promise-semaphore
  • (50) better-sqlite3: SQLite3 is the best database, and this is the best library for it. Really! I love it.
  • (1) chunk-text: It does what I want.
  • (0) cloudstorm: Discord gateway library with bring-your-own-caching that I trust.
  • (8) snowtransfer: Discord API library with bring-your-own-caching that I trust.
  • (1) discord-markdown: This is my fork! I make sure it does what I want.
  • (1) heatsync: Module hot-reloader that I trust.
  • (1) js-yaml: It seems to do what I want, and it's already pulled in by matrix-appservice.
  • (115) matrix-appservice: I wish it didn't pull in express :(
  • (0) mixin-deep: This is my fork! It fixes a bug in regular mixin-deep.
  • (3) node-fetch@2: I like it and it does what I want.
  • (0) prettier-bytes: It does what I want and has no dependencies.
  • (0) try-to-catch: Not strictly necessary, but it does what I want and has no dependencies.
  • (1) turndown: I need an HTML-to-Markdown converter and this one looked suitable enough. It has some bugs that I've worked around, so I might switch away from it later.