diff --git a/client/bun.lock b/client/bun.lock new file mode 100644 index 0000000..d14838a --- /dev/null +++ b/client/bun.lock @@ -0,0 +1,388 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "threadlet-client", + "dependencies": { + "@discordapp/twemoji": "^15.1.0", + "@emoji-mart/data": "^1.2.1", + "@j0code/threadlet-api": "npm:@jsr/j0code__threadlet-api@^0.0.21", + "@j0code/yson": "npm:@jsr/j0code__yson@^1.2.4", + "@types/dompurify": "^3.0.5", + "@types/highlight.js": "^9.12.4", + "@types/marked": "^5.0.2", + "dompurify": "^3.4.2", + "emoji-mart": "^5.6.0", + "esbuild": "^0.25.0", + "highlight.js": "^11.11.1", + "marked": "^15.0.7", + "marked-alert": "^2.1.2", + "marked-highlight": "^2.2.1", + "matrix-js-sdk": "^41.4.0", + "vite": "^6.1.0", + }, + "devDependencies": { + "vite-plugin-static-copy": "^2.3.0", + }, + }, + }, + "packages": { + "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="], + + "@discordapp/twemoji": ["@discordapp/twemoji@15.1.0", "", { "dependencies": { "@twemoji/parser": "15.1.0", "fs-extra": "^8.0.1", "jsonfile": "^5.0.0", "universalify": "^0.1.2" } }, "sha512-QdpV4ifTONAXvDjRrMohausZeGrQ1ac/Ox6togUh6Xl3XKJ/KAaMMuAEi0qsb0wDwoVTSZBll5Y6+N3hB2ktBw=="], + + "@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], + + "@discordjs/rest": ["@discordjs/rest@2.5.1", "", { "dependencies": { "@discordjs/collection": "^2.1.1", "@discordjs/util": "^1.1.1", "@sapphire/async-queue": "^1.5.3", "@sapphire/snowflake": "^3.5.3", "@vladfrangu/async_event_emitter": "^2.4.6", "discord-api-types": "^0.38.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw=="], + + "@discordjs/util": ["@discordjs/util@1.1.1", "", {}, "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g=="], + + "@emoji-mart/data": ["@emoji-mart/data@1.2.1", "", {}, "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.2", "", { "os": "android", "cpu": "arm" }, "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.2", "", { "os": "android", "cpu": "x64" }, "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.2", "", { "os": "linux", "cpu": "arm" }, "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.2", "", { "os": "linux", "cpu": "x64" }, "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.2", "", { "os": "none", "cpu": "arm64" }, "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.2", "", { "os": "none", "cpu": "x64" }, "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.2", "", { "os": "win32", "cpu": "x64" }, "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@j0code/threadlet-api": ["@jsr/j0code__threadlet-api@0.0.21", "https://npm.jsr.io/~/11/@jsr/j0code__threadlet-api/0.0.21.tgz", { "dependencies": { "@discordjs/rest": "^2.4.3", "zod": "^4.0.5" } }, "sha512-ZtNkoEbOE1s6IUd/QeTk5GuZNIhe3t1KXVcJ09HVPeUOKcd/qKrL2USj36cUJTWXWFq/kARwjFjHtb2n+nVw8Q=="], + + "@j0code/yson": ["@jsr/j0code__yson@1.2.4", "https://npm.jsr.io/~/11/@jsr/j0code__yson/1.2.4.tgz", {}, "sha512-zQ2ANtaMs3u/MXRpUUA4RXWybzQxtEGsd0OLtZ4AGbcTaPOpJTMyqu2VtwNVkCMzt/pgGp6kUk38vnAMIKctEg=="], + + "@matrix-org/matrix-sdk-crypto-wasm": ["@matrix-org/matrix-sdk-crypto-wasm@18.2.0", "", {}, "sha512-puyZefvq6sHfqlmkri8umhA44724H2JL0YtX8wlvhGuNl8awX/Q1tZyW2Iekm9ZJP7BtuOqlNdg9oQd6iaGbNw=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.40.0", "", { "os": "android", "cpu": "arm" }, "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.40.0", "", { "os": "android", "cpu": "arm64" }, "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.40.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.40.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.40.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.40.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.40.0", "", { "os": "linux", "cpu": "arm" }, "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.40.0", "", { "os": "linux", "cpu": "arm" }, "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.40.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.40.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.40.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.40.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.40.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.40.0", "", { "os": "linux", "cpu": "x64" }, "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.40.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.40.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.40.0", "", { "os": "win32", "cpu": "x64" }, "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ=="], + + "@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="], + + "@sapphire/snowflake": ["@sapphire/snowflake@3.5.5", "", {}, "sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ=="], + + "@twemoji/parser": ["@twemoji/parser@15.1.0", "", {}, "sha512-3HTiSxPvkWUJ4kZeCvwyKlIwkpTUfBOk6igpBBRQni58ceQMv5YK4smkc8vX/eqOlMMNER/9qobv+Q6Q8LVrqA=="], + + "@types/dompurify": ["@types/dompurify@3.0.5", "", { "dependencies": { "@types/trusted-types": "*" } }, "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg=="], + + "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], + + "@types/events": ["@types/events@3.0.3", "", {}, "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g=="], + + "@types/highlight.js": ["@types/highlight.js@9.12.4", "", {}, "sha512-t2szdkwmg2JJyuCM20e8kR2X59WCE5Zkl4bzm1u1Oukjm79zpbiAv+QjnwLnuuV0WHEcX2NgUItu0pAMKuOPww=="], + + "@types/marked": ["@types/marked@5.0.2", "", {}, "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg=="], + + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + + "@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.6", "", {}, "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="], + + "another-json": ["another-json@0.2.0", "", {}, "sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg=="], + + "ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base-x": ["base-x@5.0.1", "", {}, "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "bs58": ["bs58@6.0.0", "", { "dependencies": { "base-x": "^5.0.0" } }, "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "discord-api-types": ["discord-api-types@0.38.15", "", {}, "sha512-RX3skyRH7p6BlHOW62ztdnIc87+wv4TEJEURMir5k5BbRJ10wK1MCqFEO6USHTol3gkiHLE6wWoHhNQ2pqB4AA=="], + + "dompurify": ["dompurify@3.4.2", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "emoji-mart": ["emoji-mart@5.6.0", "", {}, "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow=="], + + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "esbuild": ["esbuild@0.25.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.2", "@esbuild/android-arm": "0.25.2", "@esbuild/android-arm64": "0.25.2", "@esbuild/android-x64": "0.25.2", "@esbuild/darwin-arm64": "0.25.2", "@esbuild/darwin-x64": "0.25.2", "@esbuild/freebsd-arm64": "0.25.2", "@esbuild/freebsd-x64": "0.25.2", "@esbuild/linux-arm": "0.25.2", "@esbuild/linux-arm64": "0.25.2", "@esbuild/linux-ia32": "0.25.2", "@esbuild/linux-loong64": "0.25.2", "@esbuild/linux-mips64el": "0.25.2", "@esbuild/linux-ppc64": "0.25.2", "@esbuild/linux-riscv64": "0.25.2", "@esbuild/linux-s390x": "0.25.2", "@esbuild/linux-x64": "0.25.2", "@esbuild/netbsd-arm64": "0.25.2", "@esbuild/netbsd-x64": "0.25.2", "@esbuild/openbsd-arm64": "0.25.2", "@esbuild/openbsd-x64": "0.25.2", "@esbuild/sunos-x64": "0.25.2", "@esbuild/win32-arm64": "0.25.2", "@esbuild/win32-ia32": "0.25.2", "@esbuild/win32-x64": "0.25.2" }, "bin": "bin/esbuild" }, "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ=="], + + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fdir": ["fdir@6.4.4", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "glob": ["glob@11.0.1", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^4.0.1", "minimatch": "^10.0.0", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": "dist/esm/bin.mjs" }, "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-network-error": ["is-network-error@1.3.1", "", {}, "sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jackspeak": ["jackspeak@4.1.0", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw=="], + + "jsonfile": ["jsonfile@5.0.0", "", { "dependencies": { "universalify": "^0.1.2" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w=="], + + "jwt-decode": ["jwt-decode@4.0.0", "", {}, "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="], + + "loglevel": ["loglevel@1.9.2", "", {}, "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg=="], + + "lru-cache": ["lru-cache@11.1.0", "", {}, "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A=="], + + "magic-bytes.js": ["magic-bytes.js@1.11.0", "", { "dependencies": { "rimraf": "^6.0.1" } }, "sha512-nVmadqN9gam80tdnn74qjFCKgldwzv1+96XmeCvR3bY7wNn2PjHMnRakOWC6+32g133vgZOjUiYgswIxohffzA=="], + + "marked": ["marked@15.0.8", "", { "bin": "bin/marked.js" }, "sha512-rli4l2LyZqpQuRve5C0rkn6pj3hT8EWPC+zkAxFTAJLxRbENfTAhEQq9itrmf1Y81QtAX5D/MYlGlIomNgj9lA=="], + + "marked-alert": ["marked-alert@2.1.2", "", { "peerDependencies": { "marked": ">=7.0.0" } }, "sha512-EFNRZ08d8L/iEIPLTlQMDjvwIsj03gxWCczYTht6DCiHJIZhMk4NK5gtPY9UqAYb09eV5VGT+jD4lp396E0I+w=="], + + "marked-highlight": ["marked-highlight@2.2.1", "", { "peerDependencies": { "marked": ">=4 <16" } }, "sha512-SiCIeEiQbs9TxGwle9/OwbOejHCZsohQRaNTY2u8euEXYt2rYUFoiImUirThU3Gd/o6Q1gHGtH9qloHlbJpNIA=="], + + "matrix-events-sdk": ["matrix-events-sdk@0.0.1", "", {}, "sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA=="], + + "matrix-js-sdk": ["matrix-js-sdk@41.4.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@matrix-org/matrix-sdk-crypto-wasm": "^18.1.0", "another-json": "^0.2.0", "bs58": "^6.0.0", "content-type": "^1.0.4", "jwt-decode": "^4.0.0", "loglevel": "^1.9.2", "matrix-events-sdk": "0.0.1", "matrix-widget-api": "^1.16.1", "oidc-client-ts": "^3.0.1", "p-retry": "8", "sdp-transform": "^3.0.0", "unhomoglyph": "^1.0.6", "uuid": "13" } }, "sha512-xlYXXb91T89rELlnZCRfrDd4Gpkv+F0owvsaSZ8709jR1upf/zVMpOK8d3jpvW9KFkrCkoSwTRE+zqmLqzYfhA=="], + + "matrix-widget-api": ["matrix-widget-api@1.17.0", "", { "dependencies": { "@types/events": "^3.0.0", "events": "^3.2.0" } }, "sha512-5FHoo3iEP3Bdlv5jsYPWOqj+pGdFQNLWnJLiB0V7Ygne7bb+Gsj3ibyFyHWC6BVw+Z+tSW4ljHpO17I9TwStwQ=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "oidc-client-ts": ["oidc-client-ts@3.5.0", "", { "dependencies": { "jwt-decode": "^4.0.0" } }, "sha512-l2q8l9CTCTOlbX+AnK4p3M+4CEpKpyQhle6blQkdFhm0IsBqsxm15bYaSa11G7pWdsYr6epdsRZxJpCyCRbT8A=="], + + "p-map": ["p-map@7.0.3", "", {}, "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA=="], + + "p-retry": ["p-retry@8.0.0", "", { "dependencies": { "is-network-error": "^1.3.0" } }, "sha512-kFVqH1HxOHp8LupNsOys7bSV09VYTRLxarH/mokO4Rqhk6wGi70E0jh4VzvVGXfEVNggHoHLAMWsQqHyU1Ey9A=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-scurry": ["path-scurry@2.0.0", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rimraf": ["rimraf@6.0.1", "", { "dependencies": { "glob": "^11.0.0", "package-json-from-dist": "^1.0.0" }, "bin": "dist/esm/bin.mjs" }, "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A=="], + + "rollup": ["rollup@4.40.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.40.0", "@rollup/rollup-android-arm64": "4.40.0", "@rollup/rollup-darwin-arm64": "4.40.0", "@rollup/rollup-darwin-x64": "4.40.0", "@rollup/rollup-freebsd-arm64": "4.40.0", "@rollup/rollup-freebsd-x64": "4.40.0", "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", "@rollup/rollup-linux-arm-musleabihf": "4.40.0", "@rollup/rollup-linux-arm64-gnu": "4.40.0", "@rollup/rollup-linux-arm64-musl": "4.40.0", "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-musl": "4.40.0", "@rollup/rollup-linux-s390x-gnu": "4.40.0", "@rollup/rollup-linux-x64-gnu": "4.40.0", "@rollup/rollup-linux-x64-musl": "4.40.0", "@rollup/rollup-win32-arm64-msvc": "4.40.0", "@rollup/rollup-win32-ia32-msvc": "4.40.0", "@rollup/rollup-win32-x64-msvc": "4.40.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "sdp-transform": ["sdp-transform@3.0.0", "", { "bin": { "sdp-verify": "checker.js" } }, "sha512-gfYVRGxjHkGF2NPeUWHw5u6T/KGFtS5/drPms73gaSuMaVHKCY3lpLnGDfswVQO0kddeePoti09AwhYP4zA8dQ=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="], + + "unhomoglyph": ["unhomoglyph@1.0.6", "", {}, "sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg=="], + + "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "uuid": ["uuid@13.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw=="], + + "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + + "vite-plugin-static-copy": ["vite-plugin-static-copy@2.3.1", "", { "dependencies": { "chokidar": "^3.5.3", "fast-glob": "^3.2.11", "fs-extra": "^11.1.0", "p-map": "^7.0.3", "picocolors": "^1.0.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0" } }, "sha512-EfsPcBm3ewg3UMG8RJaC0ADq6/qnUZnokXx4By4+2cAcipjT9i0Y0owIJGqmZI7d6nxk4qB1q5aXOwNuSyPdyA=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "zod": ["zod@4.0.5", "", {}, "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA=="], + + "@discordapp/twemoji/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "fs-extra/jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], + + "fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@discordapp/twemoji/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + } +} diff --git a/client/package-lock.json b/client/package-lock.json index e05194b..9cbda68 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,16 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@discord/embedded-app-sdk": "^1.9.0", "@discordapp/twemoji": "^15.1.0", - "@discordjs/rest": "^2.4.3", "@emoji-mart/data": "^1.2.1", "@j0code/threadlet-api": "npm:@jsr/j0code__threadlet-api@^0.0.21", "@j0code/yson": "npm:@jsr/j0code__yson@^1.2.4", "@types/dompurify": "^3.0.5", "@types/highlight.js": "^9.12.4", "@types/marked": "^5.0.2", - "discord-api-types": "^0.37.119", "dompurify": "^3.2.4", "emoji-mart": "^5.6.0", "esbuild": "^0.25.0", @@ -26,26 +23,20 @@ "marked": "^15.0.7", "marked-alert": "^2.1.2", "marked-highlight": "^2.2.1", + "matrix-js-sdk": "^41.4.0", "vite": "^6.1.0" }, "devDependencies": { "vite-plugin-static-copy": "^2.3.0" } }, - "node_modules/@discord/embedded-app-sdk": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@discord/embedded-app-sdk/-/embedded-app-sdk-1.9.0.tgz", - "integrity": "sha512-aesQGKyhQgcxuY4/iJoylFfFaynZeU70Y5nqDtFNQ6Hs11LH+Xly7CfD6AhkTNssIyLljEkxG5ZYLU6Bj6n1kw==", + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "license": "MIT", - "dependencies": { - "@types/lodash.transform": "^4.6.6", - "@types/uuid": "^10.0.0", - "big-integer": "^1.6.48", - "decimal.js-light": "^2.5.0", - "eventemitter3": "^5.0.0", - "lodash.transform": "^4.6.0", - "uuid": "^10.0.0", - "zod": "^3.9.8" + "engines": { + "node": ">=6.9.0" } }, "node_modules/@discordapp/twemoji": { @@ -73,20 +64,20 @@ } }, "node_modules/@discordjs/rest": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.5.1.tgz", - "integrity": "sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.6.1.tgz", + "integrity": "sha512-wwQdgjeaoYFiaG+atbqx6aJDpqW7JHAo0HrQkBTbYzM3/PJ3GweQIpgElNcGZ26DCUOXMyawYd0YF7vtr+fZXg==", "license": "Apache-2.0", "dependencies": { "@discordjs/collection": "^2.1.1", - "@discordjs/util": "^1.1.1", + "@discordjs/util": "^1.2.0", "@sapphire/async-queue": "^1.5.3", - "@sapphire/snowflake": "^3.5.3", + "@sapphire/snowflake": "^3.5.5", "@vladfrangu/async_event_emitter": "^2.4.6", - "discord-api-types": "^0.38.1", - "magic-bytes.js": "^1.10.0", + "discord-api-types": "^0.38.40", + "magic-bytes.js": "^1.13.0", "tslib": "^2.6.3", - "undici": "6.21.3" + "undici": "6.24.1" }, "engines": { "node": ">=18" @@ -95,20 +86,14 @@ "url": "https://github.com/discordjs/discord.js?sponsor" } }, - "node_modules/@discordjs/rest/node_modules/discord-api-types": { - "version": "0.38.15", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.15.tgz", - "integrity": "sha512-RX3skyRH7p6BlHOW62ztdnIc87+wv4TEJEURMir5k5BbRJ10wK1MCqFEO6USHTol3gkiHLE6wWoHhNQ2pqB4AA==", - "license": "MIT", - "workspaces": [ - "scripts/actions/documentation" - ] - }, "node_modules/@discordjs/util": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz", - "integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.2.0.tgz", + "integrity": "sha512-3LKP7F2+atl9vJFhaBjn4nOaSWahZ/yWjOvA4e5pnXkt2qyXRCHLxoBQy81GFtLGCq7K9lPm9R517M1U+/90Qg==", "license": "Apache-2.0", + "dependencies": { + "discord-api-types": "^0.38.33" + }, "engines": { "node": ">=18" }, @@ -522,23 +507,6 @@ "node": ">=18" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@j0code/threadlet-api": { "name": "@jsr/j0code__threadlet-api", "version": "0.0.21", @@ -564,6 +532,15 @@ "resolved": "https://npm.jsr.io/~/11/@jsr/j0code__yson/1.2.4.tgz", "integrity": "sha512-zQ2ANtaMs3u/MXRpUUA4RXWybzQxtEGsd0OLtZ4AGbcTaPOpJTMyqu2VtwNVkCMzt/pgGp6kUk38vnAMIKctEg==" }, + "node_modules/@matrix-org/matrix-sdk-crypto-wasm": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-18.2.0.tgz", + "integrity": "sha512-puyZefvq6sHfqlmkri8umhA44724H2JL0YtX8wlvhGuNl8awX/Q1tZyW2Iekm9ZJP7BtuOqlNdg9oQd6iaGbNw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -603,9 +580,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", - "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", "cpu": [ "arm" ], @@ -616,9 +593,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", - "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", "cpu": [ "arm64" ], @@ -629,9 +606,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", - "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", "cpu": [ "arm64" ], @@ -642,9 +619,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", - "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", "cpu": [ "x64" ], @@ -655,9 +632,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", - "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", "cpu": [ "arm64" ], @@ -668,9 +645,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", - "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", "cpu": [ "x64" ], @@ -681,12 +658,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", - "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -694,12 +674,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", - "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", "cpu": [ "arm" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -707,12 +690,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", - "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -720,38 +706,79 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", - "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "cpu": [ + "loong64" + ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", - "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", "cpu": [ "loong64" ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", - "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", "cpu": [ "ppc64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -759,12 +786,15 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", - "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -772,12 +802,15 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", - "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", "cpu": [ "riscv64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -785,12 +818,15 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", - "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -798,12 +834,15 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", - "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -811,22 +850,51 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz", - "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", - "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", "cpu": [ "arm64" ], @@ -837,9 +905,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", - "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", "cpu": [ "ia32" ], @@ -849,10 +917,23 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", - "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", "cpu": [ "x64" ], @@ -898,9 +979,15 @@ } }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/events": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", + "integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==", "license": "MIT" }, "node_modules/@types/highlight.js": { @@ -909,21 +996,6 @@ "integrity": "sha512-t2szdkwmg2JJyuCM20e8kR2X59WCE5Zkl4bzm1u1Oukjm79zpbiAv+QjnwLnuuV0WHEcX2NgUItu0pAMKuOPww==", "license": "MIT" }, - "node_modules/@types/lodash": { - "version": "4.17.16", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", - "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", - "license": "MIT" - }, - "node_modules/@types/lodash.transform": { - "version": "4.6.9", - "resolved": "https://registry.npmjs.org/@types/lodash.transform/-/lodash.transform-4.6.9.tgz", - "integrity": "sha512-1iIn+l7Vrj8hsr2iZLtxRkcV9AtjTafIyxKO9DX2EEcdOgz3Op5dhwKQFhMJgdfIRbYHBUF+SU97Y6P+zyLXNg==", - "license": "MIT", - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/marked": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.2.tgz", @@ -936,12 +1008,6 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT" }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "license": "MIT" - }, "node_modules/@vladfrangu/async_event_emitter": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.6.tgz", @@ -952,29 +1018,11 @@ "npm": ">=7.0.0" } }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } + "node_modules/another-json": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/another-json/-/another-json-0.2.0.tgz", + "integrity": "sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==", + "license": "Apache-2.0" }, "node_modules/anymatch": { "version": "3.1.3", @@ -991,9 +1039,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -1003,21 +1051,12 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", "license": "MIT" }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1031,15 +1070,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1053,6 +1083,15 @@ "node": ">=8" } }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1078,77 +1117,39 @@ "fsevents": "~2.3.2" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, "engines": { - "node": ">= 8" + "node": ">= 0.6" } }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", - "license": "MIT" - }, "node_modules/discord-api-types": { - "version": "0.37.120", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.120.tgz", - "integrity": "sha512-7xpNK0EiWjjDFp2nAhHXezE4OUWm7s1zhc/UXXN6hnFFU8dfoPHgV0Hx0RPiCa3ILRpdeh152icc68DGCyXYIw==", - "license": "MIT" + "version": "0.38.47", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.47.tgz", + "integrity": "sha512-XgXQodHQBAE6kfD7kMvVo30863iHX1LHSqNq6MGUTDwIFCCvHva13+rwxyxVXDqudyApMNAd32PGjgVETi5rjA==", + "license": "MIT", + "workspaces": [ + "scripts/actions/documentation" + ] }, "node_modules/dompurify": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz", - "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", + "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, "node_modules/emoji-mart": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", "license": "MIT" }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, "node_modules/esbuild": { "version": "0.25.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", @@ -1189,11 +1190,14 @@ "@esbuild/win32-x64": "0.25.2" } }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } }, "node_modules/fast-glob": { "version": "3.3.3", @@ -1249,22 +1253,6 @@ "node": ">=8" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -1302,29 +1290,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/glob": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", - "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1376,15 +1341,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1398,6 +1354,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-network-error": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.1.tgz", + "integrity": "sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1408,27 +1376,6 @@ "node": ">=0.12.0" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", - "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/jsonfile": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", @@ -1441,30 +1388,34 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha512-LO37ZnhmBVx0GvOU/caQuipEh4GN82TcWv3yHlebGDgOxbxiwwzW5Pcx2AcvpIv2WmvmSMoC492yQFNhy/l/UQ==", - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "license": "ISC", + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", "engines": { - "node": "20 || >=22" + "node": ">=18" } }, - "node_modules/magic-bytes.js": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.11.0.tgz", - "integrity": "sha512-nVmadqN9gam80tdnn74qjFCKgldwzv1+96XmeCvR3bY7wNn2PjHMnRakOWC6+32g133vgZOjUiYgswIxohffzA==", + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", "license": "MIT", - "dependencies": { - "rimraf": "^6.0.1" + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" } }, + "node_modules/magic-bytes.js": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.13.0.tgz", + "integrity": "sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg==", + "license": "MIT" + }, "node_modules/marked": { "version": "15.0.8", "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.8.tgz", @@ -1495,6 +1446,47 @@ "marked": ">=4 <16" } }, + "node_modules/matrix-events-sdk": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz", + "integrity": "sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==", + "license": "Apache-2.0" + }, + "node_modules/matrix-js-sdk": { + "version": "41.4.0", + "resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-41.4.0.tgz", + "integrity": "sha512-xlYXXb91T89rELlnZCRfrDd4Gpkv+F0owvsaSZ8709jR1upf/zVMpOK8d3jpvW9KFkrCkoSwTRE+zqmLqzYfhA==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@matrix-org/matrix-sdk-crypto-wasm": "^18.1.0", + "another-json": "^0.2.0", + "bs58": "^6.0.0", + "content-type": "^1.0.4", + "jwt-decode": "^4.0.0", + "loglevel": "^1.9.2", + "matrix-events-sdk": "0.0.1", + "matrix-widget-api": "^1.16.1", + "oidc-client-ts": "^3.0.1", + "p-retry": "8", + "sdp-transform": "^3.0.0", + "unhomoglyph": "^1.0.6", + "uuid": "13" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/matrix-widget-api": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/matrix-widget-api/-/matrix-widget-api-1.17.0.tgz", + "integrity": "sha512-5FHoo3iEP3Bdlv5jsYPWOqj+pGdFQNLWnJLiB0V7Ygne7bb+Gsj3ibyFyHWC6BVw+Z+tSW4ljHpO17I9TwStwQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/events": "^3.0.0", + "events": "^3.2.0" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1520,9 +1512,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -1532,30 +1524,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -1584,6 +1552,18 @@ "node": ">=0.10.0" } }, + "node_modules/oidc-client-ts": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.5.0.tgz", + "integrity": "sha512-l2q8l9CTCTOlbX+AnK4p3M+4CEpKpyQhle6blQkdFhm0IsBqsxm15bYaSa11G7pWdsYr6epdsRZxJpCyCRbT8A==", + "license": "Apache-2.0", + "dependencies": { + "jwt-decode": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/p-map": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", @@ -1597,35 +1577,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "license": "BlueOak-1.0.0" - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/p-retry": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-8.0.0.tgz", + "integrity": "sha512-kFVqH1HxOHp8LupNsOys7bSV09VYTRLxarH/mokO4Rqhk6wGi70E0jh4VzvVGXfEVNggHoHLAMWsQqHyU1Ey9A==", "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "is-network-error": "^1.3.0" }, "engines": { - "node": "20 || >=22" + "node": ">=22" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/picocolors": { @@ -1635,9 +1599,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { "node": ">=12" @@ -1647,9 +1611,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz", + "integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==", "funding": [ { "type": "opencollective", @@ -1666,7 +1630,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -1709,9 +1673,9 @@ } }, "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -1732,32 +1696,13 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "license": "ISC", - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz", - "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -1767,26 +1712,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.40.0", - "@rollup/rollup-android-arm64": "4.40.0", - "@rollup/rollup-darwin-arm64": "4.40.0", - "@rollup/rollup-darwin-x64": "4.40.0", - "@rollup/rollup-freebsd-arm64": "4.40.0", - "@rollup/rollup-freebsd-x64": "4.40.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", - "@rollup/rollup-linux-arm-musleabihf": "4.40.0", - "@rollup/rollup-linux-arm64-gnu": "4.40.0", - "@rollup/rollup-linux-arm64-musl": "4.40.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", - "@rollup/rollup-linux-riscv64-gnu": "4.40.0", - "@rollup/rollup-linux-riscv64-musl": "4.40.0", - "@rollup/rollup-linux-s390x-gnu": "4.40.0", - "@rollup/rollup-linux-x64-gnu": "4.40.0", - "@rollup/rollup-linux-x64-musl": "4.40.0", - "@rollup/rollup-win32-arm64-msvc": "4.40.0", - "@rollup/rollup-win32-ia32-msvc": "4.40.0", - "@rollup/rollup-win32-x64-msvc": "4.40.0", + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", "fsevents": "~2.3.2" } }, @@ -1814,37 +1764,13 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { + "node_modules/sdp-transform": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-3.0.0.tgz", + "integrity": "sha512-gfYVRGxjHkGF2NPeUWHw5u6T/KGFtS5/drPms73gaSuMaVHKCY3lpLnGDfswVQO0kddeePoti09AwhYP4zA8dQ==", "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "bin": { + "sdp-verify": "checker.js" } }, "node_modules/source-map-js": { @@ -1856,102 +1782,6 @@ "node": ">=0.10.0" } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/tinyglobby": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", @@ -1988,14 +1818,20 @@ "license": "0BSD" }, "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", + "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", "license": "MIT", "engines": { "node": ">=18.17" } }, + "node_modules/unhomoglyph": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/unhomoglyph/-/unhomoglyph-1.0.6.tgz", + "integrity": "sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==", + "license": "MIT" + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -2006,22 +1842,22 @@ } }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.1.tgz", + "integrity": "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist-node/bin/uuid" } }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -2093,9 +1929,9 @@ } }, "node_modules/vite-plugin-static-copy": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.1.tgz", - "integrity": "sha512-EfsPcBm3ewg3UMG8RJaC0ADq6/qnUZnokXx4By4+2cAcipjT9i0Y0owIJGqmZI7d6nxk4qB1q5aXOwNuSyPdyA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.2.tgz", + "integrity": "sha512-iwrrf+JupY4b9stBttRWzGHzZbeMjAHBhkrn67MNACXJVjEMRpCI10Q3AkxdBkl45IHaTfw/CNVevzQhP7yTwg==", "dev": true, "license": "MIT", "dependencies": { @@ -2149,121 +1985,6 @@ "engines": { "node": ">= 10.0.0" } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/zod": { - "version": "3.24.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/client/package.json b/client/package.json index 569ff62..e0ba232 100644 --- a/client/package.json +++ b/client/package.json @@ -12,23 +12,21 @@ "preview": "vite preview" }, "dependencies": { - "@discord/embedded-app-sdk": "^1.9.0", "@discordapp/twemoji": "^15.1.0", - "@discordjs/rest": "^2.4.3", "@emoji-mart/data": "^1.2.1", "@j0code/threadlet-api": "npm:@jsr/j0code__threadlet-api@^0.0.21", "@j0code/yson": "npm:@jsr/j0code__yson@^1.2.4", "@types/dompurify": "^3.0.5", "@types/highlight.js": "^9.12.4", "@types/marked": "^5.0.2", - "discord-api-types": "^0.37.119", - "dompurify": "^3.2.4", + "dompurify": "^3.4.2", "emoji-mart": "^5.6.0", "esbuild": "^0.25.0", "highlight.js": "^11.11.1", "marked": "^15.0.7", "marked-alert": "^2.1.2", "marked-highlight": "^2.2.1", + "matrix-js-sdk": "^41.4.0", "vite": "^6.1.0" }, "devDependencies": { diff --git a/client/public/2pills.png b/client/public/2pills.png new file mode 100644 index 0000000..e80e594 Binary files /dev/null and b/client/public/2pills.png differ diff --git a/client/src/comps/App.ts b/client/src/comps/App.ts index 612b55f..ed0a0bb 100644 --- a/client/src/comps/App.ts +++ b/client/src/comps/App.ts @@ -1,30 +1,57 @@ +import { ClientEvent, Room, RoomEvent } from "matrix-js-sdk" +import { initMatrixClient, matrix } from "../matrix" import ChannelList from "./ChannelList" import Component from "./Component" import Form from "./Form" import View from "./View" +import MemberList from "./MemberList" export default class App extends Component { readonly channelList: ChannelList private currentView?: View | Form + readonly memberList: MemberList - constructor(forums: Array) { + constructor() { super("div", { id: "app" }) - this.channelList = new ChannelList(forums) + this.channelList = new ChannelList([]) this.element.appendChild(this.channelList.element) + this.memberList = new MemberList() + this.element.appendChild(this.memberList.element) + + matrix.once(ClientEvent.Sync, () => { + this.updateChannelList(); + }) + + matrix.on(RoomEvent.MyMembership, () => { + this.updateChannelList(); + }) + + void initMatrixClient() } - renderView(view: View | Form, ...args: any[]) { + updateChannelList() { + let rooms = matrix.getRooms() + this.channelList.reset(rooms) + } + + renderView(view: View | Form | undefined, ...args: any[]) { if (this.currentView) { this.currentView.element.remove() } + if(!view) return view.reset(...args) - this.element.appendChild(view.element) + this.element.insertBefore(view.element, this.memberList.element) this.currentView = view } + async updateMemberList(room: Room | null) { + const members = matrix.getRoom(room?.roomId)?.getMembers() || [] + await this.memberList.reset(members, room?.roomId) + } + getCurrentView() { return this.currentView } diff --git a/client/src/comps/Avatar.ts b/client/src/comps/Avatar.ts new file mode 100644 index 0000000..022b61c --- /dev/null +++ b/client/src/comps/Avatar.ts @@ -0,0 +1,60 @@ +import { matrix } from "../matrix"; +import Component from "./Component"; +import MXCImage from "./MXCImage"; + +export default class Avatar extends Component { + public readonly mxid: string + + constructor(mxid: string, className?: string) { + super("div", { classes: ["avatar", className].filter((v): v is string => !!v) }) + this.mxid = mxid + this.element.setAttribute("data-mxid", mxid) + this.reset() + } + + async reset() { + const mxid = this.element.getAttribute("data-mxid") + if(!mxid) return + + this.element.innerHTML = "" + + const user = matrix.getUser(mxid) + let displayname = user?.displayName + let avatar_url = user?.avatarUrl + if(!user) { + const profile = await matrix.getProfileInfo(mxid) + displayname = profile?.displayname || mxid + avatar_url = profile?.avatar_url + } + if(avatar_url) { + let img = new MXCImage(avatar_url) + await img.reset() + this.element.appendChild(img.element) + } else { + this.element.style.backgroundColor = this.stringToColor(mxid) + this.element.style.color = this.contrastingColor(this.stringToColor(mxid)) + this.element.style.fontSize = "24px" + this.element.style.display = "flex" + this.element.style.alignItems = "center" + this.element.style.justifyContent = "center" + this.element.innerHTML = displayname?.[0].toUpperCase() || "?" + } + } + + private stringToColor(str: string) { + let hash = 0 + for(let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash) + } + const color = (hash & 0x00FFFFFF).toString(16).toUpperCase() + return "#" + "00000".substring(0, 6 - color.length) + color + } + + private contrastingColor(hex: string): "#000000" | "#FFFFFF" { + const r = parseInt(hex.substr(1, 2), 16) + const g = parseInt(hex.substr(3, 2), 16) + const b = parseInt(hex.substr(5, 2), 16) + const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 + return luminance > 0.5 ? "#000000" : "#FFFFFF" + } +} \ No newline at end of file diff --git a/client/src/comps/ChannelList.ts b/client/src/comps/ChannelList.ts index 8d46145..64853c8 100644 --- a/client/src/comps/ChannelList.ts +++ b/client/src/comps/ChannelList.ts @@ -3,26 +3,38 @@ import { app, views } from "../main"; import Component from "./Component"; import FormButton from "./FormButton"; import ForumTab from "./ForumTab"; +import { Room } from "matrix-js-sdk"; +import App from "./App"; export default class ChannelList extends Component { - constructor(forums: Array) { + constructor(rooms: Array) { super("div", { id: "channels" }) - this.reset(forums) + this.reset(rooms) } - reset(forums: Array) { + reset(forums: Array) { for (let child of Array.from(this.element.children)) { child.remove() } + if(!(app instanceof App)) { + // How did we get here + return + } + + let _app = app satisfies App - const createButton = new FormButton("create-forum-button", "(+) New", () => app.renderView(views.forumCreateForm)) + const createButton = new FormButton("create-forum-button", "(+) New", () => _app.renderView(views.roomCreateForm)) this.element.appendChild(createButton.element) - for (let forum of forums) { + for (let forum of forums.filter(r => r.getMyMembership() != "leave")) { const tab = new ForumTab(forum) - tab.element.addEventListener("click", () => app.renderView(views.forumView, forum)) + tab.tab.addEventListener("click", () => { + const membership = forum.getMyMembership() + _app.renderView(membership == "join" ? views.roomView : views.roomInviteView, forum) + _app.updateMemberList(forum) + }) this.element.appendChild(tab.element) } } diff --git a/client/src/comps/ChatInput.ts b/client/src/comps/ChatInput.ts index f35557c..448395e 100644 --- a/client/src/comps/ChatInput.ts +++ b/client/src/comps/ChatInput.ts @@ -1,14 +1,17 @@ +import { MsgType } from "matrix-js-sdk" import { api, app } from "../main" +import { matrix } from "../matrix" import Component from "./Component" import EmojiPicker from "./EmojiPicker" import PostView from "./PostView" +import RoomView from "./RoomView" // Credits to DeepSeek-R1, wow (edited though) export default class ChatInput extends Component { readonly emojiPicker: EmojiPicker - constructor(postView: PostView) { + constructor(view: PostView | RoomView) { super("div", { id: "chat-input-container" }) // Create file upload button @@ -34,14 +37,26 @@ export default class ChatInput extends Component { chatInput.innerHTML = "" async function createMessage() { - const forum_id = postView.getCurrentForumId() - const post_id = postView.getCurrentPostId() - if (!forum_id || !post_id) { - throw new Error("TODO") + // const forum_id = view.getCurrentForumId() + // const post_id = view.getCurrentPostId() + // if (!forum_id || !post_id) { + // throw new Error("TODO") + // } + + // const msg = await api.createMessage(forum_id, post_id, { content }) + // console.log(msg) + if (view instanceof PostView) { + // TODO + return } - const msg = await api.createMessage(forum_id, post_id, { content }) - console.log(msg) + const room = view.getCurrentRoom() + if (!room) return + + await matrix.sendMessage(room.roomId, { + body: content, + msgtype: MsgType.Text + }) } console.log("Send MSG:", chatInput.innerText) diff --git a/client/src/comps/ContextMenu.ts b/client/src/comps/ContextMenu.ts new file mode 100644 index 0000000..47c1971 --- /dev/null +++ b/client/src/comps/ContextMenu.ts @@ -0,0 +1,34 @@ +import Component from "./Component"; + +export default class ContextMenu extends Component { + public readonly content: HTMLElement + public readonly trigger: HTMLElement + + constructor(tagName: keyof HTMLElementTagNameMap, { id, classes }: { id?: string, classes?: string[] }) { + super("div", { classes: ["context-menu"] }) + + this.content = document.createElement(tagName) + if (id) this.content.id = id + this.content.classList.add("context-menu-content") + if (classes) this.content.classList.add(...classes) + this.content.style.position = "absolute" + this.content.style.display = "none" + + this.element.appendChild(this.content) + + this.trigger = document.createElement("div") + this.element.appendChild(this.trigger) + + this.trigger.addEventListener("contextmenu", e => { + e.preventDefault() + this.content.style.left = `${e.clientX}px` + this.content.style.top = `${e.clientY}px` + this.content.style.display = "" + const hide = () => { + this.content.style.display = "none" + window.removeEventListener("click", hide) + } + window.addEventListener("click", hide) + }) + } +} \ No newline at end of file diff --git a/client/src/comps/MessageList.ts b/client/src/comps/EventList.ts similarity index 64% rename from client/src/comps/MessageList.ts rename to client/src/comps/EventList.ts index 77e692e..d00adc5 100644 --- a/client/src/comps/MessageList.ts +++ b/client/src/comps/EventList.ts @@ -2,31 +2,31 @@ import { type Post, type Message as APIMessage } from "@j0code/threadlet-api/v0/ import { api } from "../main" import Component from "./Component" import Message from "./Message" +import { MatrixEvent } from "matrix-js-sdk" +import { renderEvent } from "./events/Event" -export default class MessageList extends Component { +export default class EventList extends Component { constructor() { - super("div", { id: `messages` }) + super("div", { id: `events` }) } - async reset(post: Post) { + async reset(events: MatrixEvent[]) { for (let child of Array.from(this.element.children)) { child.remove() } - const msgs = await api.getMessages(post.forum_id, post.id) - - for (let msg of msgs) { - this.pushMessage(msg) + for (let event of events) { + this.pushMessage(event) } this.element.scrollTop = this.element.scrollHeight } - pushMessage(msg: APIMessage) { + pushMessage(event: MatrixEvent) { const autoscroll = this.element.scrollTop + this.element.clientHeight >= this.element.scrollHeight - 10 - const comp = new Message(msg) + const comp = renderEvent(event) this.element.appendChild(comp.element) if (autoscroll) { diff --git a/client/src/comps/FormCheckbox.ts b/client/src/comps/FormCheckbox.ts new file mode 100644 index 0000000..1fc36a8 --- /dev/null +++ b/client/src/comps/FormCheckbox.ts @@ -0,0 +1,29 @@ +import Component from "./Component" +import EmojiButton from "./EmojiButton" + +export default class FormCheckbox extends Component { + + private readonly input: HTMLInputElement + private readonly label: HTMLSpanElement + + constructor(id: string, label: string) { + super("div", { id, classes: ["form-input", "form-checkbox-input"] }) + + this.input = document.createElement("input") + this.input.type = "checkbox" + this.element.append(this.input) + + this.label = document.createElement("span") + this.label.textContent = label + this.element.append(this.label) + } + + get value() { + return this.input.checked + } + + clear() { + this.input.checked = false + } + +} diff --git a/client/src/comps/ForumTab.ts b/client/src/comps/ForumTab.ts index b17b3a7..7a0308e 100644 --- a/client/src/comps/ForumTab.ts +++ b/client/src/comps/ForumTab.ts @@ -1,12 +1,36 @@ +import { Room } from "matrix-js-sdk"; +import { matrix } from "../matrix"; import { twemojiParse } from "../md"; import Component from "./Component"; +import ContextMenu from "./ContextMenu"; +import { app, views } from "../main"; +import App from "./App"; export default class ForumTab extends Component { - constructor(forum: any) { + readonly tab: HTMLElement + + constructor(forum: Room) { super("div", { classes: ["list-tab"] }) - this.element.innerHTML = twemojiParse(forum.name) + const ctxMenu = new ContextMenu("div", { classes: ["forum-tab-menu"] }) + + const leaveButton = document.createElement("div") + leaveButton.textContent = "Leave" + leaveButton.addEventListener("click", async () => { + if(!confirm(`Are you sure you want to leave ${forum.name}?`)) return + await matrix.leave(forum.roomId) + let _app = app as App + _app.updateChannelList() + _app.renderView(undefined) + _app.updateMemberList(null) + }) + ctxMenu.content.appendChild(leaveButton) + + this.tab = ctxMenu.trigger + ctxMenu.trigger.innerHTML = twemojiParse(forum.name) + + this.element.appendChild(ctxMenu.element) } } diff --git a/client/src/comps/Login.ts b/client/src/comps/Login.ts new file mode 100644 index 0000000..2938296 --- /dev/null +++ b/client/src/comps/Login.ts @@ -0,0 +1,162 @@ +import { MatrixError } from "matrix-js-sdk"; +import { matrix } from "../matrix"; +import Component from "./Component"; + +export default class Login extends Component { + + constructor() { + super("div", { id: "login" }) + + this.element.style.width = "100%" + this.element.style.height = "100%" + + let title = document.createElement("h1") + title.textContent = "Welcome to Threadlet!" + title.id = "loginTitle" + this.element.appendChild(title) + + let morpheusImg = document.createElement("img") + morpheusImg.src = "/2pills.png" + morpheusImg.id = "morpehusImg" + this.element.appendChild(morpheusImg) + + let loginButton = document.createElement("button") + loginButton.textContent = "Login" + loginButton.style.bottom = "calc(anchor(bottom) + 10.5vw)" + loginButton.style.left = "calc(anchor(left) + 12.5vw)" + loginButton.style.transform = "translateX(-50%) translateY(50%)" + loginButton.classList.add("loginButton"); + this.element.appendChild(loginButton) + + loginButton.addEventListener("click", () => this.loginDialog()) + + let registerButton = document.createElement("button") + registerButton.textContent = "Register" + registerButton.style.bottom = "calc(anchor(bottom) + 9vw)" + registerButton.style.right = "calc(anchor(right) + 17vw)" + registerButton.style.transform = "translateX(50%) translateY(50%)" + registerButton.classList.add("loginButton"); + this.element.appendChild(registerButton) + + registerButton.addEventListener("click", () => this.registerDialog()) + } + + loginDialog() { + const el = document.createElement("dialog") + el.innerHTML = ` +

Login

+ + + + + + ` + document.body.appendChild(el) + el.showModal() + + el.querySelector("#loginHomeserver")!.value = localStorage.getItem("homeserver") || "https://matrix.org" + + el.querySelector("#loginHSSubmit")!.addEventListener("click", async () => { + const homeserver = (el.querySelector("#loginHomeserver") as HTMLInputElement).value + if(homeserver != localStorage.getItem("homeserver")) { + localStorage.setItem("homeserver", homeserver); + location.reload(); + return; + } + const flows = await matrix.loginFlows() + if(!flows.flows.some(flow => flow.type == "m.login.password")) { + alert("No supported login flows found"); + return; + } + el.querySelector("#loginHomeserver")!.style.display = "none" + el.querySelector("#loginHSSubmit")!.style.display = "none" + el.querySelector("#loginUsername")!.style.display = "block" + el.querySelector("#loginPassword")!.style.display = "block" + el.querySelector("#loginSubmit")!.style.display = "block" + }); + + el.querySelector("#loginSubmit")!.addEventListener("click", async () => { + const username = el.querySelector("#loginUsername")!.value; + const password = el.querySelector("#loginPassword")!.value; + try { + const res = await matrix.loginRequest({ + type: "m.login.password", + identifier: { + type: "m.id.user", + user: username + }, + password: password + }); + console.log(res); + localStorage.setItem("accessToken", res.access_token); + localStorage.setItem("userId", res.user_id); + localStorage.setItem("deviceId", res.device_id); + // localStorage.setItem("refreshToken", res.refresh_token); + location.reload(); + } catch(e) { + if (typeof e === "object" && e instanceof MatrixError) { + console.error(e.httpStatus); + alert("Login failed, " + (e.httpStatus === 403 ? "invalid username or password" : "an unknown error occurred")); + } else { + console.error(e); + alert("An unknown error occurred"); + } + } + }); + } + + registerDialog() { + const el = document.createElement("dialog") + el.innerHTML = ` +

Register

+ + + + + + ` + document.body.appendChild(el) + el.showModal() + + el.querySelector("#registerHomeserver")!.value = localStorage.getItem("homeserver") || "https://matrix.org" + + el.querySelector("#registerHSSubmit")!.addEventListener("click", async () => { + const homeserver = (el.querySelector("#registerHomeserver") as HTMLInputElement).value + if(homeserver != localStorage.getItem("homeserver")) { + localStorage.setItem("homeserver", homeserver); + location.reload(); + return; + } + el.querySelector("#registerHomeserver")!.style.display = "none" + el.querySelector("#registerHSSubmit")!.style.display = "none" + el.querySelector("#registerUsername")!.style.display = "block" + el.querySelector("#registerPassword")!.style.display = "block" + el.querySelector("#registerSubmit")!.style.display = "block" + }); + + el.querySelector("#registerSubmit")!.addEventListener("click", async () => { + const username = el.querySelector("#registerUsername")!.value; + const password = el.querySelector("#registerPassword")!.value; + try { + const res = await matrix.registerRequest({ + username, + password + }, "user"); + console.log(res); + localStorage.setItem("accessToken", res.access_token!); + localStorage.setItem("userId", res.user_id); + localStorage.setItem("deviceId", res.device_id!); + location.reload(); + } catch(e) { + if(typeof e === "object" && e instanceof MatrixError) { + console.error(e.httpStatus); + alert("Registration failed, " + e.httpStatus); + } else { + console.error(e); + alert("An unknown error occurred"); + } + } + }); + } + +} \ No newline at end of file diff --git a/client/src/comps/MXCImage.ts b/client/src/comps/MXCImage.ts new file mode 100644 index 0000000..a82cdff --- /dev/null +++ b/client/src/comps/MXCImage.ts @@ -0,0 +1,36 @@ +import { matrix } from "../matrix"; +import Component from "./Component"; + +export default class MXCImage extends Component { + constructor(mxc: string) { + super("img", { classes: ["mxc-image"] }) + this.element.setAttribute("data-mxc", mxc) + } + + async reset() { + const mxc = this.element.getAttribute("data-mxc") + if(mxc) { + const url = await this.getMXCImage(mxc) + if(url) { + this.element.setAttribute("src", url) + } + } + } + + async getMXCImage(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/MemberList.ts b/client/src/comps/MemberList.ts new file mode 100644 index 0000000..150990d --- /dev/null +++ b/client/src/comps/MemberList.ts @@ -0,0 +1,38 @@ +import { RoomMember } from "matrix-js-sdk"; +import Component from "./Component"; +import MXCImage from "./MXCImage"; +import Avatar from "./Avatar"; +import FormButton from "./FormButton"; +import { matrix } from "../matrix"; + +export default class MemberList extends Component { + constructor() { + super("div", { id: "members" }) + } + + async reset(members: RoomMember[], roomId?: string) { + this.element.innerHTML = "" + + if(roomId) { + const inviteButton = new FormButton("invite-to-room-button", "Invite", async () => { + const user = prompt("Enter the MXID of the user you want to invite (e.g. @example:matrix.org)") + if(!user) return + await matrix.invite(roomId, user); + }) + this.element.appendChild(inviteButton.element) + } + + members.forEach(member => { + const memberEl = document.createElement("div") + memberEl.className = "member" + const avatar = new Avatar(member.userId, "member-avatar") + memberEl.appendChild(avatar.element) + avatar.reset() + const nameEl = document.createElement("span") + nameEl.className = "member-name" + nameEl.textContent = member.name || member.userId + memberEl.appendChild(nameEl) + this.element.appendChild(memberEl) + }) + } +} \ No newline at end of file diff --git a/client/src/comps/Message.ts b/client/src/comps/Message.ts index d9cb829..be0ded5 100644 --- a/client/src/comps/Message.ts +++ b/client/src/comps/Message.ts @@ -4,18 +4,20 @@ import Component from "./Component" import CDN from "@j0code/threadlet-api/v0/cdn" import { api, clientUser } from "../main" import twemoji from "@discordapp/twemoji" +import { MatrixEvent } from "matrix-js-sdk" +import { matrix } from "../matrix" export default class Message extends Component { - readonly message: APIMessage + readonly message: MatrixEvent readonly contentElement: HTMLDivElement readonly avatarElement: HTMLImageElement readonly nameElement: HTMLSpanElement readonly timestampElement: HTMLTimeElement - constructor(msg: APIMessage) { - super("div", { id: `message-${msg.id}`, classes: ["message"] }) + constructor(msg: MatrixEvent) { + super("div", { id: `message-${msg.getId()}`, classes: ["message"] }) this.message = msg this.contentElement = document.createElement("div") @@ -49,13 +51,36 @@ export default class Message extends Component { async reset() { const msg = this.message - this.contentElement.innerHTML = markdownToHtml(msg.content) + this.contentElement.innerHTML = markdownToHtml(msg.getContent().body || "```json\n" + JSON.stringify(msg.getContent()) + "\n```") + + const user = matrix.getUser(msg.getSender()!) + let displayname = user?.displayName + let avatar_url = user?.avatarUrl + if(!user) { + const profile = await matrix.getProfileInfo(msg.getSender()!) + displayname = profile?.displayname || msg.getSender() + avatar_url = profile?.avatar_url + } + this.avatarElement.src = await this.getAvatarUrl(avatar_url || "") || "" + this.nameElement.innerHTML = twemojiParse(displayname || msg.getSender() || "Unknown") + this.timestampElement.dateTime = msg.getDate()?.toISOString() || "" + this.timestampElement.textContent = msg.getDate()?.toISOString() || "" + } - const user = await api.getUser(msg.author_id) - this.avatarElement.src = CDN.avatar(msg.author_id, user.avatar) - this.nameElement.innerHTML = twemojiParse(user.name) - this.timestampElement.dateTime = msg.created_at - this.timestampElement.textContent = new Date(msg.created_at).toLocaleString(clientUser.locale) + async getAvatarUrl(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) } } diff --git a/client/src/comps/PostView.ts b/client/src/comps/PostView.ts index 45b2671..ba70ee0 100644 --- a/client/src/comps/PostView.ts +++ b/client/src/comps/PostView.ts @@ -4,7 +4,7 @@ import PostContent from "./PostContent" import View from "./View" import { api } from "../main" import ChatInput from "./ChatInput" -import MessageList from "./MessageList" +import EventList from "./EventList" import TagList from "./TagList" export default class PostView extends View { @@ -15,7 +15,7 @@ export default class PostView extends View { public readonly author: PostAuthor private tagList: TagList public readonly content: PostContent - public readonly msgList: MessageList + public readonly msgList: EventList public readonly chatInput: ChatInput constructor() { @@ -24,7 +24,7 @@ export default class PostView extends View { this.author = new PostAuthor() this.tagList = new TagList() this.content = new PostContent() - this.msgList = new MessageList() + this.msgList = new EventList() this.chatInput = new ChatInput(this) const container = document.createElement("div") diff --git a/client/src/comps/RoomCreationForm.ts b/client/src/comps/RoomCreationForm.ts new file mode 100644 index 0000000..dc9fae8 --- /dev/null +++ b/client/src/comps/RoomCreationForm.ts @@ -0,0 +1,52 @@ +import { Forum } from "@j0code/threadlet-api/v0/types" +import { api, app, views } from "../main" +import Form from "./Form" +import FormButton from "./FormButton" +import FormTextInput from "./FormTextInput" +import FormInputList from "./FormInputList" +import { Room } from "matrix-js-sdk" +import { matrix } from "../matrix" +import FormCheckbox from "./FormCheckbox" +import App from "./App" + +export default class RoomCreationForm extends Form { + + readonly nameInput: FormTextInput + readonly topicInput: FormTextInput + readonly unfederateInput: FormCheckbox + + constructor() { + super(`Create Room`, { id: "room-creation-view", classes: ["view"] }) + + this.nameInput = new FormTextInput("room-name", "Room Name", 0, 64, true) + this.topicInput = new FormTextInput("room-topic", "Room Topic", 0, 128, true) + this.unfederateInput = new FormCheckbox("room-unfederate", "Disable Federation (cannot be undone)") + const submitButton = new FormButton("room-submit", "Create", () => this.submit()) + + this.body.appendChild(this.nameInput.element) + this.body.appendChild(this.topicInput.element) + this.body.appendChild(this.unfederateInput.element) + this.body.appendChild(submitButton.element) + } + + reset() { + this.nameInput.clear() + } + + async submit() { + const res = await matrix.createRoom({ + name: this.nameInput.value, + topic: this.topicInput.value == "" ? undefined : this.topicInput.value, + creation_content: this.unfederateInput.value ? { + "m.federate": false + } : undefined + }) + console.log("Room created with ID", res.room_id) + await matrix.roomInitialSync(res.room_id, 20) + let _app = app as App + _app.updateChannelList() + _app.renderView(views.roomView, matrix.getRoom(res.room_id)) + _app.updateMemberList(matrix.getRoom(res.room_id)) + } + +} diff --git a/client/src/comps/RoomInviteView.ts b/client/src/comps/RoomInviteView.ts new file mode 100644 index 0000000..56a1569 --- /dev/null +++ b/client/src/comps/RoomInviteView.ts @@ -0,0 +1,36 @@ +import { Room } from "matrix-js-sdk"; +import View from "./View"; +import { matrix } from "../matrix"; +import { app, views } from "../main"; +import App from "./App"; + +export default class RoomInviteView extends View { + constructor() { + super("Room Invite", { id: "room-invite-view" }) + } + + reset(room: Room): void { + this.head.titleElement.textContent = `You've been invited to join ${room.name}!` + this.body.innerHTML = "" + const joinButton = document.createElement("button") + joinButton.textContent = "Join" + joinButton.addEventListener("click", async () => { + await matrix.joinRoom(room.roomId) + await matrix.roomInitialSync(room.roomId, 20) + let _app = app as App + _app.renderView(views.roomView, room) + _app.updateMemberList(room) + }) + this.body.appendChild(joinButton) + const declineButton = document.createElement("button") + declineButton.textContent = "Decline" + declineButton.addEventListener("click", async () => { + await matrix.leave(room.roomId) + let _app = app as App + _app.renderView(undefined) + _app.updateMemberList(null) + _app.updateChannelList() + }) + this.body.appendChild(declineButton) + } +} \ No newline at end of file diff --git a/client/src/comps/RoomView.ts b/client/src/comps/RoomView.ts new file mode 100644 index 0000000..7cd5618 --- /dev/null +++ b/client/src/comps/RoomView.ts @@ -0,0 +1,62 @@ +import { Post } from "@j0code/threadlet-api/v0/types" +import PostAuthor from "./PostAuthor" +import PostContent from "./PostContent" +import View from "./View" +import { api } from "../main" +import ChatInput from "./ChatInput" +import EventList from "./EventList" +import TagList from "./TagList" +import { MatrixEvent, Room, RoomEvent, RoomMember } from "matrix-js-sdk" +import { matrix } from "../matrix" +import MemberList from "./MemberList" + +export default class RoomView extends View { + + private currentRoom?: Room + + public readonly msgList: EventList + public readonly chatInput: ChatInput + + private timelineEventHandler?: (event: MatrixEvent) => void + + constructor() { + super("div", { id: "room-view" }) + + this.msgList = new EventList() + this.chatInput = new ChatInput(this) + + const container = document.createElement("div") + container.className = "post-container" + container.appendChild(this.msgList.element) + + this.body.appendChild(container) + this.element.appendChild(this.chatInput.element) + } + + onTimelineEvent(room: Room) { + return async (event: MatrixEvent) => { + if(event.getRoomId() === room.roomId) { + this.msgList.pushMessage(event); + } + }; + } + + async reset(room: Room) { + this.head.reset(room.name) + await matrix.roomInitialSync(room.roomId, 20); + const events = room.getLiveTimeline().getEvents() + this.msgList.reset(events) + + if(this.timelineEventHandler) matrix.off(RoomEvent.Timeline, this.timelineEventHandler); + + this.currentRoom = room + + this.timelineEventHandler = this.onTimelineEvent(this.currentRoom) + matrix.on(RoomEvent.Timeline, this.timelineEventHandler); + } + + getCurrentRoom() { + return this.currentRoom + } + +} diff --git a/client/src/comps/events/ChatMessageBase.ts b/client/src/comps/events/ChatMessageBase.ts new file mode 100644 index 0000000..edabc15 --- /dev/null +++ b/client/src/comps/events/ChatMessageBase.ts @@ -0,0 +1,100 @@ +import { type Message as APIMessage } from "@j0code/threadlet-api/v0/types" +import { markdownToHtml, twemojiParse } from "../../md" +import Component from "../Component" +import CDN from "@j0code/threadlet-api/v0/cdn" +import { api, clientUser } from "../../main" +import twemoji from "@discordapp/twemoji" +import { MatrixEvent } from "matrix-js-sdk" +import { matrix } from "../../matrix" +import Avatar from "../Avatar" +import EventBase from "./EventBase" + +export default class ChatMessageBase extends EventBase { + + readonly contentElement: HTMLDivElement + readonly avatarElement: Avatar + readonly nameElement: HTMLSpanElement + readonly timestampElement: HTMLTimeElement + + constructor(msg: MatrixEvent) { + super(msg, "div", { id: `message-${msg.getId()}`, classes: ["message"] }) + + this.contentElement = document.createElement("div") + this.contentElement.className = "message-content md" + + this.avatarElement = new Avatar(msg.getSender()!, "message-author-avatar") + + this.nameElement = document.createElement("span") + this.nameElement.className = "message-author-name" + + this.timestampElement = document.createElement("time") + this.timestampElement.className = "message-timestamp" + + const aside = document.createElement("div") + aside.className = "message-aside" + aside.append(this.avatarElement.element) + + const header = document.createElement("div") + header.className = "message-header" + header.append(this.nameElement, this.timestampElement) + + const main = document.createElement("div") + main.className = "message-main" + main.append(header, this.contentElement) + + this.element.append(aside, main) + + this.reset() + } + + async reset() { + const msg = this.message + const user = matrix.getUser(msg.getSender()!) + let displayname = user?.displayName + if(!user) { + const profile = await matrix.getProfileInfo(msg.getSender()!) + displayname = profile?.displayname || msg.getSender() + } + this.nameElement.innerHTML = twemojiParse(displayname || msg.getSender() || "Unknown") + this.timestampElement.dateTime = msg.getDate()?.toISOString() || "" + // this.timestampElement.textContent = msg.getDate()?.toISOString() || "" + this.timestampElement.textContent = await this.relativeTimeFormat(msg.getDate() || new Date()) + + this.contentElement.querySelectorAll("[data-mx-spoiler]").forEach(el => { + el.addEventListener("click", () => el.style.filter = "none"); + }); + } + + async relativeTimeFormat(date: Date) { + const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }) + const now = new Date() + const diff = (date.getTime() - now.getTime()) / 1000 + + if (Math.abs(diff) < 60) { + return rtf.format(Math.round(diff), "second") + } else if (Math.abs(diff) < 3600) { + return rtf.format(Math.round(diff / 60), "minute") + } else if (Math.abs(diff) < 86400) { + return rtf.format(Math.round(diff / 3600), "hour") + } else { + return rtf.format(Math.round(diff / 86400), "day") + } + } + + async getAvatarUrl(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} diff --git a/client/src/comps/events/Event.ts b/client/src/comps/events/Event.ts new file mode 100644 index 0000000..140a777 --- /dev/null +++ b/client/src/comps/events/Event.ts @@ -0,0 +1,38 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import Component from "../Component"; +import RoomTextMessage from "./RoomTextMessage"; +import ChatMessageBase from "./ChatMessageBase"; +import RoomImageMessage from "./RoomImageMessage"; +import RoomEmoteMessage from "./RoomEmoteMessage"; +import EventMessageBase from "./EventMessageBase"; +import EventBase from "./EventBase"; +import RoomNoticeMessage from "./RoomNoticeMessage"; +import RoomVideoMessage from "./RoomVideoMessage"; +import RoomAudioMessage from "./RoomAudioMessage"; +import RoomFileMessage from "./RoomFileMessage"; +import UnknownEvent from "./UnknownEvent"; +import RoomNameEvent from "./RoomNameEvent"; + +const eventTypes: Record = { + "m.room.message": RoomTextMessage, + "m.room.name": RoomNameEvent, +} + +const msgTypes: Record = { + "m.text": RoomTextMessage, + "m.image": RoomImageMessage, + "m.emote": RoomEmoteMessage, + "m.notice": RoomNoticeMessage, + "m.audio": RoomAudioMessage, + "m.video": RoomVideoMessage, + "m.file": RoomFileMessage, +} + +export function renderEvent(event: MatrixEvent) { + let EventClass = eventTypes[event.getType()] || UnknownEvent + if(event.getType() === "m.room.message" && event.getContent().msgtype) { + const msgtype = event.getContent().msgtype! + EventClass = msgTypes[msgtype] || RoomTextMessage + } + return new EventClass(event) +} diff --git a/client/src/comps/events/EventBase.ts b/client/src/comps/events/EventBase.ts new file mode 100644 index 0000000..9a57f92 --- /dev/null +++ b/client/src/comps/events/EventBase.ts @@ -0,0 +1,13 @@ +import { MatrixEvent } from "matrix-js-sdk" +import Component from "../Component" + +export default class EventBase extends Component { + + readonly message: MatrixEvent + + constructor(msg: MatrixEvent, tagName: keyof HTMLElementTagNameMap = "div", options: { id?: string, classes?: string[] } = {}) { + super(tagName, options) + this.message = msg + } + +} diff --git a/client/src/comps/events/EventMessageBase.ts b/client/src/comps/events/EventMessageBase.ts new file mode 100644 index 0000000..14a128a --- /dev/null +++ b/client/src/comps/events/EventMessageBase.ts @@ -0,0 +1,84 @@ +import { type Message as APIMessage } from "@j0code/threadlet-api/v0/types" +import { markdownToHtml, twemojiParse } from "../../md" +import Component from "../Component" +import CDN from "@j0code/threadlet-api/v0/cdn" +import { api, clientUser } from "../../main" +import twemoji from "@discordapp/twemoji" +import { MatrixEvent } from "matrix-js-sdk" +import { matrix } from "../../matrix" +import Avatar from "../Avatar" +import EventBase from "./EventBase" + +export default class EventMessageBase extends EventBase { + + readonly contentElement: HTMLDivElement + readonly avatarElement: Avatar + readonly timestampElement: HTMLTimeElement + + constructor(msg: MatrixEvent) { + super(msg, "div", { id: `message-${msg.getId()}`, classes: ["message"] }) + + this.contentElement = document.createElement("div") + this.contentElement.className = "message-content md" + + this.avatarElement = new Avatar(msg.getSender()!, "message-author-avatar") + + this.timestampElement = document.createElement("time") + this.timestampElement.className = "message-timestamp" + + const aside = document.createElement("div") + aside.className = "message-aside" + aside.append(this.avatarElement.element) + + const main = document.createElement("div") + main.className = "message-main" + main.style.flexDirection = "row" + main.style.gap = "0.5em" + main.style.alignItems = "center" + main.append(this.contentElement, this.timestampElement) + + this.element.append(aside, main) + + this.reset() + } + + async reset() { + const msg = this.message + this.timestampElement.dateTime = msg.getDate()?.toISOString() || "" + // this.timestampElement.textContent = msg.getDate()?.toISOString() || "" + this.timestampElement.textContent = await this.relativeTimeFormat(msg.getDate() || new Date()) + } + + async relativeTimeFormat(date: Date) { + const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }) + const now = new Date() + const diff = (date.getTime() - now.getTime()) / 1000 + + if (Math.abs(diff) < 60) { + return rtf.format(Math.round(diff), "second") + } else if (Math.abs(diff) < 3600) { + return rtf.format(Math.round(diff / 60), "minute") + } else if (Math.abs(diff) < 86400) { + return rtf.format(Math.round(diff / 3600), "hour") + } else { + return rtf.format(Math.round(diff / 86400), "day") + } + } + + async getAvatarUrl(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} diff --git a/client/src/comps/events/HTMLFormat.ts b/client/src/comps/events/HTMLFormat.ts new file mode 100644 index 0000000..5658593 --- /dev/null +++ b/client/src/comps/events/HTMLFormat.ts @@ -0,0 +1,67 @@ +import DOMPurify from "dompurify"; + +/* +From spec (10.2.1.1.): +Clients should limit the HTML they render to avoid Cross-Site Scripting, HTML injection, and similar attacks. +The strongly suggested set of HTML tags to permit, denying the use and rendering of anything else, is: +del, h1, h2, h3, h4, h5, h6, blockquote, p, a, ul, ol, sup, sub, li, b, i, u, strong, em, s, code, hr, +br, div, table, thead, tbody, tr, th, td, caption, pre, span, img, details, summary. + +Not all attributes on those tags should be permitted as they may be avenues for other disruption attempts, +such as adding onclick handlers or excessively large text. +Clients should only permit the attributes listed for the tags below. +Where data-mx-bg-color and data-mx-color are listed, clients should translate the value +(a # character followed by a 6-character hex color code) to the appropriate CSS/attributes for the tag. +Tag | Permitted Attributes +-----|---------------------- +span | data-mx-bg-color, data-mx-color, data-mx-spoiler (see spoiler messages), data-mx-maths (see mathematical messages) +a | target, href (provided the value is not relative and has a scheme matching one of: https, http, ftp, mailto, magnet) +img | width, height, alt, title, src (provided it is a Matrix Content (mxc://) URI) +ol | start +code | class (only classes which start with language- for syntax highlighting) +div | data-mx-maths (see mathematical messages) + +Additionally, web clients should ensure that all a tags get a rel="noopener" to prevent the target page from referencing the client’s tab/window. +*/ + +DOMPurify.addHook("afterSanitizeAttributes", (node) => { + if(node.tagName === "A") { + node.setAttribute("rel", "noopener") + } else if(node.tagName === "SPAN") { + const bgColor = node.getAttribute("data-mx-bg-color") + const color = node.getAttribute("data-mx-color") + if(bgColor && node instanceof HTMLElement) { + node.style.backgroundColor = bgColor + } + if(color && node instanceof HTMLElement) { + node.style.color = color + } + } +}) + +DOMPurify.addHook("uponSanitizeAttribute", (node, data) => { + if(node.tagName === "CODE" && data.attrName === "class") { + if(!data.attrValue.startsWith("language-")) { + return null + } + } +}) + +export function purifyHTML(html: string): string { + return DOMPurify.sanitize(html, { + ALLOWED_TAGS: [ + "del", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "p", "a", "ul", "ol", "sup", "sub", "li", "b", "i", "u", "strong", "em", "s", "code", "hr", + "br", "div", "table", "thead", "tbody", "tr", "th", "td", "caption", "pre", "span", "img", "details", "summary", "#text" + ], + ADD_ATTR: (attributeName, tagName) => { + if(tagName === "span" && ["data-mx-bg-color", "data-mx-color", "data-mx-spoiler", "data-mx-maths"].includes(attributeName)) return true + if(tagName === "a" && ["target", "href"].includes(attributeName)) return true + if(tagName === "img" && ["width", "height", "alt", "title", "src"].includes(attributeName)) return true + if(tagName === "ol" && attributeName === "start") return true + if(tagName === "code" && attributeName === "class") return true + if(tagName === "div" && attributeName === "data-mx-maths") return true + return false + }, + ALLOWED_URI_REGEXP: /^(?:(?:https?|ftp|mailto|magnet):|mxc:\/\/)/i, + }) +} diff --git a/client/src/comps/events/RoomAudioMessage.ts b/client/src/comps/events/RoomAudioMessage.ts new file mode 100644 index 0000000..9ce2ad3 --- /dev/null +++ b/client/src/comps/events/RoomAudioMessage.ts @@ -0,0 +1,39 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; + +export default class RoomAudioMessage extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + this.contentElement.innerHTML = "" + + let audio = document.createElement("audio") + audio.controls = true + audio.src = await this.getMXCAudio(this.message.getContent().url || "") || "" + audio.style.maxWidth = "50%" + this.contentElement.appendChild(audio) + super.reset() + } + + async getMXCAudio(mxc: string) { + console.log("Getting media url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/events/RoomEmoteMessage.ts b/client/src/comps/events/RoomEmoteMessage.ts new file mode 100644 index 0000000..38ded04 --- /dev/null +++ b/client/src/comps/events/RoomEmoteMessage.ts @@ -0,0 +1,38 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; +import EventMessageBase from "./EventMessageBase"; +import { purifyHTML } from "./HTMLFormat"; + +export default class RoomEmoteMessage extends EventMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + const sender = matrix.getUser(this.message.getSender()!) + this.contentElement.innerHTML = "" + this.contentElement.style.display = "flex" + this.contentElement.style.gap = "1ch" + const emote = document.createElement("span") + emote.innerText = "* " + (sender?.displayName || this.message.getSender()) + this.contentElement.appendChild(emote) + const body = document.createElement("span") + switch (this.message.getContent().format) { + case "org.matrix.custom.html": + body.innerHTML = purifyHTML(this.message.getContent().formatted_body || "") + break + case "org.matrix.custom.markdown": // This is not official, but its useful. Should it be renamed to something else because its not official? + body.innerHTML = markdownToHtml(this.message.getContent().body || "") + break + case undefined: + default: + body.innerText = this.message.getContent().body || "" + break + } + this.contentElement.appendChild(body) + super.reset() + } +} \ No newline at end of file diff --git a/client/src/comps/events/RoomFileMessage.ts b/client/src/comps/events/RoomFileMessage.ts new file mode 100644 index 0000000..ee1e15e --- /dev/null +++ b/client/src/comps/events/RoomFileMessage.ts @@ -0,0 +1,40 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; + +export default class RoomFileMessage extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + this.contentElement.innerHTML = "" + + let file = document.createElement("a") + file.href = await this.getMXCFile(this.message.getContent().url || "") || "" + file.target = "_blank" + file.rel = "noopener noreferrer" + file.textContent = this.message.getContent().body || "Download File" + this.contentElement.appendChild(file) + super.reset() + } + + async getMXCFile(mxc: string) { + console.log("Getting media url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/events/RoomImageMessage.ts b/client/src/comps/events/RoomImageMessage.ts new file mode 100644 index 0000000..e99bbfa --- /dev/null +++ b/client/src/comps/events/RoomImageMessage.ts @@ -0,0 +1,36 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; + +export default class RoomImageMessage extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + this.contentElement.innerHTML = "" + let img = new MXCImage(this.message.getContent().url || "") + await img.reset() + this.contentElement.appendChild(img.element) + super.reset() + } + + async getMXCImage(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/events/RoomNameEvent.ts b/client/src/comps/events/RoomNameEvent.ts new file mode 100644 index 0000000..3600a47 --- /dev/null +++ b/client/src/comps/events/RoomNameEvent.ts @@ -0,0 +1,17 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import EventMessageBase from "./EventMessageBase"; +import { matrix } from "../../matrix"; + +export default class RoomNameEvent extends EventMessageBase { + constructor(msg: MatrixEvent) { + super(msg); + this.reset(); + } + + async reset() { + await super.reset(); + + let author = matrix.getUser(this.message.getSender() || ""); + this.contentElement.textContent = `${author?.displayName || this.message.getSender()} changed the room name to ${this.message.getContent().name}`; + } +} \ No newline at end of file diff --git a/client/src/comps/events/RoomNoticeMessage.ts b/client/src/comps/events/RoomNoticeMessage.ts new file mode 100644 index 0000000..3f3c52c --- /dev/null +++ b/client/src/comps/events/RoomNoticeMessage.ts @@ -0,0 +1,46 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; +import { purifyHTML } from "./HTMLFormat"; + +export default class RoomNoticeMessage extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + switch (this.message.getContent().format) { + case "org.matrix.custom.html": + this.contentElement.innerHTML = purifyHTML(this.message.getContent().formatted_body || "") + break + case "org.matrix.custom.markdown": // This is not official, but its useful. Should it be renamed to something else because its not official? + this.contentElement.innerHTML = markdownToHtml(this.message.getContent().body || "") + break + case undefined: + default: + this.contentElement.innerText = this.message.getContent().body || "" + break + } + this.contentElement.style.color = "#acacac" + super.reset() + } + + async getMXCImage(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/events/RoomTextMessage.ts b/client/src/comps/events/RoomTextMessage.ts new file mode 100644 index 0000000..c01367d --- /dev/null +++ b/client/src/comps/events/RoomTextMessage.ts @@ -0,0 +1,45 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; +import { purifyHTML } from "./HTMLFormat"; + +export default class RoomTextMessage extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + switch (this.message.getContent().format) { + case "org.matrix.custom.html": + this.contentElement.innerHTML = purifyHTML(this.message.getContent().formatted_body || "") + break + case "org.matrix.custom.markdown": // This is not official, but its useful. Should it be renamed to something else because its not official? + this.contentElement.innerHTML = markdownToHtml(this.message.getContent().body || "") + break + case undefined: + default: + this.contentElement.innerText = this.message.getContent().body || "" + break + } + super.reset() + } + + async getMXCImage(mxc: string) { + console.log("Getting avatar url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/events/RoomVideoMessage.ts b/client/src/comps/events/RoomVideoMessage.ts new file mode 100644 index 0000000..0b203ed --- /dev/null +++ b/client/src/comps/events/RoomVideoMessage.ts @@ -0,0 +1,39 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; +import { matrix } from "../../matrix"; +import MXCImage from "../MXCImage"; + +export default class RoomVideoMessage extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + this.contentElement.innerHTML = "" + + let video = document.createElement("video") + video.controls = true + video.src = await this.getMXCVideo(this.message.getContent().url || "") || "" + video.style.maxWidth = "50%" + this.contentElement.appendChild(video) + super.reset() + } + + async getMXCVideo(mxc: string) { + console.log("Getting media url for", mxc) + // TODO: caching + const url = matrix.mxcUrlToHttp(mxc, undefined, undefined, undefined, false, true, true) + if(!url) { + return null + } + const img = await fetch(url, { + headers: { + Authorization: `Bearer ${matrix.getAccessToken()}` + } + }) + const blob = await img.blob() + return URL.createObjectURL(blob) + } + +} \ No newline at end of file diff --git a/client/src/comps/events/UnknownEvent.ts b/client/src/comps/events/UnknownEvent.ts new file mode 100644 index 0000000..d57d45a --- /dev/null +++ b/client/src/comps/events/UnknownEvent.ts @@ -0,0 +1,14 @@ +import { MatrixEvent } from "matrix-js-sdk"; +import ChatMessageBase from "./ChatMessageBase"; +import { markdownToHtml } from "../../md"; + +export default class UnknownEvent extends ChatMessageBase { + constructor(msg: MatrixEvent) { + super(msg) + } + + async reset(): Promise { + this.contentElement.innerHTML = markdownToHtml(this.message.getType() + "\n```json\n" + JSON.stringify(this.message.getContent()) + "\n```") + super.reset() + } +} \ No newline at end of file diff --git a/client/src/main.ts b/client/src/main.ts index 1569c16..504127d 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -1,117 +1,121 @@ -import { DiscordSDK } from "@discord/embedded-app-sdk" -import { REST } from '@discordjs/rest' import "../style.css" import "../md.css" import "highlight.js/styles/github-dark.min.css" import App from "./comps/App" import ForumSettingsForm from "./comps/ForumSettingsForm" import ThreadletAPI from "@j0code/threadlet-api/v0" -import { APIUser, Routes } from "discord-api-types/v10" import PostSettingsForm from "./comps/PostSettingsForm" import ForumView from "./comps/ForumView" import PostView from "./comps/PostView" +import { User } from "matrix-js-sdk" +import Login from "./comps/Login" +import RoomView from "./comps/RoomView" +import RoomInviteView from "./comps/RoomInviteView" +import RoomCreationForm from "./comps/RoomCreationForm" -// Will eventually store the authenticated user's access_token -let auth: Awaited> -let rest: REST - -const discordSdk = new DiscordSDK(import.meta.env.VITE_DISCORD_CLIENT_ID) export let api: ThreadletAPI -export let app: App -export let clientUser: APIUser +export let app: App | Login +export let clientUser: User export const views = { forumCreateForm: new ForumSettingsForm(), postCreateForm: new PostSettingsForm(), forumView: new ForumView(), postView: new PostView(), + roomView: new RoomView(), + roomInviteView: new RoomInviteView(), + roomCreateForm: new RoomCreationForm() } as const -setupDiscordSdk().then(async () => { - console.log("Discord SDK is authenticated") +document.getElementById("loadingScreen")!.remove(); +app = localStorage.getItem("accessToken") ? new App() : new Login() +document.body.appendChild(app.element) + +// setupDiscordSdk().then(async () => { +// console.log("Discord SDK is authenticated") - document.getElementById("loadingScreen")!.remove() - document.body.appendChild(app.element) +// document.getElementById("loadingScreen")!.remove() +// document.body.appendChild(app.element) - // ------------------------------------------------------------ +// // ------------------------------------------------------------ - // We can now make API calls within the scopes we requested in setupDiscordSDK() - // Note: the access_token returned is a sensitive secret and should be treated as such - let guildName = "Unknown" // likely DM if Unknown +// // We can now make API calls within the scopes we requested in setupDiscordSDK() +// // Note: the access_token returned is a sensitive secret and should be treated as such +// let guildName = "Unknown" // likely DM if Unknown - if (discordSdk.guildId != null) { - try { - const guilds = await rest.get(Routes.userGuilds()) +// if (discordSdk.guildId != null) { +// try { +// const guilds = await rest.get(Routes.userGuilds()) - if (guilds && guilds instanceof Array) { - const guild = guilds.find(g => g.id == discordSdk.guildId) - if (guild && typeof guild == "object" && "name" in guild) { - guildName = guild.name as string - } - } - } catch (ignore) {} - } +// if (guilds && guilds instanceof Array) { +// const guild = guilds.find(g => g.id == discordSdk.guildId) +// if (guild && typeof guild == "object" && "name" in guild) { +// guildName = guild.name as string +// } +// } +// } catch (ignore) {} +// } - clientUser = await rest.get(Routes.user()) as APIUser +// clientUser = await rest.get(Routes.user()) as APIUser - api.on("messageCreate", msg => { - const view = app.getCurrentView() - if (!(view instanceof PostView)) return - if (view.getCurrentPostId() != msg.post_id) return - view.msgList.pushMessage(msg) - }) +// api.on("messageCreate", msg => { +// const view = app.getCurrentView() +// if (!(view instanceof PostView)) return +// if (view.getCurrentPostId() != msg.post_id) return +// view.msgList.pushMessage(msg) +// }) - api.on("forumCreate", async forum => { - // TODO: update and read cache instead of fetching - const forums = await api.getForums() - app.channelList.reset(forums) - }) -}) +// api.on("forumCreate", async forum => { +// // TODO: update and read cache instead of fetching +// const forums = await api.getForums() +// app.channelList.reset(forums) +// }) +// }) -async function setupDiscordSdk() { - await discordSdk.ready() - console.log("Discord SDK is ready") +// async function setupDiscordSdk() { +// await discordSdk.ready() +// console.log("Discord SDK is ready") - // Authorize with Discord Client - const { code } = await discordSdk.commands.authorize({ - client_id: import.meta.env.VITE_DISCORD_CLIENT_ID, - response_type: "code", - state: "", - prompt: "none", - scope: [ - "identify", - "guilds", - "applications.commands" - ] - }) +// // Authorize with Discord Client +// const { code } = await discordSdk.commands.authorize({ +// client_id: import.meta.env.VITE_DISCORD_CLIENT_ID, +// response_type: "code", +// state: "", +// prompt: "none", +// scope: [ +// "identify", +// "guilds", +// "applications.commands" +// ] +// }) - // Retrieve an access_token from your activity's server - // Note: We need to prefix our backend `/api/token` route with `/.proxy` to stay compliant with the CSP. - // Read more about constructing a full URL and using external resources at - // https://discord.com/developers/docs/activities/development-guides#construct-a-full-url - const response = await fetch(`/.proxy/api/v0/token`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - code, - }) - }) - const { access_token } = await response.json() +// // Retrieve an access_token from your activity's server +// // Note: We need to prefix our backend `/api/token` route with `/.proxy` to stay compliant with the CSP. +// // Read more about constructing a full URL and using external resources at +// // https://discord.com/developers/docs/activities/development-guides#construct-a-full-url +// const response = await fetch(`/.proxy/api/v0/token`, { +// method: "POST", +// headers: { +// "Content-Type": "application/json" +// }, +// body: JSON.stringify({ +// code, +// }) +// }) +// const { access_token } = await response.json() - // Authenticate with Discord client (using the access_token) - auth = await discordSdk.commands.authenticate({ - access_token, - }) +// // Authenticate with Discord client (using the access_token) +// auth = await discordSdk.commands.authenticate({ +// access_token, +// }) - if (auth == null) { - throw new Error("Authenticate command failed") - } +// if (auth == null) { +// throw new Error("Authenticate command failed") +// } - rest = new REST({ version: '10', authPrefix: "Bearer" }).setToken(auth.access_token) - api = new ThreadletAPI(access_token) +// rest = new REST({ version: '10', authPrefix: "Bearer" }).setToken(auth.access_token) +// api = new ThreadletAPI(access_token) - const forums = await api.getForums() - app = new App(forums) -} \ No newline at end of file +// const forums = await api.getForums() +// app = new App(forums) +// } \ No newline at end of file diff --git a/client/src/matrix.ts b/client/src/matrix.ts new file mode 100644 index 0000000..6caf9ed --- /dev/null +++ b/client/src/matrix.ts @@ -0,0 +1,15 @@ +import { createClient } from "matrix-js-sdk"; + +export const matrix = createClient({ + baseUrl: localStorage.getItem("homeserver") || "https://matrix.org", + accessToken: localStorage.getItem("accessToken") || undefined, + userId: localStorage.getItem("userId") || undefined, + deviceId: localStorage.getItem("deviceId") || undefined, +}); + +export async function initMatrixClient() { + if(!(localStorage.getItem("accessToken") && localStorage.getItem("userId") && localStorage.getItem("deviceId"))) { + return; + } + await matrix.startClient(); +} diff --git a/client/style.css b/client/style.css index 21ce824..5ac5a71 100644 --- a/client/style.css +++ b/client/style.css @@ -59,7 +59,8 @@ body { display: flex; } -#channels { +#channels, +#members { display: flex; flex-direction: column; height: 100vh; @@ -258,9 +259,10 @@ body { } #post-content, -#messages { +#events { overflow: hidden auto; scrollbar-gutter: stable; + width: 100%; } #post-content { @@ -268,7 +270,7 @@ body { max-height: 50%; } -#messages { +#events { display: flex; flex-direction: column; flex: 1 1 auto; @@ -602,4 +604,97 @@ body { border-radius: 20px; font-size: 10px; font-family: monospace; -} \ No newline at end of file +} + +dialog { + border: 2px solid #202020; + border-radius: 8px; +} + +#login { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; +} + +#loginTitle { + position: absolute; + top: anchor(top); + left: anchor(center); + transform: translateX(-50%); + font-size: 4vw; + position-anchor: --morpheusAnchor; +} + +#morpehusImg { + anchor-name: --morpheusAnchor; +} + +.loginButton { + width: 8vw; + height: 8vw; + font-size: 1.5vw; + background: none; + border: none; + border-radius: 100%; + cursor: pointer; + position-anchor: --morpheusAnchor; + position: absolute; +} + +.loginButton:hover { + background: radial-gradient(#ffffff50, transparent); +} + +#members { + gap: var(--gap-half); +} + +.member { + display: flex; + gap: var(--gap-half); + align-items: center; + margin-left: 10px; +} + +.member:first-of-type { + margin-top: 10px; +} + +.member-avatar { + width: 30px; + aspect-ratio: 1 / 1; + border-radius: 100%; + font-size: 14px !important; +} + +.context-menu-content { + background-color: var(--background-secondary); + border: 2px solid #40444b; + border-radius: 5px; + padding: 5px 0; + display: flex; + flex-direction: column; + gap: 5px; +} + +.form-checkbox-input input { + width: unset !important; +} + +.form-checkbox-input { + display: flex; + gap: var(--gap-half); +} + +.message-content { + max-width: 100%; + overflow-y: scroll; +} + +[data-mx-spoiler] { + filter: blur(5px); + transition: filter 0.3s; + cursor: pointer; +} diff --git a/client/vite.config.js b/client/vite.config.js index c6f0b2b..2ee125d 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -25,7 +25,7 @@ export default defineConfig({ }, }, hmr: { - protocol: "wss", + protocol: "ws", // path: "/.proxy/" }, allowedHosts: [dev_config.vite?.host].filter(Boolean),