Monoreponir (#1046)

* Move src to apps/draupnir/src

https://github.com/the-draupnir-project/planning/issues/100

* Move package.json

https://github.com/the-draupnir-project/planning/issues/100

* Add matrix-basic-types to monorepo.

Get everything working including linting and prettier :3

https://github.com/the-draupnir-project/planning/issues/100

* Add interface-manager to monorepo.

This was a bitch because apparently we forgot to delete node_modules
before creating the workspace package.json. So it had linked a bunch
of local stuff like was in node_modules for Draupnir...

Anyways i think we're still on track.

https://github.com/the-draupnir-project/planning/issues/100

* idk why there are prettier changes in apps but there are.

* Add matrix-protection-suite to monorepo.

https://github.com/the-draupnir-project/planning/issues/100

* Add matrix-protection-suite-for-matrix-bot-sdk

https://github.com/the-draupnir-project/planning/issues/100

We will need to add the real upstreams and versions and remove the
file links as we publish the packages.

* Move mps-interface-adaptor into monorepo

https://github.com/the-draupnir-project/planning/issues/100

Wohoo, i think only draupnir is left now?

* Move Draupnir test files to draupnir directory smh smh smh.

https://github.com/the-draupnir-project/planning/issues/100

* Fix typescript config for tests and eslint.

Now we get proper linting and type checking of tests.

https://github.com/the-draupnir-project/planning/issues/100

* WIP Integrating draupnir into monorepo tooling...

https://github.com/the-draupnir-project/planning/issues/100

We need to stop aliasing bot-sdk but we should first check that
upstream is using a consistent name too.

* Remove matrix-bot-sdk alias for vector fork.

https://github.com/the-draupnir-project/planning/issues/100

* Add top command description type and weave through API.

A more recent version of typescript meant that the exectutor's
contravariance got checked which destroyed the API so we had to make a
top type for command descriptions and parametrise some of the API.

https://github.com/the-draupnir-project/planning/issues/100

* Fix typescript errors related to class property initialisation changes.

https://www.typescriptlang.org/tsconfig/#useDefineForClassFields

Seems like they were using defineProperty before which meant
properites were initialised after the constructor ran.

Honestly i like that more but we're going to stick with what they
intend to be the default.

https://github.com/the-draupnir-project/planning/issues/100

* Fix tests lacking fixtures context.

https://github.com/the-draupnir-project/planning/issues/100

* Fix typescript errors related to error destructuring in tests.

https://github.com/the-draupnir-project/planning/issues/100

* Pin postgres package to workaround upstream issue

https://github.com/porsager/postgres/issues/1150
Documented in DEPENDENCIES.md

https://github.com/the-draupnir-project/planning/issues/100

* Fix contravariance issue in hash store helper.

Part of the TS 5.9 upgrade fallout.
https://github.com/the-draupnir-project/planning/issues/100

* Fix minor typescript 5.9 migration issuess

All typescript errors finished, yay.

* Fix REUSE missing headers.

* Fix assets script in draupnir app.

* Add Draupnir to eslint scope

* Remove the appservice web API.

There are too many eslint errors here to do with unsafe parsing of
properties from the body etc. And there's actually no consumers to
this API. It's also a widget API, and all it does is provision the bot
and nothing more.

* Fix eslint config for DeadDocumentJSX.

It wasn't working well with the jsx templates.
We should probably delete the tsconfig.eslint.json shite now.

* Update src/utils.ts for eslint.

This shit is legacy i hate it.

* Fix eslint errors in config.

Really this is paint over rot since the config doesn't have a schema,
and we can't really make one either.

* Fix eslint issues in ReportManager.

This code is diabolical. It hasn't really been fixed that will take
refactoring and making sure people don't write this sorts of bad code
ever again. Which thankfully we have process in place for.

* Fix clientHelper eslint issues.

* Fix eslint for ImportCommand.

* Grinding eslint fml.

* Fix miscellaneous eslint issues.

* allow no-deprecate for logMessage.

shit's being annoying.

* Fix remaining eslint issues...

We also deleted one of the scripts used to evaluate the performance of
various endpoints, which we were not using.

* Give bot toggle asyncDispose for code consistency.

* Fix package.json access issues.

* Adjust Docker and CI for new app location in monorepo.

* Fix broken integration tests.

* Remove prepare script from matrix-protection-suite package.

Isn't needed anymore


* Fix build:all script missing base files.

* Remove test script from matrix-protection-suite-for-matrix-bot-sdk

It doesn't have any tests :/

* Order of setup is wrong in integration test workflows.

* Fix mps interface adaptor doesn't have any tests.

* Fix appservice registration for test harness.

* Fix matrix-basic-types jest configuration

* Fix no build step in mjolnir.yaml

* Transfer common dev dependencies to the workspace root.


They were just wrong.
This commit is contained in:
Gnuxie
2026-03-19 16:13:14 +00:00
committed by GitHub
parent 1372c17db9
commit 879e822332
604 changed files with 53819 additions and 5486 deletions
+6 -7
View File
@@ -1,18 +1,17 @@
# SPDX-FileCopyrightText: 2024 Aminda Suomalainen <suomalainen+git@mikaela.info>
# SPDX-FileCopyrightText: 2024 Gnuxie <Gnuxie@protonmail.com>
#
# SPDX-License-Identifier: CC0-1.0
# SPDX-License-Identifier: 0BSD
root = true
[*]
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[{LICENSE,NOTICE,*.{md,yml,yaml,json,txt}}]
[LICENSES/**.txt]
trim_trailing_whitespace = false
indent_style = space
indent_size = unset
+11 -10
View File
@@ -26,9 +26,9 @@ jobs:
with:
node-version: "20"
- run: corepack enable
- run: corepack yarn install
- run: corepack yarn build
- run: corepack yarn lint
- run: corepack npm install
- run: corepack npm run build:all
- run: corepack npm run lint
unit:
name: Unit tests
runs-on: ubuntu-latest
@@ -38,8 +38,9 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: "20"
- run: corepack yarn install
- run: corepack yarn test:unit
- run: corepack npm install
- run: corepack npm run build:all
- run: corepack npm run test
integration:
name: Integration tests
runs-on: ubuntu-latest
@@ -54,10 +55,10 @@ jobs:
with:
crate: mx-tester
version: "0.3.3"
- name: Setup dependencies
run: corepack npm install && corepack npm run build:all
- name: Setup image
run: RUST_LOG=debug,hyper=info,rusttls=info mx-tester build up
- name: Setup dependencies
run: corepack yarn install
- name: Run tests
run: RUST_LOG=debug,hyper=info,rusttls=info mx-tester run
- name: Cleanup
@@ -76,11 +77,11 @@ jobs:
with:
crate: mx-tester
version: "0.3.3"
- name: Setup dependencies
run: corepack npm install && corepack npm run build:all
- name: Setup image
run: RUST_LOG=debug,hyper=info,rusttls=info mx-tester build up
- name: Setup dependencies
run: corepack yarn install
- name: Run tests
run: corepack yarn test:appservice:integration
run: corepack npm run -w apps/draupnir test:appservice:integration
- name: Cleanup
run: mx-tester down
+6 -1
View File
@@ -8,7 +8,12 @@ config/*
# Draupnir test data
draupnir-registration.yaml
test/harness/mjolnir-data/*
# Monorepo
**/node_modules/
**/dist/
**/lib/
*.tsbuildinfo
# Misc
+15 -10
View File
@@ -1,13 +1,13 @@
# SPDX-FileCopyrightText: 2024 Aminda Suomalainen <suomalainen+git@mikaela.info>
# SPDX-FileCopyrightText: 2024 Gnuxie <Gnuxie@protonmail.com>
#
# SPDX-License-Identifier: CC0-1.0
# SPDX-License-Identifier: 0BSD
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
# See https://pre-commit.ci for more information
ci:
autoupdate_schedule: weekly
skip: [yarn-lint]
autoupdate_schedule: monthly
skip: [npm-lint, npm-build]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
@@ -18,9 +18,6 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: check-illegal-windows-names
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
rev: "3.6.1"
hooks:
@@ -32,10 +29,18 @@ repos:
- id: reuse
- repo: local
hooks:
- id: yarn-lint
name: linter
entry: corepack yarn lint
- id: npm-build
name: npm build
entry: npm run build:all
language: system
pass_filenames: false
- repo: local
hooks:
- id: npm-lint
name: linter
entry: npm run lint
language: system
pass_filenames: false
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.37.0
hooks:
+6
View File
@@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: 2024 Gnuxie <Gnuxie@protonmail.com>
#
# SPDX-License-Identifier: AFL-3.0
dist
packages/matrix-protection-suite/docs
+1 -1
View File
@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: 2024 Gnuxie <Gnuxie@protonmail.com>
#
# SPDX-License-Identifier: CC0-1.0
# SPDX-License-Identifier: 0BSD
tabWidth: 2
useTabs: false
-1
View File
@@ -752,7 +752,6 @@ Special thanks to all contributors who helped in the beta programme: @avdb13,
https://github.com/the-draupnir-project/Draupnir/issues/622.
- The `JoinWaveShortCircuitProtection` has been improved:
- The `JoinWaveShortCircuitProtection` now uses a leaky bucket token
algorithm, prior to this the entire bucket got dumped after a preconfigured
time.
+36
View File
@@ -0,0 +1,36 @@
<!--
SPDX-FileCopyrightText: 2026 Gnuxie <Gnuxie@protonmail.com>
SPDX-License-Identifier: 0BSD
-->
# Dependencies
## Pinned dependencies
### @vector-im/matrix-bot-sdk
This is pinned and overridden because we need to have the exact same version for
all dependencies. As we create and pass `MatrixClient` through Draupnir,
matrix-protection-suite-for-matrix-bot-sdk, the vector bot-sdk fork itself, and
also matrix-appservice-bridge.
### postgres
https://github.com/porsager/postgres/issues/1143
This is pinned specifically as a work around for this issue.
## Workspace dependencies
Workspace dependencies should be kept at their same version and changesets
should be used for any changes. Package release should only be made from the
main branch once changesets have been merged and the associated package versions
bumped. This allows for the workspace state to always be used to build Draupnir
reproducibly on any branch of PR.
## Developer tooling
Developer tooling related `devDependencies` should be kept in the root package
unless it is not common to most packages. This is to make sure the versioning
remains consistent without relying on npm to do that.
+5 -6
View File
@@ -10,16 +10,15 @@ COPY . /tmp/src
RUN cd /tmp/src && git describe > version.txt.tmp && mv version.txt.tmp version.txt
# build and install
RUN cd /tmp/src \
&& yarn install --frozen-lockfile --network-timeout 100000 \
&& yarn build \
&& yarn install --frozen-lockfile --production --network-timeout 100000
&& npm ci \
&& npm run build \
&& npm prune --production
FROM node:20-slim as final-stage
COPY --from=build-stage /tmp/src/version.txt version.txt
COPY --from=build-stage /tmp/src/lib/ /draupnir/
COPY --from=build-stage /tmp/src/apps/draupnir /apps/draupnir
COPY --from=build-stage /tmp/src/packages /packages
COPY --from=build-stage /tmp/src/node_modules /node_modules
COPY --from=build-stage /tmp/src/draupnir-entrypoint.sh /
COPY --from=build-stage /tmp/src/package.json /
ENV NODE_ENV=production
ENV NODE_CONFIG_DIR=/data/config
+5
View File
@@ -0,0 +1,5 @@
Copyright (C) YEAR by AUTHOR EMAIL
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+18
View File
@@ -0,0 +1,18 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
+29 -11
View File
@@ -7,37 +7,55 @@ SPDX-PackageDownloadLocation = "https://github.com/the-draupnir-project/Draupnir
path = ".github/ISSUE_TEMPLATE/bug-report.md"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "CC0-1.0"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "CC0-1.0"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.base.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.all.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.eslint.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "REUSE.toml"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "CC0-1.0"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "yarn.lock"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "CC0-1.0"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "package-lock.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "NOTICE"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = "test/tsconfig.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "CC0-1.0"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "package.json"
+5
View File
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2026 Gnuxie <Gnuxie@protonmail.com>
#
# SPDX-License-Identifier: 0BSD
test/harness/mjolnir-data/*
+64
View File
@@ -0,0 +1,64 @@
version = 1
SPDX-PackageName = "Draupnir"
SPDX-PackageSupplier = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-PackageDownloadLocation = "https://github.com/the-draupnir-project/Draupnir"
[[annotations]]
path = ".github/ISSUE_TEMPLATE/bug-report.md"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.test.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "tsconfig.base.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "REUSE.toml"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "yarn.lock"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "package-lock.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "NOTICE"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "test/tsconfig.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = "package.json"
precedence = "aggregate"
SPDX-FileCopyrightText = "Gnuxie <Gnuxie@protonmail.com>"
SPDX-License-Identifier = "AFL-3.0"
+72
View File
@@ -0,0 +1,72 @@
{
"name": "draupnir",
"version": "2.9.0",
"description": "A moderation tool for Matrix",
"main": "lib/index.js",
"repository": "https://github.com/the-draupnir-project/Draupnir.git",
"author": "Gnuxie",
"license": "AFL-3.0",
"private": true,
"scripts": {
"build": "tsc --project test/tsconfig.json && npm run build:assets",
"build:assets": "cp src/protections/DraupnirNews/news.json dist/protections/DraupnirNews/news.json && npm run describe-version",
"describe-version": "(git describe > version.txt.tmp && mv version.txt.tmp version.txt) || true && rm -f version.txt.tmp",
"harness-registration": "node dist/appservice/cli.js -r -u \"http://host.docker.internal:9000\" --enable-source-maps",
"test:unit": "mocha --require './test/tsnode.cjs' --forbid-only 'test/unit/**/*.{ts,tsx}'",
"test:unit:single": "mocha --require test/tsnode.cjs",
"test:integration": "NODE_ENV=harness mocha --require test/tsnode.cjs --async-stack-traces --forbid-only --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json \"test/integration/**/*Test.ts\" -- --draupnir-config ../../config/harness.yaml",
"test:integration:single": "NODE_ENV=harness mocha --require test/tsnode.cjs --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json -- --draupnir-config ../../config/harness.yaml",
"test:appservice:integration": "NODE_ENV=harness mocha --require test/tsnode.cjs --async-stack-traces --forbid-only --timeout 300000 --project ./tsconfig.json \"test/appservice/integration/**/*Test.ts\" -- --draupnir-config ../../config/harness.yaml",
"test:appservice:integration:single": "NODE_ENV=harness mocha --require test/tsnode.cjs --timeout 300000 --project ./tsconfig.json -- --draupnir-config ../../config/harness.yaml",
"test:manual": "NODE_ENV=harness ts-node test/integration/manualLaunchScript.ts -- --draupnir-config ../../config/harness.yaml"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.9",
"@types/config": "^3.3.1",
"@types/crypto-js": "^4.2.2",
"@types/express": "^4.17.21",
"@types/html-to-text": "^8.0.1",
"@types/js-yaml": "^4.0.9",
"@types/jsdom": "21.1.7",
"@types/mocha": "^10.0.7",
"@types/nedb": "^1.8.16",
"@types/node": "^20.14.11",
"@types/pg": "^8.6.5",
"@types/request": "^2.48.12",
"crypto-js": "^4.2.0",
"expect": "^29.7.0",
"mocha": "^10.7.0",
"ts-auto-mock": "^3.7.4",
"ts-node": "^10.9.2"
},
"dependencies": {
"@gnuxie/typescript-result": "^1.0.0",
"@sentry/node": "^7.17.2",
"@sinclair/typebox": "0.34.13",
"@the-draupnir-project/interface-manager": "4.2.6",
"@the-draupnir-project/matrix-basic-types": "1.5.0",
"@the-draupnir-project/mps-interface-adaptor": "file:../../packages/mps-interface-adaptor",
"@vector-im/matrix-bot-sdk": "0.7.1-element.6",
"better-sqlite3": "^9.4.3",
"body-parser": "^1.20.2",
"config": "^3.3.9",
"express": "^4.19",
"html-to-text": "^8.0.0",
"js-yaml": "^4.1.0",
"jsdom": "^24.0.0",
"matrix-appservice-bridge": "10.3.1",
"matrix-protection-suite": "file:../../packages/matrix-protection-suite",
"matrix-protection-suite-for-matrix-bot-sdk": "file:../../packages/matrix-protection-suite-for-matrix-bot-sdk",
"pg": "^8.8.0",
"yaml": "^2.3.2"
},
"overrides": {
"@vector-im/matrix-bot-sdk": "0.7.1-element.6",
"@the-draupnir-project/matrix-basic-types": "$the-draupnir-project/matrix-basic-types",
"@the-draupnir-project/interface-manager": "$the-draupnir-project/interface-manager",
"matrix-protection-suite": "$matrix-protection-suite"
},
"engines": {
"node": ">=20.0.0"
}
}
@@ -39,7 +39,7 @@ import {
SynapseAdminClient,
} from "matrix-protection-suite-for-matrix-bot-sdk";
import { IConfig } from "./config";
import { LogLevel } from "matrix-bot-sdk";
import { LogLevel } from "@vector-im/matrix-bot-sdk";
import { RendererMessageCollector } from "./capabilities/RendererMessageCollector";
import { DraupnirRendererMessageCollector } from "./capabilities/DraupnirRendererMessageCollector";
import { renderProtectionFailedToStart } from "./protections/ProtectedRoomsSetRenderers";
@@ -97,7 +97,9 @@ export class Draupnir implements Client, MatrixAdaptorContext {
*/
public unlistedUserRedactionQueue = new UnlistedUserRedactionQueue();
private readonly commandDispatcher = makeDraupnirCommandDispatcher(this);
private readonly commandDispatcher: ReturnType<
typeof makeDraupnirCommandDispatcher
>;
public taskQueue: ThrottlingQueue;
/**
* Reporting back to the management room.
@@ -115,32 +117,21 @@ export class Draupnir implements Client, MatrixAdaptorContext {
public readonly reactionHandler: MatrixReactionHandler;
public readonly purgingDeactivate =
this.synapseAdminClient && this.stores.userRestrictionAuditLog
? new HomeserverUserPurgingDeactivate(
this.synapseAdminClient,
this.stores.userRestrictionAuditLog
)
: undefined;
public readonly purgingDeactivate:
| HomeserverUserPurgingDeactivate
| undefined;
private readonly timelineEventListener = this.handleTimelineEvent.bind(this);
public readonly capabilityMessageRenderer: RendererMessageCollector;
private readonly commandDispatcherTimelineListener =
makeCommandDispatcherTimelineListener(
this.managementRoom,
this.client,
this.commandDispatcher
);
private readonly commandDispatcherTimelineListener: ReturnType<
typeof makeCommandDispatcherTimelineListener
>;
private readonly JSInterfaceDispatcher: JSInterfaceCommandDispatcher<BasicInvocationInformation> =
makeDraupnirJSCommandDispatcher(this);
private readonly JSInterfaceDispatcher: JSInterfaceCommandDispatcher<BasicInvocationInformation>;
public readonly timelineRedactionQueue = new TimelineRedactionQueue(
this.clientPlatform.toRoomMessages(),
this.clientPlatform.toRoomEventRedacter()
);
public readonly timelineRedactionQueue: TimelineRedactionQueue;
private constructor(
public readonly client: MatrixSendClient,
@@ -163,6 +154,25 @@ export class Draupnir implements Client, MatrixAdaptorContext {
public readonly synapseAdminClient: SynapseAdminClient | undefined,
public readonly synapseHTTPAntispam: SynapseHttpAntispam | undefined
) {
this.commandDispatcher = makeDraupnirCommandDispatcher(this);
this.purgingDeactivate =
this.synapseAdminClient && this.stores.userRestrictionAuditLog
? new HomeserverUserPurgingDeactivate(
this.synapseAdminClient,
this.stores.userRestrictionAuditLog
)
: undefined;
this.commandDispatcherTimelineListener =
makeCommandDispatcherTimelineListener(
this.managementRoom,
this.client,
this.commandDispatcher
);
this.JSInterfaceDispatcher = makeDraupnirJSCommandDispatcher(this);
this.timelineRedactionQueue = new TimelineRedactionQueue(
this.clientPlatform.toRoomMessages(),
this.clientPlatform.toRoomEventRedacter()
);
this.managementRoomOutput = new ManagementRoomOutput(
this.managementRoomDetail,
this.clientUserID,
@@ -68,9 +68,8 @@ export function constructWebAPIs(draupnir: Draupnir): WebAPIs {
* The appservice also implements `SafeModeToggle` but has different requirements.
* This interface is exlusively used by the entrypoints to draupnir's bot mode.
*/
interface BotModeTogle extends SafeModeToggle {
interface BotModeTogle extends SafeModeToggle, AsyncDisposable {
encryptionInitialized(): Promise<void>;
stopEverything(): void;
startFromScratch(
options?: SafeModeToggleOptions
): Promise<Result<Draupnir | SafeModeDraupnir>>;
@@ -276,7 +275,7 @@ export class DraupnirBotModeToggle implements BotModeTogle {
public async maybeRecoverWithSafeMode(
error: ResultError,
options?: SafeModeToggleOptions | undefined
options?: SafeModeToggleOptions
): Promise<Result<SafeModeDraupnir>> {
switch (this.config.safeMode?.bootOption) {
case SafeModeBootOption.Never:
@@ -303,14 +302,9 @@ export class DraupnirBotModeToggle implements BotModeTogle {
public async encryptionInitialized(): Promise<void> {
if (this.draupnir !== null) {
try {
this.webAPIs = constructWebAPIs(this.draupnir);
await this.webAPIs.start();
await this.draupnir.startupComplete();
} catch (e) {
await this.stopEverything();
throw e;
}
this.webAPIs = constructWebAPIs(this.draupnir);
await this.webAPIs.start();
await this.draupnir.startupComplete();
} else if (this.safeModeDraupnir !== null) {
this.safeModeDraupnir.startupComplete();
}
@@ -328,7 +322,7 @@ export class DraupnirBotModeToggle implements BotModeTogle {
this.safeModeDraupnir = null;
}
public async stopEverything(): Promise<void> {
public async [Symbol.asyncDispose](): Promise<void> {
await this.stopDraupnir();
this.stopSafeModeDraupnir();
}
@@ -20,7 +20,6 @@ import {
} from "matrix-appservice-bridge";
import { DataStore } from ".//datastore";
import { PgDataStore } from "./postgres/PgDataStore";
import { Api } from "./Api";
import { AppserviceConfig } from "./config/config";
import { AccessControl } from "./AccessControl";
import { AppserviceCommandHandler } from "./bot/AppserviceCommandHandler";
@@ -57,7 +56,6 @@ const log = new Logger("AppService");
* the entrypoint of the application.
*/
export class MjolnirAppService {
private readonly api: Api;
public readonly commands: AppserviceCommandHandler;
/**
@@ -78,7 +76,6 @@ export class MjolnirAppService {
public readonly accessControlRoomID: StringRoomID,
public readonly botUserID: StringUserID
) {
this.api = new Api(config.homeserver.url, draupnirManager);
const client = this.bridge.getBot().getClient();
this.commands = new AppserviceCommandHandler(
botUserID,
@@ -278,7 +275,8 @@ export class MjolnirAppService {
);
} catch (e: unknown) {
log.error(
`Failed to join the room by ${mxEvent.sender} to display the welcome flow`
`Failed to join the room by ${mxEvent.sender} to display the welcome flow`,
e
);
}
try {
@@ -364,7 +362,6 @@ export class MjolnirAppService {
"Starting DraupnirAppService, Matrix-side to listen on port",
port
);
this.api.start(this.config.webAPI.port);
await this.bridge.listen(port);
this.prometheusMetrics.addAppServicePath(this.bridge);
this.bridge.addAppServicePath({
@@ -384,7 +381,6 @@ export class MjolnirAppService {
public async close(): Promise<void> {
await this.bridge.close();
await this.dataStore.close();
await this.api.close();
this.draupnirManager.unregisterListeners();
}
@@ -10,7 +10,7 @@
import { Bridge, Intent, Logger } from "matrix-appservice-bridge";
import { getProvisionedMjolnirConfig } from "../config";
import { MatrixClient } from "matrix-bot-sdk";
import { MatrixClient } from "@vector-im/matrix-bot-sdk";
import { DataStore, MjolnirRecord } from "./datastore";
import { AccessControl } from "./AccessControl";
import { randomUUID } from "crypto";
@@ -26,7 +26,10 @@ const cli = new Cli({
defaults: {},
},
generateRegistration: MjolnirAppService.generateRegistration,
run: function (port: number) {
run: function (port) {
if (port === null) {
throw new Error("Please specify a port for the appservice to run");
}
const config = cli.getConfig();
if (config === null) {
throw new Error("Couldn't load config");
@@ -13,10 +13,6 @@ db:
# See docs/access_control.md
adminRoom: "#draupnir-admin:localhost:9999"
# This is a web api that the widget connects to in order to interact with the appservice.
webAPI:
port: 9001
# The directory the bot should store various bits of information in
dataPath: "/data/storage"
@@ -8,9 +8,6 @@ db:
adminRoom: "#draupnir-admin:localhost:9999"
webAPI:
port: 9001
# The directory the bot should store various bits of information in
dataPath: "./test/harness/mjolnir-data/"
@@ -80,18 +80,6 @@ export const AppserviceConfig = Type.Object({
},
{ description: "Details for the database backend" }
),
webAPI: Type.Object(
{
port: Type.Number({
description:
"Port number for the web API used to access the appservice via the widget",
}),
},
{
description:
"Config for the web api used to access the appservice via the widget",
}
),
adminRoom: Type.String({
description:
"The admin room for the appservice bot. Not called managementRoom like draupnir on purpose, so they're not mixed in code somehow.",
@@ -2,22 +2,17 @@
//
// SPDX-License-Identifier: Apache-2.0
import { PostgresStore, SchemaUpdateFunction } from "matrix-appservice-bridge";
import { PostgresStore } from "matrix-appservice-bridge";
import { DataStore, MjolnirRecord } from "../datastore";
function getSchema(): SchemaUpdateFunction[] {
const nSchema = 2;
const schema = [];
for (let schemaID = 1; schemaID < nSchema + 1; schemaID++) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
schema.push(require(`./schema/v${schemaID}`).runSchema);
}
return schema;
}
import { runSchema as v1 } from "./schema/v1";
import { runSchema as v2 } from "./schema/v2";
const Schema = [v1, v2];
export class PgDataStore extends PostgresStore implements DataStore {
constructor(connectionString: string) {
super(getSchema(), { url: connectionString });
super(Schema, { url: connectionString });
}
public async init(): Promise<void> {
@@ -259,19 +259,19 @@ export class SqliteHashReversalStore
}, "Error trying to reverse hashed policies");
}
private storeUndiscoveredEntities<Record>(
entities: string[],
private storeUndiscoveredEntities<TEntity extends string, TRecord>(
entities: TEntity[],
filterStatement: Statement,
insertOrIgnore: Statement,
recordFactoryFn: (entity: string, hash: string) => Record,
eventEmitFn: (newRecords: Record[]) => void,
serverExtractFn?: (record: Record) => StringServerName
): Result<Record[]> {
recordFactoryFn: (entity: TEntity, hash: string) => TRecord,
eventEmitFn: (newRecords: TRecord[]) => void,
serverExtractFn?: (record: TRecord) => StringServerName
): Result<TRecord[]> {
return wrapInTryCatch(() => {
const undiscoveredEntities = entities.filter((entity) =>
filterStatement.get(entity)
);
const rowsToInsert: Record[] = undiscoveredEntities.map((entity) =>
const rowsToInsert: TRecord[] = undiscoveredEntities.map((entity) =>
recordFactoryFn(
entity,
createHash("sha256").update(entity, "utf8").digest("base64")
@@ -200,7 +200,7 @@ export class SqliteRoomStateBackingStore
.prepare(`SELECT json(event) FROM room_state_event WHERE room_id = ?`)
.pluck()
.iterate(roomID) as IterableIterator<string>) {
const rawJson = JSON.parse(event, jsonReviver);
const rawJson: unknown = JSON.parse(event, jsonReviver);
// We can't trust what's in the store, because our event decoders might have gotten
// stricter in more recent versions. Meaning the store could have invalid events
// that we don't want to blindly intern.
@@ -86,10 +86,12 @@ export function checkKnownTables(
unsortedKnownTables: string[]
): boolean {
const knownTables = unsortedKnownTables.slice().sort(),
currentTables = db
.prepare(`SELECT name FROM "sqlite_master" WHERE type = 'table';`)
.pluck()
.all()
currentTables = (
db
.prepare(`SELECT name FROM "sqlite_master" WHERE type = 'table';`)
.pluck()
.all() as string[]
)
.sort()
.filter((table: string) => !/^sqlite_/.test(table));
if (knownTables.length !== currentTables.length) {
@@ -19,9 +19,7 @@ import {
} from "@the-draupnir-project/interface-manager";
import { sendMatrixEventsFromDeadDocument } from "@the-draupnir-project/mps-interface-adaptor";
export class DraupnirRendererMessageCollector
implements RendererMessageCollector
{
export class DraupnirRendererMessageCollector implements RendererMessageCollector {
constructor(
private readonly roomMessageSender: RoomMessageSender,
private readonly managementRoomID: StringRoomID
@@ -35,9 +35,7 @@ export interface RendererMessage {
/**
* Used by capabilities to send messages to the users of Draupnir.
*/
export class AbstractRendererMessageCollector
implements RendererMessageCollector
{
export class AbstractRendererMessageCollector implements RendererMessageCollector {
private readonly messages: RendererMessage[] = [];
public getMessages(): RendererMessage[] {
return this.messages;
@@ -64,11 +64,6 @@ function renderTakedown(
}
class StandardRoomTakedownCapabilityRenderer implements RoomTakedownCapability {
public readonly requiredEventPermissions =
this.capability.requiredEventPermissions;
public readonly requiredPermissions = this.capability.requiredPermissions;
public readonly requiredStatePermissions =
this.capability.requiredStatePermissions;
constructor(
private readonly description: DescriptionMeta,
private readonly messageCollector: RendererMessageCollector,
@@ -77,6 +72,18 @@ class StandardRoomTakedownCapabilityRenderer implements RoomTakedownCapability {
// nothing to do.
}
public get requiredEventPermissions() {
return this.capability.requiredEventPermissions;
}
public get requiredPermissions() {
return this.capability.requiredPermissions;
}
public get requiredStatePermissions() {
return this.capability.requiredStatePermissions;
}
public async isRoomTakendown(roomID: StringRoomID): Promise<Result<boolean>> {
// pass this one through without rendering because it doesn't really have a consequence
return await this.capability.isRoomTakendown(roomID);
@@ -32,9 +32,7 @@ import {
renderRoomSetResult,
} from "@the-draupnir-project/mps-interface-adaptor";
class StandardServerBanSynchronisationCapabilityRenderer
implements ServerBanSynchronisationCapability
{
class StandardServerBanSynchronisationCapabilityRenderer implements ServerBanSynchronisationCapability {
constructor(
private readonly description: DescriptionMeta,
private readonly messageCollector: RendererMessageCollector,
@@ -42,11 +40,6 @@ class StandardServerBanSynchronisationCapabilityRenderer
) {
// nothing to do.
}
public readonly requiredEventPermissions =
this.capability.requiredEventPermissions;
public readonly requiredPermissions = this.capability.requiredPermissions;
public readonly requiredStatePermissions =
this.capability.requiredStatePermissions;
public async outcomeFromIntentInRoom(
roomID: StringRoomID,
projection: ServerBanIntentProjection
@@ -111,6 +104,18 @@ class StandardServerBanSynchronisationCapabilityRenderer
}
return capabilityResult;
}
public get requiredEventPermissions() {
return this.capability.requiredEventPermissions;
}
public get requiredPermissions() {
return this.capability.requiredPermissions;
}
public get requiredStatePermissions() {
return this.capability.requiredStatePermissions;
}
}
describeCapabilityRenderer<ServerBanSynchronisationCapability, Draupnir>({
@@ -36,11 +36,6 @@ class StandardEventConsequencesRenderer implements EventConsequences {
) {
// nothing to do.
}
public readonly requiredEventPermissions =
this.capability.requiredEventPermissions;
public readonly requiredPermissions = this.capability.requiredPermissions;
public readonly requiredStatePermissions =
this.capability.requiredStatePermissions;
public async consequenceForEvent(
roomID: StringRoomID,
eventID: StringEventID,
@@ -69,6 +64,18 @@ class StandardEventConsequencesRenderer implements EventConsequences {
this.messageCollector.addOneliner(this.description, this.capability, title);
return capabilityResult;
}
public get requiredEventPermissions() {
return this.capability.requiredEventPermissions;
}
public get requiredPermissions() {
return this.capability.requiredPermissions;
}
public get requiredStatePermissions() {
return this.capability.requiredStatePermissions;
}
}
describeCapabilityRenderer<EventConsequences, Draupnir>({
@@ -103,11 +103,17 @@ class StandardUserConsequencesRenderer implements UserConsequences {
) {
// nothing to do.
}
public readonly requiredEventPermissions =
this.capability.requiredEventPermissions;
public readonly requiredPermissions = this.capability.requiredPermissions;
public readonly requiredStatePermissions =
this.capability.requiredStatePermissions;
public get requiredEventPermissions() {
return this.capability.requiredEventPermissions;
}
public get requiredPermissions() {
return this.capability.requiredPermissions;
}
public get requiredStatePermissions() {
return this.capability.requiredStatePermissions;
}
public async consequenceForUserInRoom(
roomID: StringRoomID,
@@ -41,17 +41,15 @@ export class SynapseAdminRoomDetailsProvider implements RoomDetailsProvider {
}
}
export class SynapseAdminRoomTakedownCapability
implements RoomTakedownCapability
{
export class SynapseAdminRoomTakedownCapability implements RoomTakedownCapability {
public readonly requiredPermissions = [];
public readonly requiredStatePermissions = [];
public readonly requiredEventPermissions = [];
private readonly roomDetailsProvider = new SynapseAdminRoomDetailsProvider(
this.adminClient
);
private readonly roomDetailsProvider: SynapseAdminRoomDetailsProvider;
public constructor(private readonly adminClient: SynapseAdminClient) {
// nothing to do mare.
this.roomDetailsProvider = new SynapseAdminRoomDetailsProvider(
this.adminClient
);
}
public async isRoomTakendown(roomID: StringRoomID): Promise<Result<boolean>> {
@@ -118,12 +116,12 @@ export class SimulatedRoomTakedownCapability implements RoomTakedownCapability {
public readonly requiredPermissions = [];
public readonly requiredStatePermissions = [];
public readonly requiredEventPermissions = [];
private readonly roomDetailsProvider = new SynapseAdminRoomDetailsProvider(
this.adminClient
);
private readonly roomDetailsProvider: SynapseAdminRoomDetailsProvider;
isSimulated?: true;
public constructor(private readonly adminClient: SynapseAdminClient) {
// nothing to do mare.
this.roomDetailsProvider = new SynapseAdminRoomDetailsProvider(
this.adminClient
);
}
public async isRoomTakendown(roomID: StringRoomID): Promise<Result<boolean>> {
@@ -10,10 +10,14 @@
import {
ActionResult,
MembershipEventContent,
MultipleErrors,
PolicyRuleType,
RoomActionError,
RoomUpdateError,
ServerACLContent,
StateEvent,
Value,
isError,
} from "matrix-protection-suite";
import { resolveRoomReferenceSafe } from "matrix-protection-suite-for-matrix-bot-sdk";
@@ -65,17 +69,20 @@ export const DraupnirImportCommand = describeCommand({
if (isError(policyRoomEditor)) {
return policyRoomEditor;
}
const state = await draupnir.client.getRoomState(
const state = (await draupnir.client.getRoomState(
importFromRoom.ok.toRoomIDOrAlias()
);
)) as StateEvent[];
const errors: RoomUpdateError[] = [];
for (const stateEvent of state) {
const content = stateEvent["content"] || {};
if (!content || Object.keys(content).length === 0) continue;
const content = stateEvent["content"];
if (Object.keys(content).length === 0) {
// redacted event.
continue;
}
if (
stateEvent["type"] === "m.room.member" &&
stateEvent["state_key"] !== ""
stateEvent["state_key"] !== "" &&
Value.Check(MembershipEventContent, content)
) {
// Member event - check for ban
if (content["membership"] === "ban") {
@@ -93,7 +100,8 @@ export const DraupnirImportCommand = describeCommand({
}
} else if (
stateEvent["type"] === "m.room.server_acl" &&
stateEvent["state_key"] === ""
stateEvent["state_key"] === "" &&
Value.Check(ServerACLContent, content)
) {
// ACL event - ban denied servers
if (!content["deny"]) continue;
@@ -8,7 +8,7 @@
// https://github.com/matrix-org/mjolnir
// </text>
import { MatrixGlob } from "matrix-bot-sdk";
import { MatrixGlob } from "@vector-im/matrix-bot-sdk";
import {
ActionError,
Ok,
@@ -2,14 +2,14 @@
//
// SPDX-License-Identifier: AFL-3.0
import { Ok, Result } from "@gnuxie/typescript-result";
import { isError, Ok, Result } from "@gnuxie/typescript-result";
import {
StringPresentationType,
describeCommand,
} from "@the-draupnir-project/interface-manager";
import { Draupnir } from "../Draupnir";
import { ActionError } from "matrix-protection-suite";
import { DraupnirInterfaceAdaptor } from "./DraupnirCommandPrerequisites";
import { resultifyBotSDKRequestError } from "matrix-protection-suite-for-matrix-bot-sdk";
export const DraupnirDisplaynameCommand = describeCommand({
summary:
@@ -26,15 +26,15 @@ export const DraupnirDisplaynameCommand = describeCommand({
displaynameParts
): Promise<Result<void>> {
const displayname = displaynameParts.join(" ");
try {
await draupnir.client.setDisplayName(displayname);
} catch (e) {
const message = e.message || (e.body ? e.body.error : "<no message>");
return ActionError.Result(
`Failed to set displayname to ${displayname}: ${message}`
const setDisplaynameResult = await draupnir.client
.setDisplayName(displayname)
.then((_) => Ok(undefined), resultifyBotSDKRequestError);
if (isError(setDisplaynameResult)) {
return setDisplaynameResult.elaborate(
`Failed to set displayname to ${displayname}`
);
}
return Ok(undefined);
return setDisplaynameResult;
},
});
@@ -135,7 +135,7 @@ export function draupnirStatusInfo(draupnir: Draupnir): StatusInfo {
subscribedButPartedLists: watchedListInfo.subscribedButPartedLists,
documentationURL: DOCUMENTATION_URL,
version: SOFTWARE_VERSION,
repository: PACKAGE_JSON["repository"] ?? "Unknown",
repository: (PACKAGE_JSON["repository"] as string | undefined) ?? "Unknown",
...extractProtectionNotificationRooms(draupnir),
};
}
+20 -16
View File
@@ -10,7 +10,7 @@
import * as fs from "fs";
import { load } from "js-yaml";
import { LogService, RichConsoleLogger } from "matrix-bot-sdk";
import { LogService, RichConsoleLogger } from "@vector-im/matrix-bot-sdk";
// Needed for https://github.com/the-draupnir-project/Draupnir/issues/480
// sorry buddy...
process.env.SUPPRESS_NO_CONFIG_WARNING = "y";
@@ -23,6 +23,13 @@ LogService.setLogger(new RichConsoleLogger());
setGlobalLoggerProvider(new RichConsoleLogger());
const log = new Logger("Draupnir config");
/**
* Ideally we'd just have a schema for the config.
*/
function isConfigRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
/**
* The version of the configuration that has been explicitly provided,
* and does not contain default values. Secrets are marked with "REDACTED".
@@ -30,26 +37,23 @@ const log = new Logger("Draupnir config");
export function getNonDefaultConfigProperties(
config: IConfig
): Record<string, unknown> {
const nonDefault = Config.util.diffDeep(defaultConfig, config);
const nonDefault = Config.util.diffDeep(defaultConfig, config) as Record<
string,
unknown
>;
if ("accessToken" in nonDefault) {
nonDefault.accessToken = "REDACTED";
}
if (
"pantalaimon" in nonDefault &&
typeof nonDefault.pantalaimon === "object"
) {
if ("pantalaimon" in nonDefault && isConfigRecord(nonDefault.pantalaimon)) {
nonDefault.pantalaimon.password = "REDACTED";
}
if (
"web" in nonDefault &&
typeof nonDefault["web"] === "object" &&
nonDefault["web"] !== null &&
isConfigRecord(nonDefault.web) &&
"synapseHTTPAntispam" in nonDefault["web"] &&
typeof nonDefault["web"]["synapseHTTPAntispam"] === "object"
isConfigRecord(nonDefault["web"]["synapseHTTPAntispam"])
) {
if (nonDefault["web"]["synapseHTTPAntispam"] !== null) {
nonDefault["web"]["synapseHTTPAntispam"].authorization = "REDACTED";
}
nonDefault["web"]["synapseHTTPAntispam"].authorization = "REDACTED";
}
return nonDefault;
}
@@ -271,7 +275,7 @@ const defaultConfig: IConfig = {
};
export function getDefaultConfig(): IConfig {
return Config.util.cloneDeep(defaultConfig);
return Config.util.cloneDeep(defaultConfig) as IConfig;
}
function logNonDefaultConfiguration(config: IConfig): void {
@@ -435,7 +439,7 @@ export function getProvisionedMjolnirConfig(managementRoomId: string): IConfig {
allowedKeys.reduce((existingConfig, key) => {
return { ...existingConfig, [key]: configTemplate[key as keyof IConfig] };
}, {})
);
) as IConfig;
config.managementRoom = managementRoomId;
return config;
@@ -445,7 +449,7 @@ export const PACKAGE_JSON = (() => {
try {
return JSON.parse(
fs.readFileSync(path.join(__dirname, "../package.json"), "utf-8")
);
) as Record<string, unknown>;
} catch (e) {
LogService.error("config", "Could not read Draupnir package.json", e);
return {};
@@ -455,7 +459,7 @@ export const PACKAGE_JSON = (() => {
export const SOFTWARE_VERSION = (() => {
let versionFile;
const defaultText =
PACKAGE_JSON.version ??
(PACKAGE_JSON.version as string | undefined) ??
"A version was either not provided when building Draupnir or could not be read.";
try {
versionFile = fs.readFileSync(
@@ -43,7 +43,7 @@ async function safelyFetchProfile(
): Promise<{ displayname?: string } | undefined> {
const clientProfileResult = await client.getUserProfile(clientUserID).then(
(value) => Ok(value),
(error) => resultifyBotSDKRequestErrorWith404AsUndefined(error)
(error: unknown) => resultifyBotSDKRequestErrorWith404AsUndefined(error)
);
// We opt to report to the log rather than fail outright. Because this is on the critical startup path
// and when we did crash, we had unexplained server behaviour https://github.com/the-draupnir-project/Draupnir/issues/703
@@ -54,7 +54,7 @@ async function safelyFetchProfile(
);
return undefined;
} else {
return clientProfileResult.ok;
return clientProfileResult.ok as { displayname?: string };
}
}
@@ -9,7 +9,7 @@
// </text>
import * as http from "http";
import { LogService } from "matrix-bot-sdk";
import { LogService } from "@vector-im/matrix-bot-sdk";
import { IConfig } from "../config";
// allowed to use the global configuration since this is only intended to be used by `src/index.ts`.
+6 -5
View File
@@ -17,7 +17,7 @@ import {
PantalaimonClient,
SimpleFsStorageProvider,
RustSdkCryptoStorageProvider,
} from "matrix-bot-sdk";
} from "@vector-im/matrix-bot-sdk";
import { StoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";
import { configRead as configRead, getStoragePath } from "./config";
import { initializeSentry } from "./utils";
@@ -99,9 +99,10 @@ void (async function () {
);
} catch (err) {
console.error(
`Failed to setup draupnir from the config ${config.dataPath}: ${err}`
`Failed to setup draupnir from the config ${config.dataPath}`,
err
);
await bot?.stopEverything();
await bot?.[Symbol.asyncDispose]();
throw err;
}
try {
@@ -109,8 +110,8 @@ void (async function () {
await bot.encryptionInitialized();
healthz.isHealthy = true;
} catch (err) {
console.error(`Draupnir failed to start: ${err}`);
await bot.stopEverything();
console.error(`Draupnir failed to start:`, err);
await bot[Symbol.asyncDispose]();
throw err;
}
})();
@@ -14,7 +14,7 @@ import {
LogService,
MessageType,
TextualMessageEventContent,
} from "matrix-bot-sdk";
} from "@vector-im/matrix-bot-sdk";
import { IConfig } from "../config";
import { htmlEscape } from "../utils";
import { MatrixSendClient } from "matrix-protection-suite-for-matrix-bot-sdk";
@@ -60,9 +60,7 @@ export interface ManagementRoomOutput {
/**
* Allows the different componenets of draupnir to send messages back to the management room without introducing a dependency on the entirity of a `Draupnir` instance.
*/
export default class StandardManagementRoomOutput
implements ManagementRoomOutput
{
export default class StandardManagementRoomOutput implements ManagementRoomOutput {
private isSuccessfullySendingMessages = false;
constructor(
private readonly managementRoomDetail: ManagementRoomDetail,
@@ -16,7 +16,7 @@ import {
} from "@the-draupnir-project/matrix-basic-types";
import { Draupnir } from "../Draupnir";
import { DraupnirProtection } from "./Protection";
import { LogLevel } from "matrix-bot-sdk";
import { LogLevel } from "@vector-im/matrix-bot-sdk";
import {
AbstractProtection,
ActionResult,
@@ -118,7 +118,7 @@ function lastEventsRoomEntry(
if (roomEntry) {
return roomEntry;
} else {
const nextEntry = new Map();
const nextEntry = new Map<StringUserID, LastEvents>();
lastEvents.set(roomID, nextEntry);
return nextEntry;
}

Some files were not shown because too many files have changed in this diff Show More