commit 0c6ca6f4107e8291ffac4d3bee17ba74aeb5770c Author: Henrik Hüttemann Date: Wed May 17 18:42:26 2023 +0200 INIT diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed67baa --- /dev/null +++ b/.gitignore @@ -0,0 +1,136 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# for this project +files/ +message_example.json +rocketchat_message.json +rocketchat_room.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..61adffc --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Rocket.Chat to Matrix Migration Script + +Drafts and more + +## Exporting RC data + +Currently manually via mongodb. Run the following on the server: + +```shell +mongoexport --collection=rocketchat_message --db=rocketchat --out=rocketchat_message.json +mongoexport --collection=rocketchat_room --db=rocketchat --out=rocketchat_room.json +mongoexport --collection=users --db=rocketchat --out=users.json +``` + +## Running the Matrix Dev Server + +```shell +docker-compose up -d +# Register a admin user +docker-compose exec -it synapse register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml +``` + +## Design Decisions + +- Getting data from Rocket.Chat via (currently) manual mongodb export +- Room to Channel conversion: + - Read-only attributes of 2 verdigado channels not converted to power levels due to complexity diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..973ab2a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,50 @@ +version: '3' + +services: + + synapse: + image: docker.io/matrixdotorg/synapse:latest + # Since synapse does not retry to connect to the database, restart upon + # failure + restart: unless-stopped + # See the readme for a full documentation of the environment settings + # NOTE: You must edit homeserver.yaml to use postgres, it defaults to sqlite + environment: + - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml + volumes: + # You may either store all the files in a local folder + - ./files:/data + # .. or you may split this between different storage points + # - ./files:/data + # - /path/to/ssd:/data/uploads + # - /path/to/large_hdd:/data/media + # depends_on: + # - db + # In order to expose Synapse, remove one of the following, you might for + # instance expose the TLS port directly: + ports: + - 8008:8008/tcp + # ... or use a reverse proxy, here is an example for traefik: + + # db: + # image: docker.io/postgres:12-alpine + # # Change that password, of course! + # environment: + # - POSTGRES_USER=synapse + # - POSTGRES_PASSWORD=changeme + # # ensure the database gets created correctly + # # https://matrix-org.github.io/synapse/latest/postgres.html#set-up-database + # - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C + # volumes: + # # You may store the database tables in a local folder.. + # - ./schemas:/var/lib/postgresql/data + # # .. or store them on some high performance storage for better results + # # - /path/to/ssd/storage:/var/lib/postgresql/data + + synapse-admin: + container_name: synapse-admin + hostname: synapse-admin + image: awesometechnologies/synapse-admin:latest + ports: + - "8080:80" + restart: unless-stopped diff --git a/draft.drawio b/draft.drawio new file mode 100644 index 0000000..21a4263 --- /dev/null +++ b/draft.drawio @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/functions.js b/functions.js new file mode 100644 index 0000000..df676ff --- /dev/null +++ b/functions.js @@ -0,0 +1,93 @@ +postToMatrix (endpoint, payload) {} +mapUserId (id) {} +mapChannelId (id) {} +mapMessageId (id) {} +generateHmac(user) {} + +mapRoom (rcRoom) { + const room = { + creation_content: { + 'm.federate': false + }, + name: rcRoom.name, + room_alias_name: rcRoom.name, + topic: rcRoom.description, + // TODO: Invite users (Rate Limit?) + // POST /_matrix/client/v3/rooms/{roomId}/invite + // { + // "reason": "Welcome to the team!", + // "user_id": "@cheeky_monkey:matrix.org" + // } + } + + switch (rcRoom.t) { + case 'd': + room.is_direct = true + break; + + case 'c': + room.preset = 'public_chat' + break; + + case 'p': + room.preset = 'private_chat' + break; + + default: + // log; 'l' for livechat, anything else is undefined + break; + } + // POST /_matrix/client/v3/createRoom +} + +mapUser (rcUser) { + return { + 'nonce': '', + 'username': rcUser.username, + 'displayname': rcUser.name, + 'password': '', + 'admin': rcUser.roles.includes('admin'), + 'mac': '', + } +} + +getUserRegisterNonce () {} // GET /_synapse/admin/v1/register + +createUser (rcUser) { + const user = mapUser(rcUser) + user.nonce = getUserRegisterNonce() + user.mac = generateHmac(user) + const mUser = postToMatrix('/_synapse/admin/v1/register', user) // POST /_synapse/admin/v1/register + + // rcUser.__rooms.map(mapChannelId) + return mUser +} + +mapMessage (rcMessage) { + const message = { + 'content': { + 'body': rc.msg, + // 'format': 'org.matrix.custom.html', + // 'formatted_body': 'This is an example text message', + 'msgtype': 'm.text', + }, + 'event_id': '$143273582443PhrSn:example.org', // TODO: ?? + 'origin_server_ts': new Date(rc.t.$date).valueOf(), + 'room_id': mapChannelId(rcMessage.rid), + 'sender': mapUserId(rc.u._id), + 'type': 'm.room.message', + 'unsigned': { + 'age': 1234, // TODO: ?? + }, + } + // TODO: Other media types + + if (rc.tmid) { // If it is a thread reply + message.content['m.relates_to'] = { + rel_type: 'm.thread', + event_id: mapMessageId(rc.tmid), + } + } + + return message +}