Compare commits
No commits in common. "V3" and "main" have entirely different histories.
24 changed files with 495 additions and 3234 deletions
|
@ -1,3 +0,0 @@
|
|||
POSTGRES_PASSWORD=
|
||||
POSTGRES_USER=
|
||||
POSTGRES_DB=
|
|
@ -1,7 +1,3 @@
|
|||
node_modules/
|
||||
dist/
|
||||
config.json
|
||||
domains.txt
|
||||
nicknames.txt
|
||||
matrix_db.json
|
||||
.env
|
||||
uabot
|
||||
|
|
19
.env.example
Normal file → Executable file
19
.env.example
Normal file → Executable file
|
@ -1,6 +1,15 @@
|
|||
DATABASE_URL="postgresql://uabot@postgres:5432/uabot"
|
||||
MASTODON_ACCESS_TOKEN=
|
||||
MASTODON_HOMESERVER_URL=
|
||||
MATRIX_HOMESERVER_URL=
|
||||
POSTGRES_HOST=
|
||||
POSTGRES_USER=
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_DB=
|
||||
POSTGRES_PORT=
|
||||
|
||||
MATRIX_HOMESERVER=
|
||||
MATRIX_USERNAME=
|
||||
MATRIX_ACCESS_TOKEN=
|
||||
MATRIX_ROOM_ID=
|
||||
MATRIX_ROOM_ID=
|
||||
|
||||
MASTODON_HOMESERVER=
|
||||
MASTODON_CLIENT_ID=
|
||||
MASTODON_CLIENT_SECRET=
|
||||
MASTODON_ACCESS_TOKEN=
|
||||
|
|
25
.eslintrc.js
25
.eslintrc.js
|
@ -1,25 +0,0 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'prettier'],
|
||||
rules: {
|
||||
yoda: 'error',
|
||||
eqeqeq: 'error',
|
||||
complexity: 'error',
|
||||
'prefer-const': 'error',
|
||||
'prefer-template': 'error',
|
||||
'object-shorthand': 'warn',
|
||||
'prettier/prettier': 'warn',
|
||||
'prefer-destructuring': 'warn',
|
||||
'prefer-arrow-callback': 'error',
|
||||
'@typescript-eslint/no-namespace': 'off'
|
||||
}
|
||||
};
|
57
.github/workflows/docker-image.yml
vendored
57
.github/workflows/docker-image.yml
vendored
|
@ -1,57 +0,0 @@
|
|||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# GitHub recommends pinning actions to a commit SHA.
|
||||
# To get a newer version, you will need to update the SHA.
|
||||
# You can also reference a tag or branch, but the action may change without warning.
|
||||
|
||||
name: Create and publish a Docker image on push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -1,7 +1,5 @@
|
|||
node_modules/
|
||||
dist/
|
||||
config.json
|
||||
domains.txt
|
||||
nicknames.txt
|
||||
matrix_db.json
|
||||
.env
|
||||
.env
|
||||
.db.env
|
||||
blacklist.txt
|
||||
whitelist.txt
|
||||
uabot
|
||||
|
|
12
.prettierrc
12
.prettierrc
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid",
|
||||
"bracketSpacing": true,
|
||||
"semi": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
|
14
Dockerfile
14
Dockerfile
|
@ -1,15 +1,15 @@
|
|||
FROM node:18-bookworm
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM golang:1.20
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
COPY go.mod go.sum .
|
||||
|
||||
RUN npm i -g pnpm
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN pnpm generate && pnpm build
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/uabot
|
||||
|
||||
ENTRYPOINT [ "./entrypoint.sh" ]
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
|
|
33
README.md
33
README.md
|
@ -3,46 +3,45 @@
|
|||
**UA-Bot** - Bot for Mastodon that reboosts message if mentioned.
|
||||
|
||||
### Features
|
||||
* Moderation - Send to Matrix room before reblog
|
||||
* Reply or broken thread detection (not fully tested)
|
||||
* Block instances and nicknames by regex
|
||||
|
||||
- Moderation - Send to Matrix room before reblog
|
||||
- Reply or broken thread detection (not fully tested)
|
||||
- Block instances and nicknames by regex
|
||||
|
||||
### Install
|
||||
|
||||
First, install Postgres.
|
||||
First, install Postgres (>= 14 will be fine, i guess).
|
||||
|
||||
Second, clone repo.
|
||||
|
||||
Copy `.env.example` to `.env` and edit with your data:
|
||||
Copy `.env.example` to `.env` and edit with your data
|
||||
|
||||
Also create `nicknames.txt` and `domains.txt` (regex files):
|
||||
|
||||
* `nicknames.txt` - block by username or display name
|
||||
* `domains.txt` - block by domain name
|
||||
- `nicknames.txt` - block by username or display name
|
||||
- `domains.txt` - block by domain name
|
||||
|
||||
Tip: `#` in the beginning of the regex file means that this line will be ignored. You can use it as comment
|
||||
|
||||
Now you can install using **Dockerimage** or **manually**:
|
||||
|
||||
#### Docker
|
||||
|
||||
Build `Dockerfile` and run
|
||||
Also, mount `domains.txt` and `nicknames.txt` to the `/app`
|
||||
Also, mount `domains.txt` and `nicknames.txt` to the `/app`
|
||||
|
||||
### Manually
|
||||
|
||||
Install Node >= 18
|
||||
Install Go >= 1.20
|
||||
|
||||
Next, install packages, generate Prisma package for the project and build it:
|
||||
Next, build the project:
|
||||
|
||||
```sh
|
||||
npm i # alias for npm install
|
||||
npm run generate
|
||||
npm run build
|
||||
go build
|
||||
```
|
||||
|
||||
Migrate database and run:
|
||||
Run:
|
||||
|
||||
```sh
|
||||
npm run migrate
|
||||
npm start
|
||||
```
|
||||
./uabot
|
||||
```
|
||||
|
|
|
@ -2,13 +2,15 @@ version: '3'
|
|||
|
||||
services:
|
||||
bot:
|
||||
image: ghcr.io/ua-fediland/ua-bot:main
|
||||
# image: securetowntop/ua-bot:arm64-latest
|
||||
# image: 374fe5dee955
|
||||
build: .
|
||||
restart: always
|
||||
env_file:
|
||||
- ./.env
|
||||
volumes:
|
||||
- ./nicknames.txt:/app/nicknames.txt
|
||||
- ./domains.txt:/app/domains.txt
|
||||
- ./whitelist.txt:/app/whitelist.txt
|
||||
- ./blacklist.txt:/app/blacklist.txt
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
|
@ -16,7 +18,7 @@ services:
|
|||
|
||||
db:
|
||||
restart: unless-stopped
|
||||
restart: always
|
||||
# restart: always
|
||||
image: postgres:15-alpine
|
||||
networks:
|
||||
- default
|
||||
|
@ -29,5 +31,6 @@ services:
|
|||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
networks:
|
||||
default:
|
||||
networks:
|
||||
default:
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#!/bin/sh
|
||||
pnpm migrate
|
||||
pnpm start
|
||||
|
||||
test -f domains.txt || touch domains.txt
|
||||
test -f nicknames.txt || touch nicknames.txt
|
||||
|
||||
./uabot
|
||||
|
|
39
go.mod
Executable file
39
go.mod
Executable file
|
@ -0,0 +1,39 @@
|
|||
module uabot
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/UA-Fediland/go-mastodon v0.0.0-20240105213412-04581fbfe202
|
||||
gorm.io/gorm v1.25.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.3.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/rs/zerolog v1.30.0 // indirect
|
||||
github.com/tidwall/gjson v1.16.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
go.mau.fi/util v0.1.0 // indirect
|
||||
golang.org/x/crypto v0.13.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/net v0.15.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
maunium.net/go/maulogger/v2 v2.4.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
|
||||
gorm.io/driver/postgres v1.5.2
|
||||
maunium.net/go/mautrix v0.16.1
|
||||
)
|
76
go.sum
Executable file
76
go.sum
Executable file
|
@ -0,0 +1,76 @@
|
|||
github.com/UA-Fediland/go-mastodon v0.0.0-20240105213412-04581fbfe202 h1:UOj1nI2Vn5xsIQWn9R9yotWzrkPXz3pZzCNEd3/olDU=
|
||||
github.com/UA-Fediland/go-mastodon v0.0.0-20240105213412-04581fbfe202/go.mod h1:JXtz7aNX/EdsWXua/8R7KL881WWcfx3GTDgbf2bht7E=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
|
||||
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-mastodon v0.0.6 h1:lqU1sOeeIapaDsDUL6udDZIzMb2Wqapo347VZlaOzf0=
|
||||
github.com/mattn/go-mastodon v0.0.6/go.mod h1:cg7RFk2pcUfHZw/IvKe1FUzmlq5KnLFqs7eV2PHplV8=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
|
||||
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
|
||||
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y=
|
||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE=
|
||||
go.mau.fi/util v0.1.0 h1:BwIFWIOEeO7lsiI2eWKFkWTfc5yQmoe+0FYyOFVyaoE=
|
||||
go.mau.fi/util v0.1.0/go.mod h1:AxuJUMCxpzgJ5eV9JbPWKRH8aAJJidxetNdUj7qcb84=
|
||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
|
||||
gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
|
||||
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
|
||||
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
|
||||
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
|
||||
maunium.net/go/mautrix v0.16.1 h1:Wb3CvOCe8A/NLsFeZYxKrgXKiqeZUQEBD1zqm7n/kWk=
|
||||
maunium.net/go/mautrix v0.16.1/go.mod h1:2Jf15tulVtr6LxoiRL4smRXwpkGWUNfBFhwh/aXDBuk=
|
323
main.go
Executable file
323
main.go
Executable file
|
@ -0,0 +1,323 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/UA-Fediland/go-mastodon"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"maunium.net/go/mautrix"
|
||||
m_event "maunium.net/go/mautrix/event"
|
||||
m_id "maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
type Post struct {
|
||||
ID int
|
||||
PostId string
|
||||
MessageId string
|
||||
}
|
||||
|
||||
func parseRegexFile(path string) ([]regexp.Regexp, error) {
|
||||
file, err := os.Open(path)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file_scanner := bufio.NewScanner(file)
|
||||
|
||||
file_scanner.Split(bufio.ScanLines)
|
||||
|
||||
var result []regexp.Regexp
|
||||
|
||||
for file_scanner.Scan() {
|
||||
text := file_scanner.Text()
|
||||
if strings.Trim(text, " ")[0] != '#' {
|
||||
regex, err := regexp.Compile(text)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, *regex)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
err := godotenv.Load()
|
||||
ROOM_ID := os.Getenv("MATRIX_ROOM_ID")
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ex, err := os.Getwd()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
blacklistRegexes, err := parseRegexFile(path.Join(ex, "blacklist.txt"))
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
whitelistRegexes, err := parseRegexFile(path.Join(ex, "whitelist.txt"))
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// log.Info(nicknameRegexes, domainRegexes)
|
||||
|
||||
db, err := gorm.Open(postgres.Open(fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s",
|
||||
os.Getenv("POSTGRES_HOST"),
|
||||
os.Getenv("POSTGRES_USER"),
|
||||
os.Getenv("POSTGRES_PASSWORD"),
|
||||
os.Getenv("POSTGRES_DB"),
|
||||
os.Getenv("POSTGRES_PORT"))), &gorm.Config{})
|
||||
|
||||
db.AutoMigrate(&Post{})
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
masto_client := mastodon.NewClient(&mastodon.Config{Server: os.Getenv("MASTODON_HOMESERVER"),
|
||||
ClientID: os.Getenv("MASTODON_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("MASTODON_CLIENT_SECRET"),
|
||||
AccessToken: os.Getenv("MASTODON_ACCESS_TOKEN"),
|
||||
})
|
||||
masto_user, err := masto_client.GetAccountCurrentUser(ctx)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var subscribers []*mastodon.Account
|
||||
var pg mastodon.Pagination
|
||||
log.Debug("get followers list")
|
||||
for {
|
||||
fs, err := masto_client.GetAccountFollowers(context.Background(), masto_user.ID, &pg)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
subscribers = append(subscribers, fs...)
|
||||
// log.Debug(pg)
|
||||
// log.Debug(pg.MaxID)
|
||||
if pg.MaxID == "" {
|
||||
break
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
log.Debugf("subscribers count: %v", len(subscribers))
|
||||
// for _, subscriber := range subscribers {
|
||||
// log.Debug(subscriber.Acct)
|
||||
// }
|
||||
|
||||
matrix_client, err := mautrix.NewClient(os.Getenv("MATRIX_HOMESERVER"), m_id.UserID(os.Getenv("MATRIX_USERNAME")), os.Getenv("MATRIX_ACCESS_TOKEN"))
|
||||
matrix_client.Store = mautrix.NewAccountDataStore("ua.in.fediland.uabot", matrix_client)
|
||||
syncer := matrix_client.Syncer.(*mautrix.DefaultSyncer)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Info("starting...")
|
||||
matrix_client.SendText(m_id.RoomID(ROOM_ID), "Бот запущений!")
|
||||
|
||||
syncer.OnEventType(m_event.EventReaction, func(source mautrix.EventSource, ev *m_event.Event) {
|
||||
log.Debug("reactions")
|
||||
// if ev.RoomID == ROOM_ID && ev.Content != nil &&
|
||||
content := ev.Content.AsReaction()
|
||||
key := []rune(content.RelatesTo.Key)
|
||||
log.Debug(content.RelatesTo.Key)
|
||||
if ev.RoomID.String() == ROOM_ID && (key[0] == '👍' || key[0] == '👎') {
|
||||
log.Debug("reacted well")
|
||||
var post Post
|
||||
if err := db.First(&post, "message_id = ?", content.RelatesTo.EventID.String()).Error; err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
status, err := masto_client.GetStatus(ctx, mastodon.ID(post.PostId))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if key[0] == '👍' {
|
||||
_, err = masto_client.Reblog(ctx, mastodon.ID(post.PostId))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
// matrix_client.SendMessageEvent(ROOM_ID, "m.room.message", interface{})
|
||||
body := fmt.Sprintf(`#%d: Схвалено
|
||||
%s
|
||||
`, post.ID, status.URL)
|
||||
|
||||
_, err := matrix_client.SendMessageEvent(m_id.RoomID(ROOM_ID), m_event.EventMessage, &m_event.MessageEventContent{
|
||||
Body: body,
|
||||
MsgType: m_event.MsgText,
|
||||
NewContent: &m_event.MessageEventContent{
|
||||
MsgType: m_event.MsgText,
|
||||
Body: body},
|
||||
RelatesTo: &m_event.RelatesTo{
|
||||
Type: m_event.RelReplace,
|
||||
EventID: m_id.EventID(post.MessageId),
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
body := fmt.Sprintf(`#%d: Відмовлено
|
||||
%s
|
||||
`, post.ID, status.URL)
|
||||
_, err := matrix_client.SendMessageEvent(m_id.RoomID(ROOM_ID), m_event.EventMessage, &m_event.MessageEventContent{
|
||||
Body: body,
|
||||
MsgType: m_event.MsgText,
|
||||
NewContent: &m_event.MessageEventContent{
|
||||
MsgType: m_event.MsgText,
|
||||
Body: body,
|
||||
},
|
||||
RelatesTo: &m_event.RelatesTo{
|
||||
Type: m_event.RelReplace,
|
||||
EventID: m_id.EventID(post.MessageId),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
events, err := masto_client.StreamingUser(ctx)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
if err := matrix_client.Sync(); err != nil {
|
||||
log.Error(fmt.Errorf("Sync() returned %s", err))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
notif_loop:
|
||||
for {
|
||||
notif_event, ok := (<-events).(*mastodon.NotificationEvent)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
notif := notif_event.Notification
|
||||
|
||||
// log.Println(notif)
|
||||
|
||||
if notif.Type == "follow" {
|
||||
// acct_parsed := strings.Split(notif.Account.Acct, "@")
|
||||
|
||||
for _, regex := range blacklistRegexes {
|
||||
if regex.MatchString(notif.Account.Acct) {
|
||||
_, err := masto_client.AccountBlock(ctx, notif.Account.ID)
|
||||
if err == nil {
|
||||
matrix_client.SendText(m_id.RoomID(ROOM_ID), fmt.Sprintf("%s заблокований автоматично регулярним виразом: %s", notif.Account.Acct, regex.String()))
|
||||
}
|
||||
continue notif_loop
|
||||
}
|
||||
}
|
||||
|
||||
subscribers = append(subscribers, ¬if.Account)
|
||||
|
||||
masto_client.PostStatus(ctx, &mastodon.Toot{
|
||||
Status: fmt.Sprintf("Вітаємо у нашій спільноті! @%s", notif.Account.Acct),
|
||||
Visibility: mastodon.VisibilityUnlisted,
|
||||
})
|
||||
}
|
||||
|
||||
if notif.Type == "mention" {
|
||||
log.Debugf("post %v mentioned bot", notif.Status.ID)
|
||||
}
|
||||
|
||||
if notif.Type == "mention" && notif.Status.InReplyToID == nil && notif.Status.InReplyToAccountID == nil {
|
||||
log.Debugf(`post passed reply check (%v)`, notif.Status.ID)
|
||||
|
||||
ok := false
|
||||
|
||||
for _, subscriber := range subscribers {
|
||||
if subscriber.ID == notif.Account.ID {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ok && notif.Status.Visibility == "public" {
|
||||
log.Debugf("post %v is public and user has subscription", notif.Status.ID)
|
||||
|
||||
for _, regex := range whitelistRegexes {
|
||||
if regex.MatchString(notif.Account.Acct) {
|
||||
_, err = masto_client.Reblog(ctx, notif.Status.ID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
log.Debugf("post %v belongs to whitelisted user (%v) by regex: %v", notif.Status.ID, notif.Account.Acct, regex.String())
|
||||
continue notif_loop
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.Create(&Post{
|
||||
PostId: string(notif.Status.ID),
|
||||
}).Error; err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
var post Post
|
||||
if err := db.First(&post, "post_id = ?", string(notif.Status.ID)).Error; err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
message, err := matrix_client.SendText(m_id.RoomID(ROOM_ID), fmt.Sprintf(`#%d: На модерації
|
||||
%s
|
||||
👍 - Так
|
||||
👎 - Ні
|
||||
`, post.ID, notif.Status.URL))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
db.Delete(&post, post.ID)
|
||||
}
|
||||
|
||||
post.MessageId = message.EventID.String()
|
||||
db.Save(&post)
|
||||
}
|
||||
|
||||
if ok && notif.Status.Visibility == "direct" && notif.Status.Content == "ping" {
|
||||
masto_client.PostStatus(ctx, &mastodon.Toot{
|
||||
Status: "meow",
|
||||
InReplyToID: notif.Status.ID,
|
||||
Visibility: "direct",
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
31
package.json
31
package.json
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"name": "uagroupbot",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"watch": "tsc -w",
|
||||
"build": "tsc",
|
||||
"start": "node ./dist/index.js",
|
||||
"generate": "prisma generate",
|
||||
"migrate": "prisma migrate deploy"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node18": "^18.2.0",
|
||||
"eslint": "^8.44.0",
|
||||
"nodemon": "^2.0.22",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.0.0",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "4.16.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"masto": "^5.11.3",
|
||||
"matrix-bot-sdk": "^0.6.6",
|
||||
"prisma": "^4.16.2"
|
||||
}
|
||||
}
|
2830
pnpm-lock.yaml
2830
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -1,10 +0,0 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Post" (
|
||||
"postId" TEXT NOT NULL,
|
||||
"matrixId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Post_pkey" PRIMARY KEY ("postId")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Post_matrixId_key" ON "Post"("matrixId");
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[id]` on the table `Post` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Post" ADD COLUMN "id" SERIAL NOT NULL;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Post_id_key" ON "Post"("id");
|
|
@ -1,3 +0,0 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
|
@ -1,17 +0,0 @@
|
|||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model Post {
|
||||
id Int @unique @default(autoincrement())
|
||||
postId String @id
|
||||
matrixId String @unique
|
||||
}
|
176
src/index.ts
176
src/index.ts
|
@ -1,176 +0,0 @@
|
|||
import 'dotenv/config';
|
||||
import { MatrixClient, MessageEvent, SimpleFsStorageProvider } from 'matrix-bot-sdk';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
MASTODON_ACCESS_TOKEN: string;
|
||||
MASTODON_HOMESERVER_URL: string;
|
||||
MATRIX_HOMESERVER_URL: string;
|
||||
MATRIX_ACCESS_TOKEN: string;
|
||||
MATRIX_ROOM_ID: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseAsyncRegexFile(file: Buffer): RegExp[] {
|
||||
const data = file.toString();
|
||||
return data
|
||||
.split('\n')
|
||||
.filter(regex => !regex.startsWith('#') && regex.trim() !== '')
|
||||
.map(regex => new RegExp(regex));
|
||||
}
|
||||
|
||||
async function editText(
|
||||
client: MatrixClient,
|
||||
roomId: string,
|
||||
eventId: string,
|
||||
text: string
|
||||
): Promise<void> {
|
||||
await client.sendEvent(roomId, 'm.room.message', {
|
||||
body: text,
|
||||
msgtype: 'm.text',
|
||||
'm.new_content': {
|
||||
body: text,
|
||||
msgtype: 'm.text'
|
||||
},
|
||||
'm.relates_to': {
|
||||
rel_type: 'm.replace',
|
||||
event_id: eventId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const mastodon = await (
|
||||
await import('masto')
|
||||
).login({
|
||||
url: process.env.MASTODON_HOMESERVER_URL,
|
||||
accessToken: process.env.MASTODON_ACCESS_TOKEN,
|
||||
disableVersionCheck: true
|
||||
});
|
||||
const matrix = new MatrixClient(
|
||||
process.env.MATRIX_HOMESERVER_URL,
|
||||
process.env.MATRIX_ACCESS_TOKEN,
|
||||
new SimpleFsStorageProvider('matrix_db.json')
|
||||
);
|
||||
const nicknameRegexes = parseAsyncRegexFile(await readFile(join(__dirname, '..', 'domains.txt')));
|
||||
const domainRegexes = parseAsyncRegexFile(await readFile(join(__dirname, '..', 'nicknames.txt')));
|
||||
const db = new PrismaClient();
|
||||
const ws = await mastodon.v1.stream.streamUser();
|
||||
ws.on('notification', async notification => {
|
||||
console.log('tests');
|
||||
if (
|
||||
nicknameRegexes.some(regex => regex.test(notification.account.displayName)) ||
|
||||
nicknameRegexes.some(regex => regex.test(notification.account.acct.split('@').at(0) || '')) ||
|
||||
domainRegexes.some(regex => regex.test(notification.account.acct.split('@').at(-1) || ''))
|
||||
) {
|
||||
await mastodon.v1.accounts.block(notification.account.id);
|
||||
await matrix.sendText(
|
||||
process.env.MATRIX_ROOM_ID,
|
||||
`Юзер ${notification.account.acct} був заблокований автоматично`
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
notification.type === 'mention' &&
|
||||
!notification.status?.inReplyToId &&
|
||||
!notification.status?.inReplyToAccountId &&
|
||||
notification.status?.visibility === 'public'
|
||||
) {
|
||||
const matrixId = await matrix.sendText(
|
||||
process.env.MATRIX_ROOM_ID,
|
||||
`${notification.status.url}\nY/т - Так\nN/н - Ні`
|
||||
);
|
||||
const { id } = await db.post.create({
|
||||
data: {
|
||||
postId: notification.status.id,
|
||||
matrixId
|
||||
},
|
||||
select: {
|
||||
id: true
|
||||
}
|
||||
});
|
||||
await editText(
|
||||
matrix,
|
||||
process.env.MATRIX_ROOM_ID,
|
||||
matrixId,
|
||||
`#${id} ${notification.status.url}\nY/т - Так\nN/н - Ні`
|
||||
);
|
||||
}
|
||||
if (notification.type === 'follow') {
|
||||
await mastodon.v1.statuses.create({
|
||||
visibility: 'public',
|
||||
status: `Вітаємо у нашій спільноті! @${notification.account.acct}`
|
||||
});
|
||||
console.log('follow message');
|
||||
}
|
||||
if (
|
||||
notification.type === 'mention' &&
|
||||
notification.status?.visibility === 'direct' &&
|
||||
!notification.status.inReplyToId &&
|
||||
notification.status.content.includes('ping')
|
||||
) {
|
||||
await mastodon.v1.statuses.create({
|
||||
inReplyToId: notification.status.id,
|
||||
visibility: 'direct',
|
||||
status: 'meow'
|
||||
});
|
||||
}
|
||||
});
|
||||
matrix.on('room.message', async (roomId, event) => {
|
||||
if (
|
||||
roomId === process.env.MATRIX_ROOM_ID &&
|
||||
event['content'] &&
|
||||
['y', 'n', 'т', 'н'].includes(
|
||||
(event['content']['body'].split('\n').at(-1).trim() as string).toLowerCase()
|
||||
) &&
|
||||
event['content']['m.relates_to'] &&
|
||||
event['content']['m.relates_to']['m.in_reply_to']
|
||||
) {
|
||||
const post = await db.post.findUnique({
|
||||
where: {
|
||||
matrixId: event['content']['m.relates_to']['m.in_reply_to']['event_id']
|
||||
}
|
||||
});
|
||||
if (
|
||||
post &&
|
||||
['y', 'т'].includes((event['content']['body'].split('\n').at(-1) as string).toLowerCase())
|
||||
) {
|
||||
await mastodon.v1.statuses.reblog(post.postId);
|
||||
await matrix.replyText(process.env.MATRIX_ROOM_ID, event, 'Пост успішно опубліковано');
|
||||
await editText(
|
||||
matrix,
|
||||
roomId,
|
||||
event['event_id'],
|
||||
event['content']['body'].split('\n').at(0) + ' ✅'
|
||||
);
|
||||
}
|
||||
if (
|
||||
post &&
|
||||
['n', 'н'].includes((event['content']['body'].split('\n').at(-1) as string).toLowerCase())
|
||||
) {
|
||||
await db.post.delete({
|
||||
where: {
|
||||
matrixId: event['content']['m.relates_to']['m.in_reply_to']['event_id']
|
||||
}
|
||||
});
|
||||
await matrix.replyText(process.env.MATRIX_ROOM_ID, event, 'Пост відхилено');
|
||||
await editText(
|
||||
matrix,
|
||||
roomId,
|
||||
event['event_id'],
|
||||
event['content']['body'].split('\n').at(0) + ' ❌'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
await db.$connect();
|
||||
await matrix.start();
|
||||
}
|
||||
main()
|
||||
.then(() => console.log('everything started!'))
|
||||
.catch(e => console.error(e));
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "@tsconfig/node18/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"target": "esnext"
|
||||
},
|
||||
"esModuleInterop": true
|
||||
}
|
Loading…
Reference in a new issue