Initial code
This commit is contained in:
commit
1f20a611da
26 changed files with 1050 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
dist
|
||||
1
auth.json
Normal file
1
auth.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"secretKey":"XT0HBMKvfXV9zp8r1CFuIHU4XWLps6qkfabacrxdkNQ="}
|
||||
432
package-lock.json
generated
Normal file
432
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
{
|
||||
"name": "aslobot-matrix",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "aslobot-matrix",
|
||||
"version": "0.1.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"matrix-js-sdk": "^39.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.0.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
||||
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@matrix-org/matrix-sdk-crypto-wasm": {
|
||||
"version": "15.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-15.3.0.tgz",
|
||||
"integrity": "sha512-QyxHvncvkl7nf+tnn92PjQ54gMNV8hMSpiukiDgNrqF6IYwgySTlcSdkPYdw8QjZJ0NR6fnVrNzMec0OohM3wA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
|
||||
"integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"dev": true,
|
||||
"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/node": {
|
||||
"version": "25.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
|
||||
"integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"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/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"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/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/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",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"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/is-network-error": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz",
|
||||
"integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"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": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/loglevel": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz",
|
||||
"integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/loglevel"
|
||||
}
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"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": "39.4.0",
|
||||
"resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-39.4.0.tgz",
|
||||
"integrity": "sha512-0RZLcwbMxMTU+ORPhpFUnX8nDbKwLtdW20T6VesSxEwjKL5j2TM/mIt4u3h0HJiMh63PpAb2QUcNr0R82YfTOA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@matrix-org/matrix-sdk-crypto-wasm": "^15.3.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.14.0",
|
||||
"oidc-client-ts": "^3.0.1",
|
||||
"p-retry": "7",
|
||||
"sdp-transform": "^3.0.0",
|
||||
"unhomoglyph": "^1.0.6",
|
||||
"uuid": "13"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/matrix-widget-api": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/matrix-widget-api/-/matrix-widget-api-1.15.0.tgz",
|
||||
"integrity": "sha512-Yu9rX9wyF3A1sqviKgiYHz8aGgL3HhJe9OXKi/lccr1eZnNb6y+ELdbshTjs+VLKM4rkTWt6CE3THsw3f/CZhg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/events": "^3.0.0",
|
||||
"events": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/oidc-client-ts": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.4.1.tgz",
|
||||
"integrity": "sha512-jNdst/U28Iasukx/L5MP6b274Vr7ftQs6qAhPBCvz6Wt5rPCA+Q/tUmCzfCHHWweWw5szeMy2Gfrm1rITwUKrw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"jwt-decode": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/p-retry": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-7.1.1.tgz",
|
||||
"integrity": "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-network-error": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/sdp-transform": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-3.0.0.tgz",
|
||||
"integrity": "sha512-gfYVRGxjHkGF2NPeUWHw5u6T/KGFtS5/drPms73gaSuMaVHKCY3lpLnGDfswVQO0kddeePoti09AwhYP4zA8dQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"sdp-verify": "checker.js"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"v8-compile-cache-lib": "^3.0.1",
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"ts-node": "dist/bin.js",
|
||||
"ts-node-cwd": "dist/bin-cwd.js",
|
||||
"ts-node-esm": "dist/bin-esm.js",
|
||||
"ts-node-script": "dist/bin-script.js",
|
||||
"ts-node-transpile-only": "dist/bin-transpile.js",
|
||||
"ts-script": "dist/bin-script-deprecated.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": ">=1.2.50",
|
||||
"@swc/wasm": ">=1.2.50",
|
||||
"@types/node": "*",
|
||||
"typescript": ">=2.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@swc/wasm": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"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/uuid": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
|
||||
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist-node/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
package.json
Normal file
21
package.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "aslobot-matrix",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"license": "ISC",
|
||||
"author": "",
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "npx tsc",
|
||||
"start": "npx tsc && node dist/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.0.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"matrix-js-sdk": "^39.4.0"
|
||||
}
|
||||
}
|
||||
33
src/auth/auth.ts
Normal file
33
src/auth/auth.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||
import crypto from "crypto";
|
||||
import type { BotAuth, BotAuthJson } from "./types.js";
|
||||
|
||||
const newAuth = (): BotAuth => {
|
||||
return {
|
||||
secretKey: new Uint8Array(crypto.randomBytes(32)),
|
||||
};
|
||||
};
|
||||
|
||||
const saveAuth = (authPath: string, auth: BotAuth) => {
|
||||
const authJson: BotAuthJson = {
|
||||
secretKey: Buffer.from(auth.secretKey).toString("base64"),
|
||||
};
|
||||
const json = JSON.stringify(authJson);
|
||||
|
||||
writeFileSync(authPath, json);
|
||||
};
|
||||
|
||||
const loadAuth = (authPath: string): BotAuth => {
|
||||
if (!existsSync(authPath)) {
|
||||
saveAuth(authPath, newAuth());
|
||||
}
|
||||
|
||||
const json = readFileSync(authPath).toString();
|
||||
const authJson = JSON.parse(json) as BotAuthJson;
|
||||
|
||||
return {
|
||||
secretKey: new Uint8Array(Buffer.from(authJson.secretKey, "base64")),
|
||||
};
|
||||
};
|
||||
|
||||
export { newAuth, saveAuth, loadAuth };
|
||||
2
src/auth/index.ts
Normal file
2
src/auth/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./auth.js";
|
||||
export * from "./types.js";
|
||||
9
src/auth/types.ts
Normal file
9
src/auth/types.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
interface BotAuth {
|
||||
secretKey: Uint8Array<ArrayBuffer>;
|
||||
}
|
||||
|
||||
interface BotAuthJson {
|
||||
secretKey: string;
|
||||
}
|
||||
|
||||
export { type BotAuth, type BotAuthJson };
|
||||
18
src/config.json
Normal file
18
src/config.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"baseUrl": "https://matrix.aslan2142.space",
|
||||
"userId": "@aslobot:aslan2142.space",
|
||||
"authPath": "auth.json",
|
||||
"storePath": "store.json",
|
||||
"auth": {
|
||||
"accessToken": "mct_iW6Cif22H34s5yAHrmqfBQUsMrGaH2_0QWfYU",
|
||||
"deviceId": "PBz1Ig9c3p"
|
||||
},
|
||||
"app": {
|
||||
"triggerPrefix": "!",
|
||||
"experience": {
|
||||
"gain": 5,
|
||||
"startingRequirement": 50,
|
||||
"timeout": 60000
|
||||
}
|
||||
}
|
||||
}
|
||||
3
src/config.ts
Normal file
3
src/config.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import config from "./config.json" with { type: "json" };
|
||||
|
||||
export { config };
|
||||
0
src/consts.ts
Normal file
0
src/consts.ts
Normal file
51
src/helpers.ts
Normal file
51
src/helpers.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { config } from "./config.js";
|
||||
import { state } from "./store/store.js";
|
||||
import { type IUser, type TRole } from "./store/types.js";
|
||||
import type { IRank } from "./types.js";
|
||||
|
||||
const getUserById = (userId: string): IUser => {
|
||||
return (
|
||||
state.users.find((user) => user.id === userId) ?? {
|
||||
id: ":",
|
||||
role: "NONE",
|
||||
experience: 0,
|
||||
lastMessageTimestamp: 0,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const checkRoles = (roles: TRole[], userId: string) => {
|
||||
const user = getUserById(userId);
|
||||
return roles.includes(user.role);
|
||||
};
|
||||
|
||||
const getRank = (experience: number): IRank => {
|
||||
let tmpExperience = experience;
|
||||
let expToNextRank = config.app.experience.startingRequirement;
|
||||
let rank = 0;
|
||||
|
||||
while (tmpExperience >= expToNextRank) {
|
||||
rank++;
|
||||
tmpExperience -= expToNextRank;
|
||||
expToNextRank = expToNextRank *= 1.2;
|
||||
}
|
||||
|
||||
return {
|
||||
rank: rank,
|
||||
experience: Math.floor(experience),
|
||||
experienceInRank: Math.floor(tmpExperience),
|
||||
expToNextRank: Math.floor(expToNextRank),
|
||||
};
|
||||
};
|
||||
|
||||
const getUserName = (user: IUser): string => {
|
||||
const userPattern = /@[a-zA-Z0-9]*/;
|
||||
const match = user.id.match(userPattern)?.at(0);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return match.replaceAll("@", "");
|
||||
};
|
||||
|
||||
export { getUserById, checkRoles, getRank, getUserName };
|
||||
41
src/index.ts
Normal file
41
src/index.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import config from "./config.json" with { type: "json" };
|
||||
|
||||
import { MatrixClient, createClient, ClientEvent } from "matrix-js-sdk";
|
||||
import { registerModules } from "./modules/module.js";
|
||||
|
||||
let matrixClient: MatrixClient | undefined = undefined;
|
||||
|
||||
const initialize = async (): Promise<number> => {
|
||||
matrixClient = createClient({
|
||||
baseUrl: config.baseUrl,
|
||||
userId: config.userId,
|
||||
accessToken: config.auth.accessToken,
|
||||
deviceId: config.auth.deviceId,
|
||||
});
|
||||
|
||||
matrixClient.once(ClientEvent.Sync, function (state) {
|
||||
if (state === "PREPARED") {
|
||||
console.log("prepared");
|
||||
}
|
||||
});
|
||||
|
||||
matrixClient.startClient({ initialSyncLimit: 1 });
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
const listen = async () => {
|
||||
if (!matrixClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
registerModules(matrixClient);
|
||||
};
|
||||
|
||||
const initCode = await initialize();
|
||||
|
||||
if (initCode > 0) {
|
||||
process.exit(initCode);
|
||||
}
|
||||
|
||||
listen();
|
||||
47
src/modules/admin/admin.ts
Normal file
47
src/modules/admin/admin.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import { MatrixClient } from "matrix-js-sdk";
|
||||
import type { ICallbackStore } from "../types.js";
|
||||
import { config } from "../../config.js";
|
||||
import { load, save } from "../../store/store.js";
|
||||
|
||||
let client: MatrixClient;
|
||||
|
||||
const registerModuleAdmin = (
|
||||
matrixClient: MatrixClient,
|
||||
callbackStore: ICallbackStore,
|
||||
) => {
|
||||
client = matrixClient;
|
||||
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}shutdown`,
|
||||
allowedRoles: ["ADMIN"],
|
||||
callbackFunc: onShutdown,
|
||||
});
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}loaddata`,
|
||||
allowedRoles: ["MODERATOR", "ADMIN"],
|
||||
callbackFunc: onLoadData,
|
||||
});
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}savedata`,
|
||||
allowedRoles: ["MODERATOR", "ADMIN"],
|
||||
callbackFunc: onSaveData,
|
||||
});
|
||||
};
|
||||
|
||||
const onShutdown = (text: string) => {
|
||||
if (!text.includes("nosave")) {
|
||||
save();
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
const onLoadData = () => {
|
||||
load();
|
||||
};
|
||||
|
||||
const onSaveData = () => {
|
||||
save();
|
||||
};
|
||||
|
||||
export { registerModuleAdmin };
|
||||
1
src/modules/admin/index.ts
Normal file
1
src/modules/admin/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./admin.js";
|
||||
63
src/modules/base/base.ts
Normal file
63
src/modules/base/base.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { MatrixClient } from "matrix-js-sdk";
|
||||
import type { ICallbackStore } from "../types.js";
|
||||
import { config } from "../../config.js";
|
||||
|
||||
let client: MatrixClient;
|
||||
|
||||
const registerModuleTest = (
|
||||
matrixClient: MatrixClient,
|
||||
callbackStore: ICallbackStore,
|
||||
) => {
|
||||
client = matrixClient;
|
||||
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}ping`,
|
||||
callbackFunc: onPing,
|
||||
});
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}say `,
|
||||
callbackFunc: onSay,
|
||||
});
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}help`,
|
||||
callbackFunc: onHelp,
|
||||
});
|
||||
};
|
||||
|
||||
const onPing = (_text: string, roomId: string) => {
|
||||
client.sendTextMessage(roomId, "Pong!");
|
||||
};
|
||||
|
||||
const onSay = (text: string, roomId: string) => {
|
||||
const trigger = `${config.app.triggerPrefix}say `;
|
||||
|
||||
client.sendTextMessage(roomId, text.replace(trigger, ""));
|
||||
};
|
||||
|
||||
const onHelp = (_text: string, roomId: string) => {
|
||||
client.sendHtmlMessage(
|
||||
roomId,
|
||||
"",
|
||||
`<h3>Role: User</h3>
|
||||
<ul>
|
||||
<li><b>!ping</b> - Pong!</li>
|
||||
<li><b>!say {text}</b> - Repeats your message</li>
|
||||
<li><b>!help</b> - Prints this help message</li>
|
||||
<li><b>!rank</b> - Prints your rank and experience</li>
|
||||
<li><b>!leaderboard</b> - Prints total user ranking</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<h3>Role: Moderator</h3>
|
||||
<ul>
|
||||
<li><b>!load</b> - Load bot data</li>
|
||||
<li><b>!save</b> - Save bot data</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<h3>Role: Admin</h3>
|
||||
<ul>
|
||||
<li><b>!shutdown</b> - Shutdown bot</li>
|
||||
</ul>`,
|
||||
);
|
||||
};
|
||||
|
||||
export { registerModuleTest };
|
||||
1
src/modules/base/index.ts
Normal file
1
src/modules/base/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./base.js";
|
||||
55
src/modules/global.ts
Normal file
55
src/modules/global.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import type { MatrixClient } from "matrix-js-sdk";
|
||||
import type { TRole } from "../store/types.js";
|
||||
import { getRank, getUserById } from "../helpers.js";
|
||||
import { config } from "../config.js";
|
||||
import { state } from "../store/store.js";
|
||||
|
||||
const onAnyMessage = (
|
||||
client: MatrixClient,
|
||||
_text: string,
|
||||
roomId: string,
|
||||
sender: string,
|
||||
) => {
|
||||
const date = Date.now();
|
||||
|
||||
const user = getUserById(sender);
|
||||
if (user.id === ":") {
|
||||
state.users.push({
|
||||
id: sender,
|
||||
role: "USER",
|
||||
experience: 0,
|
||||
lastMessageTimestamp: date,
|
||||
});
|
||||
return onAnyMessage(client, _text, roomId, sender);
|
||||
}
|
||||
|
||||
const rankBefore = getRank(user.experience);
|
||||
|
||||
if (date > user.lastMessageTimestamp + config.app.experience.timeout) {
|
||||
user.experience += config.app.experience.gain;
|
||||
}
|
||||
user.lastMessageTimestamp = date;
|
||||
|
||||
const rankAfter = getRank(user.experience);
|
||||
if (rankAfter.rank > rankBefore.rank) {
|
||||
client.sendHtmlMessage(
|
||||
roomId,
|
||||
"",
|
||||
`${sender} - You are now rank <b>${rankAfter.rank}</b>`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const onMissingRole = (
|
||||
client: MatrixClient,
|
||||
userRole: TRole,
|
||||
roomId: string,
|
||||
) => {
|
||||
client.sendHtmlMessage(
|
||||
roomId,
|
||||
"",
|
||||
`You are missing the required role.<br/>Your current role is <b>${userRole}</b>`,
|
||||
);
|
||||
};
|
||||
|
||||
export { onAnyMessage, onMissingRole };
|
||||
102
src/modules/module.ts
Normal file
102
src/modules/module.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import {
|
||||
MatrixClient,
|
||||
MatrixEvent,
|
||||
RoomEvent,
|
||||
type IContent,
|
||||
} from "matrix-js-sdk";
|
||||
import { registerModuleTest } from "./base/base.js";
|
||||
import type { ICallback, ICallbackStore } from "./types.js";
|
||||
import { registerModuleAdmin } from "./admin/admin.js";
|
||||
import { registerModuleUser } from "./user/user.js";
|
||||
import { checkRoles, getUserById } from "../helpers.js";
|
||||
import { onAnyMessage, onMissingRole } from "./global.js";
|
||||
import { config } from "../config.js";
|
||||
|
||||
const callbacks: ICallbackStore = {
|
||||
messageCallbacks: [],
|
||||
};
|
||||
|
||||
const checkMessageCallback = (
|
||||
client: MatrixClient,
|
||||
text: string,
|
||||
callback: ICallback,
|
||||
roomId: string,
|
||||
sender: string,
|
||||
) => {
|
||||
if (callback.allowedRooms && !callback.allowedRooms.includes(roomId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callback.startCondition && !text.startsWith(callback.startCondition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
callback.includesCondition &&
|
||||
!text.includes(callback.includesCondition)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callback.allowedRoles && !checkRoles(callback.allowedRoles, sender)) {
|
||||
onMissingRole(client, getUserById(sender).role, roomId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const registerModules = (client: MatrixClient) => {
|
||||
const startupTime = Date.now();
|
||||
|
||||
client.on(RoomEvent.Timeline, (event: MatrixEvent) => {
|
||||
const ts = event.getTs();
|
||||
if (ts < startupTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getType() !== "m.room.message") {
|
||||
return;
|
||||
}
|
||||
|
||||
const content = event.getContent<IContent>();
|
||||
const body = content?.body;
|
||||
if (!body || !client) {
|
||||
return;
|
||||
}
|
||||
|
||||
const roomId = event.getRoomId();
|
||||
const sender = event.getSender();
|
||||
if (!roomId || !sender) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender === config.userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Message from ${sender} in ${roomId}: ${body}`);
|
||||
|
||||
onAnyMessage(client, body.toString(), roomId, sender);
|
||||
|
||||
callbacks.messageCallbacks.forEach((callback) => {
|
||||
if (
|
||||
checkMessageCallback(
|
||||
client,
|
||||
body.toString(),
|
||||
callback,
|
||||
roomId,
|
||||
sender,
|
||||
)
|
||||
) {
|
||||
callback.callbackFunc(body.toString(), roomId, sender);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
registerModuleTest(client, callbacks);
|
||||
registerModuleAdmin(client, callbacks);
|
||||
registerModuleUser(client, callbacks);
|
||||
};
|
||||
|
||||
export { registerModules };
|
||||
15
src/modules/types.ts
Normal file
15
src/modules/types.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import type { TRole } from "../store/types.js";
|
||||
|
||||
interface ICallbackStore {
|
||||
messageCallbacks: ICallback[];
|
||||
}
|
||||
|
||||
interface ICallback {
|
||||
startCondition?: string;
|
||||
includesCondition?: string;
|
||||
allowedRoles?: TRole[];
|
||||
allowedRooms?: string;
|
||||
callbackFunc: (text: string, roomId: string, sender: string) => void;
|
||||
}
|
||||
|
||||
export { type ICallbackStore, type ICallback };
|
||||
1
src/modules/user/index.ts
Normal file
1
src/modules/user/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./user.js";
|
||||
57
src/modules/user/user.ts
Normal file
57
src/modules/user/user.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import { MatrixClient } from "matrix-js-sdk";
|
||||
import type { ICallbackStore } from "../types.js";
|
||||
import { config } from "../../config.js";
|
||||
import { getRank, getUserById, getUserName } from "../../helpers.js";
|
||||
import { state } from "../../store/store.js";
|
||||
import type { IUser } from "../../store/types.js";
|
||||
let client: MatrixClient;
|
||||
|
||||
const registerModuleUser = (
|
||||
matrixClient: MatrixClient,
|
||||
callbackStore: ICallbackStore,
|
||||
) => {
|
||||
client = matrixClient;
|
||||
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}rank`,
|
||||
callbackFunc: onRank,
|
||||
});
|
||||
callbackStore.messageCallbacks.push({
|
||||
startCondition: `${config.app.triggerPrefix}leaderboard`,
|
||||
callbackFunc: onLeaderboard,
|
||||
});
|
||||
};
|
||||
|
||||
const onRank = (_text: string, roomId: string, sender: string) => {
|
||||
const rank = getRank(getUserById(sender).experience);
|
||||
|
||||
client.sendHtmlMessage(
|
||||
roomId,
|
||||
"",
|
||||
`<h3>Your Rank: ${rank.rank}</h3>
|
||||
<i>Next rank progress: ${rank.experienceInRank}/${rank.expToNextRank}exp</i>`,
|
||||
);
|
||||
};
|
||||
|
||||
const onLeaderboard = (_text: string, roomId: string) => {
|
||||
const mapUsersToLeaderboard = (user: IUser): string => {
|
||||
const rank = getRank(user.experience);
|
||||
|
||||
return `<li>${getUserName(user)}: rank ${rank.rank} (${rank.experienceInRank}/${rank.expToNextRank}exp)</li>`;
|
||||
};
|
||||
|
||||
const users = state.users.sort(
|
||||
(userA, userB) => userB.experience - userA.experience,
|
||||
);
|
||||
|
||||
client.sendHtmlMessage(
|
||||
roomId,
|
||||
"",
|
||||
`<h3>Leaderboard</h3>
|
||||
<ul>
|
||||
${users.map(mapUsersToLeaderboard)}
|
||||
</ul>`,
|
||||
);
|
||||
};
|
||||
|
||||
export { registerModuleUser };
|
||||
2
src/store/index.ts
Normal file
2
src/store/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./store.js";
|
||||
export * from "./types.js";
|
||||
25
src/store/store.ts
Normal file
25
src/store/store.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import config from "../config.json" with { type: "json" };
|
||||
|
||||
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||
|
||||
import type { IState } from "./types.js";
|
||||
|
||||
let state: IState = {
|
||||
users: [],
|
||||
};
|
||||
|
||||
const load = () => {
|
||||
if (!existsSync(config.storePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const json = readFileSync(config.storePath).toString();
|
||||
state = JSON.parse(json) as IState;
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
const json = JSON.stringify(state);
|
||||
writeFileSync(config.storePath, json);
|
||||
};
|
||||
|
||||
export { state, load, save };
|
||||
14
src/store/types.ts
Normal file
14
src/store/types.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
interface IState {
|
||||
users: IUser[];
|
||||
}
|
||||
|
||||
interface IUser {
|
||||
id: string;
|
||||
role: TRole;
|
||||
experience: number;
|
||||
lastMessageTimestamp: number;
|
||||
}
|
||||
|
||||
type TRole = "NONE" | "USER" | "MODERATOR" | "ADMIN";
|
||||
|
||||
export { type IState, type IUser, type TRole };
|
||||
8
src/types.ts
Normal file
8
src/types.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
interface IRank {
|
||||
rank: number;
|
||||
experience: number;
|
||||
experienceInRank: number;
|
||||
expToNextRank: number;
|
||||
}
|
||||
|
||||
export { type IRank };
|
||||
46
tsconfig.json
Normal file
46
tsconfig.json
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
// Visit https://aka.ms/tsconfig to read more about this file
|
||||
"compilerOptions": {
|
||||
// File Layout
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
|
||||
// Environment Settings
|
||||
// See also https://aka.ms/tsconfig/module
|
||||
"module": "nodenext",
|
||||
"target": "esnext",
|
||||
"types": ["node"],
|
||||
// For nodejs:
|
||||
// "lib": ["esnext"],
|
||||
// "types": ["node"],
|
||||
// and npm install -D @types/node
|
||||
|
||||
// Other Outputs
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
|
||||
// Stricter Typechecking Options
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
|
||||
// Style Options
|
||||
// "noImplicitReturns": true,
|
||||
// "noImplicitOverride": true,
|
||||
// "noUnusedLocals": true,
|
||||
// "noUnusedParameters": true,
|
||||
// "noFallthroughCasesInSwitch": true,
|
||||
// "noPropertyAccessFromIndexSignature": true,
|
||||
|
||||
// Recommended Options
|
||||
"strict": true,
|
||||
"jsx": "react-jsx",
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
"moduleDetection": "force",
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
},
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue