From a1806cbac945f63448f572361d5ec8289b034405 Mon Sep 17 00:00:00 2001 From: qugalet Date: Sun, 9 Jul 2023 23:53:49 +0300 Subject: [PATCH 01/46] initial commit --- .dockerignore | 7 + .env.example | 1 + .eslintrc.js | 25 + .gitignore | 7 + .prettierrc | 12 + Dockerfile | 15 + README.md | 58 + config.json.example | 8 + docker-compose.yml | 13 + entrypoint.sh | 3 + package.json | 30 + pnpm-lock.yaml | 2822 +++++++++++++++++ .../20230708200924_initial/migration.sql | 10 + prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 16 + src/index.ts | 115 + tsconfig.json | 10 + 17 files changed, 3155 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 config.json.example create mode 100644 docker-compose.yml create mode 100755 entrypoint.sh create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 prisma/migrations/20230708200924_initial/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma create mode 100644 src/index.ts create mode 100644 tsconfig.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7098559 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +config.json +domains.txt +nicknames.txt +matrix_db.json +.env \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2e9c5d7 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +DATABASE_URL="postgresql://uabot@postgres:5432/uabot" \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..82ead7f --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,25 @@ +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' + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7098559 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +config.json +domains.txt +nicknames.txt +matrix_db.json +.env \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..87e9568 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "arrowParens": "avoid", + "bracketSpacing": true, + "semi": true, + "printWidth": 100, + "trailingComma": "none", + "endOfLine": "lf" + } + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a392e62 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:18-bookworm + +WORKDIR /app + +COPY package.json . + +RUN npm i + +COPY . . + +RUN npm run generate + +RUN npm run build + +ENTRYPOINT [ "./entrypoint.sh" ] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d3ce0c6 --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +## UA-Bot + +**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 + +### Install + +First, install Postgres. + +Second, clone repo. + +Copy `.env.example` to `.env` and edit with your data: +```sh +DATABASE_URL="postgresql://uabot@postgres:5432/uabot" +``` +Also copy `config.json.example` to `config.json` with your data: +* `mastodonClientId` - Mastodon Client Id +* `mastodonAccessToken` - Mastodon Access Token +* `mastodonHomeserverURL` - Mastodon Homeserver URL +* `matrixHomeserverURL` - Matrix Homeserver URL bot for moderation +* `matrixAccessToken` - Matrix Access Token for Matrix bot for moderation +* `matrixRoomId` - Matrix Room Id for moderation + +Also create `nicknames.txt` and `domains.txt` (regex files): + +* `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 `config.json`, `domains.txt` and `nicknames.txt` to the `/app` + +### Manually + +Install Node >= 18 + +Next, install packages, generate Prisma package for the project and build it: + +```sh +npm i # alias for npm install +npm run generate +npm run build +``` + +Migrate database and run: + +```sh +npm run migrate +npm start +``` \ No newline at end of file diff --git a/config.json.example b/config.json.example new file mode 100644 index 0000000..bcc930c --- /dev/null +++ b/config.json.example @@ -0,0 +1,8 @@ +{ + "pleromaClientId": "", + "pleromaAccessToken": "", + "pleromaHomeserverURL": "", + "matrixHomeserverURL": "", + "matrixAccessToken": "", + "matrixRoomId": "" +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..bc723d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3' + +services: + bot: + build: . + env_file: + - ./.env + volumes: + - ./config.json:/app/config.json + - ./nicknames.txt:/app/nicknames.txt + - ./domains.txt:/app/domains.txt + extra_hosts: + - host.docker.internal:host-gateway diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..5c794f8 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh +npm run migrate +npm run start \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..2893f92 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "uagroupbot", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "watch": "tsc -w", + "build": "tsc", + "start": "node ./dist", + "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.14.1", + "masto": "^5.11.3", + "matrix-bot-sdk": "^0.6.6", + "prisma": "^4.16.2" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..4b8b3ff --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2822 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@prisma/client': + specifier: 4.14.1 + version: 4.14.1(prisma@4.16.2) + masto: + specifier: ^5.11.3 + version: 5.11.3 + matrix-bot-sdk: + specifier: ^0.6.6 + version: 0.6.6 + prisma: + specifier: ^4.16.2 + version: 4.16.2 + +devDependencies: + '@tsconfig/node18': + specifier: ^18.2.0 + version: 18.2.0 + eslint: + specifier: ^8.44.0 + version: 8.44.0 + nodemon: + specifier: ^2.0.22 + version: 2.0.22 + npm-run-all: + specifier: ^4.1.5 + version: 4.1.5 + prettier: + specifier: ^3.0.0 + version: 3.0.0 + typescript: + specifier: ^5.1.6 + version: 5.1.6 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.44.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.44.0 + eslint-visitor-keys: 3.4.1 + dev: true + + /@eslint-community/regexpp@4.5.1: + resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.0: + resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.0 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.44.0: + resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.10: + resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@mastojs/ponyfills@1.0.4: + resolution: {integrity: sha512-1NaIGmcU7OmyNzx0fk+cYeGTkdXlOJOSdetaC4pStVWsrhht2cdlYSAfe5NDW3FcUmcEm2vVceB9lcClN1RCxw==} + dependencies: + '@types/node': 18.16.19 + '@types/node-fetch': 2.6.4 + abort-controller: 3.0.0 + form-data: 4.0.0 + node-fetch: 2.6.12 + transitivePeerDependencies: + - encoding + dev: false + + /@matrix-org/matrix-sdk-crypto-nodejs@0.1.0-beta.6: + resolution: {integrity: sha512-JXyrHuCVMydUGgSetWsfqbbvHj3aUMOX5TUghlMtLFromyEu7wIsNgYt7PjJ+k3WdF4GVABRy4P6GNjaEMy2uA==} + engines: {node: '>= 16'} + requiresBuild: true + dependencies: + https-proxy-agent: 5.0.1 + node-downloader-helper: 2.1.7 + transitivePeerDependencies: + - supports-color + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@prisma/client@4.14.1(prisma@4.16.2): + resolution: {integrity: sha512-TZIswkeX1ccsHG/eN2kICzg/csXll0osK3EHu1QKd8VJ3XLcXozbNELKkCNfsCUvKJAwPdDtFCzF+O+raIVldw==} + engines: {node: '>=14.17'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + '@prisma/engines-version': 4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c + prisma: 4.16.2 + dev: false + + /@prisma/engines-version@4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c: + resolution: {integrity: sha512-3jum8/YSudeSN0zGW5qkpz+wAN2V/NYCQ+BPjvHYDfWatLWlQkqy99toX0GysDeaUoBIJg1vaz2yKqiA3CFcQw==} + dev: false + + /@prisma/engines@4.16.2: + resolution: {integrity: sha512-vx1nxVvN4QeT/cepQce68deh/Turxy5Mr+4L4zClFuK1GlxN3+ivxfuv+ej/gvidWn1cE1uAhW7ALLNlYbRUAw==} + requiresBuild: true + dev: false + + /@selderee/plugin-htmlparser2@0.6.0: + resolution: {integrity: sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==} + dependencies: + domhandler: 4.3.1 + selderee: 0.6.0 + dev: false + + /@tsconfig/node18@18.2.0: + resolution: {integrity: sha512-yhxwIlFVSVcMym3O31HoMnRXpoenmpIxcj4Yoes2DUpe+xCJnA7ECQP1Vw889V0jTt/2nzvpLQ/UuMYCd3JPIg==} + dev: true + + /@types/body-parser@1.19.2: + resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} + dependencies: + '@types/connect': 3.4.35 + '@types/node': 20.4.0 + dev: false + + /@types/connect@3.4.35: + resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} + dependencies: + '@types/node': 20.4.0 + dev: false + + /@types/express-serve-static-core@4.17.35: + resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} + dependencies: + '@types/node': 20.4.0 + '@types/qs': 6.9.7 + '@types/range-parser': 1.2.4 + '@types/send': 0.17.1 + dev: false + + /@types/express@4.17.17: + resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} + dependencies: + '@types/body-parser': 1.19.2 + '@types/express-serve-static-core': 4.17.35 + '@types/qs': 6.9.7 + '@types/serve-static': 1.15.2 + dev: false + + /@types/http-errors@2.0.1: + resolution: {integrity: sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==} + dev: false + + /@types/mime@1.3.2: + resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} + dev: false + + /@types/mime@3.0.1: + resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} + dev: false + + /@types/node-fetch@2.6.4: + resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} + dependencies: + '@types/node': 18.16.19 + form-data: 3.0.1 + dev: false + + /@types/node@18.16.19: + resolution: {integrity: sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==} + dev: false + + /@types/node@20.4.0: + resolution: {integrity: sha512-jfT7iTf/4kOQ9S7CHV9BIyRaQqHu67mOjsIQBC3BKZvzvUB6zLxEwJ6sBE3ozcvP8kF6Uk5PXN0Q+c0dfhGX0g==} + dev: false + + /@types/qs@6.9.7: + resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} + dev: false + + /@types/range-parser@1.2.4: + resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} + dev: false + + /@types/send@0.17.1: + resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} + dependencies: + '@types/mime': 1.3.2 + '@types/node': 20.4.0 + dev: false + + /@types/serve-static@1.15.2: + resolution: {integrity: sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==} + dependencies: + '@types/http-errors': 2.0.1 + '@types/mime': 3.0.1 + '@types/node': 20.4.0 + dev: false + + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + + /abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 + dev: false + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /acorn-jsx@5.3.2(acorn@8.10.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.10.0 + dev: true + + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + /another-json@0.2.0: + resolution: {integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==} + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + dev: false + + /async-lock@1.4.0: + resolution: {integrity: sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ==} + dev: false + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + dev: false + + /aws4@1.12.0: + resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /basic-auth@2.0.1: + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} + engines: {node: '>= 0.8'} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + dependencies: + tweetnacl: 0.14.5 + dev: false + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: false + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + dependencies: + pascal-case: 3.1.2 + tslib: 2.6.0 + dev: false + + /capital-case@1.0.4: + resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + upper-case-first: 2.0.2 + dev: false + + /caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + dev: false + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /change-case@4.1.2: + resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} + dependencies: + camel-case: 4.1.2 + capital-case: 1.0.4 + constant-case: 3.0.4 + dot-case: 3.0.4 + header-case: 2.0.4 + no-case: 3.0.4 + param-case: 3.0.4 + pascal-case: 3.1.2 + path-case: 3.0.4 + sentence-case: 3.0.4 + snake-case: 3.0.4 + tslib: 2.6.0 + dev: false + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /constant-case@3.0.4: + resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + upper-case: 2.0.2 + dev: false + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + dev: false + + /cross-spawn@6.0.5: + resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + engines: {node: '>=4.8'} + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.1 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug@3.2.7(supports-color@5.5.0): + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + supports-color: 5.5.0 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: false + + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /discontinuous-range@1.0.0: + resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==} + dev: false + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + dev: false + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dev: false + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: false + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: false + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: false + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dev: false + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: false + + /dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + dev: false + + /ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: false + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: false + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.21.2: + resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.2.1 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.10 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.0 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.9 + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + /eslint-scope@7.2.0: + resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.1: + resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.44.0: + resolution: {integrity: sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@eslint-community/regexpp': 4.5.1 + '@eslint/eslintrc': 2.1.0 + '@eslint/js': 8.44.0 + '@humanwhocodes/config-array': 0.11.10 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.0 + eslint-visitor-keys: 3.4.1 + espree: 9.6.0 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.20.0 + graphemer: 1.4.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.0: + resolution: {integrity: sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.1 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: false + + /extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + dev: false + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + dev: false + + /form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /form-data@3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + + /getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + dependencies: + assert-plus: 1.0.0 + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + dev: false + + /har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + dev: false + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: false + + /header-case@2.0.4: + resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} + dependencies: + capital-case: 1.0.4 + tslib: 2.6.0 + dev: false + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /html-to-text@8.2.1: + resolution: {integrity: sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==} + engines: {node: '>=10.23.2'} + hasBin: true + dependencies: + '@selderee/plugin-htmlparser2': 0.6.0 + deepmerge: 4.3.1 + he: 1.2.0 + htmlparser2: 6.1.0 + minimist: 1.2.8 + selderee: 0.6.0 + dev: false + + /htmlencode@0.0.4: + resolution: {integrity: sha512-0uDvNVpzj/E2TfvLLyyXhKBRvF1y84aZsyRxRXFsQobnHaL4pcaXk+Y9cnFlvnxrBLeXDNq/VJBD+ngdBgQG1w==} + dev: false + + /htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + dev: false + + /htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + dev: false + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.17.0 + dev: false + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.10 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.12.1: + resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} + dependencies: + has: 1.0.3 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: false + + /is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: false + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.10: + resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: false + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isomorphic-ws@5.0.0(ws@8.13.0): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.13.0 + dev: false + + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: false + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + dev: false + + /json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: false + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: false + + /jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: false + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /load-json-file@4.0.0: + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} + engines: {node: '>=4'} + dependencies: + graceful-fs: 4.2.11 + parse-json: 4.0.0 + pify: 3.0.0 + strip-bom: 3.0.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /lowdb@1.0.0: + resolution: {integrity: sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==} + engines: {node: '>=4'} + dependencies: + graceful-fs: 4.2.11 + is-promise: 2.2.2 + lodash: 4.17.21 + pify: 3.0.0 + steno: 0.4.4 + dev: false + + /lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + dependencies: + tslib: 2.6.0 + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: false + + /masto@5.11.3: + resolution: {integrity: sha512-GtSnrqm5fHPaaU0iwag4LCmvpp82rDng6yOZinmOJHHlUfo6Gnq5QY6x3lJCxCnsPIXpTu1yaX42bWrSQyoQPA==} + dependencies: + '@mastojs/ponyfills': 1.0.4 + change-case: 4.1.2 + eventemitter3: 5.0.1 + isomorphic-ws: 5.0.0(ws@8.13.0) + qs: 6.11.2 + semver: 7.5.3 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /matrix-bot-sdk@0.6.6: + resolution: {integrity: sha512-iYwgDjlP4+TKrTR2OEoVnrJoaWXGoV0U+y1LCUTA7IROJEn4MTpobA8LbSgIiHyF7i11mMqcmc87c/ARcI+KQQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@matrix-org/matrix-sdk-crypto-nodejs': 0.1.0-beta.6 + '@types/express': 4.17.17 + another-json: 0.2.0 + async-lock: 1.4.0 + chalk: 4.1.2 + express: 4.18.2 + glob-to-regexp: 0.4.1 + hash.js: 1.1.7 + html-to-text: 8.2.1 + htmlencode: 0.0.4 + lowdb: 1.0.0 + lru-cache: 7.18.3 + mkdirp: 1.0.4 + morgan: 1.10.0 + request: 2.88.2 + request-promise: 4.2.6(request@2.88.2) + sanitize-html: 2.11.0 + transitivePeerDependencies: + - supports-color + dev: false + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + dev: true + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: false + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /moo@0.5.2: + resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} + dev: false + + /morgan@1.10.0: + resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} + engines: {node: '>= 0.8.0'} + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: false + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /nearley@2.20.1: + resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} + hasBin: true + dependencies: + commander: 2.20.3 + moo: 0.5.2 + railroad-diagrams: 1.0.0 + randexp: 0.4.6 + dev: false + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + dev: true + + /no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + dependencies: + lower-case: 2.0.2 + tslib: 2.6.0 + dev: false + + /node-downloader-helper@2.1.7: + resolution: {integrity: sha512-3dBuMF/XPy5WFi3XiiXaglafzoycRH5GjmRz1nAt2uI9D+TcBrc+n/AzH8bzLHR85Wsf6vZSZblzw+MiUS/WNQ==} + engines: {node: '>=14.18'} + hasBin: true + dev: false + + /node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /nodemon@2.0.22: + resolution: {integrity: sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==} + engines: {node: '>=8.10.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + debug: 3.2.7(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 3.1.2 + pstree.remy: 1.1.8 + semver: 5.7.1 + simple-update-notifier: 1.1.0 + supports-color: 5.5.0 + touch: 3.1.0 + undefsafe: 2.0.5 + dev: true + + /nopt@1.0.10: + resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.2 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-all@4.1.5: + resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} + engines: {node: '>= 4'} + hasBin: true + dependencies: + ansi-styles: 3.2.1 + chalk: 2.4.2 + cross-spawn: 6.0.5 + memorystream: 0.3.1 + minimatch: 3.1.2 + pidtree: 0.3.1 + read-pkg: 3.0.0 + shell-quote: 1.8.1 + string.prototype.padend: 3.1.4 + dev: true + + /oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + dev: false + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.0 + dev: false + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + dev: true + + /parse-srcset@1.0.2: + resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} + dev: false + + /parseley@0.7.0: + resolution: {integrity: sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==} + dependencies: + moo: 0.5.2 + nearley: 2.20.1 + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + dev: false + + /path-case@3.0.4: + resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.0 + dev: false + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /path-type@3.0.0: + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} + dependencies: + pify: 3.0.0 + dev: true + + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + dev: false + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pidtree@0.3.1: + resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + + /postcss@8.4.25: + resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier@3.0.0: + resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /prisma@4.16.2: + resolution: {integrity: sha512-SYCsBvDf0/7XSJyf2cHTLjLeTLVXYfqp7pG5eEVafFLeT0u/hLFz/9W196nDRGUOo1JfPatAEb+uEnTQImQC1g==} + engines: {node: '>=14.17'} + hasBin: true + requiresBuild: true + dependencies: + '@prisma/engines': 4.16.2 + dev: false + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: false + + /pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /qs@6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + dev: false + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /railroad-diagrams@1.0.0: + resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} + dev: false + + /randexp@0.4.6: + resolution: {integrity: sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==} + engines: {node: '>=0.12'} + dependencies: + discontinuous-range: 1.0.0 + ret: 0.1.15 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /read-pkg@3.0.0: + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} + engines: {node: '>=4'} + dependencies: + load-json-file: 4.0.0 + normalize-package-data: 2.5.0 + path-type: 3.0.0 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regexp.prototype.flags@1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /request-promise-core@1.1.4(request@2.88.2): + resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} + engines: {node: '>=0.10.0'} + peerDependencies: + request: ^2.34 + dependencies: + lodash: 4.17.21 + request: 2.88.2 + dev: false + + /request-promise@4.2.6(request@2.88.2): + resolution: {integrity: sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==} + engines: {node: '>=0.10.0'} + deprecated: request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 + peerDependencies: + request: ^2.34 + dependencies: + bluebird: 3.7.2 + request: 2.88.2 + request-promise-core: 1.1.4(request@2.88.2) + stealthy-require: 1.1.1 + tough-cookie: 2.5.0 + dev: false + + /request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + dependencies: + aws-sign2: 0.7.0 + aws4: 1.12.0 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.3 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + dev: false + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + dependencies: + is-core-module: 2.12.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /sanitize-html@2.11.0: + resolution: {integrity: sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==} + dependencies: + deepmerge: 4.3.1 + escape-string-regexp: 4.0.0 + htmlparser2: 8.0.2 + is-plain-object: 5.0.0 + parse-srcset: 1.0.2 + postcss: 8.4.25 + dev: false + + /selderee@0.6.0: + resolution: {integrity: sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==} + dependencies: + parseley: 0.7.0 + dev: false + + /semver@5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + + /semver@7.0.0: + resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} + hasBin: true + dev: true + + /semver@7.5.3: + resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /sentence-case@3.0.4: + resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + upper-case-first: 2.0.2 + dev: false + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + + /simple-update-notifier@1.1.0: + resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==} + engines: {node: '>=8.10.0'} + dependencies: + semver: 7.0.0 + dev: true + + /snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.0 + dev: false + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: false + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.13 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.13 + dev: true + + /spdx-license-ids@3.0.13: + resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} + dev: true + + /sshpk@1.17.0: + resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /stealthy-require@1.1.1: + resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} + engines: {node: '>=0.10.0'} + dev: false + + /steno@0.4.4: + resolution: {integrity: sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==} + dependencies: + graceful-fs: 4.2.11 + dev: false + + /string.prototype.padend@3.1.4: + resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /touch@3.1.0: + resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} + hasBin: true + dependencies: + nopt: 1.0.10 + dev: true + + /tough-cookie@2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /tslib@2.6.0: + resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} + dev: false + + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + dev: false + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.10 + dev: true + + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /upper-case-first@2.0.2: + resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} + dependencies: + tslib: 2.6.0 + dev: false + + /upper-case@2.0.2: + resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} + dependencies: + tslib: 2.6.0 + dev: false + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: false + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array@1.1.9: + resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.10 + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/prisma/migrations/20230708200924_initial/migration.sql b/prisma/migrations/20230708200924_initial/migration.sql new file mode 100644 index 0000000..8ac1546 --- /dev/null +++ b/prisma/migrations/20230708200924_initial/migration.sql @@ -0,0 +1,10 @@ +-- 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"); diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..f5fd15d --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,16 @@ +// 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 { + postId String @id + matrixId String @unique +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..2172157 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,115 @@ +import { MatrixClient, MessageEvent, SimpleFsStorageProvider } from 'matrix-bot-sdk'; +import { PrismaClient } from '@prisma/client'; +import { readFile } from 'fs/promises'; +import { join } from 'path'; + +function parseAsyncRegexFile(file: Buffer): RegExp[] { + const data = file.toString(); + return data + .split('\n') + .filter(regex => !regex.trim().startsWith('#')) + .map(regex => new RegExp(regex)); +} + +async function main() { + const config = JSON.parse((await readFile(join(__dirname, '..', 'config.json'))).toString()); + console.log(config); + const mastodon = await ( + await import('masto') + ).login({ + url: config.mastodonHomeserverURL, + accessToken: config.mastodonAccessToken, + disableVersionCheck: true + }); + const matrix = new MatrixClient( + config.matrixHomeserverURL, + config.matrixAccessToken, + 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( + config.matrixRoomId, + `Юзер ${notification.account.acct} був заблокований автоматично` + ); + } + + if ( + notification.type === 'mention' && + !notification.status?.inReplyToId && + !notification.status?.inReplyToAccountId && + notification.status?.visibility === 'public' + ) { + const matrixId = await matrix.sendText( + config.matrixRoomId, + `Одобряємо?\n${notification.status.url}\nт - Так\nн - Ні` + ); + await db.post.create({ + data: { + postId: notification.status.id, + matrixId + } + }); + } + if (notification.type === 'follow') { + await mastodon.v1.statuses.create({ + visibility: 'public', + status: `Вітаємо у нашій спільноті! @${notification.account.acct}` + }); + console.log('follow message'); + } + }); + matrix.on('room.message', async (roomId, event) => { + if ( + roomId === config.matrixRoomId && + event['content'] && + ['т', 'н'].includes(event['content']['body'].split('\n').at(-1).trim()) && + 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 && event['content']['body'].split('\n').at(-1) === 'т') { + console.log('test'); + await mastodon.v1.statuses.reblog(post.postId); + await matrix.replyText( + config.matrixRoomId, + event['content']['m.relates_to']['m.in_reply_to']['event_id'], + 'Пост успішно опубліковано' + ); + } + if (post && event['content']['body'].split('\n').at(-1) === 'н') { + await matrix.redactEvent( + config.matrixRoomId, + event['content']['m.relates_to']['event_id'], + 'Не одобрили :(' + ); + await db.post.delete({ + where: { + matrixId: event['content']['m.relates_to']['m.in_reply_to']['event_id'] + } + }); + await matrix.replyText( + config.matrixRoomId, + event['content']['m.relates_to']['m.in_reply_to']['event_id'], + 'Пост відхилено' + ); + } + } + }); + await db.$connect(); + await matrix.start(); +} +main().then(() => console.log('everything started!')); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..bf3bafd --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@tsconfig/node18/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "esModuleInterop": true, + "resolveJsonModule": true, + "target": "esnext" + }, + "esModuleInterop": true +} From 672bf10546dc19e39c1b360997cdd41f301e78db Mon Sep 17 00:00:00 2001 From: qugalet Date: Mon, 10 Jul 2023 16:34:35 +0300 Subject: [PATCH 02/46] migrated config to .env file --- .env.example | 7 ++++++- README.md | 12 +----------- config.json.example | 8 -------- package.json | 1 + pnpm-lock.yaml | 8 ++++++++ src/index.ts | 35 +++++++++++++++++++++++------------ 6 files changed, 39 insertions(+), 32 deletions(-) delete mode 100644 config.json.example diff --git a/.env.example b/.env.example index 2e9c5d7..ec857db 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,6 @@ -DATABASE_URL="postgresql://uabot@postgres:5432/uabot" \ No newline at end of file +DATABASE_URL="postgresql://uabot@postgres:5432/uabot" +MASTODON_ACCESS_TOKEN= +MASTODON_HOMESERVER_URL= +MATRIX_HOMESERVER_URL= +MATRIX_ACCESS_TOKEN= +MATRIX_ROOM_ID= \ No newline at end of file diff --git a/README.md b/README.md index d3ce0c6..9cd8bae 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,6 @@ First, install Postgres. Second, clone repo. Copy `.env.example` to `.env` and edit with your data: -```sh -DATABASE_URL="postgresql://uabot@postgres:5432/uabot" -``` -Also copy `config.json.example` to `config.json` with your data: -* `mastodonClientId` - Mastodon Client Id -* `mastodonAccessToken` - Mastodon Access Token -* `mastodonHomeserverURL` - Mastodon Homeserver URL -* `matrixHomeserverURL` - Matrix Homeserver URL bot for moderation -* `matrixAccessToken` - Matrix Access Token for Matrix bot for moderation -* `matrixRoomId` - Matrix Room Id for moderation Also create `nicknames.txt` and `domains.txt` (regex files): @@ -36,7 +26,7 @@ Now you can install using **Dockerimage** or **manually**: #### Docker Build `Dockerfile` and run -Also, mount `config.json`, `domains.txt` and `nicknames.txt` to the `/app` +Also, mount `domains.txt` and `nicknames.txt` to the `/app` ### Manually diff --git a/config.json.example b/config.json.example deleted file mode 100644 index bcc930c..0000000 --- a/config.json.example +++ /dev/null @@ -1,8 +0,0 @@ -{ - "pleromaClientId": "", - "pleromaAccessToken": "", - "pleromaHomeserverURL": "", - "matrixHomeserverURL": "", - "matrixAccessToken": "", - "matrixRoomId": "" -} diff --git a/package.json b/package.json index 2893f92..0bdf4db 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "dependencies": { "@prisma/client": "4.14.1", + "dotenv": "^16.3.1", "masto": "^5.11.3", "matrix-bot-sdk": "^0.6.6", "prisma": "^4.16.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b8b3ff..074c9a7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@prisma/client': specifier: 4.14.1 version: 4.14.1(prisma@4.16.2) + dotenv: + specifier: ^16.3.1 + version: 16.3.1 masto: specifier: ^5.11.3 version: 5.11.3 @@ -759,6 +762,11 @@ packages: tslib: 2.6.0 dev: false + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: false + /ecc-jsbn@0.1.2: resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} dependencies: diff --git a/src/index.ts b/src/index.ts index 2172157..0863044 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,21 @@ +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 @@ -12,18 +25,16 @@ function parseAsyncRegexFile(file: Buffer): RegExp[] { } async function main() { - const config = JSON.parse((await readFile(join(__dirname, '..', 'config.json'))).toString()); - console.log(config); const mastodon = await ( await import('masto') ).login({ - url: config.mastodonHomeserverURL, - accessToken: config.mastodonAccessToken, + url: process.env.MASTODON_HOMESERVER_URL, + accessToken: process.env.MASTODON_ACCESS_TOKEN, disableVersionCheck: true }); const matrix = new MatrixClient( - config.matrixHomeserverURL, - config.matrixAccessToken, + process.env.MATRIX_HOMESERVER_URL, + process.env.MATRIX_ACCESS_TOKEN, new SimpleFsStorageProvider('matrix_db.json') ); const nicknameRegexes = parseAsyncRegexFile(await readFile(join(__dirname, '..', 'domains.txt'))); @@ -39,7 +50,7 @@ async function main() { ) { await mastodon.v1.accounts.block(notification.account.id); await matrix.sendText( - config.matrixRoomId, + process.env.MATRIX_ROOM_ID, `Юзер ${notification.account.acct} був заблокований автоматично` ); } @@ -51,7 +62,7 @@ async function main() { notification.status?.visibility === 'public' ) { const matrixId = await matrix.sendText( - config.matrixRoomId, + process.env.MATRIX_ROOM_ID, `Одобряємо?\n${notification.status.url}\nт - Так\nн - Ні` ); await db.post.create({ @@ -71,7 +82,7 @@ async function main() { }); matrix.on('room.message', async (roomId, event) => { if ( - roomId === config.matrixRoomId && + roomId === process.env.MATRIX_ROOM_ID && event['content'] && ['т', 'н'].includes(event['content']['body'].split('\n').at(-1).trim()) && event['content']['m.relates_to']['m.in_reply_to'] @@ -85,14 +96,14 @@ async function main() { console.log('test'); await mastodon.v1.statuses.reblog(post.postId); await matrix.replyText( - config.matrixRoomId, + process.env.MATRIX_ROOM_ID, event['content']['m.relates_to']['m.in_reply_to']['event_id'], 'Пост успішно опубліковано' ); } if (post && event['content']['body'].split('\n').at(-1) === 'н') { await matrix.redactEvent( - config.matrixRoomId, + process.env.MATRIX_ROOM_ID, event['content']['m.relates_to']['event_id'], 'Не одобрили :(' ); @@ -102,7 +113,7 @@ async function main() { } }); await matrix.replyText( - config.matrixRoomId, + process.env.MATRIX_ROOM_ID, event['content']['m.relates_to']['m.in_reply_to']['event_id'], 'Пост відхилено' ); From a13bfb50b90a2b86f8fd73bbd568263cd5f6dcb5 Mon Sep 17 00:00:00 2001 From: Qugalet Date: Thu, 13 Jul 2023 00:17:02 +0300 Subject: [PATCH 03/46] Create docker-image.yml --- .github/workflows/docker-image.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..7576b6d --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,18 @@ +name: Docker Image CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag uabot:$(date +%s) From 217afc1857833bfc345c59cb562aae2dc7f2045d Mon Sep 17 00:00:00 2001 From: Qugalet Date: Thu, 13 Jul 2023 10:41:54 +0300 Subject: [PATCH 04/46] create docker image on push --- .github/workflows/docker-image.yml | 49 +++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 7576b6d..981d646 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,4 +1,13 @@ -name: Docker Image CI +# 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: @@ -6,13 +15,39 @@ on: pull_request: branches: [ "main" ] +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + jobs: - - build: - + build-and-push-image: runs-on: ubuntu-latest + permissions: + contents: read + packages: write steps: - - uses: actions/checkout@v3 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag uabot:$(date +%s) + - name: Checkout repository + uses: actions/checkout@v3 + + - 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@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + From b2f80d0e0be31721c0de3e8fee22b4a02a1d689d Mon Sep 17 00:00:00 2001 From: Kitanit <65107731+Kitanit@users.noreply.github.com> Date: Thu, 13 Jul 2023 10:54:25 +0300 Subject: [PATCH 05/46] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index bc723d0..de7f83d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: bot: - build: . + image: ghcr.io/ua-fediland/ua-bot:main env_file: - ./.env volumes: From 293c2295b42bc84f2010957fee8a60a2f0a52ea4 Mon Sep 17 00:00:00 2001 From: Qugalet Date: Thu, 13 Jul 2023 11:41:47 +0300 Subject: [PATCH 06/46] arm builds --- .github/workflows/docker-image.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 981d646..3f194a6 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -25,6 +25,12 @@ jobs: permissions: contents: read packages: write + strategy: + fail-fast: false + matrix: + platform: + - linux/amd64 + - linux/arm64 steps: - name: Checkout repository @@ -48,6 +54,7 @@ jobs: with: context: . push: true + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} From f0077fabb8c121ad7ae255dadc729f4fad91aac5 Mon Sep 17 00:00:00 2001 From: Qugalet Date: Thu, 13 Jul 2023 11:42:29 +0300 Subject: [PATCH 07/46] removed strategy --- .github/workflows/docker-image.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 3f194a6..144823f 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -25,12 +25,6 @@ jobs: permissions: contents: read packages: write - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64 steps: - name: Checkout repository From 8739350b101d60dc56058b9b1b992034c65bb5b3 Mon Sep 17 00:00:00 2001 From: Kitanit <65107731+Kitanit@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:44:11 +0300 Subject: [PATCH 08/46] Update docker-compose.yml --- docker-compose.yml | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index de7f83d..2d1f39c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,8 +6,27 @@ services: env_file: - ./.env volumes: - - ./config.json:/app/config.json - - ./nicknames.txt:/app/nicknames.txt - - ./domains.txt:/app/domains.txt - extra_hosts: - - host.docker.internal:host-gateway + - ./nicknames.txt:/app/nicknames.txt + - ./domains.txt:/app/domains.txt + depends_on: + - db + networks: + - default + + db: + restart: unless-stopped + restart: always + image: postgres:15-alpine + networks: + - default + env_file: + - .db.env + volumes: + - ./db:/var/lib/postgresql/data + healthcheck: + test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" + interval: 5s + retries: 20 + + networks: + default: From d0c27f1ac9ad524ca03cd076bf96476670d9babf Mon Sep 17 00:00:00 2001 From: Qugalet Date: Thu, 13 Jul 2023 11:44:18 +0300 Subject: [PATCH 09/46] trying to fix docker buildx issue --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 144823f..d9dfc44 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -44,7 +44,7 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + uses: docker/build-push-action@v4 with: context: . push: true From f617fbc5de95d08312f1e5925dd3460623ea5ba9 Mon Sep 17 00:00:00 2001 From: Kitanit <65107731+Kitanit@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:46:21 +0300 Subject: [PATCH 10/46] Add files via upload --- .db.env | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .db.env diff --git a/.db.env b/.db.env new file mode 100644 index 0000000..37f6cec --- /dev/null +++ b/.db.env @@ -0,0 +1,3 @@ +POSTGRES_PASSWORD= +POSTGRES_USER= +POSTGRES_DB= From b57fbbd019a0e0891a3fff1cd708b8b762ada1aa Mon Sep 17 00:00:00 2001 From: Qugalet Date: Thu, 13 Jul 2023 11:49:28 +0300 Subject: [PATCH 11/46] fixed buildx issue with docker driver --- .github/workflows/docker-image.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index d9dfc44..bd4c65c 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -29,6 +29,9 @@ jobs: 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 @@ -42,7 +45,7 @@ jobs: 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: From 2d7ec516f9effcb209fcaace166d809ad4050196 Mon Sep 17 00:00:00 2001 From: Kitanit <65107731+Kitanit@users.noreply.github.com> Date: Thu, 13 Jul 2023 08:52:29 +0000 Subject: [PATCH 12/46] Fix name .db.env.example --- .db.env => .db.env.example | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .db.env => .db.env.example (100%) diff --git a/.db.env b/.db.env.example similarity index 100% rename from .db.env rename to .db.env.example From 6e51197616d05888c780ab08fc5d1b310b6693f0 Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 12:05:23 +0300 Subject: [PATCH 13/46] pnpm --- Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index a392e62..5518723 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,14 +2,16 @@ FROM node:18-bookworm WORKDIR /app -COPY package.json . +COPY package.json pnpm-lock.yaml ./ -RUN npm i +RUN npm i -g pnpm + +RUN pnpm install --frozen-lockfile --prod COPY . . -RUN npm run generate +RUN pnpm generate -RUN npm run build +RUN pnpm build ENTRYPOINT [ "./entrypoint.sh" ] \ No newline at end of file From d5f3ae25ee42d0a5973d467cba2211f7af93037c Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 12:09:18 +0300 Subject: [PATCH 14/46] fixed build command --- Dockerfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5518723..2dfd185 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,12 +6,10 @@ COPY package.json pnpm-lock.yaml ./ RUN npm i -g pnpm -RUN pnpm install --frozen-lockfile --prod +RUN pnpm install --frozen-lockfile COPY . . -RUN pnpm generate - -RUN pnpm build +RUN pnpm generate && pnpm build ENTRYPOINT [ "./entrypoint.sh" ] \ No newline at end of file From 338e9be5407d6b9d6eea1ea8fa0411ccb3e631f9 Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 14:11:06 +0300 Subject: [PATCH 15/46] arm and typo fix --- entrypoint.sh | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 5c794f8..83772d1 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,3 +1,3 @@ #!/bin/sh -npm run migrate -npm run start \ No newline at end of file +pnpm migrate +pnpm start \ No newline at end of file diff --git a/package.json b/package.json index 0bdf4db..5874815 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "watch": "tsc -w", "build": "tsc", - "start": "node ./dist", + "start": "node ./dist/index.js", "generate": "prisma generate", "migrate": "prisma migrate deploy" }, From 34c552703af95e6c3a280465af3ffd1dfb7b3236 Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 15:01:34 +0300 Subject: [PATCH 16/46] fixed undefined property error --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 0863044..1bf9afc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -85,6 +85,7 @@ async function main() { roomId === process.env.MATRIX_ROOM_ID && event['content'] && ['т', 'н'].includes(event['content']['body'].split('\n').at(-1).trim()) && + event['content']['m.relates_to'] && event['content']['m.relates_to']['m.in_reply_to'] ) { const post = await db.post.findUnique({ From f8e480bfee3db0e0238d912070362c7fb8684fd4 Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 15:07:32 +0300 Subject: [PATCH 17/46] fixed regex reading --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 1bf9afc..0fb0ab4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,7 @@ function parseAsyncRegexFile(file: Buffer): RegExp[] { const data = file.toString(); return data .split('\n') - .filter(regex => !regex.trim().startsWith('#')) + .filter(regex => !regex.startsWith('#') && regex.trim() !== '') .map(regex => new RegExp(regex)); } From a9a8b6a750aeb84d57c56f0b0be1d48aaac65a17 Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 15:22:12 +0300 Subject: [PATCH 18/46] added easter egg --- src/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/index.ts b/src/index.ts index 0fb0ab4..d7e688b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -79,6 +79,13 @@ async function main() { }); console.log('follow message'); } + if (notification.type === 'mention' && notification.status?.visibility === 'direct') { + await mastodon.v1.statuses.create({ + inReplyToId: notification.status.id, + visibility: 'direct', + status: 'meow' + }); + } }); matrix.on('room.message', async (roomId, event) => { if ( From 64d6334971871901788c0c1beebe66b9fbfd0708 Mon Sep 17 00:00:00 2001 From: qugalet Date: Thu, 13 Jul 2023 15:47:26 +0300 Subject: [PATCH 19/46] fixed panic on bad reblog --- src/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index d7e688b..391c95d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -131,4 +131,6 @@ async function main() { await db.$connect(); await matrix.start(); } -main().then(() => console.log('everything started!')); +main() + .then(() => console.log('everything started!')) + .catch(e => console.error(e)); From a65846891408262d6a8625d1c7102cbfc57180ac Mon Sep 17 00:00:00 2001 From: Kitanit <65107731+Kitanit@users.noreply.github.com> Date: Thu, 13 Jul 2023 16:07:54 +0300 Subject: [PATCH 20/46] Update docker-compose.yml --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 2d1f39c..a874c95 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ version: '3' services: bot: image: ghcr.io/ua-fediland/ua-bot:main + restart: always env_file: - ./.env volumes: From eb0650f98b33680cb9675f60501b43c4945e7bd9 Mon Sep 17 00:00:00 2001 From: Kitanit <65107731+Kitanit@users.noreply.github.com> Date: Thu, 13 Jul 2023 16:09:43 +0300 Subject: [PATCH 21/46] Add files via upload --- domains.txt | 0 nicknames.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 domains.txt create mode 100644 nicknames.txt diff --git a/domains.txt b/domains.txt new file mode 100644 index 0000000..e69de29 diff --git a/nicknames.txt b/nicknames.txt new file mode 100644 index 0000000..e69de29 From 5986b173a3ea733a7e894a588f856964ed1edf9d Mon Sep 17 00:00:00 2001 From: qugalet Date: Wed, 19 Jul 2023 23:37:42 +0300 Subject: [PATCH 22/46] fixed prisma version mismatch --- package.json | 2 +- pnpm-lock.yaml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 5874815..18151f9 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "typescript": "^5.1.6" }, "dependencies": { - "@prisma/client": "4.14.1", + "@prisma/client": "4.16.2", "dotenv": "^16.3.1", "masto": "^5.11.3", "matrix-bot-sdk": "^0.6.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 074c9a7..16a231b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@prisma/client': - specifier: 4.14.1 - version: 4.14.1(prisma@4.16.2) + specifier: 4.16.2 + version: 4.16.2(prisma@4.16.2) dotenv: specifier: ^16.3.1 version: 16.3.1 @@ -149,8 +149,8 @@ packages: fastq: 1.15.0 dev: true - /@prisma/client@4.14.1(prisma@4.16.2): - resolution: {integrity: sha512-TZIswkeX1ccsHG/eN2kICzg/csXll0osK3EHu1QKd8VJ3XLcXozbNELKkCNfsCUvKJAwPdDtFCzF+O+raIVldw==} + /@prisma/client@4.16.2(prisma@4.16.2): + resolution: {integrity: sha512-qCoEyxv1ZrQ4bKy39GnylE8Zq31IRmm8bNhNbZx7bF2cU5aiCCnSa93J2imF88MBjn7J9eUQneNxUQVJdl/rPQ==} engines: {node: '>=14.17'} requiresBuild: true peerDependencies: @@ -159,12 +159,12 @@ packages: prisma: optional: true dependencies: - '@prisma/engines-version': 4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c + '@prisma/engines-version': 4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81 prisma: 4.16.2 dev: false - /@prisma/engines-version@4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c: - resolution: {integrity: sha512-3jum8/YSudeSN0zGW5qkpz+wAN2V/NYCQ+BPjvHYDfWatLWlQkqy99toX0GysDeaUoBIJg1vaz2yKqiA3CFcQw==} + /@prisma/engines-version@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81: + resolution: {integrity: sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg==} dev: false /@prisma/engines@4.16.2: From 534b6c436d51a5670736402f86d6cc36ebda9795 Mon Sep 17 00:00:00 2001 From: qugalet Date: Wed, 19 Jul 2023 23:38:12 +0300 Subject: [PATCH 23/46] fixed replies and added edit in matrix mesages --- prisma/schema.prisma | 1 + src/index.ts | 76 +++++++++++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f5fd15d..ce0c64d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -11,6 +11,7 @@ datasource db { } model Post { + id Int @unique @default(autoincrement()) postId String @id matrixId String @unique } diff --git a/src/index.ts b/src/index.ts index 391c95d..196ccdd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,6 +24,26 @@ function parseAsyncRegexFile(file: Buffer): RegExp[] { .map(regex => new RegExp(regex)); } +async function editText( + client: MatrixClient, + roomId: string, + eventId: string, + text: string +): Promise { + 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') @@ -63,14 +83,23 @@ async function main() { ) { const matrixId = await matrix.sendText( process.env.MATRIX_ROOM_ID, - `Одобряємо?\n${notification.status.url}\nт - Так\nн - Ні` + `${notification.status.url}\nY/т - Так\nN/н - Ні` ); - await db.post.create({ + 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({ @@ -79,7 +108,12 @@ async function main() { }); console.log('follow message'); } - if (notification.type === 'mention' && notification.status?.visibility === 'direct') { + 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', @@ -100,30 +134,34 @@ async function main() { matrixId: event['content']['m.relates_to']['m.in_reply_to']['event_id'] } }); - if (post && event['content']['body'].split('\n').at(-1) === 'т') { - console.log('test'); + 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['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) + ' ✅' ); } - if (post && event['content']['body'].split('\n').at(-1) === 'н') { - await matrix.redactEvent( - process.env.MATRIX_ROOM_ID, - event['content']['m.relates_to']['event_id'], - 'Не одобрили :(' - ); + 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['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) + ' ❌' ); } } From b8e9d7d4c0df034128f5f8b0ebff7d7481761c5c Mon Sep 17 00:00:00 2001 From: qugalet Date: Mon, 24 Jul 2023 18:47:40 +0300 Subject: [PATCH 24/46] migration fix --- prisma/migrations/20230724154656_ids/migration.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 prisma/migrations/20230724154656_ids/migration.sql diff --git a/prisma/migrations/20230724154656_ids/migration.sql b/prisma/migrations/20230724154656_ids/migration.sql new file mode 100644 index 0000000..49f90d9 --- /dev/null +++ b/prisma/migrations/20230724154656_ids/migration.sql @@ -0,0 +1,11 @@ +/* + 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"); From 5e042670c425da26fa463ca11b491f873b881a86 Mon Sep 17 00:00:00 2001 From: qugalet Date: Mon, 24 Jul 2023 18:47:58 +0300 Subject: [PATCH 25/46] fixed choose typo --- src/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 196ccdd..48c2e42 100644 --- a/src/index.ts +++ b/src/index.ts @@ -125,7 +125,9 @@ async function main() { if ( roomId === process.env.MATRIX_ROOM_ID && event['content'] && - ['т', 'н'].includes(event['content']['body'].split('\n').at(-1).trim()) && + ['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'] ) { From 66e906f139ee93ddf6a81ca5824e2ffddc737a84 Mon Sep 17 00:00:00 2001 From: qugalet Date: Tue, 19 Sep 2023 22:19:25 +0300 Subject: [PATCH 26/46] Rewrite in Go Signed-off-by: qugalet --- .dockerignore | 3 + .env.example | 15 +++ .gitignore | 4 + Dockerfile | 15 +++ README.md | 47 ++++++++ entrypoint.sh | 6 + go.mod | 39 +++++++ go.sum | 74 +++++++++++++ main.go | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 499 insertions(+) create mode 100644 .dockerignore create mode 100755 .env.example create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 entrypoint.sh create mode 100755 go.mod create mode 100755 go.sum create mode 100755 main.go diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8ba473e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +domains.txt +nicknames.txt +uabot diff --git a/.env.example b/.env.example new file mode 100755 index 0000000..499e7e8 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +POSTGRES_HOST= +POSTGRES_USER= +POSTGRES_PASSWORD= +POSTGRES_DB= +POSTGRES_PORT= + +MATRIX_HOMESERVER= +MATRIX_USERNAME= +MATRIX_ACCESS_TOKEN= +MATRIX_ROOM_ID= + +MASTODON_HOMESERVER= +MASTODON_CLIENT_ID= +MASTODON_CLIENT_SECRET= +MASTODON_ACCESS_TOKEN= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..469158f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.env +domains.txt +nicknames.txt +uabot diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a7ec6ca --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +# syntax=docker/dockerfile:1 + +FROM golang:1.20 + +WORKDIR /app + +COPY go.mod go.sum . + +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux go build -o /app/uabot + +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..4369a76 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +## UA-Bot + +**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 + +### Install + +First, install Postgres (>= 14 will be fine, i guess). + +Second, clone repo. + +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 + +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` + +### Manually + +Install Go >= 1.20 + +Next, build the project: + +```sh +go build +``` + +Run: + +```sh +./uabot +``` diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..ab53ff9 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +test -f domains.txt || touch domains.txt +test -f nicknames.txt || touch nicknames.txt + +./uabot diff --git a/go.mod b/go.mod new file mode 100755 index 0000000..1d284ff --- /dev/null +++ b/go.mod @@ -0,0 +1,39 @@ +module uabot + +go 1.20 + +require ( + github.com/mattn/go-mastodon v0.0.6 + 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 +) diff --git a/go.sum b/go.sum new file mode 100755 index 0000000..2a01d26 --- /dev/null +++ b/go.sum @@ -0,0 +1,74 @@ +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= diff --git a/main.go b/main.go new file mode 100755 index 0000000..60f01be --- /dev/null +++ b/main.go @@ -0,0 +1,296 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "os" + "path" + "regexp" + "strings" + + "github.com/joho/godotenv" + log "github.com/sirupsen/logrus" + + "github.com/mattn/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() + + if err != nil { + log.Fatal(err) + } + + ex, err := os.Getwd() + + if err != nil { + log.Fatal(err) + } + + domainRegexes, err := parseRegexFile(path.Join(ex, "domains.txt")) + + if err != nil { + log.Fatal(err) + } + + nicknameRegexes, err := parseRegexFile(path.Join(ex, "nicknames.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) + } + + // log.Println(my_account) + + 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...") + + syncer.OnEventType(m_event.EventReaction, func(source mautrix.EventSource, ev *m_event.Event) { + log.Info("reactions") + // if ev.RoomID == os.Getenv("MATRIX_ROOM_ID") && ev.Content != nil && + content := ev.Content.AsReaction() + key := []rune(content.RelatesTo.Key) + log.Info(content.RelatesTo.Key) + if ev.RoomID.String() == os.Getenv("MATRIX_ROOM_ID") && (key[0] == '👍' || key[0] == '👎') { + log.Info("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(os.Getenv("MATRIX_ROOM_ID"), "m.room.message", interface{}) + body := fmt.Sprintf(`#%d: Схвалено +%s +`, post.ID, status.URL) + + _, err := matrix_client.SendMessageEvent(m_id.RoomID(os.Getenv("MATRIX_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(os.Getenv("MATRIX_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 domainRegexes { + if len(acct_parsed) == 2 && regex.MatchString(acct_parsed[1]) { + _, err := masto_client.AccountBlock(ctx, notif.Account.ID) + if err == nil { + matrix_client.SendText(m_id.RoomID(os.Getenv("MATRIX_ROOM_ID")), fmt.Sprintf("%s заблокований автоматично регексом доменів: %s", notif.Account.Acct, regex.String())) + } + continue notif_loop + } + } + + for _, regex := range nicknameRegexes { + if regex.MatchString(acct_parsed[0]) { + _, err := masto_client.AccountBlock(ctx, notif.Account.ID) + if err == nil { + matrix_client.SendText(m_id.RoomID(os.Getenv("MATRIX_ROOM_ID")), fmt.Sprintf("%s заблокований автоматично регексом нікнеймів: %s", notif.Account.Acct, regex.String())) + } + continue notif_loop + } + } + + masto_client.PostStatus(ctx, &mastodon.Toot{ + Status: fmt.Sprintf("Вітаємо у нашій спільноті! @%s", notif.Account.Acct), + Visibility: mastodon.VisibilityUnlisted, + }) + } + + if notif.Type == "mention" && notif.Status.InReplyToID == nil && notif.Status.InReplyToAccountID == nil { + subscribers, err := masto_client.GetAccountFollowers(ctx, masto_user.ID, &mastodon.Pagination{Limit: 10000}) + if err != nil { + log.Error(err) + continue + } + + ok := false + + for _, subscriber := range subscribers { + if subscriber.ID == notif.Account.ID { + ok = true + break + } + } + + if ok && notif.Status.Visibility == "public" { + 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(os.Getenv("MATRIX_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", + }) + } + + } + + } + +} From 664657d9d04560397de8edd712e1b46b5025fbaa Mon Sep 17 00:00:00 2001 From: Shizanit Date: Tue, 19 Sep 2023 19:59:20 +0000 Subject: [PATCH 27/46] Upload files to "/" --- docker-compose.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cf01382 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,35 @@ +version: '3' + +services: + bot: +# image: securetowntop/ua-bot:arm64-latest + image: 374fe5dee955 + restart: always + env_file: + - ./.env + volumes: + - ./nicknames.txt:/app/nicknames.txt + - ./domains.txt:/app/domains.txt + depends_on: + - db + networks: + - default + + db: + restart: unless-stopped + restart: always + image: postgres:15-alpine + networks: + - default + env_file: + - .db.env + volumes: + - ./db:/var/lib/postgresql/data + healthcheck: + test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" + interval: 5s + retries: 20 + + networks: + default: + From 36b3b5f25619f2853c605ee50417a362a96e6c7b Mon Sep 17 00:00:00 2001 From: qugalet Date: Tue, 19 Sep 2023 23:08:56 +0300 Subject: [PATCH 28/46] Fix permissions in entrypoint file --- entrypoint.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 entrypoint.sh diff --git a/entrypoint.sh b/entrypoint.sh old mode 100644 new mode 100755 From 71b3ac18fabf45c5b1c4aa22f7b5de888f1c71ae Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Thu, 4 Jan 2024 21:05:56 +0200 Subject: [PATCH 29/46] add debug info to inspect issues --- main.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/main.go b/main.go index 60f01be..1c78e45 100755 --- a/main.go +++ b/main.go @@ -239,7 +239,14 @@ notif_loop: }) } + 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) +text: %v +actor: %v`, notif.Status.ID, notif.Status.Content, notif.Account.Acct) subscribers, err := masto_client.GetAccountFollowers(ctx, masto_user.ID, &mastodon.Pagination{Limit: 10000}) if err != nil { log.Error(err) @@ -256,6 +263,7 @@ notif_loop: } if ok && notif.Status.Visibility == "public" { + log.Debugf("post %v is public and has subscription", notif.Status.ID) if err := db.Create(&Post{ PostId: string(notif.Status.ID), }).Error; err != nil { From 8b875882e988e1bf799ee9e17b5c43289cedc0b2 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Thu, 4 Jan 2024 22:01:06 +0200 Subject: [PATCH 30/46] add send text to matrix when started --- main.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 1c78e45..7b6d8d1 100755 --- a/main.go +++ b/main.go @@ -55,6 +55,7 @@ func parseRegexFile(path string) ([]regexp.Regexp, error) { func main() { ctx := context.Background() err := godotenv.Load() + ROOM_ID := os.Getenv("MATRIX_ROOM_ID") if err != nil { log.Fatal(err) @@ -115,14 +116,15 @@ func main() { 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.Info("reactions") - // if ev.RoomID == os.Getenv("MATRIX_ROOM_ID") && ev.Content != nil && + // if ev.RoomID == ROOM_ID && ev.Content != nil && content := ev.Content.AsReaction() key := []rune(content.RelatesTo.Key) log.Info(content.RelatesTo.Key) - if ev.RoomID.String() == os.Getenv("MATRIX_ROOM_ID") && (key[0] == '👍' || key[0] == '👎') { + if ev.RoomID.String() == ROOM_ID && (key[0] == '👍' || key[0] == '👎') { log.Info("reacted well") var post Post if err := db.First(&post, "message_id = ?", content.RelatesTo.EventID.String()).Error; err != nil { @@ -142,12 +144,12 @@ func main() { log.Error(err) return } - // matrix_client.SendMessageEvent(os.Getenv("MATRIX_ROOM_ID"), "m.room.message", interface{}) + // 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(os.Getenv("MATRIX_ROOM_ID")), m_event.EventMessage, &m_event.MessageEventContent{ + _, 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{ @@ -167,7 +169,7 @@ func main() { body := fmt.Sprintf(`#%d: Відмовлено %s `, post.ID, status.URL) - _, err := matrix_client.SendMessageEvent(m_id.RoomID(os.Getenv("MATRIX_ROOM_ID")), m_event.EventMessage, &m_event.MessageEventContent{ + _, 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{ @@ -217,7 +219,7 @@ notif_loop: if len(acct_parsed) == 2 && regex.MatchString(acct_parsed[1]) { _, err := masto_client.AccountBlock(ctx, notif.Account.ID) if err == nil { - matrix_client.SendText(m_id.RoomID(os.Getenv("MATRIX_ROOM_ID")), fmt.Sprintf("%s заблокований автоматично регексом доменів: %s", notif.Account.Acct, regex.String())) + matrix_client.SendText(m_id.RoomID(ROOM_ID), fmt.Sprintf("%s заблокований автоматично регексом доменів: %s", notif.Account.Acct, regex.String())) } continue notif_loop } @@ -227,7 +229,7 @@ notif_loop: if regex.MatchString(acct_parsed[0]) { _, err := masto_client.AccountBlock(ctx, notif.Account.ID) if err == nil { - matrix_client.SendText(m_id.RoomID(os.Getenv("MATRIX_ROOM_ID")), fmt.Sprintf("%s заблокований автоматично регексом нікнеймів: %s", notif.Account.Acct, regex.String())) + matrix_client.SendText(m_id.RoomID(ROOM_ID), fmt.Sprintf("%s заблокований автоматично регексом нікнеймів: %s", notif.Account.Acct, regex.String())) } continue notif_loop } @@ -275,7 +277,7 @@ actor: %v`, notif.Status.ID, notif.Status.Content, notif.Account.Acct) log.Error(err) continue } - message, err := matrix_client.SendText(m_id.RoomID(os.Getenv("MATRIX_ROOM_ID")), fmt.Sprintf(`#%d: На модерації + message, err := matrix_client.SendText(m_id.RoomID(ROOM_ID), fmt.Sprintf(`#%d: На модерації %s 👍 - Так 👎 - Ні From d5ae0bcb0c67c66215db899915352f7112e0848f Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 00:44:33 +0200 Subject: [PATCH 31/46] add whitelist and replace old blacklist files with one --- .gitignore | 4 ++-- main.go | 36 +++++++++++++++++++----------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 469158f..6243184 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .env -domains.txt -nicknames.txt +blacklist.txt +whitelist.txt uabot diff --git a/main.go b/main.go index 7b6d8d1..dd8875f 100755 --- a/main.go +++ b/main.go @@ -67,13 +67,13 @@ func main() { log.Fatal(err) } - domainRegexes, err := parseRegexFile(path.Join(ex, "domains.txt")) + blacklistRegexes, err := parseRegexFile(path.Join(ex, "blacklist.txt")) if err != nil { log.Fatal(err) } - nicknameRegexes, err := parseRegexFile(path.Join(ex, "nicknames.txt")) + whitelistRegexes, err := parseRegexFile(path.Join(ex, "whitelist.txt")) if err != nil { log.Fatal(err) @@ -213,23 +213,13 @@ notif_loop: // log.Println(notif) if notif.Type == "follow" { - acct_parsed := strings.Split(notif.Account.Acct, "@") + // acct_parsed := strings.Split(notif.Account.Acct, "@") - for _, regex := range domainRegexes { - if len(acct_parsed) == 2 && regex.MatchString(acct_parsed[1]) { + 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 - } - } - - for _, regex := range nicknameRegexes { - if regex.MatchString(acct_parsed[0]) { - _, 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())) + matrix_client.SendText(m_id.RoomID(ROOM_ID), fmt.Sprintf("%s заблокований автоматично регулярним виразом: %s", notif.Account.Acct, regex.String())) } continue notif_loop } @@ -265,7 +255,19 @@ actor: %v`, notif.Status.ID, notif.Status.Content, notif.Account.Acct) } if ok && notif.Status.Visibility == "public" { - log.Debugf("post %v is public and has subscription", notif.Status.ID) + 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 { From 32f70f43eff8497aceb298d9775f076f66602283 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 00:50:35 +0200 Subject: [PATCH 32/46] replace log with debug in old code --- main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index dd8875f..8abfe96 100755 --- a/main.go +++ b/main.go @@ -119,13 +119,13 @@ func main() { matrix_client.SendText(m_id.RoomID(ROOM_ID), "Бот запущений!") syncer.OnEventType(m_event.EventReaction, func(source mautrix.EventSource, ev *m_event.Event) { - log.Info("reactions") + log.Debug("reactions") // if ev.RoomID == ROOM_ID && ev.Content != nil && content := ev.Content.AsReaction() key := []rune(content.RelatesTo.Key) - log.Info(content.RelatesTo.Key) + log.Debug(content.RelatesTo.Key) if ev.RoomID.String() == ROOM_ID && (key[0] == '👍' || key[0] == '👎') { - log.Info("reacted well") + log.Debug("reacted well") var post Post if err := db.First(&post, "message_id = ?", content.RelatesTo.EventID.String()).Error; err != nil { log.Error(err) From 09f966ee111d48e79ef2798ac6b6a9b5b0584f82 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 01:06:35 +0200 Subject: [PATCH 33/46] set debug level for log output --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 8abfe96..3c33569 100755 --- a/main.go +++ b/main.go @@ -56,6 +56,7 @@ 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) From d3f51c73b52e35e13de120e42d25b645b4980719 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 01:12:13 +0200 Subject: [PATCH 34/46] add more info about posts in debug logs --- main.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 3c33569..29a2522 100755 --- a/main.go +++ b/main.go @@ -95,8 +95,7 @@ func main() { log.Fatal(err) } - masto_client := mastodon.NewClient(&mastodon.Config{ - Server: os.Getenv("MASTODON_HOMESERVER"), + 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"), @@ -238,8 +237,7 @@ notif_loop: if notif.Type == "mention" && notif.Status.InReplyToID == nil && notif.Status.InReplyToAccountID == nil { log.Debugf(`post passed reply check (%v) -text: %v -actor: %v`, notif.Status.ID, notif.Status.Content, notif.Account.Acct) + raw data: %v`, notif.Status.ID, notif.Status) subscribers, err := masto_client.GetAccountFollowers(ctx, masto_user.ID, &mastodon.Pagination{Limit: 10000}) if err != nil { log.Error(err) From 4a63f5e45dc3c44f9a19daa90db980ef02e12816 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 20:29:04 +0200 Subject: [PATCH 35/46] fix subscription check --- main.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 29a2522..3d2f487 100755 --- a/main.go +++ b/main.go @@ -106,6 +106,19 @@ func main() { log.Fatal(err) } + var subscribers []*mastodon.Account + var pg mastodon.Pagination + for { + fs, err := masto_client.GetAccountFollowers(context.Background(), masto_user.ID, &pg) + if err != nil { + log.Fatal(err) + } + subscribers = append(subscribers, fs...) + if pg.MaxID == "" { + break + } + } + // log.Println(my_account) matrix_client, err := mautrix.NewClient(os.Getenv("MATRIX_HOMESERVER"), m_id.UserID(os.Getenv("MATRIX_USERNAME")), os.Getenv("MATRIX_ACCESS_TOKEN")) @@ -225,6 +238,8 @@ notif_loop: } } + subscribers = append(subscribers, ¬if.Account) + masto_client.PostStatus(ctx, &mastodon.Toot{ Status: fmt.Sprintf("Вітаємо у нашій спільноті! @%s", notif.Account.Acct), Visibility: mastodon.VisibilityUnlisted, @@ -236,13 +251,7 @@ notif_loop: } if notif.Type == "mention" && notif.Status.InReplyToID == nil && notif.Status.InReplyToAccountID == nil { - log.Debugf(`post passed reply check (%v) - raw data: %v`, notif.Status.ID, notif.Status) - subscribers, err := masto_client.GetAccountFollowers(ctx, masto_user.ID, &mastodon.Pagination{Limit: 10000}) - if err != nil { - log.Error(err) - continue - } + log.Debugf(`post passed reply check (%v)`, notif.Status.ID) ok := false From 03dc5753d4ae4a9ab3b72ce3321181524b117bd9 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:18:55 +0200 Subject: [PATCH 36/46] add debug to subscription list fetch --- main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.go b/main.go index 3d2f487..01f8997 100755 --- a/main.go +++ b/main.go @@ -108,12 +108,14 @@ func main() { 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) if pg.MaxID == "" { break } From 45fb7b5fce60a516d31f9d8387d8b05f75b04fb8 Mon Sep 17 00:00:00 2001 From: qugalet Date: Fri, 5 Jan 2024 19:29:23 +0000 Subject: [PATCH 37/46] fix docker compose --- .gitignore | 1 + docker-compose.yml | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 6243184..871f2b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env +.db.env blacklist.txt whitelist.txt uabot diff --git a/docker-compose.yml b/docker-compose.yml index cf01382..a81ac35 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,13 +3,14 @@ version: '3' services: bot: # image: securetowntop/ua-bot:arm64-latest - image: 374fe5dee955 +# 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: @@ -17,7 +18,7 @@ services: db: restart: unless-stopped - restart: always + # restart: always image: postgres:15-alpine networks: - default @@ -30,6 +31,6 @@ services: interval: 5s retries: 20 - networks: - default: +networks: + default: From 8bac8f3b22f86851bb9fcafb6eb88bbcd80174ae Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:44:31 +0200 Subject: [PATCH 38/46] change debug info --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 01f8997..2d5177d 100755 --- a/main.go +++ b/main.go @@ -115,7 +115,7 @@ func main() { log.Fatal(err) } subscribers = append(subscribers, fs...) - log.Debug(pg) + log.Debug(pg.MaxID) if pg.MaxID == "" { break } From f66b828084a02543e8e696051a1d2de348e6a7a5 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:46:22 +0200 Subject: [PATCH 39/46] change debug info --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 2d5177d..1fb2197 100755 --- a/main.go +++ b/main.go @@ -115,6 +115,7 @@ func main() { log.Fatal(err) } subscribers = append(subscribers, fs...) + log.Debug(pg) log.Debug(pg.MaxID) if pg.MaxID == "" { break From 063083a0969912e0846f3969e3a554d9ee06fc90 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:48:26 +0200 Subject: [PATCH 40/46] check if debug --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 1fb2197..f34157c 100755 --- a/main.go +++ b/main.go @@ -108,6 +108,7 @@ func main() { var subscribers []*mastodon.Account var pg mastodon.Pagination + log.Info("test") log.Debug("get followers list") for { fs, err := masto_client.GetAccountFollowers(context.Background(), masto_user.ID, &pg) From 19349e08f7b93148906ecab3663ada263ff487c1 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:49:50 +0200 Subject: [PATCH 41/46] check if infinite loop --- main.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index f34157c..444eb95 100755 --- a/main.go +++ b/main.go @@ -100,28 +100,28 @@ func main() { ClientSecret: os.Getenv("MASTODON_CLIENT_SECRET"), AccessToken: os.Getenv("MASTODON_ACCESS_TOKEN"), }) - masto_user, err := masto_client.GetAccountCurrentUser(ctx) + // masto_user, err := masto_client.GetAccountCurrentUser(ctx) if err != nil { log.Fatal(err) } var subscribers []*mastodon.Account - var pg mastodon.Pagination - log.Info("test") - 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 - } - } + // var pg mastodon.Pagination + // log.Info("test") + // 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 + // } + // } // log.Println(my_account) From a8a9cf27ba522b87d8053d9cc9218d5b4a7b277a Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:50:59 +0200 Subject: [PATCH 42/46] check if fetch issue --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 444eb95..a3179a3 100755 --- a/main.go +++ b/main.go @@ -100,7 +100,7 @@ func main() { ClientSecret: os.Getenv("MASTODON_CLIENT_SECRET"), AccessToken: os.Getenv("MASTODON_ACCESS_TOKEN"), }) - // masto_user, err := masto_client.GetAccountCurrentUser(ctx) + _, err = masto_client.GetAccountCurrentUser(ctx) if err != nil { log.Fatal(err) From b3bf6d7b1784d15fc676c1690fcfea871e6befcd Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:53:38 +0200 Subject: [PATCH 43/46] check if infinite loop or go-mastodon is bad --- main.go | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/main.go b/main.go index a3179a3..3754bd8 100755 --- a/main.go +++ b/main.go @@ -100,30 +100,28 @@ func main() { ClientSecret: os.Getenv("MASTODON_CLIENT_SECRET"), AccessToken: os.Getenv("MASTODON_ACCESS_TOKEN"), }) - _, err = masto_client.GetAccountCurrentUser(ctx) + masto_user, err := masto_client.GetAccountCurrentUser(ctx) if err != nil { log.Fatal(err) } var subscribers []*mastodon.Account - // var pg mastodon.Pagination - // log.Info("test") - // 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 - // } - // } - - // log.Println(my_account) + var pg mastodon.Pagination + log.Info("test") + 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 + } + } 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) From 5d3bcb5c3dbf963ba96e44ecd47dde48d45d1352 Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 21:58:28 +0200 Subject: [PATCH 44/46] add subscribers list debug --- main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.go b/main.go index 3754bd8..1d6d0af 100755 --- a/main.go +++ b/main.go @@ -122,6 +122,9 @@ func main() { break } } + for subscriber := range subscribers { + log.Debug(subscriber) + } 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) From ae764ce83a0c5afbeb2e08397b72005f6688d7ce Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 23:42:47 +0200 Subject: [PATCH 45/46] replace go-mastodon with own fork --- go.mod | 2 +- go.sum | 2 ++ main.go | 15 ++++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 1d284ff..3bc3a46 100755 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module uabot go 1.20 require ( - github.com/mattn/go-mastodon v0.0.6 + github.com/UA-Fediland/go-mastodon v0.0.0-20240105213412-04581fbfe202 gorm.io/gorm v1.25.4 ) diff --git a/go.sum b/go.sum index 2a01d26..c23c541 100755 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +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= diff --git a/main.go b/main.go index 1d6d0af..a7adb82 100755 --- a/main.go +++ b/main.go @@ -8,11 +8,12 @@ import ( "path" "regexp" "strings" + "time" "github.com/joho/godotenv" log "github.com/sirupsen/logrus" - "github.com/mattn/go-mastodon" + "github.com/UA-Fediland/go-mastodon" "gorm.io/driver/postgres" "gorm.io/gorm" "maunium.net/go/mautrix" @@ -108,7 +109,6 @@ func main() { var subscribers []*mastodon.Account var pg mastodon.Pagination - log.Info("test") log.Debug("get followers list") for { fs, err := masto_client.GetAccountFollowers(context.Background(), masto_user.ID, &pg) @@ -116,15 +116,16 @@ func main() { log.Fatal(err) } subscribers = append(subscribers, fs...) - log.Debug(pg) - log.Debug(pg.MaxID) + // log.Debug(pg) + // log.Debug(pg.MaxID) if pg.MaxID == "" { break } + time.Sleep(200 * time.Millisecond) } - for subscriber := range subscribers { - log.Debug(subscriber) - } + // 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) From afaaf6f57733ca2f463063a658de018229e21bfd Mon Sep 17 00:00:00 2001 From: Andriy Cherniy Date: Fri, 5 Jan 2024 23:45:49 +0200 Subject: [PATCH 46/46] add subcribers count to debug --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index a7adb82..4823721 100755 --- a/main.go +++ b/main.go @@ -123,6 +123,7 @@ func main() { } time.Sleep(200 * time.Millisecond) } + log.Debugf("subscribers count: %v", len(subscribers)) // for _, subscriber := range subscribers { // log.Debug(subscriber.Acct) // }