diff --git a/.config/devenv.yml b/.config/devenv.yml index 65b819b569..77d4ce66b6 100644 --- a/.config/devenv.yml +++ b/.config/devenv.yml @@ -1,38 +1,28 @@ -url: http://localhost:3000 -port: 3000 +url: http://localhost:3030 +port: 3030 db: - host: 127.0.0.1 + host: firefish_db port: 5432 - db: firefish - + db: firefish_db user: firefish - pass: firefish + pass: password redis: - host: localhost + host: firefish_redis port: 6379 - family: 4 -#sonic: -# host: localhost -# port: 1491 -# auth: SecretPassword -# collection: notes -# bucket: default - -#elasticsearch: -# host: localhost -# port: 9200 -# ssl: false -# user: -# pass: id: 'aid' -reservedUsernames: - - root - - admin - - administrator - - me - - system +#allowedPrivateNetworks: [ +# '10.69.1.0/24' +#] + +logLevel: [ + 'error', + 'success', + 'warning', + 'debug', + 'info' +] diff --git a/.config/example.yml b/.config/example.yml index 02c0296172..9082dfb868 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -41,11 +41,11 @@ db: port: 5432 #ssl: false # Database name - db: firefish + db: firefish_db # Auth - user: example-firefish-user - pass: example-firefish-pass + user: firefish + pass: password # Whether disable Caching queries #disableCache: true @@ -85,28 +85,6 @@ redis: #prefix: example-prefix #db: 1 -# Please configure either MeiliSearch *or* Sonic. -# If both MeiliSearch and Sonic configurations are present, MeiliSearch will take precedence. - -# ┌───────────────────────────┐ -#───┘ MeiliSearch configuration └───────────────────────────────────── -#meilisearch: -# host: meilisearch -# port: 7700 -# ssl: false -# apiKey: - -# ┌─────────────────────┐ -#───┘ Sonic configuration └───────────────────────────────────── - -#sonic: -# host: localhost -# port: 1491 -# auth: SecretPassword -# collection: notes -# bucket: default - - # ┌───────────────┐ #───┘ ID generation └─────────────────────────────────────────── @@ -203,9 +181,6 @@ logLevel: [ # Proxy remote files (default: false) #proxyRemoteFiles: true -# Use authorized fetch for outgoing requests -signToActivityPubGet: true - #allowedPrivateNetworks: [ # '127.0.0.1/32' #] diff --git a/.dockerignore b/.dockerignore index 2efc98f8fc..f1c6bfd84a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -45,8 +45,6 @@ docker-compose.yml docker-compose.example.yml firefish.apache.conf firefish.nginx.conf -flake.lock -flake.nix title.svg /.gitlab /chart diff --git a/.envrc b/.envrc deleted file mode 100644 index 3ce7171a3c..0000000000 --- a/.envrc +++ /dev/null @@ -1,4 +0,0 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" -fi -use flake . --impure diff --git a/.gitignore b/.gitignore index 47518231b9..8ad525d636 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,8 @@ coverage !/.config/docker_ci.env !/.config/helm_values_example.yml !/.config/LICENSE -docker-compose.yml +/docker-compose.yml +/custom # ESLint .eslintcache @@ -59,6 +60,11 @@ packages/backend/assets/LICENSE packages/megalodon/lib packages/megalodon/.idea +dev/container/firefish +dev/container/db +dev/container/redis +dev/config.env + # blender backups *.blend1 *.blend2 @@ -70,10 +76,6 @@ packages/megalodon/.idea .yarn yarn* -# Nix Development shell items -.devenv -.direnv - # Cargo cache for Docker /.cargo-cache /.cargo-target diff --git a/.vscode/extensions.json b/.vscode/extensions.json index ac8124f48a..0083604d44 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,7 +2,6 @@ "recommendations": [ "editorconfig.editorconfig", "vue.volar", - "vue.vscode-typescript-vue-plugin", "arcanis.vscode-zipfs", "orta.vscode-twoslash-queries", "antfu.iconify", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af4e7b08db..f6e3ff4b02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,17 @@ Before creating an issue, please check the following: > **Warning** > Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged. -## Before implementation +## Coding + +### Preparing a development environment + +You can prepare your local Firefish environment in multiple ways: + +- [Run Firefish and databases on your host](../dev/docs/local-installation.md) +- [Run Firefish on your host and databases in containers](../dev/docs/db-container.md) +- [Run Firefish and databases in containers](../dev/docs/container.md) + +### Before implementation When you want to add a feature or fix a bug, **first have the design and policy reviewed in an Issue** (if it is not there, please make one). Without this step, there is a high possibility that the MR will not be merged even if it is implemented. At this point, you also need to clarify the goals of the MR you will create, and make sure that the other members of the team are aware of them. @@ -30,14 +40,14 @@ MRs that do not have a clear set of do's and don'ts tend to be bloated and diffi Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask another member to assign you). By expressing your intention to work the Issue, you can prevent conflicts in the work. -## Well-known branches +### Well-known branches - The **`main`** branch is tracking the latest release and used for production purposes. - The **`develop`** branch is where we work for the next release. - When you create a MR, basically target it to this branch. **But create a different branch** - The **`l10n_develop`** branch is reserved for localization management. - **`feature/*`** branches are reserved for the development of a specific feature -## Creating a merge request (MR) +### Creating a merge request (MR) Thank you for your MR! Before creating a MR, please check the following: - If possible, prefix the title with a keyword that identifies the type of this MR, as shown below. - `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc. You are also welcome to use gitmoji. This is important as we use these to A) easier read the git history and B) generate our changelog. Without propper prefixing it is possible that your MR is rejected. @@ -68,235 +78,3 @@ Be willing to comment on the good points and not just the things you want fixed - Does the test ensure the expected behavior? - Are there any omissions or gaps? - Does it check for anomalies? - -## Preparing the development environment - -1. Install the following software - - nodejs - - rustup - - cargo - - sea-orm-cli - - podman - - podman-compose -2. Copy the config file - ```sh - cp .config/dev.example.yml .config/default.yml - ``` -3. Start postgres/redis containers - ```sh - pnpm run dev:up - ``` -4. Build Firefish - ```sh - pnpm install - pnpm run build:debug - pnpm run migrate - ``` -5. Start Firefish on your localhost - ```sh - pnpm run start - ``` - -You can use the following commands to initialize the database: -```sh -pnpm run dev:init -pnpm run migrate -``` - -Make sure to clear your browser local storage after initializing the dev instance. - -## Deploy (SOON) -The `/deploy` command by issue comment can be used to deploy the contents of a MR to the preview environment. -``` -/deploy sha= -``` -An actual domain will be assigned so you can test the federation. - -# THE FOLLOWING IS OUTDATED: - -## Merge - -## Release -### Release Instructions -1. Commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json)) -2. Create a release PR. - - Into `master` from `develop` branch. - - The title must be in the format `Release: x.y.z`. - - `x.y.z` is the new version you are trying to release. -3. Deploy and perform a simple QA check. Also verify that the tests passed. -4. Merge it. -5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) - - The target branch must be `master` - - The tag name must be the version - -## Development -During development, it is useful to use the `pnpm run dev` command. -This command monitors the server-side and client-side source files and automatically builds them if they are modified. -In addition, it will also automatically start the Firefish server process. - -## Testing -- Test codes are located in [`/test`](/test). - -### Run test -Create a config file. -``` -cp test/test.yml .config/ -``` -Prepare DB/Redis for testing. -``` -docker-compose -f test/docker-compose.yml up -``` -Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`. - -Run all test. -``` -yarn test -``` - -#### Run specify test -``` -TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT="./test/tsconfig.json" pnpx mocha test/foo.ts --require ts-node/register -``` - -## Vue -Firefish uses Vue(v3) as its front-end framework. -- Use TypeScript. -- **When creating a new component, please use the Composition API (with [setup syntax](https://v3.vuejs.org/api/sfc-script-setup.html) and [ref syntax](https://github.com/vuejs/rfcs/discussions/369)) instead of the Options API.** - - Some of the existing components are implemented in the Options API, but it is an old implementation. Refactors that migrate those components to the Composition API are also welcome. - -## nirax -niraxは、Misskeyで使用しているオリジナルのフロントエンドルーティングシステムです。 -**vue-routerから影響を多大に受けているので、まずはvue-routerについて学ぶことをお勧めします。** - -### ルート定義 -ルート定義は、以下の形式のオブジェクトの配列です。 - -``` ts -{ - name?: string; - path: string; - component: Component; - query?: Record; - loginRequired?: boolean; - hash?: string; - globalCacheKey?: string; - children?: RouteDef[]; -} -``` - -> **Warning** -> 現状、ルートは定義された順に評価されます。 -> たとえば、`/foo/:id`ルート定義の次に`/foo/bar`ルート定義がされていた場合、後者がマッチすることはありません。 - -### 複数のルーター -vue-routerとの最大の違いは、niraxは複数のルーターが存在することを許可している点です。 -これにより、アプリ内ウィンドウでブラウザとは個別にルーティングすることなどが可能になります。 - -## Notes -### How to resolve conflictions occurred at yarn.lock? - -Just execute `yarn` to fix it. - -### INSERTするときにはsaveではなくinsertを使用する -#6441 - -### placeholder -SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない -例えば -``` ts -query.andWhere(new Brackets(qb => { - for (const type of ps.fileType) { - qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type }); - } -})); -``` -と書くと、ループ中で`type`というプレースホルダが複数回使われてしまいおかしくなる -だから次のようにする必要がある -```ts -query.andWhere(new Brackets(qb => { - for (const type of ps.fileType) { - const i = ps.fileType.indexOf(type); - qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type }); - } -})); -``` - -### Not `null` in TypeORM -```ts -const foo = await Foos.findOne({ - bar: Not(null) -}); -``` -のようなクエリ(`bar`が`null`ではない)は期待通りに動作しない。 -次のようにします: -```ts -const foo = await Foos.findOne({ - bar: Not(IsNull()) -}); -``` - -### `null` in SQL -SQLを発行する際、パラメータが`null`になる可能性のある場合はSQL文を出し分けなければならない -例えば -``` ts -query.where('file.folderId = :folderId', { folderId: ps.folderId }); -``` -という処理で、`ps.folderId`が`null`だと結果的に`file.folderId = null`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない -だから次のようにする必要がある -``` ts -if (ps.folderId) { - query.where('file.folderId = :folderId', { folderId: ps.folderId }); -} else { - query.where('file.folderId IS NULL'); -} -``` - -### `[]` in SQL -SQLを発行する際、`IN`のパラメータが`[]`(空の配列)になる可能性のある場合はSQL文を出し分けなければならない -例えば -``` ts -const users = await Users.find({ - id: In(userIds) -}); -``` -という処理で、`userIds`が`[]`だと結果的に`user.id IN ()`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない -だから次のようにする必要がある -``` ts -const users = userIds.length > 0 ? await Users.find({ - id: In(userIds) -}) : []; -``` - -### 配列のインデックス in SQL -SQLでは配列のインデックスは**1始まり**。 -`[a, b, c]`の `a`にアクセスしたいなら`[0]`ではなく`[1]`と書く - -### null IN -nullが含まれる可能性のあるカラムにINするときは、そのままだとおかしくなるのでORなどでnullのハンドリングをしよう。 - -### `undefined`にご用心 -MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 -MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください - -### Migration作成方法 -packages/backendで: -```sh -pnpm dlx typeorm migration:generate -d ormconfig.js -o -``` - -- 生成後、ファイルをmigration下に移してください -- 作成されたスクリプトは不必要な変更を含むため除去してください - -### コネクションには`markRaw`せよ -**Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。 - -### JSONのimportに気を付けよう -TypeScriptでjsonをimportすると、tscでコンパイルするときにそのjsonファイルも一緒にdistディレクトリに吐き出されてしまう。この挙動により、意図せずファイルの書き換えが発生することがあるので、jsonをimportするときは書き換えられても良いものかどうか確認すること。書き換えされて欲しくない場合は、importで読み込むのではなく、`fs.readFileSync`などの関数を使って読み込むようにすればよい。 - -### コンポーネントのスタイル定義でmarginを持たせない -コンポーネント自身がmarginを設定するのは問題の元となることはよく知られている -marginはそのコンポーネントを使う側が設定する - -## その他 -### HTMLのクラス名で follow という単語は使わない -広告ブロッカーで誤ってブロックされる diff --git a/Dockerfile b/Dockerfile index 9117d71900..b19001772a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ FROM docker.io/node:20-alpine WORKDIR /firefish # Install runtime dependencies -RUN apk update && apk add --no-cache zip unzip tini ffmpeg +RUN apk update && apk add --no-cache zip unzip tini ffmpeg curl COPY . ./ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..d2aa6a2bfd --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +ifneq (dev,$(wildcard config.env)) + include ./dev/config.env + export +endif + + +.PHONY: pre-commit +pre-commit: format entities update-index-js + +.PHONY: format +format: + pnpm run format + +.PHONY: entities +entities: + pnpm run migrate + $(MAKE) -C ./packages/backend-rs regenerate-entities + +.PHONY: update-index-js +update-index-js: + $(MAKE) -C ./packages/backend-rs index.js + + +.PHONY: build +build: + corepack prepare pnpm@latest --activate + pnpm install + NODE_OPTIONS='--max_old_space_size=3072' pnpm run build:debug + pnpm run migrate + + +.PHONY: db.init db.up db.down +db.init: + $(MAKE) -C ./dev/db-container init +db.up: + $(MAKE) -C ./dev/db-container up +db.down: + $(MAKE) -C ./dev/db-container down + +.PHONY: psql redis-cli +psql: + $(MAKE) -C ./dev/db-container psql +redis-cli: + $(MAKE) -C ./dev/db-container redis-cli diff --git a/README.md b/README.md index b7ba3cc6fe..67e9f58d4a 100644 --- a/README.md +++ b/README.md @@ -15,217 +15,22 @@ Firefish is based off of Misskey, a powerful microblogging server on ActivityPub
+# Documents + +- [Installation guide](./docs/install.md) +- [Contributing guide](./CONTRIBUTING.md) +- [Changelog](./docs/changelog.md) + # Links -### Want to get involved? Great! - -- If you have the means to, [donations](https://opencollective.com/Firefish) are a great way to keep us going. -- If you know how to program in TypeScript, Vue, or Rust, read the [contributing](./CONTRIBUTING.md) document. -- If you know a non-English language, translating Firefish on [Weblate](https://hosted.weblate.org/engage/firefish/) help bring Firefish to more people. No technical experience needed! - -### Links - -- Donations: - - OpenCollective: +- Donations: - Matrix space: - Official account: `@firefish@info.firefish.dev` - Weblate: -# Getting started +# Want to get involved? Great! -This guide will work for both **starting from scratch** and **migrating from Misskey**. +- If you know how to program in TypeScript, Vue, or Rust, please read the [contributing guide](./CONTRIBUTING.md). +- If you have the means to, [donations](https://opencollective.com/Firefish) are a great way to keep us going. +- If you know a non-English language, translating Firefish on [Weblate](https://hosted.weblate.org/engage/firefish/) help bring Firefish to more people. No technical experience needed! - - -## Containerization - -- [How to run Firefish with Docker](https://firefish.dev/firefish/firefish/-/blob/develop/docs/docker.md) -- [How to run Firefish with Kubernetes/Helm](https://firefish.dev/firefish/firefish/-/blob/develop/docs/kubernetes.md) - -## Dependencies - -- At least [NodeJS](https://nodejs.org/en/) v18.16.0 (v20/v21 recommended) -- At least [PostgreSQL](https://www.postgresql.org/) v12 (v16 recommended) -- At least [Redis](https://redis.io/) v7 -- Web Proxy (one of the following) - - Nginx (recommended) - - Caddy (recommended) - - Apache - -### Optional dependencies - -- [FFmpeg](https://ffmpeg.org/) for video transcoding -- Full text search (one of the following) - - [Sonic](https://crates.io/crates/sonic-server) - - [MeiliSearch](https://www.meilisearch.com/) - - [ElasticSearch](https://www.elastic.co/elasticsearch/) -- Caching server (one of the following) - - [DragonflyDB](https://www.dragonflydb.io/) (recommended) - - [KeyDB](https://keydb.dev/) - - Another [Redis](https://redis.io/) server - -### Build dependencies - -- At least [Rust](https://www.rust-lang.org/) v1.74 -- C/C++ compiler & build tools - - `build-essential` on Debian/Ubuntu Linux - - `base-devel` on Arch Linux -- [Python 3](https://www.python.org/) - -## Get folder ready - -```sh -git clone https://firefish.dev/firefish/firefish.git -cd firefish/ -``` - -> **Note** -> By default, you're on the develop branch. Run `git checkout main` to switch to the Main branch. - -## Install dependencies - -```sh -# nvm install 19 && nvm use 19 -sudo corepack enable -corepack prepare pnpm@latest --activate -pnpm install --frozen-lockfile -``` - -### pm2 - -To install pm2 run: - -``` -npm i -g pm2 -pm2 install pm2-logrotate -``` - -> **Note** -> [`pm2-logrotate`](https://github.com/keymetrics/pm2-logrotate/blob/master/README.md) ensures that log files don't infinitely gather size, as Firefish produces a lot of logs. - -## Create database - -In PostgreSQL (`psql`), run the following command: - -```sql -CREATE DATABASE firefish WITH encoding = 'UTF8'; -``` - -or run the following from the command line: - -```sh -psql postgres -c "create database firefish with encoding = 'UTF8';" -``` - -In Firefish's directory, fill out the `db` section of `.config/default.yml` with the correct information, where the `db` key is `firefish`. - -## Caching server - -If you experience a lot of traffic, it's a good idea to set up another Redis-compatible caching server. If you don't set one one up, it'll fall back to the mandatory Redis server. DragonflyDB is the recommended option due to its unrivaled performance and ease of use. - -## Set up search - -### Sonic - -Sonic is better suited for self hosters with smaller deployments. It uses almost no resources, barely any any disk space, and is relatively fast. - -Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#installation) - -> **Note** -> If you use IPv4: in Sonic's directory, edit the `config.cfg` file to change `inet` to `"0.0.0.0:1491"`. - -In Firefish's directory, fill out the `sonic` section of `.config/default.yml` with the correct information. - -### Meilisearch - -Meilisearch is better suited for larger deployments. It's faster but uses far more resources and disk space. - -Follow Meilisearch's [quick start guide](https://www.meilisearch.com/docs/learn/getting_started/quick_start) - -In Firefish's directory, fill out the `meilisearch` section of `.config/default.yml` with the correct information. - -### ElasticSearch - -Please don't use ElasticSearch unless you already have an ElasticSearch setup and want to continue using it for Firefish. ElasticSearch is slow, heavy, and offers very few benefits over Sonic/Meilisearch. - -## Customize - -- To add custom CSS for all users, edit `./custom/assets/instance.css`. -- To add static assets (such as images for the splash screen), place them in the `./custom/assets/` directory. They'll then be available on `https://yourserver.tld/static-assets/filename.ext`. -- To add custom locales, place them in the `./custom/locales/` directory. If you name your custom locale the same as an existing locale, it will overwrite it. If you give it a unique name, it will be added to the list. Also make sure that the first part of the filename matches the locale you're basing it on. (Example: `en-FOO.yml`) -- To add custom error images, place them in the `./custom/assets/badges` directory, replacing the files already there. -- To add custom sounds, place only mp3 files in the `./custom/assets/sounds` directory. -- To update custom assets without rebuilding, just run `pnpm run gulp`. -- To block ChatGPT, CommonCrawl, or other crawlers from indexing your instance, uncomment the respective rules in `./custom/robots.txt`. - -## Configuring a new server - -- Run `cp .config/example.yml .config/default.yml` -- Edit `.config/default.yml`, making sure to fill out required fields. -- Also copy and edit `.config/docker_example.env` to `.config/docker.env` if you're using Docker. - -## Migrating from Misskey/FoundKey to Firefish - -For migrating from Misskey v13, Misskey v12, and FoundKey, read [this document](https://firefish.dev/firefish/firefish/-/blob/develop/docs/migrate.md). - -## Web proxy - -### Nginx (recommended) - -- Run `sudo cp ./firefish.nginx.conf /etc/nginx/sites-available/ && cd /etc/nginx/sites-available/` -- Edit `firefish.nginx.conf` to reflect your server properly -- Run `sudo ln -s ./firefish.nginx.conf ../sites-enabled/firefish.nginx.conf` -- Run `sudo nginx -t` to validate that the config is valid, then restart the NGINX service. - -### Caddy (recommended) - -- Add the following block to your `Caddyfile`, replacing `example.tld` with your own domain: -```caddy -example.tld { - reverse_proxy http://127.0.0.1:3000 -} -``` -- Reload your caddy configuration - -### Apache - -> **Warning** -> Apache has some known problems with Firefish. Only use it if you have to. - -- Run `sudo cp ./firefish.apache.conf /etc/apache2/sites-available/ && cd /etc/apache2/sites-available/` -- Edit `firefish.apache.conf` to reflect your server properly -- Run `sudo a2ensite firefish.apache` to enable the site -- Run `sudo service apache2 restart` to reload apache2 configuration - -## Build and launch! - -### NodeJS + pm2 - -#### `git pull` and run these steps to update Firefish in the future! - -```sh -# git pull -pnpm install -NODE_ENV=production pnpm run build && pnpm run migrate -pm2 start "NODE_ENV=production pnpm run start" --name Firefish -``` - -## Tips & Tricks - -- When editing the config file, please don't fill out the settings at the bottom. They're designed *only* for managed hosting, not self hosting. Those settings are much better off being set in Firefish's control panel. -- Port 3000 (used in the default config) might be already used on your server for something else. To find an open port for Firefish, run `for p in {3000..4000}; do ss -tlnH | tr -s ' ' | cut -d" " -sf4 | grep -q "${p}$" || echo "${p}"; done | head -n 1`. Replace 3000 with the minimum port and 4000 with the maximum port if you need it. -- I'd recommend you use a S3 Bucket/CDN for Object Storage, especially if you use Docker. -- When using object storage, setting a proper `Access-Control-Allow-Origin` response header is highly recommended. -- I'd ***strongly*** recommend against using CloudFlare, but if you do, make sure to turn code minification off. -- For push notifications, run `npx web-push generate-vapid-keys`, then put the public and private keys into Control Panel > General > ServiceWorker. -- For translations, make a [DeepL](https://deepl.com) account and generate an API key, then put it into Control Panel > General > DeepL Translation. -- To add another admin account: - - Go to the user's page > 3 Dots > About > Moderation > turn on "Moderator" - - Go back to Overview > click the clipboard icon next to the ID - - Run `psql -d firefish` (or whatever the database name is) - - Run `UPDATE "user" SET "isAdmin" = true WHERE id='999999';` (replace `999999` with the copied ID) - - Restart your Firefish server diff --git a/SECURITY.md b/SECURITY.md index 2f26af6b64..415d9cadd2 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,16 +1,5 @@ # Reporting Security Issues -## Minor Security Issues - -If you discover a minor security issue in Firefish, please report it by sending an -email to [kainoa@t1c.dev](mailto:kainoa@t1c.dev). - -## High Security Issues - -If you discover a security issue, which is so high risk, that too much is affected by it, please dont send it over unencrypted communication. You can share your PGP keys with us using kainoa@t1c.dev and after we established a secure communication, send it over E-Mail, or message us using matrix' encrypted private messages at @t1c:matrix.fedibird.com or @cleo:tchncs.de - - -This will allow us to assess the risk, and make a fix available before we add a -bug report to the Codeberg repository. +If you discover a security issue, please report it as a confidential issue. You can create a confidential issue by checking the "This issue is confidential and should only be visible to team members with at least Reporter access." checkbox in . Thanks for helping make Firefish safe for everyone. diff --git a/chart/.helmignore b/chart/.helmignore deleted file mode 100644 index 0e8a0eb36f..0000000000 --- a/chart/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/chart/Chart.yaml b/chart/Chart.yaml deleted file mode 100644 index 32a0c28446..0000000000 --- a/chart/Chart.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: v2 -name: firefish -description: A fun, new, open way to experience social media https://joinfirefish.org - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.2 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: 'v1.0.4-beta31' - -dependencies: - - name: elasticsearch - version: 19.0.1 - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami - condition: elasticsearch.enabled - - name: postgresql - version: 11.1.3 - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami - condition: postgresql.enabled - - name: redis - version: 16.13.2 - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami - condition: redis.enabled diff --git a/chart/README.md b/chart/README.md deleted file mode 100644 index 1b80e11812..0000000000 --- a/chart/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# firefish - -![Version: 0.1.2](https://img.shields.io/badge/Version-0.1.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: rc](https://img.shields.io/badge/AppVersion-rc-informational?style=flat-square) - -A fun, new, open way to experience social media https://joinfirefish.org - -## Requirements - -| Repository | Name | Version | -|------------|------|---------| -| https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | elasticsearch | 19.0.1 | -| https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | postgresql | 11.1.3 | -| https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | redis | 16.13.2 | - -## Values - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| affinity | object | `{}` | | -| autoscaling.enabled | bool | `false` | | -| autoscaling.maxReplicas | int | `100` | | -| autoscaling.minReplicas | int | `1` | | -| autoscaling.targetCPUUtilizationPercentage | int | `80` | | -| firefish.allowedPrivateNetworks | list | `[]` | If you want to allow firefish to connect to private ips, enter the cidrs here. | -| firefish.deepl.authKey | string | `""` | | -| firefish.deepl.isPro | bool | `false` | | -| firefish.deepl.managed | bool | `false` | | -| firefish.domain | string | `"firefish.local"` | | -| firefish.isManagedHosting | bool | `true` | | -| firefish.libreTranslate.apiKey | string | `""` | | -| firefish.libreTranslate.apiUrl | string | `""` | | -| firefish.libreTranslate.managed | bool | `false` | | -| firefish.objectStorage.access_key | string | `""` | | -| firefish.objectStorage.access_secret | string | `""` | | -| firefish.objectStorage.baseUrl | string | `""` | | -| firefish.objectStorage.bucket | string | `""` | | -| firefish.objectStorage.endpoint | string | `""` | | -| firefish.objectStorage.managed | bool | `true` | | -| firefish.objectStorage.prefix | string | `"files"` | | -| firefish.objectStorage.region | string | `""` | | -| firefish.reservedUsernames[0] | string | `"root"` | | -| firefish.reservedUsernames[1] | string | `"admin"` | | -| firefish.reservedUsernames[2] | string | `"administrator"` | | -| firefish.reservedUsernames[3] | string | `"me"` | | -| firefish.reservedUsernames[4] | string | `"system"` | | -| firefish.smtp.from_address | string | `"notifications@example.com"` | | -| firefish.smtp.login | string | `""` | | -| firefish.smtp.managed | bool | `true` | | -| firefish.smtp.password | string | `""` | | -| firefish.smtp.port | int | `587` | | -| firefish.smtp.server | string | `"smtp.mailgun.org"` | | -| firefish.smtp.useImplicitSslTls | bool | `false` | | -| elasticsearch | object | `{"auth":{},"enabled":false,"hostname":"","port":9200,"ssl":false}` | https://github.com/bitnami/charts/tree/master/bitnami/elasticsearch#parameters | -| fullnameOverride | string | `""` | | -| image.pullPolicy | string | `"IfNotPresent"` | | -| image.repository | string | `"registry.firefish.dev/firefish/firefish"` | | -| image.tag | string | `""` | | -| imagePullSecrets | list | `[]` | | -| ingress.annotations | object | `{}` | | -| ingress.className | string | `""` | | -| ingress.enabled | bool | `false` | | -| ingress.hosts[0].host | string | `"chart-example.local"` | | -| ingress.hosts[0].paths[0].path | string | `"/"` | | -| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | -| ingress.tls | list | `[]` | | -| nameOverride | string | `""` | | -| nodeSelector | object | `{}` | | -| podAnnotations | object | `{}` | | -| podSecurityContext | object | `{}` | | -| postgresql.auth.database | string | `"firefish_production"` | | -| postgresql.auth.password | string | `""` | | -| postgresql.auth.username | string | `"firefish"` | | -| postgresql.enabled | bool | `true` | disable if you want to use an existing db; in which case the values below must match those of that external postgres instance | -| redis.auth.password | string | `""` | you must set a password; the password generated by the redis chart will be rotated on each upgrade: | -| redis.enabled | bool | `true` | | -| redis.hostname | string | `""` | | -| redis.port | int | `6379` | | -| replicaCount | int | `1` | | -| resources | object | `{}` | | -| securityContext | object | `{}` | | -| service.port | int | `80` | | -| service.type | string | `"ClusterIP"` | | -| serviceAccount.annotations | object | `{}` | | -| serviceAccount.create | bool | `true` | | -| serviceAccount.name | string | `""` | | -| tolerations | list | `[]` | | - ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/chart/templates/NOTES.txt b/chart/templates/NOTES.txt deleted file mode 100644 index e84ee93cf4..0000000000 --- a/chart/templates/NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ -1. Get the application URL by running these commands: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "firefish.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "firefish.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "firefish.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "firefish.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT -{{- end }} diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl deleted file mode 100644 index 215d209eef..0000000000 --- a/chart/templates/_helpers.tpl +++ /dev/null @@ -1,327 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "firefish.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "firefish.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "firefish.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "firefish.labels" -}} -helm.sh/chart: {{ include "firefish.chart" . }} -{{ include "firefish.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "firefish.selectorLabels" -}} -app.kubernetes.io/name: {{ include "firefish.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "firefish.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "firefish.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{/* -Create a default fully qualified name for dependent services. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "firefish.elasticsearch.fullname" -}} -{{- printf "%s-%s" .Release.Name "elasticsearch" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- define "firefish.redis.fullname" -}} -{{- printf "%s-%s" .Release.Name "redis" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- define "firefish.postgresql.fullname" -}} -{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -config/default.yml content -*/}} -{{- define "firefish.configDir.default.yml" -}} -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# Firefish configuration -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -# ┌─────┐ -#───┘ URL └───────────────────────────────────────────────────── - -# Final accessible URL seen by a user. -url: "https://{{ .Values.firefish.domain }}/" - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# URL SETTINGS AFTER THAT! - -# ┌───────────────────────┐ -#───┘ Port and TLS settings └─────────────────────────────────── - -# -# Firefish requires a reverse proxy to support HTTPS connections. -# -# +----- https://example.tld/ ------------+ -# +------+ |+-------------+ +----------------+| -# | User | ---> || Proxy (443) | ---> | Firefish (3000) || -# +------+ |+-------------+ +----------------+| -# +---------------------------------------+ -# -# You need to set up a reverse proxy. (e.g. nginx) -# An encrypted connection with HTTPS is highly recommended -# because tokens may be transferred in GET requests. - -# The port that your Firefish server should listen on. -port: 3000 - -# ┌──────────────────────────┐ -#───┘ PostgreSQL configuration └──────────────────────────────── - -db: - {{- if .Values.postgresql.enabled }} - host: {{ template "firefish.postgresql.fullname" . }} - port: 5432 - {{- else }} - host: {{ .Values.postgresql.postgresqlHostname }} - port: {{ .Values.postgresql.postgresqlPort | default 5432 }} - {{- end }} - - # Database name - db: {{ .Values.postgresql.auth.database }} - - # Auth - user: {{ .Values.postgresql.auth.username }} - pass: "{{ .Values.postgresql.auth.password }}" - - # Whether disable Caching queries - #disableCache: true - - # Extra Connection options - #extra: - # ssl: - # host: localhost - # rejectUnauthorized: false - -# ┌─────────────────────┐ -#───┘ Redis configuration └───────────────────────────────────── - -redis: - {{- if .Values.redis.enabled }} - host: {{ template "firefish.redis.fullname" . }}-master - {{- else }} - host: {{ required "When the redis chart is disabled .Values.redis.hostname is required" .Values.redis.hostname }} - {{- end }} - port: {{ .Values.redis.port | default 6379 }} - #family: 0 # 0=Both, 4=IPv4, 6=IPv6 - pass: {{ .Values.redis.auth.password | quote }} - #prefix: example-prefix - #db: 1 - #user: default - #tls: - # host: localhost - # rejectUnauthorized: false - -# ┌─────────────────────┐ -#───┘ Sonic configuration └───────────────────────────────────── - -#sonic: -# host: localhost -# port: 1491 -# auth: SecretPassword -# collection: notes -# bucket: default - -# ┌─────────────────────────────┐ -#───┘ Elasticsearch configuration └───────────────────────────── - -{{- if .Values.elasticsearch.enabled }} -elasticsearch: - host: {{ template "mastodon.elasticsearch.fullname" . }}-master-hl - port: 9200 - ssl: false -{{- else if .Values.elasticsearch.hostname }} -elasticsearch: - host: {{ .Values.elasticsearch.hostname | quote }} - port: {{ .Values.elasticsearch.port }} - ssl: {{ .Values.elasticsearch.ssl }} - {{- if .Values.elasticsearch.auth }} - user: {{ .Values.elasticsearch.auth.username | quote }} - pass: {{ .Values.elasticsearch.auth.password | quote }} - {{- end }} -{{- end }} - -# ┌───────────────┐ -#───┘ ID generation └─────────────────────────────────────────── - -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. - -# Available methods: -# aid ... Short, Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: 'aid' - -# ┌─────────────────────┐ -#───┘ Other configuration └───────────────────────────────────── - -# Max note length, should be < 8000. -#maxNoteLength: 3000 - -# Maximum lenght of an image caption or file comment (default 1500, max 8192) -#maxCaptionLength: 1500 - -# Reserved usernames that only the administrator can register with -reservedUsernames: {{ .Values.firefish.reservedUsernames | toJson }} - -# Whether disable HSTS -#disableHsts: true - -# Number of worker processes -#clusterLimit: 1 - -# Job concurrency per worker -# deliverJobConcurrency: 128 -# inboxJobConcurrency: 16 - -# Job rate limiter -# deliverJobPerSec: 128 -# inboxJobPerSec: 16 - -# Job attempts -# deliverJobMaxAttempts: 12 -# inboxJobMaxAttempts: 8 - -# IP address family used for outgoing request (ipv4, ipv6 or dual) -#outgoingAddressFamily: ipv4 - -# Syslog option -#syslog: -# host: localhost -# port: 514 - -# Proxy for HTTP/HTTPS -#proxy: http://127.0.0.1:3128 - -#proxyBypassHosts: [ -# 'example.com', -# '192.0.2.8' -#] - -# Proxy for SMTP/SMTPS -#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT -#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4 -#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 - -# Media Proxy -#mediaProxy: https://example.com/proxy - -# Proxy remote files (default: false) -#proxyRemoteFiles: true - -allowedPrivateNetworks: {{ .Values.firefish.allowedPrivateNetworks | toJson }} - -# TWA -#twa: -# nameSpace: android_app -# packageName: tld.domain.twa -# sha256CertFingerprints: ['AB:CD:EF'] - -# Upload or download file size limits (bytes) -#maxFileSize: 262144000 - -# Managed hosting settings -# !!!!!!!!!! -# >>>>>> NORMAL SELF-HOSTERS, STAY AWAY! <<<<<< -# >>>>>> YOU DON'T NEED THIS! <<<<<< -# !!!!!!!!!! -# Each category is optional, but if each item in each category is mandatory! -# If you mess this up, that's on you, you've been warned... - -#maxUserSignups: 100 -isManagedHosting: {{ .Values.firefish.isManagedHosting }} -deepl: - managed: {{ .Values.firefish.deepl.managed }} - authKey: {{ .Values.firefish.deepl.authKey | quote}} - isPro: {{ .Values.firefish.deepl.isPro }} - -libreTranslate: - managed: {{ .Values.firefish.libreTranslate.managed }} - apiUrl: {{ .Values.firefish.libreTranslate.apiUrl | quote }} - apiKey: {{ .Values.firefish.libreTranslate.apiKey | quote }} - -email: - managed: {{ .Values.firefish.smtp.managed }} - address: {{ .Values.firefish.smtp.from_address | quote }} - host: {{ .Values.firefish.smtp.server | quote }} - port: {{ .Values.firefish.smtp.port }} - user: {{ .Values.firefish.smtp.login | quote }} - pass: {{ .Values.firefish.smtp.password | quote }} - useImplicitSslTls: {{ .Values.firefish.smtp.useImplicitSslTls }} -objectStorage: - managed: {{ .Values.firefish.objectStorage.managed }} - baseUrl: {{ .Values.firefish.objectStorage.baseUrl | quote }} - bucket: {{ .Values.firefish.objectStorage.bucket | quote }} - prefix: {{ .Values.firefish.objectStorage.prefix | quote }} - endpoint: {{ .Values.firefish.objectStorage.endpoint | quote }} - region: {{ .Values.firefish.objectStorage.region | quote }} - accessKey: {{ .Values.firefish.objectStorage.access_key | quote }} - secretKey: {{ .Values.firefish.objectStorage.access_secret | quote }} - useSsl: true - connnectOverProxy: false - setPublicReadOnUpload: true - s3ForcePathStyle: true - -# !!!!!!!!!! -# >>>>>> AGAIN, NORMAL SELF-HOSTERS, STAY AWAY! <<<<<< -# >>>>>> YOU DON'T NEED THIS, ABOVE SETTINGS ARE FOR MANAGED HOSTING ONLY! <<<<<< -# !!!!!!!!!! - -# Seriously. Do NOT fill out the above settings if you're self-hosting. -# They're much better off being set from the control panel. -{{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml deleted file mode 100644 index ca63167632..0000000000 --- a/chart/templates/deployment.yaml +++ /dev/null @@ -1,82 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "firefish.fullname" . }} - labels: - {{- include "firefish.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "firefish.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - checksum/secret-config: {{ include ( print $.Template.BasePath "/secret-config.yaml" ) . | sha256sum | quote }} - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "firefish.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "firefish.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - volumes: - - name: config-volume - secret: - secretName: {{ template "firefish.fullname" . }}-config - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - command: - - pnpm - - run - - start - env: - - name: "NODE_ENV" - value: "production" - volumeMounts: - - name: config-volume - mountPath: /firefish/.config - ports: - - name: http - containerPort: 3000 - protocol: TCP - startupProbe: - httpGet: - path: / - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: / - port: http - readinessProbe: - httpGet: - path: / - port: http - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/chart/templates/hpa.yaml b/chart/templates/hpa.yaml deleted file mode 100644 index db19534a87..0000000000 --- a/chart/templates/hpa.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "firefish.fullname" . }} - labels: - {{- include "firefish.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "firefish.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml deleted file mode 100644 index 65caa43e89..0000000000 --- a/chart/templates/ingress.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "firefish.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "firefish.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/chart/templates/job-db-migrate.yaml b/chart/templates/job-db-migrate.yaml deleted file mode 100644 index 1aedeab5b1..0000000000 --- a/chart/templates/job-db-migrate.yaml +++ /dev/null @@ -1,59 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "firefish.fullname" . }}-db-migrate - labels: - {{- include "firefish.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": post-install,pre-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - "helm.sh/hook-weight": "-2" -spec: - template: - metadata: - name: {{ include "firefish.fullname" . }}-db-migrate - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - restartPolicy: Never - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "firefish.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - volumes: - - name: config-volume - secret: - secretName: {{ template "firefish.fullname" . }}-config - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - command: - - pnpm - - run - - migrate - env: - - name: "NODE_ENV" - value: "production" - volumeMounts: - - name: config-volume - mountPath: /firefish/.config - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/chart/templates/secret-config.yaml b/chart/templates/secret-config.yaml deleted file mode 100644 index 9f683cfcd8..0000000000 --- a/chart/templates/secret-config.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "firefish.fullname" . }}-config - labels: - {{- include "firefish.labels" . | nindent 4 }} -type: Opaque -data: - default.yml: {{ include "firefish.configDir.default.yml" . | b64enc }} diff --git a/chart/templates/service.yaml b/chart/templates/service.yaml deleted file mode 100644 index f49d9cd5d7..0000000000 --- a/chart/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "firefish.fullname" . }} - labels: - {{- include "firefish.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "firefish.selectorLabels" . | nindent 4 }} diff --git a/chart/templates/serviceaccount.yaml b/chart/templates/serviceaccount.yaml deleted file mode 100644 index d8db3a3ae2..0000000000 --- a/chart/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "firefish.serviceAccountName" . }} - labels: - {{- include "firefish.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/chart/templates/tests/test-connection.yaml b/chart/templates/tests/test-connection.yaml deleted file mode 100644 index 7abe03611a..0000000000 --- a/chart/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "firefish.fullname" . }}-test-connection" - labels: - {{- include "firefish.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "firefish.fullname" . }}:{{ .Values.service.port }}'] - restartPolicy: Never diff --git a/chart/values.yaml b/chart/values.yaml deleted file mode 100644 index d8c6b7175b..0000000000 --- a/chart/values.yaml +++ /dev/null @@ -1,168 +0,0 @@ -# Default values for firefish. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -image: - repository: registry.firefish.dev/firefish/firefish - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - -firefish: - isManagedHosting: true - domain: firefish.local - - deepl: - managed: false - authKey: "" - isPro: false - - libreTranslate: - managed: false - apiUrl: "" - apiKey: "" - - smtp: - managed: true - from_address: notifications@example.com - port: 587 - server: smtp.mailgun.org - useImplicitSslTls: false - login: "" - password: "" - - objectStorage: - managed: true - access_key: "" - access_secret: "" - baseUrl: "" # e.g. "https://my-bucket.nyc3.cdn.digitaloceanspaces.com" - bucket: "" # e.g. "my-bucket" - prefix: files - endpoint: "" # e.g. "nyc3.digitaloceanspaces.com:443" - region: "" # e.g. "nyc3" - - # -- If you want to allow firefish to connect to private ips, enter the cidrs here. - allowedPrivateNetworks: [] - # - "10.0.0.0/8" - - reservedUsernames: - - root - - admin - - administrator - - me - - system - -# https://github.com/bitnami/charts/tree/master/bitnami/postgresql#parameters -postgresql: - # -- disable if you want to use an existing db; in which case the values below - # must match those of that external postgres instance - enabled: true - # postgresqlHostname: preexisting-postgresql - # postgresqlPort: 5432 - auth: - database: firefish_production - username: firefish - # you must set a password; the password generated by the postgresql chart will - # be rotated on each upgrade: - # https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrade - password: "" - -# https://github.com/bitnami/charts/tree/master/bitnami/redis#parameters -redis: - # disable if you want to use an existing redis instance; in which case the - # values below must match those of that external redis instance - enabled: true - hostname: "" - port: 6379 - auth: - # -- you must set a password; the password generated by the redis chart will be - # rotated on each upgrade: - password: "" - -# -- https://github.com/bitnami/charts/tree/master/bitnami/elasticsearch#parameters -elasticsearch: - # disable if you want to use an existing redis instance; in which case the - # values below must match those of that external elasticsearch instance - enabled: false - hostname: "" - port: 9200 - ssl: false - auth: {} - # username: "" - # password: "" - # @ignored - image: - tag: 7 - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/dev/config.example.env b/dev/config.example.env new file mode 100644 index 0000000000..62ee2dc14d --- /dev/null +++ b/dev/config.example.env @@ -0,0 +1,4 @@ +COMPOSE='docker compose' +POSTGRES_PASSWORD=password +POSTGRES_USER=firefish +POSTGRES_DB=firefish_db diff --git a/dev/container/docker-compose.yml b/dev/container/docker-compose.yml new file mode 100644 index 0000000000..6416b70025 --- /dev/null +++ b/dev/container/docker-compose.yml @@ -0,0 +1,49 @@ +version: "3" + +services: + web: + image: docker.io/node:18.17.0-bookworm + container_name: firefish_web + restart: unless-stopped + depends_on: + - db + - redis + ports: + - "3030:3030" + networks: + - firefishnet + environment: + NODE_ENV: production + PGPASSWORD: password + URL: http://localhost:3030 + volumes: + - ./firefish:/firefish:rw + - ./docker-entrypoint.sh:/docker-entrypoint.sh:ro + entrypoint: /docker-entrypoint.sh + + redis: + restart: unless-stopped + image: docker.io/redis:7.0-alpine + container_name: firefish_redis + networks: + - firefishnet + ports: + - "26379:6379" + volumes: + - ./redis:/data + + db: + restart: unless-stopped + image: docker.io/groonga/pgroonga:3.1.8-alpine-12 + container_name: firefish_db + networks: + - firefishnet + env_file: + - ../config.env + ports: + - "25432:5432" + volumes: + - ./db:/var/lib/postgresql/data + +networks: + firefishnet: diff --git a/dev/container/docker-entrypoint.sh b/dev/container/docker-entrypoint.sh new file mode 100755 index 0000000000..6f60427d66 --- /dev/null +++ b/dev/container/docker-entrypoint.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +set -xeu +node --version + +# Check Environment Initialized Flag +if [ ! -f '/.firefish_env_initialized' ]; then + + # Install entrypoint dependencies + apt-get update + DEBIAN_FRONTEND='noninteractive' apt-get install -y --no-install-recommends wget curl ca-certificates lsb-release gnupg + + # Create the PostgreSQL file repository configuration + sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + + # Import the PostgreSQL repository signing key + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - + + # Install compilation dependencies + apt-get update + DEBIAN_FRONTEND='noninteractive' apt-get install -y --no-install-recommends build-essential python3 ffmpeg git postgresql-client-12 + curl -vvv --proto '=https' --tlsv1.2 --show-error --fail https://sh.rustup.rs | sh -s -- -y + + # Add Cargo PATH + PATH="/root/.cargo/bin:${PATH}" + + # If Firefish not exist + if [ ! -f '/firefish/README.md' ]; then + + # Clone Firefish + cd / + git clone -v https://firefish.dev/firefish/firefish.git + + # Configuring a new server + cd /firefish + cp .config/devenv.yml .config/default.yml + + URL="$(echo "${URL}" | sed 's#/#\\/#g')" + sed -i'.bak' "s/http:\/\/localhost:3030/${URL}/" .config/default.yml + + fi + + # Configure postgres, add pgroonga search + psql --user=firefish --host=firefish_db --dbname=firefish_db --command='CREATE EXTENSION IF NOT EXISTS pgroonga;' + + # Configure pnpm, and install dev mode dependencies for compilation + cd /firefish + corepack enable + corepack prepare pnpm@latest --activate + pnpm install --prod false + +fi + +# Add Environment Initialized Flag +touch /.firefish_env_initialized + +# Add Cargo PATH +PATH="/root/.cargo/bin:${PATH}" + +# Start a new server +cd /firefish +pnpm install --prod false +pnpm run build:debug +pnpm run migrate +pnpm run start diff --git a/dev/db-container/Makefile b/dev/db-container/Makefile new file mode 100644 index 0000000000..0238308de4 --- /dev/null +++ b/dev/db-container/Makefile @@ -0,0 +1,12 @@ +.PHONY: init up down +init: down up +up: + $(COMPOSE) up --detach +down: + $(COMPOSE) down + +.PHONY: psql redis-cli +psql: + $(COMPOSE) exec db psql --user=$(POSTGRES_USER) --dbname=$(POSTGRES_DB) +redis-cli: + $(COMPOSE) exec redis redis-cli diff --git a/dev/db-container/docker-compose.yml b/dev/db-container/docker-compose.yml new file mode 100644 index 0000000000..4cd121d2d4 --- /dev/null +++ b/dev/db-container/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3" + +services: + redis: + image: docker.io/redis:7-alpine + ports: + - "26379:6379" + db: + image: docker.io/groonga/pgroonga:3.1.8-alpine-12 + env_file: + - ../config.env + ports: + - "25432:5432" + volumes: + - "./install.sql:/docker-entrypoint-initdb.d/install.sql:ro" diff --git a/dev/db-container/install.sql b/dev/db-container/install.sql new file mode 100644 index 0000000000..11418be32b --- /dev/null +++ b/dev/db-container/install.sql @@ -0,0 +1 @@ +CREATE EXTENSION pgroonga; diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml deleted file mode 100644 index 184c0366c9..0000000000 --- a/dev/docker-compose.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: "3" - -services: - redis: - image: docker.io/redis:7-alpine - ports: - - "26379:6379" - db: - image: docker.io/postgres:16-alpine - environment: - - "POSTGRES_PASSWORD=password" - - "POSTGRES_USER=firefish" - - "POSTGRES_DB=firefish_db" - ports: - - "25432:5432" diff --git a/dev/docs/container.md b/dev/docs/container.md new file mode 100644 index 0000000000..4b21afbc32 --- /dev/null +++ b/dev/docs/container.md @@ -0,0 +1,34 @@ +# Set up a fully-containerized development environment + +## Prerequisites + +- Container runtime installation + - [Docker](https://docs.docker.com/get-docker/) + - [Podman](https://podman.io/docs/installation) and [Podman Compose](https://github.com/containers/podman-compose) + - [containerd](https://github.com/containerd/containerd) and [nerdctl](https://github.com/containerd/nerdctl) + - or whatever you want to use +- The following ports are not in use + - 3030 + - 25432 + - 26379 + +## Start up the environment + +1. Download the [`dev/container` directory](./dev/container) and execute `chmod +x docker-entrypoint.sh` + - Alternatively, you can use `git clone https://firefish.dev/firefish/firefish.git && cd firefish/dev/container`, although this will clone the entire repository. +1. Copy the example config file + ```sh + cp config.example.env config.env + ``` +1. Edit `docker-compose.yml` and set `URL` to the URL you want to use (or leave it as `http://localhost:3030`) +1. Run `docker compose up` + - This will build the environment, install dependencies and prepare the needed config files. + - If you use Podman, you should run `podman-compose up` instead. +1. Wait until the following message shows up + ```log + DONE * [core boot] All workers started + DONE * [core boot] Now listening on port 3030 on https://your_firefish_url.example.com + ``` +1. A fresh Firefish environment is created on the URL you have set! + +When you want to restart the dev server, you just need to terminate the process (a.k.a. press `Ctrl+C`) and run `docker compose up` again. diff --git a/dev/docs/db-container.md b/dev/docs/db-container.md new file mode 100644 index 0000000000..61e7b2609e --- /dev/null +++ b/dev/docs/db-container.md @@ -0,0 +1,95 @@ +# Set up database containers and run Firefish locally + +## Prerequisites + +- Dependencies + - git + - Node.js + - pnpm + - Rust toolchain + - FFmpeg + - Container runtime + - [Docker](https://docs.docker.com/get-docker/) + - [Podman](https://podman.io/docs/installation) and [Podman Compose](https://github.com/containers/podman-compose) + - [containerd](https://github.com/containerd/containerd) and [nerdctl](https://github.com/containerd/nerdctl) + - or whatever you want to use + - GNU Make +- The following ports are not in use + - 25432 + - 26379 + +You can refer to [local-installation.md](./local-installation.md) to install the dependencies. + +## Configure the environment + +1. Fork the Firefish repository on GitLab +1. Clone your Firefish repository + ```sh + git clone https://firefish.dev/your-user-name/firefish.git + cd firefish + ``` +1. Copy example config file + ```sh + cp dev/config.example.env dev/config.env + # If you use container runtime other than Docker, you need to modify the "COMPOSE" variable + # vim dev/config.env + ``` +1. Create `.config/default.yml` with the following content + ```yaml + # You can change the port if 3000 is already used + url: http://localhost:3000 + port: 3000 + + db: + host: localhost + port: 25432 + db: firefish_db + user: firefish + pass: password + + redis: + host: localhost + port: 26379 + + logLevel: [ + 'error', + 'success', + 'warning', + 'info' + ] + ``` +1. Start database containers + ```sh + make db.up + ``` + +## Build and start Firefish + +1. Build Firefish + ```sh + pnpm install + pnpm run build:debug + ``` +1. Execute database migrations + ```sh + pnpm run migrate + ``` +1. Start Firefish + ```sh + pnpm run start + ``` + You can access to the local Firefish server on http://localhost:3000 after this message shows up! + ``` + DONE * [core boot] All workers started + DONE * [core boot] Now listening on port 3000 on http://localhost:3000 + ``` + +## Reset the environment + +You can recreate a fresh local Firefish environment by recreating the database containers: + +```sh +make db.init +pnpm run migrate +pnpm run start +``` diff --git a/dev/docs/local-installation.md b/dev/docs/local-installation.md new file mode 100644 index 0000000000..154f768037 --- /dev/null +++ b/dev/docs/local-installation.md @@ -0,0 +1,177 @@ +# Set up a development environment by installing all dependencies locally + +This document demonstrates an example procedure to set up a Firefish development environment on Debian 12. You can refer to this document if you prefer to install all dependencies (Node.js, PostgreSQL, Redis, etc.) locally. + +Make sure that you can use the `sudo` command before proceeding. + +## 1. Install dependencies + +### Utilities + +```sh +sudo apt update +sudo apt install build-essential python3 curl wget git lsb-release +``` + +### Node.js + +Firefish requires Node.js v18.17.0 or later. While you can choose any versions between v18.17.0 and the latest version (v21.6.2 as of writing), we recommend that you install v18.x so as not to use new features inadvertently and introduce incompatibility issues. + +Instructions can be found at [this repository](https://github.com/nodesource/distributions). + +```sh +NODE_MAJOR=18 +curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | sudo -E bash - +sudo apt install nodejs + +# check version +node --version +``` + +### Rust toolchain + +Instructions can be found at [this page](https://www.rust-lang.org/tools/install). + +```sh +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +. "${HOME}/.cargo/env" + +# check version +cargo --version +``` + +### PostgreSQL and PGroonga + +PostgreSQL install instructions can be found at [this page](https://www.postgresql.org/download/). + +```sh +sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' +wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - +sudo apt update +sudo apt install postgresql-12 + +sudo systemctl enable --now postgresql + +# check version +psql --version +``` + +PGroonga install instructions can be found at [this page](https://pgroonga.github.io/install/). + +```sh +wget "https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb" +sudo apt install "./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb" +wget "https://packages.groonga.org/debian/groonga-apt-source-latest-$(lsb_release --codename --short).deb" +sudo apt install "./groonga-apt-source-latest-$(lsb_release --codename --short).deb" +sudo apt update +sudo apt install postgresql-12-pgdg-pgroonga + +rm "apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb" "groonga-apt-source-latest-$(lsb_release --codename --short).deb" +``` + +### Redis + +Instructions can be found at [this page](https://redis.io/docs/install/install-redis/). + +```sh +curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg +echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list +sudo apt update +sudo apt install redis + +sudo systemctl enable --now redis-server + +# check version +redis-cli --version +``` + +### FFmpeg + +```sh +sudo apt install ffmpeg +``` + +## 2. Set up a database + +1. Create a database user + ```sh + sudo -u postgres createuser --no-createdb --no-createrole --no-superuser --encrypted --pwprompt firefish + ``` + If you forgot the password you typed, you can reset it by executing `sudo -u postgres psql -c "ALTER USER firefish PASSWORD 'password';"`. +2. Create a database + ```sh + sudo -u postgres createdb --encoding='UTF8' --owner=firefish firefish_db + ``` +3. Enable PGronnga extension + ```sh + sudo -u postgres psql --command='CREATE EXTENSION pgroonga;' --dbname=firefish_db + ``` + +## 3. Configure Firefish + +1. Fork the Firefish repository on GitLab +1. Clone your Firefish repository + ```sh + git clone https://firefish.dev/your-user-name/firefish.git + ``` +1. Copy the example database config file + ```sh + cp dev/config.example.env dev/config.env + ``` +1. Create a config file for Firefish + ```sh + cd firefish + vim .config/default.yml + ``` + + ```yaml + url: http://localhost:3000 + port: 3000 + + db: + host: localhost + port: 5432 + db: firefish_db + user: firefish + pass: password + + redis: + host: localhost + port: 6379 + + logLevel: [ + 'error', + 'success', + 'warning', + 'info' + ] + ``` + +## 4. Build and start Firefish + +1. Install pnpm + ```sh + sudo corepack enable + corepack prepare pnpm@latest --activate + + # check version + pnpm --version + ``` +1. Build + ```sh + pnpm install + pnpm run build:debug + ``` +1. Execute database migrations + ```sh + pnpm run migrate + ``` +1. Start Firefish + ```sh + pnpm run start + ``` + You can access to the local Firefish server on http://localhost:3000 after this message shows up! + ``` + DONE * [core boot] All workers started + DONE * [core boot] Now listening on port 3000 on http://localhost:3000 + ``` diff --git a/docker-compose.example.yml b/docker-compose.example.yml index a5fd4c315e..fc6c0268a2 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -6,11 +6,10 @@ services: container_name: firefish_web restart: unless-stopped depends_on: - - db - - redis -### Uncomment one of the following to use a search engine -# - meilisearch -# - sonic + db: + condition: service_healthy + redis: + condition: service_healthy ports: - "3000:3000" networks: @@ -22,6 +21,15 @@ services: - ./custom:/firefish/custom:ro - ./files:/firefish/files - ./.config:/firefish/.config:ro + healthcheck: + test: curl -f http://localhost:3000 || exit 1 + interval: 5s + timeout: 5s + retries: 5 + deploy: + resources: + limits: + memory: 4096M redis: restart: unless-stopped @@ -31,10 +39,20 @@ services: - calcnet volumes: - ./redis:/data + healthcheck: + test: redis-cli ping + interval: 5s + timeout: 5s + retries: 5 + # deploy: + # resources: + # limits: + # memory: 200M + db: restart: unless-stopped - image: docker.io/postgres:16-alpine + image: docker.io/groonga/pgroonga:3.1.8-alpine-16-slim container_name: firefish_db networks: - calcnet @@ -42,33 +60,15 @@ services: - .config/docker.env volumes: - ./db:/var/lib/postgresql/data - -### Only one of the below should be used. -### Meilisearch is better overall, but resource-intensive. Sonic is a very light full text search engine. - -# meilisearch: -# container_name: meilisearch -# image: getmeili/meilisearch:v1.1.1 -# environment: -# - MEILI_ENV=${MEILI_ENV:-development} -# ports: -# - "7700:7700" -# networks: -# - calcnet -# volumes: -# - ./meili_data:/meili_data -# restart: unless-stopped - -# sonic: -# restart: unless-stopped -# image: docker.io/valeriansaliou/sonic:v1.4.0 -# logging: -# driver: none -# networks: -# - calcnet -# volumes: -# - ./sonic:/var/lib/sonic/store -# - ./sonic/config.cfg:/etc/sonic.cfg + healthcheck: + test: pg_isready --user="$${POSTGRES_USER}" --dbname="$${POSTGRES_DB}" + interval: 5s + timeout: 5s + retries: 5 + # deploy: + # resources: + # limits: + # memory: 200M networks: calcnet: diff --git a/docs/activitypub-extensions.md b/docs/activitypub-extensions.md new file mode 100644 index 0000000000..4d5faeff80 --- /dev/null +++ b/docs/activitypub-extensions.md @@ -0,0 +1,10 @@ +# Firefish's ActivityPub extensions + +These are the extensions to ActivityPub that Firefish implements. This page uses [compact IRIs](https://www.w3.org/TR/json-ld/#dfn-compact-iri). The `firefish` prefix is used to refer to `https://firefish.dev/ns#`. + +## speakAsCat + +- Compact IRI: `firefish:speakAsCat` +- Canonical IRI: `https://firefish.dev/ns#speakascat` + +Used on actors to indicate that they not only identify as a cat, but also want to have their text be transformed to speak like one, expressed as a boolean value. If this property is set to true, displaying the actor’s posts will make them speak with “nya” instead of “na” and other cat-related text mannerisms. Used in combination with [misskey:isCat](https://misskey-hub.net/ns/#iscat). diff --git a/docs/api-change.md b/docs/api-change.md index 4046e5c48c..fdda2e78b4 100644 --- a/docs/api-change.md +++ b/docs/api-change.md @@ -2,6 +2,17 @@ Breaking changes are indicated by the :warning: icon. +## v20240319 + +- :warning: `followingCount` and `followersCount` in `users/show` will be `null` (instead of 0) if these values are unavailable. +- :warning: `admin/search/index-all` is removed since posts are now indexed automatically. +- New optional parameters are added to `notes/search` endpoint: + - `sinceDate` + - `untilDate` + - `withFiles` + - `searchCwAndAlt` +- Added `enableGuestTimeline` field to the response of `meta` and `admin/meta`, and the request of `admin/update-meta` (optional). + ## v20240301 - With the addition of new features, the following endpoints are added: diff --git a/docs/changelog.md b/docs/changelog.md index 71ba30951e..4fc46cfc76 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,7 +2,22 @@ Critical security updates are indicated by the :warning: icon. -## v20240301 +- Server administrators should check [notice-for-admins.md](./notice-for-admins.md) as well. +- Third-party client/bot developers may want to check [api-change.md](./api-change.md) as well. + +## [v20240319](https://firefish.dev/firefish/firefish/-/compare/v20240301...v20240319?from_project_id=7&straight=false) + +- Introduce new full-text search engine and post search filters +- Refactoring +- Show unlisted posts from following users in antennas (similar to [Fedibird](https://github.com/fedibird/mastodon/tree/fedibird) and [kmyblue](https://github.com/kmycode/mastodon), unlisted posts from people you don't follow won't be shown) +- Add ability to publish the Local and Global timelines on `/timeline` page +- Add langage annotation to post contents (!10687) +- Add a toggleable setting to show a warning when you attempt to post files without alt text +- Fix bugs +- Update documents and example config files +- Added `/authorize_interaction` page, allowing users to jump from a remote Mastodon post/user page to the corresponding page in Firefish (!10702) + +## [v20240301](https://firefish.dev/firefish/firefish/-/compare/v20240229...v20240301?from_project_id=7&straight=false) - Add a page (`/my/follow-requests/sent`) to check your follow requests that haven't been approved - Add ability to hide replies from certain users in timelines @@ -19,35 +34,36 @@ Critical security updates are indicated by the :warning: icon. - Set reaction history to public - Change default server settings (existing servers are not affected) - Disable new user registration +- Fix bugs -## v20240229 +## [v20240229](https://firefish.dev/firefish/firefish/-/compare/v20240228...v20240229?from_project_id=7&straight=false) - Add ability to pull-down-to-refresh timelines in PWA - Make passkey/security key independent of TOTP (!10670) - Fix bugs -## v20240228 +## [v20240228](https://firefish.dev/firefish/firefish/-/compare/v20240225...v20240228?from_project_id=7&straight=false) - Update "About Firefish" page (!10673) - Fix bugs (!10675 !10676 !10678 !10679) - Remove charts generation to improve performance (#10611) -## v20240225 +## [v20240225](https://firefish.dev/firefish/firefish/-/compare/v20240222...v20240225?from_project_id=7&straight=false) - Fix bugs - Add syntax highlighting in MFM code blocks in various programming languages -## v20240222 +## [v20240222](https://firefish.dev/firefish/firefish/-/compare/v20240221-1...v20240222?from_project_id=7&straight=false) - Enhance Mastodon post import feature (!10652) - Minor style change in the web client - Refactoring -## v20240221-1 +## [v20240221-1](https://firefish.dev/firefish/firefish/-/compare/v20240221...v20240221-1?from_project_id=7&straight=false) - Fix a bug -## v20240221 +## [v20240221](https://firefish.dev/firefish/firefish/-/compare/v20240217-1...v20240221?from_project_id=7&straight=false) - Add the ability to give regular (non-moderator) users permission to manage custom emojis - Fix a bug that made impossible to update user profiles under some conditions @@ -55,11 +71,11 @@ Critical security updates are indicated by the :warning: icon. - It's just a paraphrase of DMs without recipients - You can also convert your existing public posts to private posts -## :warning: v20240217-1 +## :warning: [v20240217-1](https://firefish.dev/firefish/firefish/-/compare/v20240217...v20240217-1?from_project_id=7&straight=false) - Fix a [security issue](https://github.com/misskey-dev/misskey/security/advisories/GHSA-qqrm-9grj-6v32) -## v20240217 +## [v20240217](https://firefish.dev/firefish/firefish/-/compare/v20240216...v20240217?from_project_id=7&straight=false) - Add ability to specify the search engine used in the search bar MFM - Remove auto NSFW media detection @@ -68,49 +84,49 @@ Critical security updates are indicated by the :warning: icon. - Change the second tab on the notifications page from "unread" to "reactions" - Add ability to show a huge post button on the posting form - This is a joke feature inspired by https://mstdn.poyo.me/@prime/110668364208741253 -- Bug fix +- Fix bugs - Add `/api/emojis` endpoint (compatible with Misskey v13) for better experiences with Misskey clients - This does not mean we will continue to maintain API compatibility with Misskey. Instead, we plan to improve the compatibility with the Mastodon API. -## v20240216 +## [v20240216](https://firefish.dev/firefish/firefish/-/compare/v20240215...v20240216?from_project_id=7&straight=false) - Style changes in the web client (a770ef4314e21f17fdce1f19feb3758953b04486 ab39ff5954a392cc6688a02f1723e1702df5e35c 4eefd534d8150e2cd5cf31dddd327edceb5b84dc) - Clicking the "like" button now sends the actual emoji reaction (star, good, heart, etc.) instead of an empty "like" -## v20240215 +## [v20240215](https://firefish.dev/firefish/firefish/-/compare/v20240214...v20240215?from_project_id=7&straight=false) - Separate settings for displaying rounded avatars for cat and non-cat accounts - Add a toggleable setting to replace the chat button with account menu on mobile - Reduce the size of the container image (!10667) -## v20240214 +## [v20240214](https://firefish.dev/firefish/firefish/-/compare/v20240213...v20240214?from_project_id=7&straight=false) - Fix container images -## v20240213 +## [v20240213](https://firefish.dev/firefish/firefish/-/compare/v20240212...v20240213?from_project_id=7&straight=false) -- Bug fix +- Fix bugs - Refactoring -## v20240212 +## [v20240212](https://firefish.dev/firefish/firefish/-/compare/v20240210...v20240212?from_project_id=7&straight=false) - Refactoring - Add a toggleable setting to hide follow buttons in a misclickable position - Add a toggleable setting to show preview in posting form by default -## v20240210 +## [v20240210](https://firefish.dev/firefish/firefish/-/compare/v20240208...v20240210?from_project_id=7&straight=false) - Security update (cf5b42a160ae8a4d94bf3dcea04ce12935ca4f76) - Refactoring -## v20240208 +## [v20240208](https://firefish.dev/firefish/firefish/-/compare/v20240206...v20240208?from_project_id=7&straight=false) -- Bug fix (!10654 !10665) +- Fix bugs (!10654 !10665) - Enlarge profile picture by clicking it (!10659) - Support Pleroma chat (!10660) - [Add documentation about downgrading](./docs/downgrade.md) -## v20240206 +## [v20240206](https://firefish.dev/firefish/firefish/-/compare/v1.0.5-rc...v20240206?from_project_id=7&straight=false) -- Many bug fixes +- Fix many bugs - Per-post language selector (!10616) diff --git a/docs/development.md b/docs/development.md deleted file mode 100644 index 797c8273ee..0000000000 --- a/docs/development.md +++ /dev/null @@ -1,108 +0,0 @@ -# Firefish Developer Docs - -## Nix Dev Environment -The Firefish repo comes with a Nix-based shell environment to help make development as easy as possible! - -Please note, however, that this environment will not work on Windows outside of a WSL2 environment. - -### Prerequisites - -- Installed the [Nix Package Manager](https://nixos.org/download.html) (use the comman on their website) -- Installed [direnv](https://direnv.net/docs/installation.html) and added its hook to your shell. (package manager) - -Once the repo is cloned to your computer, follow these next few steps inside the Firefish folder: - -- Run `direnv allow`. This will build the environment and install all needed tools. -- Run `install-deps`, then `prepare-config`, to install the node dependencies and prepare the needed config files. -- In a second terminal, run `devenv up`. This will spawn a **Redis** server, a **Postgres** server, and the **Firefish** server in dev mode. -- Once you see the Firefish banner printed in your second terminal, run `migrate` in the first. -- Once migrations finish, open http://localhost:3000 in your web browser. -- You should now see the admin user creation screen! - -Note: When you want to restart a dev server, all you need to do is run `devenv up`, no other steps are necessary. - -# Possible Troubles with the dev enviroment -(this doesn't have to be done under normal conditions, this is for future reference) - -### direnv -If you have any trouble with `direnv allow` -Check that the contents of `.envrc` have the same version of nix-direnv that is specified here: -> nix-direnv under -> installation -> using direnv source url -> https://github.com/nix-community/nix-direnv#direnv-source_url - -there should be no errors during `direnv allow` - -### outdated nix packages -if `install-deps` or any subsequent command doesn't run due to versioning problems -`flake.nix` and `flake.lock` may be outdated - -delete `flake.lock`, or better, run `nix flake update --extra-experimental-features flakes --extra-experimental-features nix-command` -after that, run `direnv rebuild` - -if there are any errors, you might have to change `flake.nix` -(because the available options can change between versions - consider getting support in [the matrix channel](https://matrix.to/#/#firefish-community:nitro.chat)) - -### after changing a node version -in my case, i had to change the node version from 19, to 18 - -! before proceeding, make sure to delete all build artifacts! -remove `node_modules` and `built` folders, and maybe `.devenv` and `.direnv` as well -manually, or run `npm cache clean --force` and `pnpm cleanall` - -### Windows Subsystem for Linux -if `devenv up` terminates because of wrong folder permissions, - -create the file `/etc/wsl.conf` in your distro and add -```shell -[automount] -options = "metadata" -``` - -this allows `chmod` calls to actually have an effect. -the build scripts DO actually set the permissions, it just needs to work in wsl. - -### devenv up -devenv up may take a looong time. (some say this is fake news, maybe it was bad luck in my case) - -do not get spooked by this error: -``` -> firefish@14.0.0-dev32 start /mnt/.../firefish -> pnpm --filter backend run start - - -> backend@ start /mnt/.../firefish/packages/backend -> pnpm node ./built/index.js - -node:internal/modules/cjs/loader:1078 - throw err; - ^ - -Error: Cannot find module '/mnt/.../firefish/packages/backend/built/index.js' - at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15) - at Module._load (node:internal/modules/cjs/loader:920:27) - at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) - at node:internal/main/run_main_module:23:47 { - code: 'MODULE_NOT_FOUND', - requireStack: [] -} - -Node.js v18.16.0 -undefined -/mnt/.../firefish/packages/backend: - ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  backend@ start: `pnpm node ./built/index.js` -Exit status 1 - ELIFECYCLE  Command failed with exit code 1. -``` - -the script is designed to constantly try to start the server, while the build is still running. -this just means that the build isn't finished yet. - -at some point you should see a banner that says "Firefish" in big letters - -then you're good to go and can run `migrate` (in another terminal)! - -if you don't see the banner, -and it's for some reason stuck on `Finished 'build' after 917 ms` for a view minutes, - -just leave devenv running and open another terminal in the folder -run `migrate` and then `pnpm --filter backend run start` by yourself -the server should start diff --git a/docs/downgrade.sql b/docs/downgrade.sql index 8a7769dcb9..1d26a6fa3b 100644 --- a/docs/downgrade.sql +++ b/docs/downgrade.sql @@ -1,6 +1,12 @@ BEGIN; DELETE FROM "migrations" WHERE name IN ( + 'FixMutingIndices1710690239308', + 'NoteFile1710304584214', + 'RenameMetaColumns1705944717480', + 'SeparateHardMuteWordsAndPatterns1706413792769', + 'IndexAltTextAndCw1708872574733', + 'Pgroonga1698420787202', 'ChangeDefaultConfigs1709251460718', 'AddReplyMuting1704851359889', 'FixNoteUrlIndex1709129810501', @@ -12,6 +18,39 @@ DELETE FROM "migrations" WHERE name IN ( 'RemoveNativeUtilsMigration1705877093218' ); +-- fix-muting-indices +DROP INDEX "IDX_renote_muting_createdAt"; +DROP INDEX "IDX_renote_muting_muteeId"; +DROP INDEX "IDX_renote_muting_muterId"; +DROP INDEX "IDX_reply_muting_createdAt"; +DROP INDEX "IDX_reply_muting_muteeId"; +DROP INDEX "IDX_reply_muting_muterId"; +CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt"); +CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId"); +CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId"); + +-- note-file +DROP TABLE "note_file"; + +-- rename-meta-columns +ALTER TABLE "meta" RENAME COLUMN "tosUrl" TO "ToSUrl"; +ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSsl" TO "objectStorageUseSSL"; +ALTER TABLE "meta" RENAME COLUMN "customMotd" TO "customMOTD"; + +-- separate-hard-mute-words-and-patterns +UPDATE "user_profile" SET "mutedWords" = "mutedWords" || array_to_json("mutedPatterns")::jsonb; +ALTER TABLE "user_profile" DROP "mutedPatterns"; + +-- index-alt-text-and-cw +DROP INDEX "IDX_f4f7b93d05958527300d79ac82"; +DROP INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f"; + +-- pgroonga +DROP INDEX "IDX_f27f5d88941e57442be75ba9c8"; +DROP INDEX "IDX_065d4d8f3b5adb4a08841eae3c"; +DROP INDEX "IDX_fcb770976ff8240af5799e3ffc"; +DROP EXTENSION pgroonga CASCADE; + -- change-default-configs ALTER TABLE "user_profile" ALTER COLUMN "noCrawle" SET DEFAULT false; ALTER TABLE "user_profile" ALTER COLUMN "publicReactions" SET DEFAULT false; diff --git a/docs/fk.patch b/docs/fk.patch deleted file mode 100644 index 2d51512c96..0000000000 --- a/docs/fk.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/packages/backend/migration/1661376843000-remove-mentioned-remote-users-column.js b/packages/backend/migration/1661376843000-remove-mentioned-remote-users-column.js -index 42d79b5b5..1fd5e0f10 100644 ---- a/packages/backend/migration/1661376843000-remove-mentioned-remote-users-column.js -+++ b/packages/backend/migration/1661376843000-remove-mentioned-remote-users-column.js -@@ -7,6 +7,22 @@ export class removeMentionedRemoteUsersColumn1661376843000 { - - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "note" ADD "mentionedRemoteUsers" TEXT NOT NULL DEFAULT '[]'::text`); -- await queryRunner.query(`UPDATE "note" SET "mentionedRemoteUsers" = (SELECT COALESCE(json_agg(row_to_json("data"))::text, '[]') FROM (SELECT "url", "uri", "username", "host" FROM "user" JOIN "user_profile" ON "user"."id" = "user_profile". "userId" WHERE "user"."host" IS NOT NULL AND "user"."id" = ANY("note"."mentions")) AS "data")`); -+ await queryRunner.query(` -+ CREATE TEMP TABLE IF NOT EXISTS "temp_mentions" AS -+ SELECT "id", "url", "uri", "username", "host" -+ FROM "user" -+ JOIN "user_profile" ON "user"."id" = "user_profile"."userId" WHERE "user"."host" IS NOT NULL -+ `); -+ -+ await queryRunner.query(` -+ CREATE UNIQUE INDEX "temp_mentions_id" ON "temp_mentions"("id") -+ `); -+ -+ await queryRunner.query(` -+ UPDATE "note" SET "mentionedRemoteUsers" = ( -+ SELECT COALESCE(json_agg(row_to_json("data")::jsonb - 'id')::text, '[]') FROM "temp_mentions" AS "data" -+ WHERE "data"."id" = ANY("note"."mentions") -+ ) -+ `); - } - } -diff --git a/packages/backend/migration/1663399074403-resize-comments-drive-file.js b/packages/backend/migration/1663399074403-resize-comments-drive-file.js -index a037f1655..0873aec9b 100644 ---- a/packages/backend/migration/1663399074403-resize-comments-drive-file.js -+++ b/packages/backend/migration/1663399074403-resize-comments-drive-file.js -@@ -9,6 +9,6 @@ export class resizeCommentsDriveFile1663399074403 { - } - - async down(queryRunner) { -- await queryRunner.query(`ALTER TABLE "drive_file" ALTER COLUMN "comment" TYPE character varying(512)`); -- } -+ console.log('This migration cannot be reverted, skipping...'); -+ } - } diff --git a/docs/docker.md b/docs/install-container.md similarity index 61% rename from docs/docker.md rename to docs/install-container.md index 2b8667d1e1..38852e6ebd 100644 --- a/docs/docker.md +++ b/docs/install-container.md @@ -1,19 +1,13 @@ -# Running a Firefish server with Docker +# Running a Firefish server with containers -## Pre-built docker container -[registry.firefish.dev/firefish/firefish](https://firefish.dev/firefish/firefish/container_registry) +## Prerequisites -## `docker-compose` +- Latest [Docker](https://docs.docker.com/get-docker/) installation + - You can also use [Podman](https://podman.io/docs/installation) and [Podman Compose](https://github.com/containers/podman-compose). -There are example config files that you can use to build the container from source +## Configuration -- docker-compose.example.yml (**compose file**) -- .config/docker_example.env (**db config settings**) -- .config/default.yml (**firefish server settings**) - -## Configuring - -Copy the files: +Copy the example config files: ```sh cp docker-compose.example.yml docker-compose.yml @@ -23,20 +17,31 @@ cp .config/docker_example.env .config/docker.env then edit them according to your environment. You can configure `docker.env` with anything you like, but you will have to pay attention to the `default.yml` file: + - `url` should be set to the URL you will be hosting the web interface for the server at. - `host`, `db`, `user`, `pass` will have to be configured in the `PostgreSQL configuration` section - `host` is the name of the postgres container (eg: *firefish_db_1*), and the others should match your `docker.env`. - `host`will need to be configured in the *Redis configuration* section - it is the name of the redis container (eg: *firefish_redis_1*) -- `auth` will need to be configured in the *Sonic* section - cannot be the default `SecretPassword` Everything else can be left as-is. -## Running docker-compose +## Pull the container image -The [prebuilt container for firefish](https://firefish.dev/firefish/firefish/container_registry) is fairly large, and may take a few minutes to download and extract using docker. +The image tag is [`registry.firefish.dev/firefish/firefish:latest`](https://firefish.dev/firefish/firefish/container_registry/1). -Copy `docker-compose.yml` and the `config/` to a directory, then run the **docker-compose** command: -`docker-compose up -d`. +```sh +docker pull registry.firefish.dev/firefish/firefish:latest +# or podman pull registry.firefish.dev/firefish/firefish:latest +``` + +## Run + +```sh +docker compose up --detach +# or podman-compose up --detach +``` NOTE: This will take some time to come fully online, even after download and extracting the container images, and it may emit some error messages before completing successfully. Specifically, the `db` container needs to initialize and so isn't available to the `web` container right away. Only once the `db` container comes online does the `web` container start building and initializing the firefish tables. Once the server is up you can use a web browser to access the web interface at `http://serverip:3000` (where `serverip` is the IP of the server you are running the firefish server on). + +To publish your server, please follow the instructions in [section 5 of this installation guide](./install.md#5-preparation-for-publishing-a-server). diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000000..061000fa32 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,317 @@ +# Install Firefish + +This document shows an example procedure for installing Firefish on Debian 12. Note that there is much room for customizing the server setup; this document merely demonstrates a simple installation. + +If you want to use the pre-built container image, please refer to [`install-container.md`](./install-container.md). + +Make sure that you can use the `sudo` command before proceeding. + +## 1. Install dependencies + +### Utilities + +```sh +sudo apt update +sudo apt install build-essential python3 curl wget git lsb-release +``` + +### Node.js and pnpm + +Instructions can be found at [this repository](https://github.com/nodesource/distributions). + +```sh +NODE_MAJOR=20 +curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | sudo -E bash - +sudo apt install nodejs + +# check version +node --version +``` + +You also need to enable `pnpm`. +```sh +sudo corepack enable +corepack prepare pnpm@latest --activate + +# check version +pnpm --version +``` + +### PostgreSQL and PGroonga + +PostgreSQL install instructions can be found at [this page](https://www.postgresql.org/download/). + +```sh +sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' +wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - +sudo apt update +sudo apt install postgresql-16 + +sudo systemctl enable --now postgresql + +# check version +psql --version +``` + +PGroonga install instructions can be found at [this page](https://pgroonga.github.io/install/). + +```sh +wget "https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb" +sudo apt install "./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb" +wget "https://packages.groonga.org/debian/groonga-apt-source-latest-$(lsb_release --codename --short).deb" +sudo apt install "./groonga-apt-source-latest-$(lsb_release --codename --short).deb" +sudo apt update +sudo apt install postgresql-16-pgdg-pgroonga + +rm "apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb" "groonga-apt-source-latest-$(lsb_release --codename --short).deb" +``` + +### Redis + +Instructions can be found at [this page](https://redis.io/docs/install/install-redis/). + +```sh +curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg +echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list +sudo apt update +sudo apt install redis + +sudo systemctl enable --now redis-server + +# check version +redis-cli --version +``` + +### FFmpeg + +```sh +sudo apt install ffmpeg +``` + +## 2. Set up a database + +1. Create a database user + ```sh + sudo -u postgres createuser --no-createdb --no-createrole --no-superuser --encrypted --pwprompt firefish + ``` + If you forgot the password you typed, you can reset it by executing `sudo -u postgres psql -c "ALTER USER firefish PASSWORD 'password';"`. +2. Create a database + ```sh + sudo -u postgres createdb --encoding='UTF8' --owner=firefish firefish_db + ``` +3. Enable PGronnga extension + ```sh + sudo -u postgres psql --command='CREATE EXTENSION pgroonga;' --dbname=firefish_db + ``` + +## 3. Configure Firefish + +1. Create an user for Firefish and switch user + ```sh + sudo useradd --create-home --user-group --shell /bin/bash firefish + sudo su --login firefish + + # check the current working directory + # the result should be /home/firefish + pwd + ``` +1. Install Rust toolchain + + Instructions can be found at [this page](https://www.rust-lang.org/tools/install). + + ```sh + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + . "${HOME}/.cargo/env" + + # check version + cargo --version + ``` +3. Clone the Firefish repository + ```sh + git clone --branch=main https://firefish.dev/firefish/firefish.git + ``` +1. Copy and edit the config file + ```sh + cd firefish + cp .config/example.yml .config/default.yml + nano .config/default.yml + ``` + + ```yaml + url: https://your-server-domain.example.com # change here + port: 3000 + + db: + host: localhost + port: 5432 + db: firefish_db + user: firefish + pass: your-database-password # and here + ``` + +## 4. Build Firefish + +1. Build + ```sh + pnpm install --frozen-lockfile + NODE_ENV=production pnpm run build + ``` +1. Execute database migrations + ```sh + pnpm run migrate + ``` +1. Logout from `firefish` user + ```sh + exit + ``` + +## 5. Preparation for publishing a server + +### 1. Set up a firewall + +To expose your server securely, you may want to set up a firewall. We use [ufw](https://launchpad.net/ufw) in this instruction. + +```sh +sudo apt install ufw +# if you use SSH +# SSH_PORT=22 +# sudo ufw limit "${SSH_PORT}/tcp" +sudo ufw default deny +sudo ufw allow 80 +sudo ufw allow 443 +sudo ufw --force enable + +# check status +sudo ufw status +``` + +### 2. Set up a reverse proxy + +In this instruction, we use [Caddy](https://caddyserver.com/) to make the Firefish server accesible from internet. However, you can also use [Nginx](https://nginx.org/en/) if you want ([example Nginx config file](../firefish.nginx.conf)). + +1. Install Caddy + ```sh + sudo apt install debian-keyring debian-archive-keyring apt-transport-https + curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg + curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list + sudo apt update + sudo apt install caddy + + # check version + caddy version + ``` +1. Replace the config file + ```sh + sudo mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak + sudo nano /etc/caddy/Caddyfile + ``` + + ```Caddyfile + your-server-domain.example.com { + reverse_proxy http://127.0.0.1:3000 + + log { + output file /var/log/caddy/firefish.log + } + } + ``` +1. Restart Caddy + ```sh + sudo systemctl restart caddy + ``` + +## 6. Publish your Firefish server + +1. Create a service file + ```sh + sudo nano /etc/systemd/system/firefish.service + ``` + + ```service + [Unit] + Description=Firefish daemon + Requires=redis.service caddy.service postgresql.service + After=redis.service caddy.service postgresql.service network-online.target + + [Service] + Type=simple + User=firefish + Group=firefish + UMask=0027 + ExecStart=/usr/bin/pnpm run start + WorkingDirectory=/home/firefish/firefish + Environment="NODE_ENV=production" + Environment="npm_config_cache=/tmp" + # uncomment the following line if you use jemalloc (note that the path varies on different environments) + # Environment="LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2" + StandardOutput=journal + StandardError=journal + SyslogIdentifier=firefish + TimeoutSec=60 + Restart=always + + CapabilityBoundingSet= + DevicePolicy=closed + NoNewPrivileges=true + LockPersonality=true + PrivateDevices=true + PrivateIPC=true + PrivateMounts=true + PrivateUsers=true + ProtectClock=true + ProtectControlGroups=true + ProtectHostname=true + ProtectKernelTunables=true + ProtectKernelModules=true + ProtectKernelLogs=true + ProtectProc=invisible + RestrictNamespaces=true + RestrictRealtime=true + RestrictSUIDSGID=true + SecureBits=noroot-locked + SystemCallArchitectures=native + SystemCallFilter=~@chown @clock @cpu-emulation @debug @ipc @keyring @memlock @module @mount @obsolete @privileged @raw-io @reboot @resources @setuid @swap + SystemCallFilter=capset pipe pipe2 setpriority + + [Install] + WantedBy=multi-user.target + ``` +1. Start Firefish + ```sh + sudo systemctl enable --now firefish + ``` + +## Upgrading + +Please refer to the [upgrade instruction](./upgrade.md). Be sure to switch to `firefish` user and go to the Firefish directory before executing the `git` command: + +```sh +sudo su --login firefish +cd ~/firefish +``` + +## Customize + +- To add custom CSS for all users, edit `./custom/assets/instance.css`. +- To add static assets (such as images for the splash screen), place them in the `./custom/assets/` directory. They'll then be available on `https://yourserver.tld/static-assets/filename.ext`. +- To add custom locales, place them in the `./custom/locales/` directory. If you name your custom locale the same as an existing locale, it will overwrite it. If you give it a unique name, it will be added to the list. Also make sure that the first part of the filename matches the locale you're basing it on. (Example: `en-FOO.yml`) +- To add custom error images, place them in the `./custom/assets/badges` directory, replacing the files already there. +- To add custom sounds, place only mp3 files in the `./custom/assets/sounds` directory. +- To update custom assets without rebuilding, just run `pnpm run gulp`. +- To block ChatGPT, CommonCrawl, or other crawlers from indexing your instance, uncomment the respective rules in `./custom/robots.txt`. + +## Tips & Tricks + +- When editing the config file, please don't fill out the settings at the bottom. They're designed *only* for managed hosting, not self hosting. Those settings are much better off being set in Firefish's control panel. +- Port 3000 (used in the default config) might be already used on your server for something else. To find an open port for Firefish, run `for p in {3000..4000}; do ss -tlnH | tr -s ' ' | cut -d" " -sf4 | grep -q "${p}$" || echo "${p}"; done | head -n 1`. Replace 3000 with the minimum port and 4000 with the maximum port if you need it. +- We'd recommend you use a S3 Bucket/CDN for Object Storage, especially if you use containers. +- When using object storage, setting a proper `Access-Control-Allow-Origin` response header is highly recommended. +- We'd recommend against using CloudFlare, but if you do, make sure to turn code minification off. +- For push notifications, run `npx web-push generate-vapid-keys`, then put the public and private keys into Control Panel > General > ServiceWorker. +- For translations, make a [DeepL](https://deepl.com) account and generate an API key, then put it into Control Panel > General > DeepL Translation. +- To add another admin account: + - Go to the user's page > 3 Dots > About > Moderation > turn on "Moderator" + - Go back to Overview > click the clipboard icon next to the ID + - Run `psql -d firefish` (or whatever the database name is) + - Run `UPDATE "user" SET "isAdmin" = true WHERE id='999999';` (replace `999999` with the copied ID) + - Restart your Firefish server diff --git a/docs/kubernetes.md b/docs/kubernetes.md deleted file mode 100644 index 5ec6b46ad2..0000000000 --- a/docs/kubernetes.md +++ /dev/null @@ -1,45 +0,0 @@ -# Running a Firefish server with Kubernetes and Helm - -This is a [Helm](https://helm.sh/) chart directory in the root of the project -that you can use to deploy firefish to a Kubernetes cluster - -## Deployment - -1. Copy the example helm values and make your changes: -```shell -cp .config/helm_values_example.yml .config/helm_values.yml -``` - -2. Update helm dependencies: -```shell -cd chart -helm dependency list $dir 2> /dev/null | tail +2 | head -n -1 | awk '{ print "helm repo add " $1 " " $3 }' | while read cmd; do $cmd; done; -cd ../ -``` - -3. Create the firefish helm release (also used to update existing deployment): -```shell -helm upgrade \ - --install \ - --namespace firefish \ - --create-namespace \ - firefish chart/ \ - -f .config/helm_values.yml -``` - -4. Watch your firefish server spin up: -```shell -kubectl -n firefish get po -w -``` - -5. Initial the admin user and managed config: -```shell -export firefish_USERNAME="my_desired_admin_handle" && \ -export firefish_PASSWORD="myDesiredInitialPassword" && \ -export firefish_HOST="firefish.example.com" && \ -export firefish_TOKEN=$(curl -X POST https://$firefish_HOST/api/admin/accounts/create -H "Content-Type: application/json" -d "{ \"username\":\"$firefish_USERNAME\", \"password\":\"$firefish_PASSWORD\" }" | jq -r '.token') && \ -echo "Save this token: ${firefish_TOKEN}" && \ -curl -X POST -H "Authorization: Bearer $firefish_TOKEN" https://$firefish_HOST/api/admin/accounts/hosted -``` - -6. Enjoy! diff --git a/docs/migrate.md b/docs/migrate.md deleted file mode 100644 index 77c7377f7a..0000000000 --- a/docs/migrate.md +++ /dev/null @@ -1,106 +0,0 @@ -# Migrating from Misskey/FoundKey to Firefish - -All the guides below assume you're starting in the root of the repo directory. - -### Before proceeding - -- **Ensure you have stopped all master and worker processes of Misskey.** -- **Ensure you have backups of the database before performing any commands.** - -## Misskey v13 and above - -Tested with Misskey v13.11.3. - -If your Misskey v13 is older, we recommend updating your Misskey to v13.11.3. - -```sh -wget -O mkv13.patch https://firefish.dev/firefish/firefish/-/raw/develop/docs/mkv13.patch -wget -O mkv13_restore.patch https://firefish.dev/firefish/firefish/-/raw/develop/docs/mkv13_restore.patch -git apply mkv13.patch mkv13_restore.patch - -cd packages/backend - -LINE_NUM="$(pnpm typeorm migration:show -d ormconfig.js | grep -n activeEmailValidation1657346559800 | cut -d ':' -f 1)" -NUM_MIGRATIONS="$(pnpm typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | wc -l)" - -for i in $(seq 1 $NUM_MIGRATIONS); do pnpm typeorm migration:revert -d ormconfig.js; done - -cd ../../ - -git remote set-url origin https://firefish.dev/firefish/firefish.git -git fetch origin -git stash push -rm -rf fluent-emojis misskey-assets -git switch main # or beta or develop -git pull --ff -wget -O renote_muting.patch https://firefish.dev/firefish/firefish/-/raw/develop/docs/renote_muting.patch -git apply renote_muting.patch - -pnpm install -NODE_ENV=production pnpm run build -pnpm run migrate -git stash push -``` - -Depending on the version you're migrating from, you may have to open Postgres with `psql -d your_database` and run the following commands: - -```sql -ALTER TABLE "meta" ADD COLUMN "disableLocalTimeline" boolean DEFAULT false; -ALTER TABLE "meta" ADD COLUMN "disableGlobalTimeline" boolean DEFAULT false; -ALTER TABLE "meta" ADD COLUMN "localDriveCapacityMb" integer DEFAULT 512; -ALTER TABLE "meta" ADD COLUMN "remoteDriveCapacityMb" integer DEFAULT 128; -ALTER TABLE "user" ADD COLUMN "isSilenced" boolean DEFAULT false; -ALTER TABLE "user" ADD COLUMN "isAdmin" boolean DEFAULT false; -ALTER TABLE "user" ADD COLUMN "isModerator" boolean DEFAULT false; -ALTER TABLE "user" ADD COLUMN "remoteDriveCapacityMb" integer DEFAULT 128; -ALTER TABLE "user" ADD COLUMN "driveCapacityOverrideMb" integer DEFAULT 128; -ALTER TABLE "instance" ADD COLUMN "caughtAt" date; -ALTER TABLE "instance" ADD COLUMN "latestRequestSentAt" date; -ALTER TABLE "instance" ADD COLUMN "latestStatus" character varying(512); -ALTER TABLE "instance" ADD COLUMN "lastCommunicatedAt" date; -``` - -then quit with `\q`, and restart Firefish. - -Note: Ignore errors of `column "xxx" of relation "xxx" already exists`. - -If no other errors happened, your Firefish is ready to launch! - -## Misskey v12.119 and before - -```sh -git remote set-url origin https://firefish.dev/firefish/firefish.git -git fetch -git checkout main # or beta or develop -git pull --ff - -NODE_ENV=production pnpm run migrate -# build using prefered method -``` - -## FoundKey - -```sh -wget -O fk.patch https://firefish.dev/firefish/firefish/-/raw/develop/docs/fk.patch -git apply fk.patch -cd packages/backend - -LINE_NUM="$(npx typeorm migration:show -d ormconfig.js | grep -n uniformThemecolor1652859567549 | cut -d ':' -f 1)" -NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | wc -l)" - -for i in $(seq 1 $NUM_MIGRATIONS); do - npx typeorm migration:revert -d ormconfig.js -done - -git remote set-url origin https://firefish.dev/firefish/firefish.git -git fetch -git checkout main # or beta or develop -git pull --ff - -NODE_ENV=production pnpm run migrate -# build using prefered method -``` - -## Reverse - -You ***cannot*** migrate back to Misskey from Firefish due to re-hashing passwords on signin with argon2. You can migrate to [Sharkey](https://github.com/transfem-org/Sharkey), a soft fork of Misskey that uses argon2 though. You can also migrate from Firefish to FoundKey, although this is not recommended due to FoundKey being end-of-life, and may have some problems with alt-text. diff --git a/docs/mkv13.patch b/docs/mkv13.patch deleted file mode 100644 index e6106b16f2..0000000000 --- a/docs/mkv13.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js b/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js -index 38a676985..c4ae690e0 100644 ---- a/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js -+++ b/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js -@@ -6,6 +6,8 @@ export class removeLastCommunicatedAt1672704017999 { - } - - async down(queryRunner) { -- await queryRunner.query(`ALTER TABLE "instance" ADD "lastCommunicatedAt" TIMESTAMP WITH TIME ZONE NOT NULL`); -+ await queryRunner.query(`ALTER TABLE "instance" ADD "lastCommunicatedAt" TIMESTAMP WITH TIME ZONE`); -+ await queryRunner.query(`UPDATE "instance" SET "lastCommunicatedAt" = COALESCE("infoUpdatedAt", "caughtAt")`); -+ await queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "lastCommunicatedAt" SET NOT NULL`); - } - } -diff --git a/packages/backend/migration/1673336077243-PollChoiceLength.js b/packages/backend/migration/1673336077243-PollChoiceLength.js -index 810c626e0..5809528cb 100644 ---- a/packages/backend/migration/1673336077243-PollChoiceLength.js -+++ b/packages/backend/migration/1673336077243-PollChoiceLength.js -@@ -6,6 +6,6 @@ export class PollChoiceLength1673336077243 { - } - - async down(queryRunner) { -- await queryRunner.query(`ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(128) array`); -+ //await queryRunner.query(`ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(128) array`); - } - } -diff --git a/packages/backend/migration/1674118260469-achievement.js b/packages/backend/migration/1674118260469-achievement.js -index 131ab96f8..57a922f83 100644 ---- a/packages/backend/migration/1674118260469-achievement.js -+++ b/packages/backend/migration/1674118260469-achievement.js -@@ -18,12 +18,13 @@ export class achievement1674118260469 { - - async down(queryRunner) { - await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'pollEnded')`); -+ await queryRunner.query(`CREATE TYPE "public"."notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); - await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`); - await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum_old"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum_old"[]`); - await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`); - await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum"`); - await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum_old" RENAME TO "user_profile_mutingnotificationtypes_enum"`); -- await queryRunner.query(`CREATE TYPE "public"."notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); -+ await queryRunner.query(`DELETE FROM "public"."notification" WHERE "type" = 'achievementEarned'`); - await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum_old" USING "type"::"text"::"public"."notification_type_enum_old"`); - await queryRunner.query(`DROP TYPE "public"."notification_type_enum"`); - await queryRunner.query(`ALTER TYPE "public"."notification_type_enum_old" RENAME TO "notification_type_enum"`); diff --git a/docs/mkv13_restore.patch b/docs/mkv13_restore.patch deleted file mode 100644 index 9ef9934edc..0000000000 --- a/docs/mkv13_restore.patch +++ /dev/null @@ -1,127 +0,0 @@ -diff --git a/packages/backend/migration/1680491187535-cleanup.js b/packages/backend/migration/1680491187535-cleanup.js -index 1e609ca06..0e6accf3e 100644 ---- a/packages/backend/migration/1680491187535-cleanup.js -+++ b/packages/backend/migration/1680491187535-cleanup.js -@@ -1,10 +1,40 @@ - export class cleanup1680491187535 { -- name = 'cleanup1680491187535' -+ name = "cleanup1680491187535"; - -- async up(queryRunner) { -- await queryRunner.query(`DROP TABLE "antenna_note" `); -- } -+ async up(queryRunner) { -+ await queryRunner.query(`DROP TABLE "antenna_note" `); -+ } - -- async down(queryRunner) { -- } -+ async down(queryRunner) { -+ await queryRunner.query( -+ `CREATE TABLE antenna_note ( id character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "antennaId" character varying(32) NOT NULL, read boolean DEFAULT false NOT NULL)`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN antenna_note."noteId" IS 'The note ID.'`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN antenna_note."antennaId" IS 'The antenna ID.'`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY antenna_note ADD CONSTRAINT "PK_fb28d94d0989a3872df19fd6ef8" PRIMARY KEY (id)`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_0d775946662d2575dfd2068a5f" ON antenna_note USING btree ("antennaId")`, -+ ); -+ await queryRunner.query( -+ `CREATE UNIQUE INDEX "IDX_335a0bf3f904406f9ef3dd51c2" ON antenna_note USING btree ("noteId", "antennaId")`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_9937ea48d7ae97ffb4f3f063a4" ON antenna_note USING btree (read)`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_bd0397be22147e17210940e125" ON antenna_note USING btree ("noteId")`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY antenna_note ADD CONSTRAINT "FK_0d775946662d2575dfd2068a5f5" FOREIGN KEY ("antennaId") REFERENCES antenna(id) ON DELETE CASCADE`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY antenna_note ADD CONSTRAINT "FK_bd0397be22147e17210940e125b" FOREIGN KEY ("noteId") REFERENCES note(id) ON DELETE CASCADE`, -+ ); -+ } - } -diff --git a/packages/backend/migration/1680582195041-cleanup.js b/packages/backend/migration/1680582195041-cleanup.js -index c587e456a..a91d6ff3c 100644 ---- a/packages/backend/migration/1680582195041-cleanup.js -+++ b/packages/backend/migration/1680582195041-cleanup.js -@@ -1,11 +1,64 @@ - export class cleanup1680582195041 { -- name = 'cleanup1680582195041' -+ name = "cleanup1680582195041"; - -- async up(queryRunner) { -- await queryRunner.query(`DROP TABLE "notification" `); -- } -+ async up(queryRunner) { -+ await queryRunner.query(`DROP TABLE "notification"`); -+ } - -- async down(queryRunner) { -- -- } -+ async down(queryRunner) { -+ await queryRunner.query( -+ `CREATE TABLE notification ( id character varying(32) NOT NULL, "createdAt" timestamp with time zone NOT NULL, "notifieeId" character varying(32) NOT NULL, "notifierId" character varying(32), "isRead" boolean DEFAULT false NOT NULL, "noteId" character varying(32), reaction character varying(128), choice integer, "followRequestId" character varying(32), type notification_type_enum NOT NULL, "customBody" character varying(2048), "customHeader" character varying(256), "customIcon" character varying(1024), "appAccessTokenId" character varying(32), achievement character varying(128))`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN notification."createdAt" IS 'The created date of the Notification.'`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN notification."notifieeId" IS 'The ID of recipient user of the Notification.'`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN notification."notifierId" IS 'The ID of sender user of the Notification.'`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN notification."isRead" IS 'Whether the Notification is read.'`, -+ ); -+ await queryRunner.query( -+ `COMMENT ON COLUMN notification.type IS 'The type of the Notification.'`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY notification ADD CONSTRAINT "PK_705b6c7cdf9b2c2ff7ac7872cb7" PRIMARY KEY (id)`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_080ab397c379af09b9d2169e5b" ON notification USING btree ("isRead")`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_33f33cc8ef29d805a97ff4628b" ON notification USING btree (type)`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_3b4e96eec8d36a8bbb9d02aa71" ON notification USING btree ("notifierId")`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_3c601b70a1066d2c8b517094cb" ON notification USING btree ("notifieeId")`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_b11a5e627c41d4dc3170f1d370" ON notification USING btree ("createdAt")`, -+ ); -+ await queryRunner.query( -+ `CREATE INDEX "IDX_e22bf6bda77b6adc1fd9e75c8c" ON notification USING btree ("appAccessTokenId")`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY notification ADD CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710" FOREIGN KEY ("notifierId") REFERENCES "user"(id) ON DELETE CASCADE`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY notification ADD CONSTRAINT "FK_3c601b70a1066d2c8b517094cb9" FOREIGN KEY ("notifieeId") REFERENCES "user"(id) ON DELETE CASCADE`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY notification ADD CONSTRAINT "FK_769cb6b73a1efe22ddf733ac453" FOREIGN KEY ("noteId") REFERENCES note(id) ON DELETE CASCADE`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY notification ADD CONSTRAINT "FK_bd7fab507621e635b32cd31892c" FOREIGN KEY ("followRequestId") REFERENCES follow_request(id) ON DELETE CASCADE`, -+ ); -+ await queryRunner.query( -+ `ALTER TABLE ONLY notification ADD CONSTRAINT "FK_e22bf6bda77b6adc1fd9e75c8c9" FOREIGN KEY ("appAccessTokenId") REFERENCES access_token(id) ON DELETE CASCADE`, -+ ); -+ } - } diff --git a/docs/notice-for-admins.md b/docs/notice-for-admins.md index 1edb5ecca2..12076730e7 100644 --- a/docs/notice-for-admins.md +++ b/docs/notice-for-admins.md @@ -1,12 +1,146 @@ -# v20240301 +# Notice for server administrators -## For all users +You can skip intermediate versions when upgrading from an old version, but please read the notices and follow the instructions for each intermediate version before [upgrading](./upgrade.md). + +## v20240319 + +The full-text search engine used in Firefish has been changed to [PGroonga](https://pgroonga.github.io/). This is no longer an optional feature, so please enable PGroonga on your system. If you are using Sonic, Meilisearch, or Elasticsearch, you can also uninstall it from your system and remove the settings from `.config/default.yml`. + +### For systemd/pm2 users + +- Required Node.js version has been bumped from v18.16.0 to v18.17.0. +- You need to install PGroonga on your system. Please follow the instructions below. + +#### 1. Install PGroonga + +Please execute `psql --version` to check your PostgreSQL major version. This will print a message like this: + +```text +psql (PostgreSQL) 16.1 +``` + +In this case, your PostgreSQL major version is `16`. + +There are official installation instructions for many operating systems on , so please follow the instructions on this page. However, since many users are using Ubuntu, and there are no instructions for Arch Linux and Fedora, we explicitly list the instructions for Ubuntu, Arch Linux and Fedora here. Please keep in mind that this is not official information and the procedures may change. + +##### Ubuntu + +1. Add apt repository + ```sh + sudo apt install -y software-properties-common + sudo add-apt-repository -y universe + sudo add-apt-repository -y ppa:groonga/ppa + sudo apt install -y wget lsb-release + wget https://packages.groonga.org/ubuntu/groonga-apt-source-latest-$(lsb_release --codename --short).deb + sudo apt install -y -V ./groonga-apt-source-latest-$(lsb_release --codename --short).deb + echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release --codename --short)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + sudo apt update + ``` +2. Install PGroonga + ```sh + # Please replace "16" with your PostgreSQL major version + sudo apt install postgresql-16-pgdg-pgroonga + ``` + +##### Arch Linux + +You can install PGroonga from the Arch User Repository. + +```sh +git clone https://aur.archlinux.org/pgroonga.git && cd pgroonga && makepkg -si +# or paru -S pgroonga +# or yay -S pgroonga +``` + +##### Fedora + +You need to build PGroonga from source and create a policy package. + +```sh +sudo dnf install make groonga-devel postgresql-server-devel redhat-rpm-config +wget https://packages.groonga.org/source/pgroonga/pgroonga-3.1.8.tar.gz +tar xvf pgroonga-3.1.8.tar.gz +cd pgroonga-3.1.8 +make +sudo make install +``` + +```sh +cat > pgroonga.te << EOF +module pgroonga 1.0; + +require { + type postgresql_t; + type postgresql_db_t; + class file map; +} + +allow postgresql_t postgresql_db_t:file map; +EOF +``` + +```sh +checkmodule -M -m -o pgroonga.mod pgroonga.te +semodule_package -o pgroonga.pp -m pgroonga.mod +sudo semodule -i pgroonga.pp +``` + +#### 2. Enable PGroonga + +After the instllation, please execute this command to enable PGroonga: + +```sh +sudo --user=postgres psql --dbname=your_database_name --command='CREATE EXTENSION pgroonga;' +``` + +The database name can be found in `.config/default.yml`. +```yaml +db: + port: 5432 + db: database_name # substitute your_database_name with this + user: firefish + pass: password +``` + +### For Docker/Podman users + +Please edit your `docker-compose.yml` to replace the database container image from `docker.io/postgres` to `docker.io/groonga/pgroonga`. + +The list of tags can be found on . Tags are named as `{PGroonga version}-{alpine or debian}-{PostgreSQL major version}`. + +Please make sure to use the same PostgreSQL version. If you are using `docker.io/postgres:16-alpine` (PostgreSQL v16), the corresponding image is `docker.io/groonga/pgroonga:3.1.8-alpine-16` (or `docker.io/groonga/pgroonga:3.1.8-alpine-16-slim`). There are also tags called `latest-alpine-16` and `latest-alpine-16-slim`, but please be careful if you use these tags since [PGroonga may introduce breaking changes](https://pgroonga.github.io/upgrade/), similar to PostgreSQL. + +```yaml +db: + restart: unless-stopped + image: docker.io/groonga/pgroonga:3.1.8-alpine-16-slim # change here + container_name: firefish_db +``` + +After that, execute this command to enable PGroonga: + +```sh +docker-compose up db --detach && docker-compose exec db sh -c 'psql --user="${POSTGRES_USER}" --dbname="${POSTGRES_DB}" --command="CREATE EXTENSION pgroonga;"' +# or podman-compose up db --detach && podman-compose exec db sh -c 'psql --user="${POSTGRES_USER}" --dbname="${POSTGRES_DB}" --command="CREATE EXTENSION pgroonga;"' +``` + +Once this is done, you can start Firefish as usual. + +```sh +docker pull registry.firefish.dev/firefish/firefish && docker-compose up --detach +# or podman pull registry.firefish.dev/firefish/firefish && podman-compose up --detach +``` + +## v20240301 + +### For all users A new setting item has been added to control the log levels, so please consider updating your `.config/default.yml`. ([example settings](https://firefish.dev/firefish/firefish/-/blob/e7689fb302a0eed192b9515162258a39800f838a/.config/example.yml#L170-179)) -# v20240225 +## v20240225 -## For Docker/Podman users +### For Docker/Podman users - The bug where `custom` directory was not working has (finally) been fixed. Please add the `custom` directory to `volumes` in your `docker-compose.yml`: ```yaml @@ -21,9 +155,9 @@ A new setting item has been added to control the log levels, so please consider - ./.config:/firefish/.config:ro ``` -# v20240222 +## v20240222 -## For Docker/Podman users +### For Docker/Podman users - You only need to pull the new container image (`docker/podman pull`) to upgrade your server, so we assume that many of you don't update the code (`git pull --ff`), but it's still worth noting here that we have renamed `docker-compose.yml` to `docker-compose.example.yml` in the repository, and `docker-compose.yml` is now set to be untracked by git. - Since `docker-compose.yml` may be edited by users (e.g., change port number, add reverse proxy), it shouldn't have been tracked by git in the first place. @@ -49,9 +183,9 @@ A new setting item has been added to control the log levels, so please consider - Also, PostgreSQL v12.2 (`docker.io/postgres:12.2-alpine`) has been used in this compose file, but we highly recommend that you upgrade it to a newer version (e.g., `docker.io/postgres:16-alpine`). - Note: some manual (painful) operations are needed to upgrade the PostgreSQL major version, so please be careful when performing upgrades: -# v20240214 +## v20240214 -## For systemd/pm2 users +### For systemd/pm2 users - Required Rust version has been bumped from v1.70 to v1.74. ```sh @@ -59,9 +193,9 @@ A new setting item has been added to control the log levels, so please consider rustup update # update version ``` -# v20240213 +## v20240213 -## For systemd/pm2 users +### For systemd/pm2 users - `packages/backend/native-utils` can be removed. - This directory was removed in the repository, but it's not completely removed from your system by `git pull --ff`, because some folders like `packages/backend/native-utils/built` are not tracked by git. @@ -70,16 +204,16 @@ A new setting item has been added to control the log levels, so please consider rm --recursive --force packages/backend/native-utils ``` -# v20240206 +## v20240206 -## For all users +### For all users - The git repository has been moved, so please update the `git remote` url. ```sh git remote set-url origin https://firefish.dev/firefish/firefish.git ``` -## For systemd/pm2 users +### For systemd/pm2 users - Required Rust version has been bumped from v1.68 to v1.70. - `libvips` is no longer required (unless your server os is *BSD), so you may uninstall it from your system. Make sure to execute the following commands after that: @@ -88,6 +222,6 @@ A new setting item has been added to control the log levels, so please consider pnpm install ``` -## For Docker/Podman users +### For Docker/Podman users - The image tag has been changed to `registry.firefish.dev/firefish/firefish:latest`, so please update `docker-compose.yml`. diff --git a/docs/renote_muting.patch b/docs/renote_muting.patch deleted file mode 100644 index c5bd2818c6..0000000000 --- a/docs/renote_muting.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/packages/backend/migration/1665091090561-add-renote-muting.js b/packages/backend/migration/1665091090561-add-renote-muting.js -index 2c76aaff5..f8541c818 100644 ---- a/packages/backend/migration/1665091090561-add-renote-muting.js -+++ b/packages/backend/migration/1665091090561-add-renote-muting.js -@@ -4,18 +4,6 @@ export class addRenoteMuting1665091090561 { - } - - async up(queryRunner) { -- await queryRunner.query( -- `CREATE TABLE "renote_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_renoteMuting_id" PRIMARY KEY ("id"))`, -- ); -- await queryRunner.query( -- `CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt") `, -- ); -- await queryRunner.query( -- `CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `, -- ); -- await queryRunner.query( -- `CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `, -- ); - } - - async down(queryRunner) {} diff --git a/docs/upgrade.md b/docs/upgrade.md new file mode 100644 index 0000000000..2d0c6c5a10 --- /dev/null +++ b/docs/upgrade.md @@ -0,0 +1,41 @@ +# Upgrade instruction + +## For systemd/pm2 users + +1. Check [`docs/notice-for-admins.md`](./notice-for-admins.md) +1. Stop the server + ```sh + sudo systemctl stop your-firefish-service.service + # or pm2 stop firefish + ``` +1. Pull the latest source code + ```sh + git checkout -- packages/backend/assets + git pull --ff origin main + ``` +1. Build Firefish and apply changes to the database + ```sh + corepack prepare pnpm@latest --activate + pnpm install --frozen-lockfile + NODE_ENV='production' NODE_OPTIONS='--max_old_space_size=3072' pnpm run rebuild + pnpm run migrate + ``` +1. Start the server + ```sh + sudo systemctl start your-firefish-service.service + # or pm2 start firefish + ``` + +## For Docker/Podman users + +1. Check [`docs/notice-for-admins.md`](./notice-for-admins.md) +1. Pull the latest container image + ```sh + docker pull registry.firefish.dev/firefish/firefish:latest + # or podman pull registry.firefish.dev/firefish/firefish:latest + ``` +1. Start the container + ```sh + docker compose up --detach + # or podman-compose up --detach + ``` diff --git a/firefish.apache.conf b/firefish.apache.conf deleted file mode 100644 index b0c69d51df..0000000000 --- a/firefish.apache.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Replace example.tld with your domain - - - ServerName example.tld - # For WebSocket - ProxyPass "/streaming" "ws://127.0.0.1:3000/streaming/" - # Proxy to Node - ProxyPass "/" "http://127.0.0.1:3000/" - ProxyPassReverse "/" "http://127.0.0.1:3000/" - ProxyPreserveHost On - # For files proxy - AllowEncodedSlashes On - \ No newline at end of file diff --git a/flake.lock b/flake.lock deleted file mode 100644 index f1ff690415..0000000000 --- a/flake.lock +++ /dev/null @@ -1,294 +0,0 @@ -{ - "nodes": { - "devenv": { - "inputs": { - "flake-compat": "flake-compat", - "nix": "nix", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1685521914, - "narHash": "sha256-0fdFP5IASLwJ0PSXrErW8PZon9TVYmi8VRF8OtjGkV4=", - "owner": "cachix", - "repo": "devenv", - "rev": "e206d8f2e3e8d6aa943656052f15bdfea8146b8d", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "fenix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ], - "rust-analyzer-src": "rust-analyzer-src" - }, - "locked": { - "lastModified": 1685514167, - "narHash": "sha256-urRxF0ZGSNeZjM4kALNg3wTh7fBscbqQmS6S/HU7Wms=", - "owner": "nix-community", - "repo": "fenix", - "rev": "3abfea51663583186f687c49a157eab1639349ca", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1685457039, - "narHash": "sha256-bEFtQm+YyLxQjKQAaBHJyPN1z2wbhBnr2g1NJWSYjwM=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "80717d11615b6f42d1ad2e18ead51193fc15de69", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-utils": { - "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "lowdown-src": { - "flake": false, - "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", - "type": "github" - }, - "original": { - "owner": "kristapsdz", - "repo": "lowdown", - "type": "github" - } - }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", - "owner": "domenkozar", - "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "relaxed-flakes", - "repo": "nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-lib": { - "locked": { - "dir": "lib", - "lastModified": 1682879489, - "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", - "type": "github" - }, - "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1678872516, - "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-22.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1685399834, - "narHash": "sha256-Lt7//5snriXSdJo5hlVcDkpERL1piiih0UXIz1RUcC4=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "58c85835512b0db938600b6fe13cc3e3dc4b364e", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1682596858, - "narHash": "sha256-Hf9XVpqaGqe/4oDGr30W8HlsWvJXtMsEPHDqHZA6dDg=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "fb58866e20af98779017134319b5663b8215d912", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "fenix": "fenix", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" - } - }, - "rust-analyzer-src": { - "flake": false, - "locked": { - "lastModified": 1685465261, - "narHash": "sha256-aJ2nUinUrNcFi+pb47bS5IIAeSiUEEPLJY8W4Q8Pcjk=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "d2b3caa5b5694125fad04a9699e919444439f6a2", - "type": "github" - }, - "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 60e2d54a25..0000000000 --- a/flake.nix +++ /dev/null @@ -1,86 +0,0 @@ -{ - description = "Firefish development flake"; - - inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; - # Flake Parts framework(https://flake.parts) - flake-parts.url = "github:hercules-ci/flake-parts"; - # Devenv for better devShells(https://devenv.sh) - devenv.url = "github:cachix/devenv"; - # Fenix for rust development - fenix.url = "github:nix-community/fenix"; - fenix.inputs.nixpkgs.follows = "nixpkgs"; - }; - outputs = inputs@{ flake-parts, ... }: - flake-parts.lib.mkFlake { inherit inputs; } { - imports = [ - inputs.devenv.flakeModule - ]; - - # Define the systems that this works on. Only tested with x66_64-linux, add more if you test and it works. - systems = [ - "x86_64-linux" - ]; - # Expose these attributes for every system defined above. - perSystem = { config, pkgs, ... }: { - # Devenv shells - devenv = { - shells = { - # The default shell, used by nix-direnv - default = { - name = "firefish-dev-shell"; - # Add additional packages to our environment - packages = [ - pkgs.nodePackages.pnpm - - pkgs.python3 - ]; - # No need to warn on a new version, we'll update as needed. - devenv.warnOnNewVersion = false; - # Enable typescript support - languages.typescript.enable = true; - # Enable javascript for NPM and PNPM - languages.javascript.enable = true; - languages.javascript.package = pkgs.nodejs_18; - # Enable stable Rust for the backend - languages.rust.enable = true; - languages.rust.version = "stable"; - processes = { - dev-server.exec = "pnpm run dev"; - }; - scripts = { - build.exec = "pnpm run build"; - clean.exec = "pnpm run clean"; - clear-state.exec = "rm -rf .devenv/state/redis .devenv/state/postgres"; - format.exec = "pnpm run format"; - install-deps.exec = "pnpm install"; - migrate.exec = "pnpm run migrate"; - prepare-config.exec = "cp .config/devenv.yml .config/default.yml"; - }; - services = { - postgres = { - enable = true; - package = pkgs.postgresql_12; - initialDatabases = [{ - name = "firefish"; - }]; - initialScript = '' - CREATE USER firefish WITH PASSWORD 'firefish'; - ALTER USER firefish WITH SUPERUSER; - GRANT ALL ON DATABASE firefish TO firefish; - ''; - listen_addresses = "127.0.0.1"; - port = 5432; - }; - redis = { - enable = true; - bind = "127.0.0.1"; - port = 6379; - }; - }; - }; - }; - }; - }; - }; -} diff --git a/locales/bg-BG.yml b/locales/bg-BG.yml new file mode 100644 index 0000000000..2ac83494ed --- /dev/null +++ b/locales/bg-BG.yml @@ -0,0 +1,869 @@ +_lang_: Български +cancel: Отказ +noNotes: Няма публикации +settings: Настройки +headlineFirefish: Децентрализирана социална медийна платформа с отворен код, която + е безплатна завинаги! 🚀 +notifications: Известия +forgotPassword: Забравена парола +uploading: Качване... +addInstance: Добавяне на сървър +favorite: Добавяне към отметките +delete: Изтриване +unpin: Откачане от профила +copyLink: Копиране на връзката +pin: Закачане в профила +deleted: Изтрито +deleteAndEditConfirm: Сигурни ли сте, че искате да изтриете тази публикация и да я + редактирате? Ще загубите всички реакции, подсилвания и отговори към нея. +copyUsername: Копиране на потребителското име +searchUser: Търсене на потребител +reply: Отговор +showMore: Покажи още +loadMore: Зареди още +followRequestAccepted: Заявка за последване приета +importAndExport: Импорт/Експорт на Данни +import: Импортиране +download: Изтегляне +export: Експортиране +files: Файлове +unblock: Отблокиране +_sensitiveMediaDetection: + setSensitiveFlagAutomatically: Маркиране като деликатно +searchWith: 'Търсене: {q}' +smtpUser: Потребителско име +notificationType: Тип известие +searchResult: Резултати от търсенето +searchByGoogle: Търсене +markAsReadAllNotifications: Маркиране на всички известия като прочетени +settingGuide: Препоръчителни настройки +smtpPass: Парола +newPasswordIs: Новата парола е "{password}" +members: Членове +help: Помощ +hide: Скриване +group: Група +groups: Групи +incorrectPassword: Грешна парола. +leaveGroup: Напускане на групата +numberOfColumn: Брой колони +passwordLessLogin: Вход без парола +newPasswordRetype: Повтори новата парола +saveAs: Запазване като... +resetPassword: Нулиране на паролата +saveConfirm: Запазване на промените? +inputNewFolderName: Въведи ново име на папка +upload: Качване +retypedNotMatch: Въвежданията не съвпадат. +_ago: + weeksAgo: преди {n}сед + secondsAgo: преди {n}сек + hoursAgo: преди {n}ч + minutesAgo: преди {n}мин + daysAgo: преди {n}д + monthsAgo: преди {n}мес + yearsAgo: преди {n}г + future: Бъдеще + justNow: Току-що +folderName: Име на папка +renameFile: Преименуване на файла +_widgets: + activity: Дейност + notifications: Известия + timeline: Инфопоток + clock: Часовник + trends: Актуални + photos: Снимки + unixClock: UNIX часовник + calendar: Календар + digitalClock: Дигитален часовник + button: Бутон + slideshow: Слайдшоу + _userList: + chooseList: Избор на списък +instanceSecurity: Сигурност на сървъра +uploadFolder: Папка по подразбиране за качвания +instanceInfo: Информация за сървъра +statistics: Статистика +fileName: Име на файл +selectFile: Избор на файл +editProfile: Редактиране на профила +instances: Сървъри +selectUser: Избор на потребител +createNew: Създаване на ново +blockThisInstance: Блокиране на този сървър +_profile: + metadata: Допълнителна информация + username: Потребителско име + name: Име + description: Биография + metadataContent: Съдържание + metadataLabel: Етикет + metadataEdit: Редактиране на допълнителната информация + changeAvatar: Промяна на профилната снимка +addAccount: Добавяне на акаунт +followRequestPending: Заявка за последване в изчакване +signinHistory: История на вписванията +or: Или +noUsers: Няма потребители +notes: Публикации +newNoteRecived: Има нови публикации +note: Публикуване +instanceFollowing: Последвани на сървъра +_filters: + followersOnly: Само последователи + notesAfter: Публикации след + fromDomain: От домейн + fromUser: От потребител + withFile: С файл + notesBefore: Публикации преди + followingOnly: Само последвани +_notification: + _types: + follow: Нови последователи + mention: Споменавания + reaction: Реакции + reply: Отговора + all: Всички + quote: Цитирания + pollEnded: Приключване на анкети + app: Известия от свързани приложения + renote: Подсилвания + pollVote: Гласувания в анкети + receiveFollowRequest: Получени заявки за следване + followRequestAccepted: Приети заявки за следване + groupInvited: Покани в групи + youGotReply: '{name} ти отговори' + fileUploaded: Файлът е качен успешно + youWereFollowed: те последва + _actions: + reply: Отговор + renote: Подсилвания + youGotQuote: '{name} те цитира' + youGotMention: '{name} те спомена' + youGotMessagingMessageFromUser: '{name} ти изпрати чат съобщение' +_channel: + notesCount: '{n} Публикации' + nameOnly: Само име + nameAndDescription: Име и описание + create: Създаване на канал +unfollow: Отследване +noLists: Нямаш никакви списъци +markAsReadAllUnreadNotes: Маркиране на всички публикации като прочетени +markAsReadAllTalkMessages: Маркиране на всички съобщения като прочетени +_time: + second: Секунди + hour: Часа + day: Дни + minute: Минути +create: Създаване +lists: Списъци +reportAbuseOf: Докладване на {name} +reporter: Докладчик +abuseReports: Доклади +logoImageUrl: URL на лого изображение +reportAbuse: Докладване +latestRequestReceivedAt: Последно получена заявка +location: Местоположение +keepOriginalUploading: Запазване на оригиналното изображение +renotesCount: Брой изпратени подсилвания +license: Лиценз +lastUsedDate: Последно използвано на +rename: Преименуване +customEmojis: Персонализирани емоджита +emoji: Емоджи +_aboutFirefish: + translation: Преведи Firefish + source: Програмен код + contributors: Основни сътрудници + allContributors: Всички сътрудници +translatedFrom: Преведено от {x} +i18nInfo: Firefish се превежда на различни езици от доброволци. Можете да помогнете + на адрес {link}. +image: Изображение +recipient: Получател(и) +notesAndReplies: Публикации и отговори +noSuchUser: Потребителят не е намерен +pinnedPages: Закачени страници +pinLimitExceeded: Не може да закачаш повече публикации +flagShowTimelineReplies: Показване на отговори в инфопотока +followersCount: Брой последователи +receivedReactionsCount: Брой получени реакции +federation: Федерация +today: Днес +yearX: '{year}' +registeredAt: Регистриран на +monthX: '{month}' +dayX: '{day}' +registration: Регистрация +popularUsers: Популярни потребители +details: Подробности +tenMinutes: 10 минути +oneDay: Един ден +file: Файл +oneHour: Един час +video: Видео +createNewClip: Създаване на нова подборка +clips: Подборки +active: Активен +menu: Меню +itsOff: Изключено +remindMeLater: Може би по-късно +removed: Успешно изтриване +deleteAllFiles: Изтриване на всички файлове +deletedNote: Изтрита публикация +deleteConfirm: Потвърждавате ли изтриването? +hasChildFilesOrFolders: Тъй като тази папка не е празна, тя не може да бъде изтрита. +nsfw: Деликатно +default: По подразбиране +_theme: + defaultValue: Стойност по подразбиране + keys: + mention: Споменаване + renote: Подсилване + link: Връзка + hashtag: Хаштаг + fg: Текст + color: Цвят + explore: Разглеждане на темите + description: Описание + manage: Управление на темите + install: Инсталиране на тема + code: Код на темата + builtinThemes: Вградени теми + func: Функции + key: Ключ + argument: Аргумент + installedThemes: Инсталирани теми + constant: Константа + addConstant: Добавяне на константа +_pages: + script: + blocks: + _dailyRannum: + arg1: Минимална стойност + arg2: Максимална стойност + _join: + arg1: Списъци + add: Добави + _rannum: + arg1: Минимална стойност + arg2: Максимална стойност + _seedRannum: + arg3: Максимална стойност + arg2: Минимална стойност + _strPick: + arg1: Текст + _if: + arg3: Иначе + arg2: Тогава + arg1: Ако + _randomPick: + arg1: Списък + fn: Функция + _strLen: + arg1: Текст + _strReplace: + arg1: Текст + _strReverse: + arg1: Текст + _stringToNumber: + arg1: Текст + text: Текст + _splitStrByLine: + arg1: Текст + _listLen: + arg1: Списък + _dailyRandomPick: + arg1: Списък + _seedRandomPick: + arg2: Списък + _pick: + arg1: Списък + categories: + value: Стойности + list: Списъци + fn: Функции + types: + string: Текст + array: Списък + blocks: + _textInput: + default: Стойност по подразбиране + text: Заглавие + _switch: + default: Стойност по подразбиране + text: Заглавие + _textareaInput: + default: Стойност по подразбиране + text: Заглавие + _numberInput: + default: Стойност по подразбиране + text: Заглавие + _radioButton: + default: Стойност по подразбиране + title: Заглавие + _if: + variable: Променлива + _counter: + text: Заглавие + inc: Стъпка + button: Бутон + if: Ако + image: Изображения + text: Текст + _post: + text: Съдържание + _button: + _action: + _dialog: + content: Съдържание + text: Заглавие + created: Страницата е създадена успешно + editPage: Редактиране на тази страница + editThisPage: Редактиране на тази страница + updated: Страницата е редактирана успешно + featured: Популярни + liked: Харесани страници + contentBlocks: Съдържание + contents: Съдържание + deleted: Страницата е изтрита успешно + newPage: Създаване на нова страница + like: Харесване + font: Шрифт + title: Заглавие + my: Моите страници + pageSetting: Настройки на страницата +_deck: + _columns: + notifications: Известия + mentions: Споменавания + tl: Инфопоток + direct: Директни съобщения + list: Списък + antenna: Антена + addColumn: Добавяне на колона +_mfm: + mention: Споменаване + search: Търсене + link: Връзка + hashtag: Хаштаг + url: URL адрес + font: Шрифт +_messaging: + groups: Групи + dms: Лични +apps: Приложения +introFirefish: Добре дошли! Firefish е децентрализирана социална медийна платформа + с отворен код, която е безплатна завинаги! 🚀 +monthAndDay: '{day}/{month}' +search: Търсене +searchPlaceholder: Търсене във Firefish +username: Потребителско име +password: Парола +fetchingAsApObject: Извличане от Федивселената +ok: Добре +gotIt: Разбрах! +noThankYou: Не, благодаря +enterUsername: Въведи потребителско име +renotedBy: Подсилено от {user} +noNotifications: Няма известия +instance: Сървър +basicSettings: Основни Настройки +otherSettings: Други Настройки +openInWindow: Отваряне в прозорец +profile: Профил +timeline: Инфопоток +noAccountDescription: Този потребител все още не е написал своята биография. +login: Вход +loggingIn: Вписване +logout: Изход +signup: Регистрация +save: Запазване +users: Потребители +addUser: Добавяне на потребител +favorites: Отметки +unfavorite: Премахване от отметките +favorited: Добавено към отметките. +alreadyFavorited: Вече е добавено към отметките. +cantFavorite: Неуспешно добавяне към отметките. +copyContent: Копиране на съдържанието +deleteAndEdit: Изтриване и редактиране +editNote: Редактиране на публикацията +edited: Редактирано на {date} {time} +addToList: Добавяне към списък +sendMessage: Изпращане на съобщение +jumpToPrevious: Премини към предишно +newer: по-ново +older: по-старо +showLess: Покажи по-малко +youGotNewFollower: те последва +receiveFollowRequest: Заявка за последване получена +mention: Споменаване +mentions: Споменавания +directNotes: Директни съобщения +cw: Предупреждение за съдържание +followers: Последователи +following: Последвани +followsYou: Следва те +createList: Създаване на списък +error: Грешка +manageLists: Управление на списъци +retry: Повторен опит +follow: Последване +followRequest: Заявка за последване +followRequests: Заявки за последване +defaultNoteVisibility: Видимост по подразбиране +unrenote: Отмяна на подсилването +renoted: Подсилено. +cantRenote: Тази публикация не може да бъде подсилена. +renote: Подсилване +enterEmoji: Въведи емоджи +sensitive: Деликатно +add: Добавяне +pinned: Закачено в профила +quote: Цитиране +pinnedNote: Закачена публикация +cantReRenote: Подсилване не може да бъде подсилено. +clickToShow: Щракни за показване +you: Ти +reaction: Реакции +removeReaction: Премахване на реакцията +enterFileName: Въведи име на файл +unmarkAsSensitive: Отмаркиране като деликатно +markAsSensitive: Маркиране като деликатно +block: Блокиране +emojis: Емоджита +addEmoji: Добавяне +emojiName: Име на емоджи +emojiUrl: URL адрес на емоджи +loginFailed: Неуспешно вписване +flagAsCat: Котка ли си? 😺 +flagSpeakAsCat: Говорене като котка +youHaveNoLists: Нямаш никакви списъци +selectInstance: Избор на сървър +annotation: Коментари +latestRequestSentAt: Последно изпратена заявка +stopActivityDelivery: Спиране на изпращането на дейности +version: Версия +clearCachedFiles: Изчистване на кеша +noInstances: Няма сървъри +federating: Федериране +defaultValueIs: 'По подразбиране: {value}' +noCustomEmojis: Няма емоджи +changePassword: Промяна на паролата +currentPassword: Текуща парола +instanceUsers: Потребители на този сървър +security: Сигурност +instanceFollowers: Последователи на сървъра +newPassword: Нова парола +more: Още! +remove: Изтриване +saved: Запазени +messaging: Чат +birthday: Рожден ден +images: Изображения +activity: Дейност +createFolder: Създаване на папка +renameFolder: Преименуване на тази папка +selectFolders: Избор на папки +selectFolder: Избор на папка +selectFiles: Избор на файлове +addFile: Добавяне на файл +inputNewFileName: Въведи ново име на файл +deleteFolder: Изтриване на тази папка +emptyFolder: Тази папка е празна +copyUrl: Копиране на URL адреса +pages: Страници +thisYear: Година +thisMonth: Месец +pinnedNotes: Закачени публикации +pinnedUsers: Закачени потребители +hcaptcha: hCaptcha +recaptcha: reCAPTCHA +name: Име +enableRecaptcha: Включване на reCAPTCHA +enableHcaptcha: Включване на hCaptcha +exploreUsersCount: Има {count} потребители +userList: Списъци +moderator: Модератор +moderation: Модерация +administrator: Администратор +lastUsed: Последно използвано +unregister: Отрегистрация +share: Споделяне +notFound: Не е намерено +inputMessageHere: Въведи съобщение тук +createGroup: Създаване на група +close: Затваряне +next: Следващо +title: Заглавие +messagingWithGroup: Групов чат +enable: Включване +retype: Въведи отново +noteOf: Публикация от {user} +quoteAttached: Цитат +newMessageExists: Има нови съобщения +noMessagesYet: Все още няма съобщения +language: Език +createAccount: Създаване на акаунт +existingAccount: Съществуващ акаунт +deleteAll: Изтриване на всички +enableAll: Включване на всички +disableAll: Изключване на всички +copy: Копиране +reporteeOrigin: Произход на докладвания +reporterOrigin: Произход на докладчика +clip: Подборка +unclip: Премахни от подборка +followingCount: Брой последвани акаунти +renotedCount: Брой получени подсилвания +notesCount: Брой публикации +repliesCount: Брой изпратени отговори +repliedCount: Брой получени отговори +sentReactionsCount: Брой изпратени реакции +yes: Да +no: Не +alwaysMarkSensitive: Маркиране като деликатно по подразбиране +noteFavoritesCount: Брой публикации с отметки +left: Ляво +nNotes: '{n} Публикации' +value: Стойност +createdAt: Създадено на +invalidValue: Невалидна стойност. +currentVersion: Настояща версия +latestVersion: Най-нова версия +typingUsers: '{users} пише' +user: Потребител +enabled: Включено +disabled: Изключено +whatIsNew: Показване на промените +translate: Превеждане +itsOn: Включено +oneWeek: Една седмица +audio: Звук +removeQuote: Премахване на цитата +_sfx: + notification: Известия + chat: Чат + antenna: Антени + note: Нова публикация +_permissions: + "read:favorites": Преглед на списъка ви с отметки + "write:favorites": Редактиране на списъка ви с отметки +_visibility: + followers: Последователи + specified: Директна + localOnly: Само местни + public: Публична + publicDescription: Публикацията ще бъде видима във всички публични инфопотоци + home: Скрита + localOnlyDescription: Не е видима за отдалечени потребители + specifiedDescription: Видима само за определени потребители + followersDescription: Видима само за последователите ти и споменатите потребители + homeDescription: Публикуване само в началния инфопоток +explore: Разглеждане +theme: Теми +wallpaper: Тапет +setWallpaper: Задаване на тапет +removeWallpaper: Премахване на тапета +themeForLightMode: Тема за използване в светъл режим +themeForDarkMode: Тема за използване в тъмен режим +light: Светла +dark: Тъмна +darkThemes: Тъмни теми +invitations: Покани +invitationCode: Код на поканата +checking: Проверка... +available: Свободно +unavailable: Не е свободно +tooShort: Твърде кратко +tooLong: Твърде дълго +weakPassword: Слаба парола +strongPassword: Силна парола +passwordMatched: Съвпада +passwordNotMatched: Не съвпада +signinWith: Вход с {x} +aboutX: Относно {x} +openInNewTab: Отваряне в нов раздел +_tutorial: + step2_1: Първо, моля, попълнете своя профил. + step2_2: Предоставянето на известна информация за това кой сте вие ще улесни другите + да разберат дали искат да видят вашите публикации или да ви следват. + title: Как се използва Firefish + step1_1: Добре дошли! + step5_1: Инфопотоци, инфопотоци навсякъде! + step3_1: Сега е време да последвате няколко хора! + step1_2: Нека да ви настроим. Ще бъдете готови за нула време! + step5_3: Началният {icon} инфопоток е мястото, където можете да видите публикации + от акаунтите, които следвате. + step6_1: И така, какво е това място? + step5_7: Глобалният {icon} инфопоток е мястото, където можете да видите публикации + от всеки друг свързан сървър. + step4_2: За първата си публикация някои хора обичат да правят публикация {introduction} + или просто „Здравей свят!“ + step5_2: Вашият сървър има активирани {timelines} различни инфопотоци. + step5_4: Местният {icon} инфопоток е мястото, където можете да видите публикации + от всички останали на този сървър. + step5_5: Социалният {icon} инфопоток е комбинация от Началния и Местния инфопоток. + step5_6: Препоръчаният {icon} инфопоток е мястото, където можете да видите публикации + от сървъри, препоръчани от администраторите. + step6_4: Сега отидете, изследвайте и се забавлявайте! + step6_3: Всеки сървър работи по различни начини и не всички сървъри работят с Firefish. + Този обаче го прави! Малко е сложно, но ще разберете за нула време. +openImageInNewTab: Отваряне на изображенията в нов раздел +showOnRemote: Отваряне на първообразната страница +lightThemes: Светли теми +syncDeviceDarkMode: Синхронизиране на тъмния режим с настройките на устройството +text: Текст +normalPassword: Средна парола +usernameInvalidFormat: Можете да използвате главни и малки букви, цифри и долни черти. +signinFailed: Неуспешно вписване. Въведените потребителско име или парола са неправилни. +signinRequired: Моля, регистрирайте се или се впишете, преди да продължите +start: Започване +confirm: Потвърждаване +failedToUpload: Неуспешно качване +_preferencesBackups: + cannotSave: Неуспешно запазване + cannotLoad: Неуспешно зареждане + saveNew: Запазване на ново резервно копие + inputName: Моля, въведи име за това резервно копие + deleteConfirm: Изтриване на резервното копие {name}? + loadFile: Зареждане от файл + save: Запазване на промените + apply: Прилагане към това устройство + list: Създадени резервни копия + saveConfirm: Запазване на резервното копие като {name}? + createdAt: 'Създадено на: {date} {time}' + updatedAt: 'Обновено на: {date} {time}' +editWidgetsExit: Готово +done: Готово +emailRequiredForSignup: Изискване на адрес на ел. поща за регистриране +preview: Преглед +privacy: Поверителност +about: Относно +aboutFirefish: Относно Firefish +author: Автор +software: Софтуер +category: Категория +renotes: Подсилвания +quotes: Цитирания +reactions: Реакции +attachCancel: Премахване на прикачен файл +mute: Заглушаване +unmute: Отмяна на заглушаването +selectAntenna: Избор на антена +selectList: Избор на списък +editWidgets: Редактиране на джаджите +flagAsCatDescription: Ще получиш котешки уши и ще говориш като котка! +host: Хост +perHour: За час +perDay: За ден +operations: Операции +mutedUsers: Заглушени потребители +imageUrl: URL адрес на изображение +announcements: Оповестявания +removeAreYouSure: Сигурни ли сте, че искате да премахнете "{x}"? +fromUrl: От URL адрес +manageGroups: Управление на групи +nUsersRead: прочетено от {n} +home: Начало +registeredDate: Присъединяване +avatar: Профилна снимка +watch: Наблюдаване +antennas: Антени +manageAntennas: Управление на антени +popularTags: Популярни тагове +cacheClear: Изчистване на кеша +groupName: Име на групата +local: Местни +total: Общо +remote: Отдалечени +accountSettings: Настройки на акаунта +showInPage: Показване в страницата +install: Инсталиране +uninstall: Деинсталиране +invisibleNote: Невидима публикация +poll: Анкета +useCw: Скриване на съдържание +smtpHost: Хост +preferencesBackups: Резервни копия +emailServer: Ел. пощенски сървър +overview: Обзор +reloadToApplySetting: Тази настройка ще се приложи само след презареждане на страницата. + Презареждане сега? +markAllAsRead: Маркиране на всички като прочетени +addDescription: Добавяне на описание +userInfo: Информация за потребителя +switchAccount: Превключване на акаунт +gallery: Галерия +priority: Приоритет +unread: Непрочетени +filter: Филтриране +manageAccounts: Управление на акаунти +deleteAccount: Изтриване на акаунта +fast: Бърза +remoteOnly: Само отдалечени +move: Преместване +navbar: Навигационна лента +moveTo: Преместване на текущия акаунт в нов акаунт +moveAccount: Преместване на акаунта! +_gallery: + my: Моята галерия + like: Харесване + liked: Харесани публикации +_registry: + keys: Ключове + key: Ключ + createKey: Създаване на ключ + domain: Домейн +_weekday: + tuesday: Вторник + wednesday: Сряда + thursday: Четвъртък + saturday: Събота + monday: Понеделник + friday: Петък + sunday: Неделя +_antennaSources: + users: Публикации от конкретни потребители + userGroup: Публикации от потребители в конкретна група + instances: Публикации от всички потребители на сървър + all: Всички публикации + homeTimeline: Публикации от последвани потребители + userList: Публикации от конкретен списък с потребители +_poll: + choiceN: Избор {n} + infinite: Никога + totalVotes: '{n} гласа общо' + votesCount: '{n} гласа' + expiration: Приключване на анкетата +_timelines: + local: Местни + home: Начало + global: Глобални + recommended: Препоръчани + social: Социални +_feeds: + copyFeed: Копиране на емисия + rss: RSS + atom: Atom + jsonFeed: JSON feed +general: Общи +metadata: Метаданни +disk: Диск +featured: Представени +yearsOld: на {age} години +reload: Опресняване +invites: Покани +blockedInstances: Блокирани сървъри +inMb: В мегабайти +unfollowConfirm: Сигурни ли сте, че искате да прекратите следването на {name}? +somethingHappened: Възникна грешка +pageLoadError: Възникна грешка при зареждането на страницата. +enterListName: Въведи име за списъка +shareWithNote: Споделяне чрез публикация +flagAsBot: Маркиране на този акаунт като автоматизиран +selectChannel: Избор на канал +all: Всичко +muteAndBlock: Заглушени и блокирани +blockedUsers: Блокирани потребители +noteDeleteConfirm: Сигурни ли сте, че искате да изтриете тази публикация? +hiddenTags: Скрити хаштагове +deleteAreYouSure: Сигурни ли сте, че искате да изтриете "{x}"? +startMessaging: Започване на нов чат +uploadFromUrl: Качване от URL адрес +instanceName: Име на сървъра +instanceDescription: Описание на сървъра +accept: Приемане +enableLocalTimeline: Включване на местния инфопоток +enableGlobalTimeline: Включване на глобалния инфопоток +removeMember: Премахване на член +isAdmin: Администратор +isModerator: Модератор +_menuDisplay: + hide: Скриване +_exportOrImport: + allNotes: Всички публикации +exploreFediverse: Разглеждане на Федивселената +recentlyUpdatedUsers: Последно активни потребители +uiLanguage: Език на потребителския интерфейс +dashboard: Табло +tags: Тагове +youHaveNoGroups: Нямаш групи +accessibility: Достъпност +email: Ел. поща +emailAddress: Адрес на ел. поща +addItem: Добавяне на елемент +visibility: Видимост +description: Описание +_relayStatus: + accepted: Прието +other: Други +channel: Канали +accountInfo: Информация за акаунта +send: Изпращане +clearCache: Изчистване на кеша +closeAccount: Затваряне на акаунта +onlineUsersCount: '{n} потребители на линия' +nUsers: '{n} Потребители' +developer: Разработчик +popularPosts: Популярни страници +info: Относно +recentPosts: Последни страници +offline: Извън линия +onlineStatus: Онлайн състояние +online: На линия +goBack: Назад +editCode: Редактиране на кода +publish: Публикувай +breakFollow: Премахване на последовател +learnMore: Научи повече +hashtags: Хаштагове +document: Документация +accounts: Акаунти +smartphone: Смартфон +isBot: Този акаунт е автоматизиран +size: Размер +tablet: Таблет +numberOfPageCache: Брой кеширани страници +localOnly: Само местни +beta: Бета +slow: Бавна +speed: Скорост +account: Акаунт +migration: Прехвърляне +moveToLabel: 'Акаунт, към който се местиш:' +withFiles: С прикачени файлове +renoteUnmute: Отмяна на заглушаването на подсилванията +selectWidget: Избор на джаджа +remoteUserCaution: Информацията от отдалечени потребители може да е непълна. +attachFile: Прикачване на файлове +unwatch: Спиране на наблюдаването +invite: Поканване +_wordMute: + mutedNotes: Заглушени публикации +_postForm: + _placeholders: + b: Какво се случва около теб? +recentlyDiscoveredUsers: Новооткрити потребители +recentlyRegisteredUsers: Новоприсъединени потребители +inviteToGroup: Поканване в група +nothing: Няма нищо за гледане тук +chooseEmoji: Избор на емоджи +switchUi: Оформление +previewNoteText: Показване на преглед +apply: Прилагане +selectAccount: Избор на акаунт +muteThread: Заглушаване на нишката +ffVisibility: Видимост на Последвани/Последователи +renoteMute: Заглушаване на подсилванията в инфопотоците +replyMute: Заглушаване на отговорите в инфопотоците +blockConfirm: Сигурни ли сте, че искате да блокирате този акаунт? +appearance: Облик +fontSize: Размер на шрифта +describeFile: Добавяне на описание +unblockConfirm: Сигурни ли сте, че искате да отблокирате този акаунт? +followConfirm: Сигурни ли сте, че искате да последвате {name}? +accountMoved: 'Потребителят се премести на нов акаунт:' +inputNewDescription: Въведете ново описание diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index a839bd8788..aea2d7f03c 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -15,10 +15,10 @@ ok: "ঠিক" gotIt: "বুঝেছি" cancel: "বাতিল" enterUsername: "ইউজারনেম লিখুন" -renotedBy: "{user} রিনোট করেছেন" -noNotes: "কোন নোট নেই" +renotedBy: "{user} দ্বারা বুস্ট করা হয়েছে" +noNotes: "No posts" noNotifications: "কোনো বিজ্ঞপ্তি নেই" -instance: "ইন্সট্যান্স" +instance: "সার্ভার" settings: "সেটিংস" basicSettings: "সাধারণ সেটিংস" otherSettings: "অন্যান্য সেটিংস" @@ -46,8 +46,8 @@ copyContent: "বিষয়বস্তু কপি করুন" copyLink: "লিঙ্ক কপি করুন" delete: "মুছুন" deleteAndEdit: "মুছুন এবং সম্পাদনা করুন" -deleteAndEditConfirm: "আপনি কি এই নোটটি মুছে এটি সম্পাদনা করার বিষয়ে নিশ্চিত? আপনি - এটির সমস্ত রিঅ্যাকশন, রিনোট এবং জবাব হারাবেন।" +deleteAndEditConfirm: "আপনি কি এই পোস্টটি মুছে ফেলার এবং এটি সম্পাদনা করার বিষয়ে + নিশ্চিত? আপনি এটির সমস্ত প্রতিক্রিয়া, বুস্ট এবং উত্তর হারাবেন।" addToList: "লিস্ট এ যোগ করুন" sendMessage: "একটি বার্তা পাঠান" copyUsername: "ব্যবহারকারীর নাম কপি করুন" @@ -61,18 +61,18 @@ receiveFollowRequest: "অনুসরণ করার জন্য অনুর followRequestAccepted: "অনুসরণ করার অনুরোধ গৃহীত হয়েছে" mention: "উল্লেখ" mentions: "উল্লেখসমূহ" -directNotes: "ডাইরেক্ট নোটগুলি" -importAndExport: "আমদানি এবং রপ্তানি" -import: "আমদানি করুণ" -export: "রপ্তানি" +directNotes: "প্রত্যক্ষ বার্তা" +importAndExport: "ডেটা ইমপোর্ট/এক্সপোর্ট" +import: "ইমপোর্ট করুণ" +export: "এক্সপোর্ট করুন" files: "ফাইলগুলি" download: "ডাউনলোড" driveFileDeleteConfirm: "আপনি কি নিশ্চিত যে আপনি \"{name}\" ডিলিট করতে চান? যে সকল - নোটের সাথে এই ফাইলটি সংযুক্ত সেগুলোও ডিলিট করা হবে।" + পোস্ট এর সাথে এই ফাইলটি সংযুক্ত সেগুলোও ডিলিট করা হবে।" unfollowConfirm: "{name} কে আনফলোও করার ব্যাপারে নিশ্চিত?" -exportRequested: "আপনার তথ্যসমূহ রপ্তানির জন্য অনুরোধ করেছেন। এতে কিছু সময় লাগতে পারে। - রপ্তানি সম্পন্ন হলে তা আপনার ড্রাইভে সংরক্ষিত হবে।" -importRequested: "আপনার তথ্যসমূহ আমদানির জন্য অনুরোধ করেছেন। এতে কিছু সময় লাগতে পারে। " +exportRequested: "আপনার তথ্যসমূহ এক্সপোর্ট জন্য অনুরোধ করেছেন। এতে কিছু সময় লাগতে + পারে। এক্সপোর্ট সম্পন্ন হলে তা আপনার ড্রাইভে সংরক্ষিত হবে।" +importRequested: "আপনার তথ্যসমূহ আমদানির জন্য অনুরোধ করেছেন। এতে কিছু সময় লাগতে পারে।" lists: "লিস্ট" noLists: "কোন লিস্ট নেই" note: "নোট" @@ -87,7 +87,7 @@ somethingHappened: "একটি ত্রুটি হয়েছে" retry: "আবার চেষ্টা করুন" pageLoadError: "পেজ লোড করা যায়নি" pageLoadErrorDescription: "এটি সাধারনত নেটওয়ার্কের সমস্যার বা ব্রাউজার ক্যাশের কারণে - ঘটে থাকে। ব্রাউজার এর ক্যাশ পরিষ্কার করুন এবং একটু পর আবার চেষ্টা করুন। " + ঘটে থাকে। ব্রাউজার এর ক্যাশ পরিষ্কার করুন এবং একটু পর আবার চেষ্টা করুন।" serverIsDead: "এই সার্ভার বর্তমানে সাড়া দিচ্ছে না। একটু পরে আবার চেষ্টা করুন।" youShouldUpgradeClient: "এই পেজ দেখার জন্য আপনার ব্রাউজার রিফ্রেশ করে ক্লায়েন্ট আপডেট করুন। " @@ -102,13 +102,13 @@ unfollow: "অনুসরণ বাতিল" followRequestPending: "অনুসরণ করার অনুরোধ বিচারাধীন" enterEmoji: "ইমোজি প্রবেশ করান" renote: "রিনোট" -unrenote: "রিনোট সরান " -renoted: "রিনোট করা হয়েছে" -cantRenote: "এই নোটটি রিনোট করা যাবে না।" -cantReRenote: "রিনোটকে রিনোট করা যাবে না।" -quote: "উদ্ধৃতি" -pinnedNote: "পিন করা নোট" -pinned: "পিন করা" +unrenote: "বুস্ট ফিরিয়ে নিন" +renoted: "বুস্ট করা হয়েছে।" +cantRenote: "এই পোস্টটি বুস্ট করা যাবে না।" +cantReRenote: "বুস্টকে বুস্ট করা যাবে না।" +quote: "উক্তি" +pinnedNote: "পিন করা পোস্ট" +pinned: "প্রোফাইলে পিন করুন" you: "আপনি" clickToShow: "দেখার জন্য ক্লিক করুন" sensitive: "সংবেদনশীল বিষয়বস্তু" @@ -1761,3 +1761,14 @@ _deck: list: "লিস্ট" mentions: "উল্লেখসমূহ" direct: "ডাইরেক্ট নোটগুলি" +removeReaction: আপনার প্রতিক্রিয়া সরান +addInstance: একটি সার্ভার যোগ করুন +deleted: মুছে ফেলা হয়েছে +editNote: পোস্ট এডিট করুন +edited: '{date} {time} এ সম্পাদিত' +searchPlaceholder: ফায়ারফিশে খুঁজুন +noThankYou: না, ধন্যবাদ +cw: সতর্কবার্তা +replies: উত্তর +quotes: উক্তি গুলো +reactions: প্রতিক্রিয়াগুলি diff --git a/locales/bul_BG.yml b/locales/bul_BG.yml deleted file mode 100644 index 7f04df7eeb..0000000000 --- a/locales/bul_BG.yml +++ /dev/null @@ -1,477 +0,0 @@ -_lang_: Български -cancel: Отмени -noNotes: Няма публикации -settings: Настройки -headlineFirefish: Децентрализирана социална медийна платформа с отворен код, която - е безплатна завинаги! 🚀 -notifications: Известия -forgotPassword: Забравена парола -uploading: Качване... -addInstance: Добави сървър -favorite: Добави в отметки -delete: Изтрий -unpin: Откачи от профила -copyLink: Копирай връзката -pin: Закачи в профила -deleted: Изтрито -deleteAndEditConfirm: Сигурни ли сте, че искате да изтриете тази публикация и да я - редактирате? Ще загубите всички реакции, подсилвания и отговори към нея. -copyUsername: Копирай потребителското име -searchUser: Търсене на потребител -reply: Отговори -showMore: Покажи още -loadMore: Зареди още -followRequestAccepted: Заявка за последване приета -importAndExport: Импорт/Експорт на Данни -import: Импортиране -download: Свали -export: Експортиране -files: Файлове -unblock: Отблокирай -_sensitiveMediaDetection: - setSensitiveFlagAutomatically: Маркиране като деликатно -searchWith: 'Търсене: {q}' -smtpUser: Потребителско име -notificationType: Тип известие -searchResult: Резултати от търсенето -searchByGoogle: Търсене -markAsReadAllNotifications: Маркирай всички известия като прочетени -settingGuide: Препоръчителни настройки -smtpPass: Парола -newPasswordIs: Новата парола е "{password}" -members: Членове -help: Помощ -hide: Скрий -group: Група -groups: Групи -incorrectPassword: Грешна парола. -leaveGroup: Напусни групата -numberOfColumn: Брой колони -passwordLessLogin: Вписване без парола -newPasswordRetype: Въведи отново парола -saveAs: Запази като... -resetPassword: Нулиране на парола -saveConfirm: Запазване на промените? -inputNewFolderName: Въведи ново име на папка -upload: Качване -retypedNotMatch: Въвежданията не съвпадат. -_ago: - weeksAgo: преди {n}с - secondsAgo: преди {n}сек - hoursAgo: преди {n}ч - minutesAgo: преди {n}мин - daysAgo: преди {n}д - monthsAgo: преди {n}м - yearsAgo: преди {n}г - future: Бъдеще - justNow: Точно сега -folderName: Име на папка -renameFile: Преименувай файл -_widgets: - activity: Дейност - notifications: Известия - timeline: Инфопоток -instanceSecurity: Сигурност на сървъра -uploadFolder: Папка по подразбиране за качвания -instanceInfo: Информация за сървъра -statistics: Статистика -fileName: Име на файл -selectFile: Избери файл -editProfile: Редактирай профил -instances: Сървъри -selectUser: Избери потребител -createNew: Създай ново -blockThisInstance: Блокирай този сървър -_profile: - metadata: Допълнителна информация - username: Потребителско име - name: Име - description: Биография - metadataContent: Съдържание -addAccount: Добави акаунт -followRequestPending: Заявка за последване в изчакване -signinHistory: История на вписванията -or: Или -noUsers: Няма потребители -notes: Публикации -newNoteRecived: Има нови публикации -note: Публикация -instanceFollowing: Последвани на сървъра -_filters: - followersOnly: Само последователи - notesAfter: Публикации след - fromDomain: От домейн - fromUser: От потребител - withFile: С файл - notesBefore: Публикации преди - followingOnly: Само последвани -_notification: - _types: - follow: Нови последователи - mention: Споменавания - reaction: Реакции -_channel: - notesCount: '{n} Публикации' -unfollow: Отследване -noLists: Нямаш никакви списъци -markAsReadAllUnreadNotes: Маркирай всички публикации като прочетени -markAsReadAllTalkMessages: Маркирай всички съобщения като прочетени -_time: - second: Секунди - hour: Часа - day: Дни - minute: Минути -create: Създай -lists: Списъци -reportAbuseOf: Докладвай {name} -reporter: Докладчик -abuseReports: Доклади -logoImageUrl: URL на лого изображение -reportAbuse: Доклад -latestRequestReceivedAt: Последно получена заявка -location: Местонахождение -keepOriginalUploading: Запази оригиналното изображение -renotesCount: Брой изпратени подсилвания -license: Лиценз -lastUsedDate: Последно използвано на -rename: Преименувай -customEmojis: Персонализирани емоджита -emoji: Емоджи -_aboutFirefish: - translation: Преведи Firefish -translatedFrom: Преведено от {x} -i18nInfo: Firefish се превежда на различни езици от доброволци. Можете да помогнете - на адрес {link}. -image: Изображение -recipient: Получател(и) -notesAndReplies: Публикации и отговори -noSuchUser: Потребителят не е намерен -pinnedPages: Закачени страници -pinLimitExceeded: Не може да закачаш повече публикации -flagShowTimelineReplies: Показване на отговори в инфопотока -followersCount: Брой последователи -receivedReactionsCount: Брой получени реакции -federation: Федерация -today: Днес -yearX: '{year}' -registeredAt: Регистриран на -monthX: '{month}' -dayX: '{day}' -registration: Регистрация -popularUsers: Популярни потребители -details: Детайли -tenMinutes: 10 минути -oneDay: Един ден -file: Файл -oneHour: Един час -video: Видео -createNewClip: Създай нова подборка -clips: Подборки -active: Активен -menu: Меню -itsOff: Изключено -remindMeLater: Може би по-късно -removed: Успешно изтриване -deleteAllFiles: Изтрий всички файлове -deletedNote: Изтрита публикация -deleteConfirm: Потвърждавате ли изтриването? -hasChildFilesOrFolders: Тъй като тази папка не е празна, тя не може да бъде изтрита. -nsfw: Деликатно съдържание -default: По подразбиране -_theme: - defaultValue: Стойност по подразбиране - keys: - mention: Споменаване - renote: Подсили - color: Цвят - explore: Разгледай темите -_pages: - script: - blocks: - _dailyRannum: - arg1: Минимална стойност - arg2: Максимална стойност - _join: - arg1: Списъци - add: Добави - _rannum: - arg1: Минимална стойност - arg2: Максимална стойност - _seedRannum: - arg3: Максимална стойност - arg2: Минимална стойност - categories: - value: Стойности - list: Списъци - blocks: - _textInput: - default: Стойност по подразбиране - _switch: - default: Стойност по подразбиране - _textareaInput: - default: Стойност по подразбиране - _numberInput: - default: Стойност по подразбиране - _radioButton: - default: Стойност по подразбиране -_deck: - _columns: - notifications: Известия - mentions: Споменавания - tl: Инфопоток - direct: Директни съобщения -_mfm: - mention: Споменаване - search: Търсене -_messaging: - groups: Групи -apps: Приложения -introFirefish: Добре дошли! Firefish е децентрализирана социална медийна платформа - с отворен код, която е безплатна завинаги! 🚀 -monthAndDay: '{day}/{month}' -search: Търсене -searchPlaceholder: Търсене в Firefish -username: Потребителско име -password: Парола -fetchingAsApObject: Извличане от федивърса -ok: Добре -gotIt: Разбрах! -noThankYou: Не, благодаря -enterUsername: Въведи потребителско име -renotedBy: Подсилено от {user} -noNotifications: Няма известия -instance: Сървър -basicSettings: Основни Настройки -otherSettings: Други Настройки -openInWindow: Отвори в прозорец -profile: Профил -timeline: Инфопоток -noAccountDescription: Този потребител все още не е написал своята биография. -login: Впиши се -loggingIn: Вписване -logout: Отпиши се -signup: Регистрирай се -save: Запазване -users: Потребители -addUser: Добави потребител -favorites: Отметки -unfavorite: Премахни от отметки -favorited: Добавено в отметки. -alreadyFavorited: Вече е добавено в отметки. -cantFavorite: Неуспешно добавяне в отметки. -copyContent: Копирай съдържанието -deleteAndEdit: Изтрий и редактирай -editNote: Редактирай публикация -edited: Редактирано на {date} {time} -addToList: Добави в списък -sendMessage: Изпрати съобщение -jumpToPrevious: Премини към предишно -newer: по-ново -older: по-старо -showLess: Затвори -youGotNewFollower: те последва -receiveFollowRequest: Заявка за последване получена -mention: Споменаване -mentions: Споменавания -directNotes: Директни съобщения -cw: Предупреждение за съдържание -followers: Последователи -following: Последвани -followsYou: Следва те -createList: Създай списък -error: Грешка -manageLists: Управление на списъци -retry: Повторен опит -follow: Следване -followRequest: Заявка за последване -followRequests: Заявки за последване -defaultNoteVisibility: Видимост по подразбиране -unrenote: Върни обратно подсилване -renoted: Подсилено. -cantRenote: Тази публикация не може да бъде подсилена. -renote: Подсили -enterEmoji: Въведи емоджи -sensitive: Деликатно съдържание -add: Добави -pinned: Закачено в профила -quote: Цитирай -pinnedNote: Закачена публикация -cantReRenote: Подсилване не може да бъде подсилено. -clickToShow: Кликни за показване -you: Ти -reaction: Реакции -removeReaction: Премахни реакцията си -enterFileName: Въведи име на файл -unmarkAsSensitive: Отмаркирай като деликатно -markAsSensitive: Маркирай като деликатно -block: Блокирай -emojis: Емоджита -addEmoji: Добави -emojiName: Име на емоджи -emojiUrl: URL на емоджи -loginFailed: Неуспешно вписване -flagAsCat: Котка ли си? 😺 -flagSpeakAsCat: Говори като котка -youHaveNoLists: Нямаш никакви списъци -selectInstance: Избери сървър -annotation: Коментари -latestRequestSentAt: Последно изпратена заявка -stopActivityDelivery: Спри изпращането на дейности -version: Версия -clearCachedFiles: Изтрий кеш -noInstances: Няма сървъри -federating: Федериране -defaultValueIs: 'По подразбиране: {value}' -noCustomEmojis: Няма емоджи -changePassword: Промени парола -currentPassword: Настояща парола -instanceUsers: Потребители на този сървър -security: Сигурност -instanceFollowers: Последователи на сървъра -newPassword: Нова парола -more: Още! -remove: Изтрий -saved: Запазено -messaging: Чат -birthday: Рожден ден -images: Изображения -activity: Дейност -createFolder: Създай папка -renameFolder: Преименувай тази папка -selectFolders: Избери папки -selectFolder: Избери папка -selectFiles: Избери файлове -addFile: Добави на файл -inputNewFileName: Въведи ново име на файл -deleteFolder: Изтрий тази папка -emptyFolder: Тази папка е празна -copyUrl: Копирай URL -pages: Страници -thisYear: Година -thisMonth: Месец -pinnedNotes: Закачени публикации -pinnedUsers: Закачени потребители -hcaptcha: hCaptcha -recaptcha: reCAPTCHA -name: Име -enableRecaptcha: Включване на reCAPTCHA -enableHcaptcha: Включване на hCaptcha -exploreUsersCount: Има {count} потребители -userList: Списъци -moderator: Модератор -moderation: Модерация -administrator: Администратор -lastUsed: Последно използвано -unregister: Отрегистрация -share: Сподели -notFound: Не е намерено -inputMessageHere: Въведи съобщение тук -createGroup: Създай група -close: Затвори -next: Следващо -title: Заглавие -messagingWithGroup: Групов чат -enable: Включи -retype: Въведи отново -noteOf: Публикация от {user} -quoteAttached: Цитат -newMessageExists: Има нови съобщения -noMessagesYet: Все още няма съобщения -language: Език -createAccount: Създай акаунт -existingAccount: Съществуващ акаунт -deleteAll: Изтрий всички -enableAll: Включване на всички -disableAll: Изключване на всички -copy: Копирай -reporteeOrigin: Произход на докладвания -reporterOrigin: Произход на докладчика -clip: Подборка -unclip: Премахни от подборка -followingCount: Брой последвани акаунти -renotedCount: Брой получени подсилвания -notesCount: Брой публикации -repliesCount: Брой изпратени отговори -repliedCount: Брой получени отговори -sentReactionsCount: Брой изпратени реакции -yes: Да -no: Не -alwaysMarkSensitive: Маркирай като деликатно по подразбиране -noteFavoritesCount: Брой публикации с отметки -left: Ляво -nNotes: '{n} Публикации' -value: Стойност -createdAt: Създадено на -invalidValue: Невалидна стойност. -currentVersion: Настояща версия -latestVersion: Най-нова версия -typingUsers: '{users} пише' -user: Потребител -enabled: Включено -disabled: Изключено -whatIsNew: Покажи промените -translate: Преведи -itsOn: Включено -oneWeek: Една седмица -audio: Звук -removeQuote: Премахни цитат -_sfx: - notification: Известия -_permissions: - "read:favorites": Виж списъка си с отметки - "write:favorites": Редактирай списъка си с отметки -_visibility: - followers: Последователи -explore: Разглеждане -theme: Теми -wallpaper: Тапет -setWallpaper: Задай тапет -removeWallpaper: Премахни тапет -themeForLightMode: Тема за използване в светъл режим -themeForDarkMode: Тема за използване в тъмен режим -light: Светло -dark: Тъмно -darkThemes: Тъмни теми -invitations: Покани -invitationCode: Код на поканата -checking: Проверка... -available: Свободно -unavailable: Не е свободно -tooShort: Твърде кратко -tooLong: Твърде дълго -weakPassword: Слаба парола -strongPassword: Силна парола -passwordMatched: Съвпада -passwordNotMatched: Не съвпада -signinWith: Вписване с {x} -aboutX: Относно {x} -openInNewTab: Отвори в нов раздел -_tutorial: - step2_1: Първо, моля, попълнете своя профил. - step2_2: Предоставянето на известна информация за това кой сте вие ще улесни другите - да разберат дали искат да видят вашите публикации или да ви следват. - title: Как се използва Firefish - step1_1: Добре дошли! - step5_1: Инфопотоци, инфопотоци навсякъде! - step3_1: Сега е време да последвате няколко хора! - step1_2: Нека да ви настроим. Ще бъдете готови за нула време! -openImageInNewTab: Отваряй изображенията в нов раздел -showOnRemote: Отвори оригиналната страница -lightThemes: Светли теми -syncDeviceDarkMode: Синхронизиране на тъмния режим с настройките на устройството -text: Текст -normalPassword: Средна парола -usernameInvalidFormat: Можете да използвате главни и малки букви, цифри и долни черти. -signinFailed: Неуспешно вписване. Въведените потребителско име или парола са неправилни. -signinRequired: Моля, регистрирайте се или се впишете, преди да продължите -start: Започни -confirm: Потвърди -failedToUpload: Неуспешно качване -_preferencesBackups: - cannotSave: Неуспешно запазване - cannotLoad: Неуспешно зареждане -editWidgetsExit: Готово -done: Готово -emailRequiredForSignup: Изискване за адрес на е-поща за регистриране -preview: Преглед -privacy: Поверителност diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 7b66b3bd98..506f3fd652 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -323,8 +323,8 @@ _2fa: securityKeyInfo: A més de l'autenticació d'empremta digital o PIN, també podeu configurar l'autenticació mitjançant claus de seguretat de maquinari compatibles amb FIDO2 per protegir encara més el vostre compte. - step4: A partir d'ara, qualsevol intent d'inici de sessió futur demanarà aquest - token d'inici de sessió. + step4: A partir d'ara, qualsevol intent d'inici de sessió futur demanarà aquesta + clau d'inici de sessió. registerSecurityKey: Registrar una clau de seguretat o d'accés step1: En primer lloc, instal·la una aplicació d'autenticació (com ara {a} o {b}) al dispositiu. @@ -1002,8 +1002,8 @@ enableEmojiReactions: Activa reaccions amb emojis blockThisInstance: Bloqueja aquest servidor registration: Registra't showEmojisInReactionNotifications: Mostrar els emojis a les notificacions de les reaccions -renoteMute: Silencia els impulsos -renoteUnmute: Treu el silenci als impulsos +renoteMute: Silencia els impulsos a les línies de temps +renoteUnmute: Treu el silenci als impulsos a les línies de temps cacheRemoteFiles: Desa fitxers remots a la memòria cau federation: Federació registeredAt: Registrat a @@ -1831,11 +1831,6 @@ pushNotificationAlreadySubscribed: Les notificacions push ja estan activades pushNotificationNotSupported: El vostre navegador o servidor no admet notificacions push license: Llicència -indexPosts: Índex de publicacions -indexFrom: Índex a partir de l'ID de Publicacions -indexFromDescription: Deixeu en blanc per indexar cada publicació -indexNotice: Ara indexant. Això probablement trigarà una estona, si us plau, no reinicieu - el servidor durant almenys una hora. _instanceTicker: none: No mostrar mai remote: Mostra per a usuaris remots @@ -2036,6 +2031,7 @@ _wordMute: de temps. muteLangs: Llenguatges silenciats muteLangsDescription: Separar amb espais o línies no es per una condició OR. + mutePatterns: Patrons per silenciar _auth: shareAccessAsk: Estàs segur que vols autoritzar aquesta aplicació per accedir al teu compte? @@ -2071,10 +2067,8 @@ _relayStatus: deleted: Eliminat editNote: Edita la publicació edited: 'Editat el {date} {time}' -findOtherInstance: Cercar un altre servidor -signupsDisabled: Actualment, les inscripcions en aquest servidor estan desactivades, - però sempre podeu registrar-vos en un altre servidor. Si teniu un codi d'invitació - per a aquest servidor, introduïu-lo a continuació. +signupsDisabled: Actualment, les inscripcions en aquest servidor estan desactivades. + Si teniu un codi d'invitació per a aquest servidor, introduïu-lo a continuació. userSaysSomethingReasonQuote: '{name} ha citat una publicació que conté {reason}' userSaysSomethingReasonReply: '{name} ha respost a una publicació que conté {reason}' userSaysSomethingReasonRenote: '{name} ha impulsat una publicació que conté {reason}' @@ -2238,3 +2232,56 @@ privateDescription: Visible només per a tu useCdn: Aconsegueix els recursos des de el CDN useCdnDescription: Carrega alguns dels recursos estàtics com ara Twemoji des de el CDN de JSDeliver en comptes de carregar-los des d'aquest servidor Firefish. +releaseToReload: Deixa anar per actualitzar +reloading: Actualitzant +enableTimelineStreaming: Actualitza les línies de temps automàticament +enablePullToRefresh: Activa "Baixa per actualitzar" +pullDownToReload: Baixa per actualitzar +pullToRefreshThreshold: Distancia de baixada per actualitzar +searchWords: Paraules / ID o adreça a URL a buscar +noSentFollowRequests: No tens cap sol·licitud de seguiment enviada +sentFollowRequests: Enviar sol·licituds de seguiment +replyMute: Silencia les respostes a les línies de temps +replyUnmute: Treu el silencia de les respostes a les línies de temps +searchWordsDescription: "Per cercar publicacions, escriu el terme a buscar. Separa + les paraules amb espais per fer condicions AND o escriules dins de cometes per fer + una cerca OR.\nPer exemple, 'dia nit' trobarà publicacions que continguin tan 'dia' + com 'nit', i 'dia OR nit' trobara publicacions que continguin tant 'dia' com 'nit' + (o ambdues).\nPots combinar condicions AND/OR per exemple '(dia OR nit) endormiscar'.\n + Si vols cercar per una seqüencia de paraules (per exemple una frase) has d'escriure-les + entre cometes dobles, per no fer una cerca amb condicionant AND: \"Avui he aprés\"\ + \n \nSi vols anar a una pàgina d'usuari o publicació en concret, escriu la adreça + URL o la ID en aquest camp i fes clic al botó 'Trobar'. Fent clic a 'Cercar' trobarà + publicacions que, literalment , continguin la ID/adreça URL." +searchPostsWithFiles: Només publicacions amb fitxers +searchCwAndAlt: Inclou avisos de contingut i arxius amb descripcions +searchUsers: Publicat per (opcional) +searchRange: Publicat dintre de (opcional) +publishTimelines: Publica línies de temps per visitants +toPost: Publicar +publishTimelinesDescription: Si està activat, les línies de temps Global i Local es + mostraran a {url} fins i tot sense estar registrat. +noAltTextWarning: Alguns fitxers adjunts no tenen una descripció. T'has s oblidat + d'escriure-les? +showNoAltTextWarning: Mostra un avís si públiques un fitxer sense descripció +toReply: Respon +toQuote: Cita +toEdit: Edita +searchUsersDescription: "Per buscar publicacions concretes d'un usuari/servidor, escriu + la ID (@usuari@exemple.com, o @usuari per un usuari local) o nom del domini (exemple.com).\n + \nSi escrius 'me' (sense cometes), totes les teves publicacions (incloent-hi publicacions + sense llistar, només per a seguidors i secretes) es buscaran.\n\nSi escrius 'local' + (sense cometes), el resultat serà filtrat per mostrar només publicacions d'aquest + servidor." +messagingUnencryptedInfo: Els xats a Firefish no són encriptats d'extrem a extrem. + No comparteixis dades sensibles fent servir Firefish. +searchRangeDescription: "Si vols filtrar per un període de temps, has de fer servir + aquest format: 20220615-20231031\n\nSi no escrius l'any (per exemple 0105-0106 o + 20231105-0110), serà interpretat com l'any en curs.\n\nInclús pots ometre la data + de començament o de finalització. Per exemple, -0102 filtrarà els resultats per + mostrar només publicacions fetes abans del 2 de gener d'aquest any, i 20231026- + filtrarà els resultats per mostrar publicacions fetes després del 26 d'octubre del + 2023." +moderationNote: Nota de moderació +ipFirstAcknowledged: Data en què es va veure la adreça IP per primera vegada +driveCapacityOverride: Capacitat del disc esgotada diff --git a/locales/da-DK.yml b/locales/da-DK.yml index f948215e9d..04f0f8c5df 100644 --- a/locales/da-DK.yml +++ b/locales/da-DK.yml @@ -157,8 +157,8 @@ pageLoadErrorDescription: Dette er normalt på grund af netværksproblemer eller browser's cache. Prøv at ryd cachen og så gentage efter et styk tid. serverIsDead: Serveren svarer ikke. Vær sød at vente et styk tid og prøv igen. editWidgetsExit: Færdig -headlineFirefish: En åben-kildekode, decentraliseret social-media platform som er frit - forevigt! 🚀 +headlineFirefish: En åben-kildekode, decentraliseret social-media platform som er + frit forevigt! 🚀 introFirefish: Velkommen! Firefish er en åbent-kildekode, decentraliseret social-media platform som er frit forevigt!🚀 enableEmojiReactions: Aktivere emoji reaktioner diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 53024bf845..df6e57ba5f 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -1500,9 +1500,6 @@ _widgets: chooseList: Wählen Sie eine Liste aus userList: Benutzerliste serverInfo: Server-Infos - meiliStatus: Server-Status - meiliSize: Indexgröße - meiliIndexCount: Indexierte Beiträge _cw: hide: "Verbergen" show: "Inhalt anzeigen" @@ -2027,7 +2024,6 @@ moveAccountDescription: 'Dieser Vorgang kann nicht rückgängig gemacht werden! sie vor dem Umzug dieses Nutzerkontos sicher, dass Sie einen Namen für Ihr neues Nutzerkonto eingerichtet haben. Bitte geben sie die Bezeichnung des neuen Nutzerkontos wie folgt ein: @name@server.xyz' -findOtherInstance: Einen anderen Server finden sendPushNotificationReadMessage: Löschung der Push-Benachrichtigungen sobald die entsprechenden Benachrichtigungen oder Nachrichten gelesen wurden signupsDisabled: Derzeit sind keine Anmeldungen auf diesem Server möglich! Anmeldungen @@ -2083,7 +2079,6 @@ preventAiLearning: KI gestütztes bot-scraping unterdrücken preventAiLearningDescription: Fordern Sie KI-Sprachmodelle von Drittanbietern auf, die von Ihnen hochgeladenen Inhalte, wie z. B. Beiträge und Bilder, nicht zu untersuchen. license: Lizenz -indexPosts: Gelistete Beiträge migrationConfirm: "Sind Sie absolut sicher, dass Sie Ihr Nutzerkonto zu diesem {account} umziehen möchten? Sobald Sie dies bestätigt haben, kann dies nicht mehr rückgängig gemacht werden und Ihr Nutzerkonto kann nicht mehr von ihnen genutzt werden.\nStellen @@ -2111,9 +2106,6 @@ _experiments: kann es zu Verlangsamungen beim Laden während des Imports kommen. noGraze: Bitte deaktivieren Sie die Browsererweiterung "Graze for Mastodon", da sie die Funktion von Firefish stört. -indexFrom: Indexieren ab Beitragskennung aufwärts -indexNotice: Wird jetzt indexiert. Dies wird wahrscheinlich eine Weile dauern, bitte - starten Sie Ihren Server für mindestens eine Stunde nicht neu. customKaTeXMacroDescription: "Richten Sie Makros ein, um mathematische Ausdrücke einfach zu schreiben! Die Notation entspricht den LaTeX-Befehlsdefinitionen und wird als \\newcommand{\\name}{content} oder \\newcommand{\\name}[number of arguments]{content} @@ -2132,7 +2124,6 @@ expandOnNoteClick: Beitrag bei Klick öffnen image: Bild video: Video audio: Audio -indexFromDescription: Leer lassen, um jeden Beitrag zu indexieren _filters: fromUser: Von Benutzer notesAfter: Beiträge nach @@ -2227,3 +2218,4 @@ renotes: Boosts quotes: Zitate moreUrlsDescription: "Die Seiten, welche angepinnt werde sollen, im Hilfe-Menü in der unteren linken Ecke in folgender Notation angeben:\n\"Anzeigename\": https://example.com/" +toQuote: Zitat diff --git a/locales/en-US.yml b/locales/en-US.yml index 0c40a340fb..f5b597e3c9 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -59,6 +59,7 @@ copyUsername: "Copy username" searchUser: "Search for a user" reply: "Reply" replies: "Replies" +toReply: "Reply" jumpToPrevious: "Jump to previous" loadMore: "Load more" showMore: "Show more" @@ -89,6 +90,7 @@ listsDesc: "Lists let you create timelines with specified users. They can be acc noLists: "You don't have any lists" note: "Post" notes: "Posts" +toPost: "Post" following: "Following" followers: "Followers" followsYou: "Follows you" @@ -121,6 +123,7 @@ cantRenote: "This post can't be boosted." cantReRenote: "A boost can't be boosted." quote: "Quote" quotes: "Quotes" +toQuote: "Quote" pinnedNote: "Pinned post" pinned: "Pin to profile" you: "You" @@ -174,8 +177,8 @@ cacheRemoteFilesDescription: "When this setting is disabled, remote files are lo flagAsBot: "Mark this account as automated" flagAsBotDescription: "Enable this option if this account is controlled by a program. If enabled, it will act as a flag for other developers to prevent endless interaction - chains with other automated accounts and adjust Firefish's internal systems to treat this - account as an automated account." + chains with other automated accounts and adjust Firefish's internal systems to treat + this account as an automated account." flagAsCat: "Are you a cat? 😺" flagAsCatDescription: "You'll get cat ears and speak like a cat!" flagSpeakAsCat: "Speak as a cat" @@ -459,7 +462,7 @@ securityKeyName: "Key name" registerSecurityKey: "Register a security key" lastUsed: "Last used" unregister: "Unregister" -passwordLessLogin: "Password-less login" +passwordLessLogin: "Password-less sign in" resetPassword: "Reset password" newPasswordIs: "The new password is \"{password}\"" reduceUiAnimation: "Reduce UI animations" @@ -524,7 +527,7 @@ disableDrawer: "Don't use drawer-style menus" youHaveNoGroups: "You have no groups" joinOrCreateGroup: "Get invited to a group or create your own." noHistory: "No history available" -signinHistory: "Login history" +signinHistory: "Sign in history" disableAnimatedMfm: "Disable MFM with animation" doing: "Processing..." category: "Category" @@ -671,6 +674,7 @@ pluginTokenRequestedDescription: "This plugin will be able to use the permission set here." notificationType: "Notification type" edit: "Edit" +toEdit: "Edit" emailServer: "Email server" enableEmail: "Enable email distribution" emailConfigInfo: "Used to confirm your email during sign-up or if you forget your @@ -713,9 +717,9 @@ useGlobalSetting: "Use global settings" useGlobalSettingDesc: "If turned on, your account's notification settings will be used. If turned off, individual configurations can be made." other: "Other" -regenerateLoginToken: "Regenerate login token" -regenerateLoginTokenDescription: "Regenerates the token used internally during login. - Normally this action is not necessary. If regenerated, all devices will be logged +regenerateLoginToken: "Regenerate sign in token" +regenerateLoginTokenDescription: "Regenerates the token used internally during sign + in. Normally this action is not necessary. If regenerated, all devices will be logged out." setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces." fileIdOrUrl: "File ID or URL" @@ -997,7 +1001,7 @@ check: "Check" driveCapOverrideLabel: "Change the drive capacity for this user" driveCapOverrideCaption: "Reset the capacity to default by inputting a value of 0 or lower." -requireAdminForView: "You must log in with an administrator account to view this." +requireAdminForView: "You must sign in with an administrator account to view this." isSystemAccount: "This account is created and automatically operated by the system. Please do not moderate, edit, delete, or otherwise tamper with this account, or it may break your server." @@ -1007,7 +1011,7 @@ document: "Documentation" numberOfPageCache: "Number of cached pages" numberOfPageCacheDescription: "Increasing this number will improve convenience for users but cause more server load as well as more memory to be used." -logoutConfirm: "Really log out?" +logoutConfirm: "Really sign out?" lastActiveDate: "Last used at" statusbar: "Status bar" pleaseSelect: "Select an option" @@ -1092,11 +1096,6 @@ migrationConfirm: "Are you absolutely sure you want to migrate your account to { as the account you're moving from." defaultReaction: "Default emoji reaction for outgoing and incoming posts" license: "License" -indexPosts: "Index Posts" -indexFrom: "Index from Post ID onwards" -indexFromDescription: "Leave blank to index every post" -indexNotice: "Now indexing. This will probably take a while, please don't restart - your server for at least an hour." customKaTeXMacro: "Custom KaTeX macros" customKaTeXMacroDescription: "Set up macros to write mathematical expressions easily! The notation conforms to the LaTeX command definitions and is written as \\newcommand{\\ @@ -1109,12 +1108,13 @@ customKaTeXMacroDescription: "Set up macros to write mathematical expressions ea advanced syntax, such as conditional branching, cannot be used here." enableCustomKaTeXMacro: "Enable custom KaTeX macros" noteId: "Post ID" -signupsDisabled: "Signups on this server are currently disabled, but you can always - sign up at another server! If you have an invitation code for this server, please - enter it below." -findOtherInstance: "Find another server" +signupsDisabled: "Signups on this server are currently disabled. If you have an invitation + code for this server, please enter it below." apps: "Apps" sendModMail: "Send Moderation Notice" +moderationNote: "Moderation Note" +ipFirstAcknowledged: "The date of the first acquisition of the IP address" +driveCapacityOverride: "Drive Capacity Override" preventAiLearning: "Prevent AI bot scraping" preventAiLearningDescription: "Request third-party AI language models not to study content you upload, such as posts and images." @@ -1162,7 +1162,8 @@ vibrate: "Play vibrations" openServerInfo: "Show server information by clicking the server ticker on a post" iconSet: "Icon set" useCdn: "Get assets from CDN" -useCdnDescription: "Load some static assets like Twemoji from the JSDelivr CDN instead of this Firefish server." +useCdnDescription: "Load some static assets like Twemoji from the JSDelivr CDN instead + of this Firefish server." suggested: "Suggested" noLanguage: "No language" showPreviewByDefault: "Show preview in posting form by default" @@ -1173,19 +1174,55 @@ replaceChatButtonWithAccountButton: "Replace chat button with account switch but replaceWidgetsButtonWithReloadButton: "Replace widgets button with reload button" searchEngine: "Search engine used in search bar MFM" postSearch: "Post search on this server" -showBigPostButton: "Show a huge post button on the posting form" +showBigPostButton: "Show a huge post button on the posting form" emojiModPerm: "Custom emoji management permission" -emojiModPermDescription: "Add: Allow this user to add new custom emojis and to set tag/category/license to newly added custom emojis.\nAdd and Edit: \"Add\" Permission + Allow this user to edit the name/category/tag/license of the existing custom emojis.\nAllow All: \"Add and Edit\" Permission + Allow this user to delete existing custom emojis." +emojiModPermDescription: "Add: Allow this user to add new custom emojis and to set + tag/category/license to newly added custom emojis.\nAdd and Edit: \"Add\" Permission + + Allow this user to edit the name/category/tag/license of the existing custom emojis.\n + Allow All: \"Add and Edit\" Permission + Allow this user to delete existing custom + emojis." private: "Private" privateDescription: "Make visible for you only" makePrivate: "Make private" -makePrivateConfirm: "This operation will send a deletion request to remote servers and change the visibility to private. Proceed?" +makePrivateConfirm: "This operation will send a deletion request to remote servers + and change the visibility to private. Proceed?" enablePullToRefresh: "Enable \"Pull down to refresh\"" pullToRefreshThreshold: "Pull distance for reloading" pullDownToReload: "Pull down to reload" releaseToReload: "Release to reload" reloading: "Reloading" enableTimelineStreaming: "Update timelines automatically" +searchWords: "Words to search / ID or URL to lookup" +searchWordsDescription: "Enter the search term here to search for posts. Separate words + with a space for an AND search, or 'OR' (without quotes) between words for an OR + search.\nFor example, 'morning night' will find posts that contain both 'morning' + and 'night', and 'morning OR night' will find posts that contain either 'morning' + or 'night' (or both).\nYou can also combine AND/OR conditions like '(morning OR + night) sleepy'.\nIf you want to search for a sequence of words (e.g., a sentence), you + must put it in double quotes, not to make it an AND search: \"Today I learned\"\n\n + If you want to go to a specific user page or post page, enter + the ID or URL in this field and click the 'Lookup' button. Clicking 'Search' will + search for posts that literally contain the ID/URL." +searchUsers: "Posted by (optional)" +searchUsersDescription: "To search for posts by a specific user/server, enter the + ID (@user@example.com, or @user for a local user) or domain name (example.com).\n + \nIf you enter 'me' (without quotes), all of your posts (including unlisted, followers-only, + direct, and secret posts) will be searched.\n\nIf you enter 'local' (without quotes), + the results will be filtered to include only posts from this server." +searchRange: "Posted within (optional)" +searchRangeDescription: "If you want to filter the time period, enter it in this format: + 20220615-20231031\n\nIf you leave out the year (like 0105-0106 or 20231105-0110), + it's interpreted as the current year.\n\nYou can also omit either the start or end + date. For example, -0102 will filter the search results to show only posts made + before 2 January this year, and 20231026- will filter the results to show only posts + made after 26 October 2023." +searchPostsWithFiles: "Only posts with files" +searchCwAndAlt: "Include content warnings and file descriptions" +publishTimelines: "Publish timelines for visitors" +publishTimelinesDescription: "If enabled, the Local and Global timelines will be shown + on {url} even when signed out." +noAltTextWarning: "Some attached file(s) have no description. Did you forget to write?" +showNoAltTextWarning: "Show a warning if you attempt to post files without a description" _emojiModPerm: unauthorized: "None" @@ -1426,6 +1463,7 @@ _menuDisplay: hide: "Hide" _wordMute: muteWords: "Muted words" + mutePatterns: "Muted patterns" muteLangs: "Muted Languages" muteWordsDescription: "Separate with spaces for an AND condition or with line breaks for an OR condition." @@ -1594,7 +1632,7 @@ _2fa: step2Url: "You can also enter this URL if you're using a desktop program:" step3Title: "Enter an authentication code" step3: "Enter the token provided by your app to finish setup." - step4: "From now on, any future login attempts will ask for such a login token." + step4: "From now on, any future sign in attempts will ask for such a token." securityKeyNotSupported: "Your browser does not support security keys." securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup authentication via hardware security keys that support FIDO2 to further secure @@ -1690,9 +1728,6 @@ _widgets: serverInfo: "Server Info" _userList: chooseList: "Select a list" - meiliStatus: "Server Status" - meiliSize: "Index size" - meiliIndexCount: "Indexed posts" _cw: hide: "Hide" @@ -2188,4 +2223,7 @@ _iconSets: fill: "Filled" duotone: "Duotone" moreUrls: "Pinned pages" -moreUrlsDescription: "Enter the pages you want to pin to the help menu in the lower left corner using this notation:\n\"Display name\": https://example.com/" +moreUrlsDescription: "Enter the pages you want to pin to the help menu in the lower + left corner using this notation:\n\"Display name\": https://example.com/" +messagingUnencryptedInfo: "Chats on Firefish are not end-to-end encrypted. Don't share + any sensitive infomation over Firefish." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 328e53a10b..b0a7059f9d 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -1474,9 +1474,6 @@ _widgets: _userList: chooseList: Seleccione una lista serverInfo: Información del servidor - meiliStatus: Estado del servidor - meiliSize: Tamaño del índice - meiliIndexCount: Publicaciones indizadas _cw: hide: "Ocultar" show: "Ver más" @@ -1988,7 +1985,6 @@ deleted: Eliminado edited: 'Editado a las {date} {time}' editNote: Editar publicación silenceThisInstance: Silenciar este servidor -findOtherInstance: Buscar otro servidor userSaysSomethingReasonRenote: '{name} impulsó una publicación que contiene {reason]' enableRecommendedTimeline: Habilitar línea de tiempo "Recomendado" searchPlaceholder: Buscar en Firefish @@ -2123,13 +2119,10 @@ moveFromDescription: 'Esto pondrá un alias en tu cuenta antigua para así poder ingresa la etiqueta de la cuenta con el formato siguiente: @persona@servidor.tld' defaultReaction: Emoji por defecto para reaccionar a las publicaciones entrantes y salientes -indexFromDescription: Deja en blanco para indizar todas las publicaciones deletePasskeys: Borrar claves de paso deletePasskeysConfirm: Esto borrará irreversiblemente todas las claves de paso y de seguridad en esta cuenta, ¿Proceder? inputNotMatch: Las entradas no coinciden -indexFrom: Indizar desde la ID de la publicación en adelante -indexPosts: Indizar publicaciones isModerator: Moderador isAdmin: Administrador isPatron: Mecenas de Firefish @@ -2139,8 +2132,6 @@ migrationConfirm: "¿Estás absolutamente seguro de que quieres migrar a tu cuen {account}? Una vez hecho esto, no podrás revertir el cambio, ni tampoco usar tu cuenta normalmente.\nTambién, asegúrate de que has configurado ésta cuenta como la cuenta desde la cual estás migrando." -indexNotice: Indizando ahora. Esto puede llevar bastante tiempo, por favor, no reinicies - el servidor por lo menos hasta dentro de una hora. customKaTeXMacro: Macros KaTeX personalizadas customKaTeXMacroDescription: '¡Configura macros para escribir expresiones matemáticas fácilmente! La notación es conforme la las definiciones de comandos LaTeX y puede diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 0b1043790c..ae612fd478 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -76,7 +76,7 @@ importRequested: "Vous avez initié une importation. Cela pourrait prendre un pe temps." lists: "Listes" noLists: "Vous n'avez aucune liste" -note: "Publication" +note: "Publier" notes: "Publications" following: "Abonnements" followers: "Abonné·e·s" @@ -666,7 +666,7 @@ useGlobalSettingDesc: "S'il est activé, les paramètres de notification de votr other: "Autre" regenerateLoginToken: "Régénérer le jeton de connexion" regenerateLoginTokenDescription: "Générer un nouveau jeton d'authentification. Cette - opération ne devrait pas être nécessaire ; lors de la génération d'un nouveau jeton, + opération ne devrait pas être nécessaire ; lors de la génération d'un nouveau jeton, tous les appareils seront déconnectés." setMultipleBySeparatingWithSpace: "Vous pouvez en définir plusieurs, en les séparant par des espaces." @@ -1152,6 +1152,7 @@ _wordMute: muteLangs: Langues filtrées muteLangsDescription: Séparer avec des espaces ou des retours à la ligne pour une condition OU (OR). + mutePatterns: Patrons masqués _instanceMute: instanceMuteDescription2: "Séparer avec des sauts de lignes" title: "Masque les publications provenant des serveurs listés." @@ -1400,10 +1401,7 @@ _widgets: _userList: chooseList: Sélectionner une liste unixClock: Horloge UNIX - meiliIndexCount: Publications indexées serverInfo: Info serveur - meiliStatus: État du serveur - meiliSize: Taille de l'index instanceCloud: Nuage de serveurs rssTicker: Bandeau RSS _cw: @@ -2002,7 +2000,7 @@ forwardReportIsAnonymous: À la place de votre compte, un compte système anonym affiché comme rapporteur au serveur distant. noThankYou: Non merci addInstance: Ajouter un serveur -renoteMute: Masquer les boosts +renoteMute: Masquer les boosts dans vos fils d'actualité flagSpeakAsCat: Parler comme un chat flagSpeakAsCatDescription: Vos messages seront « nyanifiés » en mode chat hiddenTags: Hashtags cachés @@ -2034,13 +2032,13 @@ updateAvailable: Une mise à jour peut être disponible ! accountMoved: "L'utilisateur·rice a migré vers un nouveau compte :" enableEmojiReactions: Activer les réactions par émojis showEmojisInReactionNotifications: Montrer les émojis dans les notifications de réactions -renoteUnmute: Ne plus masquer les boosts +renoteUnmute: Ne plus masquer les boosts dans vos fils d'actualité selectInstance: Choisir un serveur noInstances: Il n'y a aucun serveur showLocalPosts: 'Montrer les notes locales dans :' homeTimeline: Timeline d'Accueil socialTimeline: Timeline Sociale -requireAdminForView: Vous avez besoin d'un compte d'administration pour voir cela. +requireAdminForView: Vous avez besoin d'un compte d'administration pour voir ceci. isSystemAccount: Ce compte est créé et géré automatiquement par le système. Veuillez ne pas modérer, éditer, supprimer ou altérer d'une autre manière ce compte, ou cela risque de perturber votre serveur. @@ -2061,9 +2059,6 @@ moveToLabel: 'Compte vers lequel vous migrez :' moveFrom: Migrer vers ce compte depuis un ancien compte defaultReaction: Émoji de réaction par défaut pour les publications entrantes et sortantes license: Licence -indexPosts: Indexer les publications -indexNotice: Indexation en cours. Cela prendra certainement du temps, veuillez ne - pas redémarrer votre serveur pour au moins une heure. customKaTeXMacro: Macros KaTeX personnalisées enableCustomKaTeXMacro: Activer les macros KaTeX personnalisées noteId: ID des publications @@ -2095,11 +2090,9 @@ _experiments: de leurs anciens comptes Firefish, Misskey, Mastodon, Akkoma et Pleroma. Cela peut entraîner des ralentissements lors du chargement si votre file d'attente est congestionnée. -findOtherInstance: Trouver un autre serveur userSaysSomethingReasonQuote: '{name} a cité une publication contenant {reason}' -signupsDisabled: Les inscriptions sur ce serveur sont actuellement désactivés, mais - vous pouvez toujours vous inscrire sur un autre serveur ! Si vous avez un code d'invitation - pour ce serveur, entrez-le ci-dessous s'il vous plait. +signupsDisabled: Les inscriptions sur ce serveur sont actuellement désactivés. Si + vous avez un code d'invitation pour ce serveur, saisissez-le ci-dessous. apps: Applications userSaysSomethingReasonReply: '{noms} a répondu à une publication contenant {raison}' defaultValueIs: 'défaut : {valeur}' @@ -2110,7 +2103,6 @@ expandOnNoteClick: Ouvrir la publications en cliquant preventAiLearning: Empêcher le récupération de données par des IA listsDesc: Les listes vous laissent créer des fils personnalisés avec des utilisateur·rice·s spécifié·e·s. Elles sont accessibles depuis la page des fils. -indexFromDescription: Laisser vide pour indexer toutes les publications _feeds: jsonFeed: flux JSON atom: Atom @@ -2120,7 +2112,6 @@ alt: ALT swipeOnMobile: Permettre le balayage entre les pages expandOnNoteClickDesc: Si désactivé, vous pourrez toujours ouvrir les publications dans le menu du clic droit et en cliquant sur l'horodatage. -indexFrom: Indexer à partir de l'ID des publications older: ancien newer: récent accessibility: Accessibilité @@ -2268,3 +2259,56 @@ makePrivateConfirm: Cette opération enverra une demande de suppression aux serv useCdn: Obtenir des actifs à partir d'un réseau de diffusion de contenu useCdnDescription: Obtenir des actifs, tels que Twemoji, à partir du réseau de diffusion de contenu « JSDelivr » au lieu de ce serveur. +sentFollowRequests: Demandes d'abonnement envoyées +enablePullToRefresh: Activer « Dérouler pour actualiser » +reloading: Rechargement en cours +pullToRefreshThreshold: Distance de traction pour le rechargement +pullDownToReload: Tirer pour actualiser +releaseToReload: Relâcher pour actualiser +searchWords: Mot(s), ID ou URL à rechercher +searchUsers: Publier par (faculatif) +replyMute: Masquer les réponses dans vos fils d'actualité +replyUnmute: Ne plus masquer les réponses dans vos fils d'actualité +noSentFollowRequests: Vous n'avez envoyé aucune demande d'abonnement +enableTimelineStreaming: Actualiser les fils d'actualité automatiquement +searchRange: Publier entre (faculatif) +searchCwAndAlt: Inclure les avertissements de contenu et les descriptions de fichiers +searchPostsWithFiles: Publications uniquement avec fichiers +publishTimelines: Publier les fils d'actualité pour les visiteurs +publishTimelinesDescription: Si cette option est activée, les fils Local et Global + sera affichée sur {url} même en cas de déconnexion. +searchWordsDescription: "Pour rechercher des publications, saisissez le terme de recherche. + Des mots séparés avec un espace pour une recherche ET, ou « OR » (sans citations) + entre des mots pour une recherche OU.\nPar exemple, « matin nuit » trouvera des + publications contenant à la fois « matin » et « nuit », et « matin ou nuit » trouveront + des messages qui contiennent soit « matin » ou « nuit » (ou les deux).\nVous pouvez + également combiner des conditions ET/OU comme « (matin OR nuit) ensommeillé ».\n + \nSi vous souhaitez accéder à une page d'utilisateur ou à une page d'affichage spécifique, + saisissez l'ID ou l'URL dans ce champ et cliquez sur le bouton « Rechercher ». Cliquez + sur « Rechercher » recherchera des messages qui contiennent littéralement l'ID/URL." +searchUsersDescription: "Pour rechercher des messages par un utilisateur/serveur spécifique, + saisissez l'ID (@utilisateur@exemple.com, ou @utilisateur pour un utilisateur local) + ou le nom de domaine (exemple.com).\n\nSi vous saisissez « me » (sans guillemets), + tous vos messages (y compris les messages non-listés, abonnés-seulement, directs + et secrets) seront recherchés.\n\nSi vous saisissez « local » (sans guillemets), + les résultats seront filtrés pour inclure seulement des messages de ce serveur." +searchRangeDescription: "Si vous voulez filtrer par période de temps, saisissez-la + dans ce format : 20220615-20231031\n\nSi vous omettez l'année (comme le 0105-0106 + ou le 20231105-0110), elle est interprétée comme l'année en cours.\n\nVous pouvez + également omettre le début ou la fin de la date. Par exemple, -0102 filtrera les + résultats de recherche pour afficher seulement les messages effectués avant le 2 + janvier de cette année, et 20231026- filtrera les résultats pour afficher seulement + les messages effectués après le 26 octobre 2023." +toReply: Répondre +toPost: Publier +toQuote: Citer +toEdit: Modifier +messagingUnencryptedInfo: Les conversations sur Firefish ne sont pas cryptées. Ne + partagez aucune information sensible sur Firefish. +moderationNote: Note de modération +driveCapacityOverride: Limite de stockage personalisée +ipFirstAcknowledged: La date de la première acquisition de l'adresse IP +noAltTextWarning: Certains fichiers joints n'ont aucune description. Avez-vous oublié + de l'écrire ? +showNoAltTextWarning: Afficher un avertissement si vous essayez de publier des fichiers + sans description diff --git a/locales/hu.yml b/locales/hu.yml new file mode 100644 index 0000000000..3cb27fba29 --- /dev/null +++ b/locales/hu.yml @@ -0,0 +1 @@ +_lang_: "Magyar nyelv" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index ee902f2be3..a3f6a68f2a 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -415,7 +415,7 @@ securityKeyName: "Nama kunci" registerSecurityKey: "Daftarkan kunci keamanan" lastUsed: "Terakhir digunakan" unregister: "Batalkan pendaftaran" -passwordLessLogin: "Setel login tanpa kata sandi" +passwordLessLogin: "Masuk tanpa kata sandi" resetPassword: "Atur ulang kata sandi" newPasswordIs: "Kata sandi baru adalah \"{password}\"" reduceUiAnimation: "Kurangi animasi antarmuka" @@ -655,10 +655,10 @@ useGlobalSetting: "Gunakan setelan global" useGlobalSettingDesc: "Jika dinyalakan, setelan pemberitahuan akun kamu akan digunakan. Jika dimatikan, konfigurasi secara individu dapat dibuat." other: "Lainnya" -regenerateLoginToken: "Perbarui token login" +regenerateLoginToken: "Perbarui token masuk" regenerateLoginTokenDescription: "Perbarui token yang digunakan secara internal saat - login. Normalnya aksi ini tidak diperlukan. Jika diperbarui, semua perangkat akan - dilogout." + masuk ke akun. Normalnya aksi ini tidak diperlukan. Jika diperbarui, semua perangkat + akan dikeluarkan dari akun." setMultipleBySeparatingWithSpace: "Kamu dapat menyetel banyak dengan memisahkannya menggunakan spasi." fileIdOrUrl: "File-ID atau URL" @@ -1138,6 +1138,7 @@ _wordMute: dari timeline. muteLangs: Bahasa yang dibisukan muteLangsDescription: Pisahkan dengan spasi atau jeda baris untuk kondisi ATAU. + mutePatterns: Pola yang dibisukan _instanceMute: instanceMuteDescription: "Pengaturan ini akan membisukan postingan/pembagian apa saja dari server yang terdaftar, termasuk pengguna yang membalas pengguna lain @@ -1295,8 +1296,8 @@ _2fa: step2Url: "Di aplikasi desktop, masukkan URL berikut:" step3: "Masukkan token yang telah disediakan oleh aplikasimu untuk menyelesaikan pemasangan." - step4: "Mulai sekarang, upaya login apapun akan meminta token login dari aplikasi - otentikasi kamu." + step4: "Mulai sekarang, upaya pemasukan akun apa pun akan meminta token masuk dari + aplikasi autentikasi kamu." securityKeyInfo: "Kamu dapat memasang otentikasi WebAuthN untuk mengamankan proses login lebih lanjut dengan tidak hanya perangkat keras kunci keamanan yang mendukung FIDO2, namun juga sidik jari atau otentikasi PIN pada perangkatmu." @@ -1390,14 +1391,11 @@ _widgets: aiscript: "Konsol AiScript" aichan: "Ai" rssTicker: Telegraf RSS - meiliIndexCount: Postingan yang terindeks userList: Daftar Pengguna instanceCloud: Server Awan unixClock: Jam UNIX - meiliSize: Ukuran indeks _userList: chooseList: Pilih daftar - meiliStatus: Status Server serverInfo: Info Server _cw: hide: "Sembunyikan" @@ -1884,8 +1882,8 @@ listsDesc: Daftar mengizinkanmu membuat linimasa berisi pengguna spesifik. Itu d diakses dari halaman linimasa. enableEmojiReactions: Aktifkan reaksi emoji showEmojisInReactionNotifications: Tampilkan emoji dalam notifikasi reaksi -renoteMute: Bisukan postingan ulang -renoteUnmute: Bunyikan postingan ulang +renoteMute: Bisukan postingan ulang dalam lini masa +renoteUnmute: Bunyikan postingan ulang dalam lini masa antennasDesc: "Antena menampilkan postingan baru yang cocok dengan kriteriamu!\n Itu dapat diakses dari halaman linimasa." antennaInstancesDescription: Daftarkan satu host server per baris @@ -1984,17 +1982,14 @@ speed: Kecepatan slow: Pelan remoteOnly: Jarak jauh saja moveFrom: Dari akun lama pindahkan ke akun ini -indexNotice: Sedang mengindeks. Ini memerlukan beberapa waktu, mohon jangan mulai - ulang server setidaknya satu jam. sendPushNotificationReadMessage: Hapus pemberitahuan dorong saat pemberitahuan atau pesan relevan sudah dibaca moveAccountDescription: Proses ini permanen. Pastikan kamu sudah mengatur alias dari akun ini ke akun barumu sebelum pindah. Silakan masukkan tag akun dengan format seperti @orang@server.com sendModMail: Kirim Pemberitahuan Moderasi -signupsDisabled: Pendaftaran ke server ini nonaktif, tapi kamu dapat selalu mendaftar - ke server lain! Jika kamu memiliki kode undangan server ini, harap masukkan di bawah - ini. +signupsDisabled: Pendaftaran ke server ini nonaktifkam. Jika kamu memiliki kode undangan + server ini, harap masukkan di bawah ini. enableCustomKaTeXMacro: Aktifkan makro KaTeX khusus isBot: Akun ini akun otomatis customMOTD: MOTD khusus (pesan layar percik) @@ -2010,9 +2005,7 @@ showAds: Tampilkan spanduk komunitas enterSendsMessage: Tekan Enter pada Pesan untuk mengirim pesan (matikan dengan Ctrl + Enter) showAdminUpdates: Indikasi versi Firefish baru tersedia (hanya admin) -indexFrom: Indeks dari Post ID berikutnya noteId: ID Postingan -findOtherInstance: Cari server lain caption: Deskripsi itomatis splash: Layar Percik migration: Migrasi @@ -2022,7 +2015,6 @@ moveFromDescription: Ini akan mengatur alias akun lamamu jadi kamu dapat pindah akun tersebut ke akun sekarang. Lakukan ini SEBELUM memindahkan akun lama. Silakan masukkan tag akun dengan format seperti @orang@server.com defaultReaction: Reaksi emoji bawaan untuk postingan keluar dan masuk -indexPosts: Indeks Postingan preventAiLearning: Cegah scraping bot AI customKaTeXMacro: Makro KaTeX khusus sendPushNotificationReadMessageCaption: Pemberitahuan yang berisi teks "{emptyPushNotificationMessage}" @@ -2052,7 +2044,6 @@ migrationConfirm: "Kamu sangat yakin ingin memindahkan akunmu ke {account}? Seka lagi secara normal. \nDan juga, harap pastikan kamu sudah mengatur akun sekarang sebagai akun yang dipindahkan." license: Lisensi -indexFromDescription: Kosongkan untuk mengindeks setiap postingan noGraze: Harap nonaktifkan ekstensi peramban "Graze for Mastodon", karena akan menganggu Firefish. silencedWarning: Halaman ini tampil karena pengguna ini datang dari server yang dibisukan @@ -2193,7 +2184,7 @@ emojiModPerm: Perizinan pengelolaan emoji kustom emojiModPermDescription: "Tambah: Perbolehkan pengguna ini untuk menambahkan emoji kustom baru dan menetapkan tag/kategori/lisensi untuk semua emoji kustom yang telah ditambahkan.\nTambah dan Sunting: Perizinan \"Tambah\" + Perbolehkan pengguna ini - untuk menyunting nama/kategori/tag/lisensi emoji kustom yang sudah ada.\nPerbolehkan + untuk menyunting nama/kategori/tag/lisensi emoji kustom yang sudah ada.\n Perbolehkan Semua: Perizinan \"Tambah dan Sunting\" + Perbolehkan pengguna ini untuk menghapus semua emoji kustom yang sudah ada." private: Privat @@ -2221,3 +2212,56 @@ showPreviewByDefault: Tampilkan pratinjau dalam formulir kiriman secara bawaan useCdn: Dapatkan aset dari CDN useCdnDescription: Muat aset statis seperti Twemoji dari CDN JSDelivr daripada server Firefish ini. +sentFollowRequests: Permintaan mengikuti terkirim +replyUnmute: Suarakan balasan dalam lini masa +noSentFollowRequests: Kamu belum punya permintaan mengikuti +enablePullToRefresh: Aktifkan "Tarik ke bawah untuk memuat ulang" +pullDownToReload: Tarik ke bawah untuk memuat ulang +enableTimelineStreaming: Perbarui lini masa secara otomatis +searchWords: Kata-kata untuk dicari / ID atau URL untuk dicari +searchUsers: Dikirim oleh (opsional) +searchCwAndAlt: Termasuk peringatan konten dan deskripsi berkas +searchPostsWithFiles: Hanya kiriman dengan berkas +publishTimelines: Terbitkan lini masa untuk pengunjung +publishTimelinesDescription: Jika diaktifkan, lini masa Lokal dan Global akan ditampilkan + di {url} bahkan ketika keluar dari akun. +searchWordsDescription: "Untuk mencari kiriman, masukkan istilah pencarian. Pisahkan + kata dengan spasi untuk pencarian AND (dan), atau 'OR' ('atau', tanpa tanda kutip) + di antara kata-kata untuk pencarian OR.\nMisalnya, 'pagi malam' akan menemukan postingan + yang mengandung 'pagi' dan 'malam', dan 'pagi OR malam' akan menemukan postingan + yang mengandung 'pagi' atau 'malam' (atau keduanya).\nAnda juga dapat menggabungkan + kondisi AND/OR seperti '(pagi OR malam) mengantuk'.\n\nJika kamu ingin membuka halaman + pengguna atau halaman postingan tertentu, masukkan ID atau URL pada kolom ini dan + klik tombol 'Cari'. Mengklik 'Cari' akan mencari postingan yang secara harfiah mengandung + ID/URL." +pullToRefreshThreshold: Jarak penarikan untuk memuat ulang +releaseToReload: Lepaskan untuk memuat ulang +reloading: Memuat ulang +replyMute: Bisukan balasan dalam lini masa +searchRange: Dikirim dalam (opsional) +searchUsersDescription: "Untuk mencari kiriman oleh pengguna/server tertentu, masukkan + ID (@pengguna@contoh.id, atau @pengguna untuk pengguna lokal) atau nama domain (contoh.id)\n + \nJika kamu memasukkan 'me' ('aku', tanpa tanda kutip), semua kirimanmu (termasuk + kiriman yang tidak terdaftar, khusus pengikut, langsung, dan rahasia) akan dicari.\n + \nJika Anda memasukkan 'local' (tanpa tanda kutip), hasilnya akan disaring untuk + menyertakan hanya kiriman dari server ini." +searchRangeDescription: "Jika kamu ingin memfilter periode waktu, masukkan dalam format + ini: 20220615-20231031\n\nJika kamu menghilangkan tahun (seperti 0105-0106 atau + 20231105-0110), maka akan ditafsirkan sebagai tahun saat ini.\n\nKamu juga bisa + menghilangkan tanggal awal atau akhir. Sebagai contoh, -0102 akan memfilter hasil + pencarian untuk menampilkan hanya kiriman yang dibuat sebelum tanggal 2 Januari + tahun ini, dan 20231026- akan memfilter hasil pencarian untuk menampilkan hanya + kiriman yang dibuat setelah tanggal 26 Oktober 2023." +toPost: Kirim +toQuote: Kutip +noAltTextWarning: Beberapa berkas yang dilampirkan tidak memiliki deskripsi. Lupa + menulis deskripsinya? +toEdit: Sunting +showNoAltTextWarning: Tampilkan peringatan jika kamu mencoba mengirim berkas tanpa + deskripsi +toReply: Balas +messagingUnencryptedInfo: Percakapan di Firefish tidak terenkripsi secara ujung ke + ujung. Jangan bagikan informasi sensitif apa pun melalui Firefish. +moderationNote: Catatan Moderasi +driveCapacityOverride: Penimpaan Kapasitas Drive +ipFirstAcknowledged: Tanggal akuisisi pertama dari alamat IP diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 7c3f130928..f12b2ade4a 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1324,9 +1324,6 @@ _widgets: instanceCloud: Cloud del server unixClock: Orologio UNIX serverInfo: Informazioni sul server - meiliIndexCount: Post indicizzati - meiliStatus: Stato del server - meiliSize: Dimensione indice userList: Elenco utenti _cw: hide: "Nascondi" @@ -1838,13 +1835,10 @@ customSplashIconsDescription: Elenco degli URL di icone personalizzate da mostra le immagini siano su un URL statico, preferibilmente di dimensioni 192x192. swipeOnDesktop: Permetti lo swipe su desktop simile alla versione mobile logoImageUrl: URL del logo -indexFrom: Indicizza dal post ID customKaTeXMacro: Macro KaTeX personalizzate -indexPosts: Crea indice dei post signupsDisabled: Le iscrizioni su questo server al momento non sono possibili, ma puoi sempre iscriverti su un altro server! Se invece hai un codice di invito per questo server, inseriscilo qua sotto. -findOtherInstance: Scegli un altro server apps: App expandOnNoteClick: Apri i post con un click userSaysSomethingReasonReply: '{name} ha risposto a un post che contiene {reason}' @@ -1919,9 +1913,6 @@ lastActiveDate: Ultimo utilizzo enterSendsMessage: Premi "Invio" nei messaggi per inviare (altrimenti è "Ctrl + Invio") customMOTD: Messaggi di caricamento personalizzati (splash screen) replayTutorial: Ripeti il tutorial -indexFromDescription: Lascia vuoto per indicizzare tutti i post -indexNotice: Creazione indice in corso. Sarà necessario del tempo, fai attenzione - a non riavviare il server per almeno un'ora. enableCustomKaTeXMacro: Abilita le macro KaTeX personalizzate preventAiLearningDescription: Richiedi ai bot di intelligenza artificiale di terze parti di non studiare e acquisire il contenuto che carichi, come post e immagini. @@ -2029,8 +2020,8 @@ requireAdminForView: Devi avere un account amministratore per vedere questo cont jumpToPrevious: Vai al precedente flagShowTimelineReplies: Mostra le risposte nella timeline cw: Content warning -renoteMute: Silenzia i boost -renoteUnmute: Non silenziare i boost +renoteMute: Silenzia i boost nelle timeline +renoteUnmute: Non silenziare i boost nelle timeline enableEmojiReactions: Abilita le reazioni con emoji preferencesBackups: Backup delle preferenze adminCustomCssWarn: Questa impostazione dovrebbe essere usata solo se ne comprendi @@ -2181,8 +2172,9 @@ showPreviewByDefault: Mostra sempre l'anteprima del messaggio replaceWidgetsButtonWithReloadButton: Sostituisci il bottone dei widget con quello di reload squareCatAvatars: Mostra avatar quadrati per gli account di gatti -searchEngine: Motore della barra di ricerca MFM -hideFollowButtons: Nascondi i bottoni di follow se in posizioni cliccabili per errore +searchEngine: Motore di ricerca della barra MFM +hideFollowButtons: Nascondi i bottoni di follow se sono in una posizione cliccabile + per errore preventMisclick: Protezione dai click accidentali forMobile: Mobile replaceChatButtonWithAccountButton: Sostituisci il bottone chat con quello di cambio @@ -2205,3 +2197,17 @@ emojiModPermDescription: "Aggiungi: Permette all'utente di aggiungere emoji pers in più permette di rimuovere le emoji personalizzate." makePrivateConfirm: Questa operazione invierà ai server remoti un richiesta di rimozione e cambierà la visibilità a "Privato". Confermi? +sentFollowRequests: Richieste di follow inviate +searchWords: Parole da cercare / ID o URL da mostrare +enablePullToRefresh: Abilita il "Trascina in basso per aggiornare" +pullToRefreshThreshold: Distanza di trascinamento per ricaricare +pullDownToReload: Trascina in basso per ricaricare +releaseToReload: Rilascia per ricaricare +reloading: Ricaricamento +enableTimelineStreaming: Aggiorna le timeline in automatico +noSentFollowRequests: Non hai inviato richieste di follow +replyMute: Silenzia le risposte nelle timeline +replyUnmute: Non silenziare le risposte nelle timeline +useCdn: Carica gli asset da CDN +useCdnDescription: Carica alcuni asset statici come Twemoji dal CDN JSDelivr invece + che da questo server Firefish. diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1117231c18..c61187a510 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -53,6 +53,7 @@ copyUsername: "ユーザー名をコピー" searchUser: "ユーザーを検索" reply: "返信" replies: "返信" +toReply: "返信" loadMore: "もっと読み込む" showMore: "もっと見る" showLess: "閉じる" @@ -75,6 +76,7 @@ lists: "リスト" noLists: "リストはありません" note: "投稿" notes: "投稿" +toPost: "投稿する" following: "フォロー" followers: "フォロワー" followsYou: "フォローされています" @@ -105,6 +107,7 @@ cantRenote: "この投稿はブーストできません。" cantReRenote: "ブーストをブーストすることはできません。" quote: "引用" quotes: "引用" +toQuote: "引用する" pinnedNote: "ピン留めされた投稿" pinned: "ピン留め" you: "あなた" @@ -413,7 +416,7 @@ securityKeyName: "キーの名前" registerSecurityKey: "セキュリティキーを登録する" lastUsed: "最後の使用" unregister: "登録を解除" -passwordLessLogin: "パスワード無しでログイン" +passwordLessLogin: "パスワード無しでサインイン" resetPassword: "パスワードをリセット" newPasswordIs: "新しいパスワードは「{password}」です" reduceUiAnimation: "UIのアニメーションを減らす" @@ -478,7 +481,7 @@ disableDrawer: "メニューをドロワーで表示しない" youHaveNoGroups: "グループがありません" joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループを作成してください。" noHistory: "履歴はありません" -signinHistory: "ログイン履歴" +signinHistory: "サインイン履歴" disableAnimatedMfm: "動きのあるMFMを無効にする" doing: "やっています" category: "カテゴリ" @@ -606,6 +609,7 @@ tokenRequested: "アカウントへのアクセス許可" pluginTokenRequestedDescription: "このプラグインはここで設定した権限を行使できるようになります。" notificationType: "通知の種類" edit: "編集" +toEdit: "編集する" emailServer: "メールサーバー" enableEmail: "メール配信機能を有効化する" emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います" @@ -644,8 +648,8 @@ notificationSettingDesc: "表示する通知の種別を選択してください useGlobalSetting: "グローバル設定を使う" useGlobalSettingDesc: "オンにすると、アカウントの通知設定が使用されます。オフにすると、個別に設定できるようになります。" other: "その他" -regenerateLoginToken: "ログイントークンを再生成" -regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。" +regenerateLoginToken: "サインイントークンを再生成" +regenerateLoginTokenDescription: "サインインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスからサインアウトされます。" setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。" fileIdOrUrl: "ファイルIDまたはURL" behavior: "動作" @@ -904,14 +908,14 @@ thereIsUnresolvedAbuseReportWarning: "未対応の通報があります。" check: "チェック" driveCapOverrideLabel: "このユーザーのドライブ容量上限を変更" driveCapOverrideCaption: "0以下を指定すると解除されます。" -requireAdminForView: "閲覧するには管理者アカウントでログインしている必要があります。" +requireAdminForView: "閲覧するには管理者アカウントでサインインしている必要があります。" isSystemAccount: "システムにより自動で作成・管理されているアカウントです。モデレーション・編集・削除を行うとサーバーの動作が不正になる可能性があるため、操作しないでください。" typeToConfirm: "この操作を行うには {x} と入力してください" deleteAccount: "アカウント削除" document: "ドキュメント" numberOfPageCache: "ページキャッシュ数" numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。" -logoutConfirm: "ログアウトしますか?" +logoutConfirm: "サインアウトしますか?" lastActiveDate: "最終利用日時" statusbar: "ステータスバー" pleaseSelect: "選択してください" @@ -974,10 +978,6 @@ migrationConfirm: "本当にこのアカウントを {account} に引っ越し この操作を行う前に引っ越し先のアカウントでエイリアスを作成する必要があります。エイリアスが作成されているか、必ず確認してください。" defaultReaction: "リモートとローカルの投稿に対するデフォルトの絵文字リアクション" license: "ライセンス" -indexPosts: "投稿をインデックス" -indexFrom: "この投稿ID以降をインデックスする" -indexFromDescription: "空白で全ての投稿を指定します" -indexNotice: "インデックスを開始しました。完了まで時間がかかる場合があるため、少なくとも1時間はサーバーを再起動しないでください。" customKaTeXMacro: "カスタムKaTeXマクロ" customKaTeXMacroDescription: "数式入力を楽にするためのマクロを設定しましょう!記法はLaTeXにおけるコマンドの定義と同様に \\newcommand{\\ name}{content} または \\newcommand{\\add}[2]{#1 + #2} のように記述します。後者の例では \\add{3}{foo} @@ -1005,6 +1005,26 @@ pullDownToReload: "下に引っ張って再読み込み" releaseToReload: "離して再読み込み" reloading: "読み込み中" enableTimelineStreaming: "タイムラインを自動で更新する" +searchWords: "検索語句・照会するIDやURL" +searchWordsDescription: "投稿を検索するには、ここに検索語句を入力してください。空白区切りでAND検索になり、ORを挟むとOR検索になります。\n + 例えば「朝 夜」と入力すると「朝」と「夜」が両方含まれた投稿を検索し、「朝 OR 夜」と入力すると「朝」または「夜」(または両方)が含まれた投稿を検索します。\n + 「(朝 OR 夜) 眠い」のように、AND検索とOR検索を同時に行うこともできます。\n空白を含む文字列をAND検索ではなくそのまま検索したい場合、\"明日 買うもの\"\ + \ のように二重引用符 (\") で囲む必要があります。\n\n特定のユーザーや投稿のページに飛びたい場合には、この欄にID (@user@example.com) + や投稿のURLを入力し「照会」を押してください。「検索」を押すとそのIDやURLが文字通り含まれる投稿を検索します。" +searchUsers: "投稿元(オプション)" +searchUsersDescription: "投稿検索で投稿者を絞りたい場合、@user@example.com(ローカルユーザーなら @user)の形式で投稿者のIDを入力してください。ユーザーIDではなくドメイン名 + (example.com) を指定すると、そのサーバーの投稿を検索します。\n\nme とだけ入力すると、自分の投稿を検索します。この検索結果には未収載・フォロワー限定・ダイレクト・秘密を含む全ての投稿が含まれます。\n + \nlocal とだけ入力すると、ローカルサーバーの投稿を検索します。" +searchRange: "投稿期間(オプション)" +searchRangeDescription: "投稿検索で投稿期間を絞りたい場合、20220615-20231031 のような形式で投稿期間を入力してください。今年の日付を指定する場合には年の指定を省略できます(0105-0106 + や 20231105-0110 のように)。\n\n開始日と終了日のどちらか一方は省略可能です。例えば -0102 とすると今年1月2日までの投稿のみを、20231026- + とすると2023年10月26日以降の投稿のみを検索します。" +searchPostsWithFiles: "添付ファイルのある投稿のみ" +searchCwAndAlt: "閲覧注意の注釈と添付ファイルの代替テキストも検索する" +publishTimelines: "非ログインユーザーにもタイムラインを公開する" +publishTimelinesDescription: "有効にすると、{url} でローカルタイムラインとグローバルタイムラインが公開されます。" +noAltTextWarning: "説明が書かれていない添付ファイルがあります。書き忘れてはいませんか?" +showNoAltTextWarning: "説明が書かれていない添付ファイルを投稿しようとした場合に警告する" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。" @@ -1216,7 +1236,8 @@ _menuDisplay: hide: "隠す" _wordMute: muteWords: "ミュートするワード" - muteLangs: "ミュートされた言語" + mutePatterns: "ミュートするパターン" + muteLangs: "ミュートする言語" muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。" muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。" muteLangsDescription: "OR 条件の場合はスペースまたは改行で区切ります。" @@ -1453,10 +1474,7 @@ _widgets: userList: "ユーザーリスト" _userList: chooseList: "リストを選択" - meiliStatus: サーバーステータス serverInfo: サーバー情報 - meiliSize: インデックスサイズ - meiliIndexCount: インデックス済みの投稿 _cw: hide: "隠す" show: "もっと見る" @@ -1930,9 +1948,7 @@ sendModMail: モデレーション通知を送る deleted: 削除済み editNote: 投稿を編集 edited: '編集済み: {date} {time}' -signupsDisabled: - 現在、このサーバーでは新規登録が一般開放されていません。招待コードをお持ちの場合には、以下の欄に入力してください。招待コードをお持ちでない場合にも、新規登録を開放している他のサーバーには入れますよ! -findOtherInstance: 他のサーバーを探す +signupsDisabled: 現在、このサーバーでは新規登録が一般開放されていません。招待コードをお持ちの場合には、以下の欄に入力してください。 newer: 新しい投稿 older: 古い投稿 accessibility: アクセシビリティ @@ -2022,7 +2038,9 @@ searchEngine: "検索のMFMで使用する検索エンジン" postSearch: "このサーバーの投稿検索" showBigPostButton: "投稿ボタンを巨大にする" emojiModPerm: "カスタム絵文字の管理権" -emojiModPermDescription: "追加: カスタム絵文字の新規追加と新規追加されたカスタム絵文字(正確には、タグとカテゴリとライセンスが設定されていないカスタム絵文字)へのタグとカテゴリとライセンスの設定を許可します。\n追加と変更:「追加」の権限に加え、既存の絵文字の名前・カテゴリ・タグ・ライセンスの変更を許可します。\n全て許可:「追加と変更」の権限に加え、既存のカスタム絵文字の削除を許可します。\nこの設定にかかわらず、サーバーの管理者およびモデレーターには「全て許可」の権限が与えられます。" +emojiModPermDescription: "追加: カスタム絵文字の新規追加と新規追加されたカスタム絵文字(正確には、タグとカテゴリとライセンスが設定されていないカスタム絵文字)へのタグとカテゴリとライセンスの設定を許可します。\n\ + 追加と変更:「追加」の権限に加え、既存の絵文字の名前・カテゴリ・タグ・ライセンスの変更を許可します。\n全て許可:「追加と変更」の権限に加え、既存のカスタム絵文字の削除を許可します。\n\ + この設定にかかわらず、サーバーの管理者およびモデレーターには「全て許可」の権限が与えられます。" _emojiModPerm: unauthorized: "無し" add: "追加" @@ -2032,3 +2050,9 @@ private: "秘密" privateDescription: "あなた以外には非公開" makePrivate: "秘密にする" makePrivateConfirm: "リモートサーバーに削除リクエストを送信し、投稿の公開範囲を「秘密」にして他の人から見られないようにします。実行しますか?" +sentFollowRequests: 未承認のフォローリクエスト +noSentFollowRequests: 未承認のフォローリクエストはありません +messagingUnencryptedInfo: FirefishのチャットはE2E暗号化されていません。漏洩してはいけない情報はFirefishで送らないでください。 +moderationNote: モデレーション用のメモ +ipFirstAcknowledged: IPアドレスが最初に取得された日 +driveCapacityOverride: ドライブ容量の変更 diff --git a/locales/kab-KAB.yml b/locales/kab.yml similarity index 100% rename from locales/kab-KAB.yml rename to locales/kab.yml diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 722d48abf8..75f347a96a 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -1331,10 +1331,7 @@ _widgets: serverInfo: 서버 정보 _userList: chooseList: 리스트 선택 - meiliStatus: 서버 정보 userList: 유저 목록 - meiliSize: 인덱스 크기 - meiliIndexCount: 인덱싱 완료된 게시물 rssTicker: RSS Ticker _cw: hide: "숨기기" @@ -1827,7 +1824,6 @@ pushNotificationNotSupported: 브라우저 및 서버가 푸시 알림을 지원 enableRecommendedTimeline: 추천 타임라인을 활성화 pushNotificationAlreadySubscribed: 푸시 알림이 활성화되었습니다 caption: 자동으로 설명 붙이기 -findOtherInstance: 다른 서버 둘러보기 enableIdenticonGeneration: 유저 별 Identicon의 생성을 활성화 secureModeInfo: 인증 정보가 없는 리모트 서버로부터의 요청에 응답하지 않습니다. allowedInstances: 허가된 서버 @@ -1840,7 +1836,6 @@ customSplashIconsDescription: 유저가 페이지를 로딩/새로고침할 때 이미지는 되도록 정적 URL으로 구성하고, 192x192 해상도로 조정하여 주십시오. moveFromDescription: '이전 계정에 대한 별칭을 작성하여, 이 계정으로 옮길 수 있도록 합니다. 반드시 계정을 이전하기 전에 수행해야 합니다. 이전 계정을 다음과 같은 형식으로 입력하여 주십시오: @person@server.com' -indexFromDescription: 빈 칸으로 두면 모든 게시물을 인덱싱합니다 customKaTeXMacroDescription: 'KaTeX 매크로를 지정하여 수식을 더욱 편리하게 입력하세요! LaTeX의 커맨드 정의와 동일하게 \newcommand{\ 이름}{내용} 또는 \newcommand{\이름}[인수 갯수]{내용} 와 같이 입력하십시오. 예를 들어 \newcommand{\add}[2]{#1 + #2} 와 같이 정의한 경우 \add{3}{foo} 를 입력하면 3 + foo 으로 치환됩니다.매크로의 이름을 감싸는 중괄호를 소괄호() 또는 @@ -1895,7 +1890,6 @@ accessibility: 접근성 userSaysSomethingReasonReply: '{name} 님이 {reason} 을 포함하는 게시물에 답글했습니다' userSaysSomethingReasonRenote: '{name} 님이 {reason} 을 포함하는 게시물을 부스트했습니다' breakFollowConfirm: 팔로워를 해제하시겠습니까? -indexFrom: 이 게시물 ID부터 인덱싱하기 noThankYou: 괜찮습니다 hiddenTags: 숨길 해시태그 image: 이미지 @@ -1927,8 +1921,6 @@ removeMember: 멤버를 삭제 license: 라이선스 migrationConfirm: "정말로 이 계정을 {account}로 이사하시겠습니까? 한 번 이사하면, 현재 이 계정은 두 번 다시 사용할 수 없게 됩니다.\n또한, 이사 갈 계정에 현재 사용 중인 계정의 별칭을 올바르게 작성하였는지 다시 한 번 확인하십시오." -indexPosts: 게시물을 인덱싱 -indexNotice: 인덱싱을 시작했습니다. 이 작업은 시간이 많이 소요되므로, 최소 1시간 이내에 서버를 재시작하지 마십시오. noteId: 게시물 ID signupsDisabled: 현재 이 서버에서는 신규 등록을 받고 있지 않습니다. 초대 코드를 가지고 계신 경우 아래 칸에 입력해 주십시오. 초대 코드를 가지고 있지 않더라도, 신규 등록이 열려 있는 다른 서버에 등록하실 수 있습니다! @@ -2011,3 +2003,8 @@ detectPostLanguage: 외국어로 인식된 게시물에 번역 버튼을 표시 indexableDescription: Firefish 검색에서 나의 공개 게시물에 대한 검색을 허용합니다 indexable: 인덱스 허용 languageForTranslation: 게시물 번역에 사용할 언어 +replies: 답글 +renotes: 부스트 +quotes: 인용 +sentFollowRequests: 팔로우 요청 보냄 +reactions: 리액션 diff --git a/locales/no-NO.yml b/locales/no-NO.yml index c817d46c24..bd643c34e1 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -939,7 +939,6 @@ allowedInstancesDescription: Tjenernavn for tjenere som skal hvitelistes. En per (Vil bare bli brukt i privat modus). previewNoteText: Forhåndsvisning recentNDays: Siste {n} dager -indexPosts: Indekser poster objectStorageUseProxy: Koble til gjennom en mellomtjener objectStorageUseProxyDesc: Skru av dette dersom du ikke vil bruke mellomtjenere for API-oppkoblinger @@ -1185,10 +1184,6 @@ moveFromDescription: Dette vil sette opp et alias for din gamle kontoen slik at kan flytte fra den gamle kontoen til denne. Gjør dette FØR du flytter fra den gamle kontoen. Skriv inn den gamle kontoen på formen @person@server.com defaultReaction: Standard emoji-reaksjon for utgående og innkommende poster -indexFrom: Indekser poster fra post-id og fremover -indexNotice: Indekserer. Dette vil sannsynligvis ta litt tid, ikke restart tjeneren - før det har gått minst en time. -indexFromDescription: La stå tom for å indeksere alle poster customKaTeXMacroDescription: 'Sett opp makroer for å skrive matematiske uttrykk enkelt. Notasjonen følger LaTeX-kommandoer og er skrevet som \newcommand{\ navn}{uttrykk} eller \newcommand{\navn}{antall argumenter}{uttrykk}. For eksempel vil \newcommand{\add}{2}{#1 @@ -1201,7 +1196,6 @@ customKaTeXMacroDescription: 'Sett opp makroer for å skrive matematiske uttrykk signupsDisabled: Registreringer av nye konti på denne tjeneren er slått av, men du kan alltids registrere deg på en annen tjener! Hvis du har en invitasjonskode for denne tjeneren, skriv den inn under. -findOtherInstance: Finn en annen tjener preventAiLearningDescription: Ber tredjeparts AI-språkmodeller om å ikke bruke innhold du laster opp, sliks om poster og bilder. enableCustomKaTeXMacro: Slå på egne KaTeX-makroer @@ -1628,14 +1622,12 @@ _antennaSources: instances: Poster fra alle brukerne på denne tjeneren _widgets: timeline: Tidslinje - meiliSize: Indeks-størrelse instanceCloud: Tjenersky onlineUsers: Påloggede brukere clock: Klokke userList: Brukerliste rss: RSS-leser serverMetric: Tjenermetrikker - meiliIndexCount: Indekserte poster button: Knapp unixClock: Unix-klokke calendar: Kalender @@ -1647,7 +1639,6 @@ _widgets: photos: Bilder rssTicker: RSS-rulletekst aiscript: AiScript-konsoll - meiliStatus: Tjenerstatus memo: Notatlapp notifications: Varsler postForm: Ny post diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 1369babee2..95a05009bd 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -1892,11 +1892,6 @@ sendPushNotificationReadMessageCaption: Powiadomienie zawierające tekst "{empty baterii Twojego urządzenia. defaultReaction: Domyślna reakcja emoji dla wychodzących i przychodzących wpisów license: Licencja -indexPosts: Indeksuj wpisy -indexFrom: Indeksuj wpisy od ID -indexFromDescription: Zostaw puste dla indeksowania wszystkich wpisów -indexNotice: Indeksuję. Zapewne zajmie to chwilę, nie restartuj serwera przez co najmniej - godzinę. customKaTeXMacro: Niestandardowe makra KaTeX enableCustomKaTeXMacro: Włącz niestandardowe makra KaTeX noteId: ID wpisu @@ -1997,7 +1992,6 @@ deleted: Usunięte editNote: Edytuj wpis edited: 'Edytowano o {date} {time}' silenced: Wyciszony -findOtherInstance: Znajdź inny serwer userSaysSomethingReasonReply: '{name} odpowiedział na wpis zawierający {reason}' userSaysSomethingReasonRenote: '{name} podbił post zawierający {reason}' signupsDisabled: Rejestracja na tym serwerze jest obecnie zamknięta, ale zawsze możesz diff --git a/locales/pt_BR.yml b/locales/pt-BR.yml similarity index 100% rename from locales/pt_BR.yml rename to locales/pt-BR.yml diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml index 51c7b30810..eea5d1b1f6 100644 --- a/locales/ro-RO.yml +++ b/locales/ro-RO.yml @@ -1,7 +1,9 @@ ---- _lang_: "Română" headlineFirefish: "O rețea conectată prin note" -introFirefish: "Bine ai venit! Firefish este un serviciu de microblogging open source și decentralizat.\nCreează \"note\" cu care să îți poți împărți gândurile cu oricine din jurul tău. 📡\nCu \"reacții\" îți poți expirma rapid părerea despre notele oricui. 👍\nHai să explorăm o lume nouă! 🚀" +introFirefish: "Bine ai venit! Firefish este un serviciu de microblogging open source + și decentralizat.\nCreează \"note\" cu care să îți poți împărți gândurile cu oricine + din jurul tău. 📡\nCu \"reacții\" îți poți expirma rapid părerea despre notele oricui. + 👍\nHai să explorăm o lume nouă! 🚀" monthAndDay: "{day}/{month}" search: "Caută" notifications: "Notificări" @@ -44,7 +46,8 @@ copyContent: "Copiază conținutul" copyLink: "Copiază link-ul" delete: "Şterge" deleteAndEdit: "Șterge și editează" -deleteAndEditConfirm: "Ești sigur că vrei să ștergi această notă și să o editezi? Vei pierde reacțiile, re-notele și răspunsurile acesteia." +deleteAndEditConfirm: "Ești sigur că vrei să ștergi această notă și să o editezi? + Vei pierde reacțiile, re-notele și răspunsurile acesteia." addToList: "Adaugă în listă" sendMessage: "Trimite un mesaj" copyUsername: "Copiază numele de utilizator" @@ -64,9 +67,11 @@ import: "Importă" export: "Exportă" files: "Fișiere" download: "Descarcă" -driveFileDeleteConfirm: "Ești sigur ca vrei să ștergi fișierul \"{name}\"? Notele atașate fișierului vor fi șterse și ele." +driveFileDeleteConfirm: "Ești sigur ca vrei să ștergi fișierul \"{name}\"? Notele + atașate fișierului vor fi șterse și ele." unfollowConfirm: "Ești sigur ca vrei să nu mai urmărești pe {name}?" -exportRequested: "Ai cerut un export. S-ar putea să ia un pic. Va fi adăugat in Drive-ul tău odată completat." +exportRequested: "Ai cerut un export. S-ar putea să ia un pic. Va fi adăugat in Drive-ul + tău odată completat." importRequested: "Ai cerut un import. S-ar putea să ia un pic." lists: "Liste" noLists: "Nu ai nici o listă" @@ -81,9 +86,12 @@ error: "Eroare" somethingHappened: "A survenit o eroare" retry: "Reîncearcă" pageLoadError: "A apărut o eroare la încărcarea paginii." -pageLoadErrorDescription: "De obicei asta este cauzat de o eroare de rețea sau cache-ul browser-ului. Încearcă să cureți cache-ul și apoi să încerci din nou puțin mai târziu." -serverIsDead: "Serverul nu răspunde. Te rugăm să aștepți o perioadă și să încerci din nou." -youShouldUpgradeClient: "Pentru a vedea această pagină, te rugăm să îți actualizezi clientul." +pageLoadErrorDescription: "De obicei asta este cauzat de o eroare de rețea sau cache-ul + browser-ului. Încearcă să cureți cache-ul și apoi să încerci din nou puțin mai târziu." +serverIsDead: "Serverul nu răspunde. Te rugăm să aștepți o perioadă și să încerci + din nou." +youShouldUpgradeClient: "Pentru a vedea această pagină, te rugăm să îți actualizezi + clientul." enterListName: "Introdu un nume pentru listă" privacy: "Confidenţialitate" makeFollowManuallyApprove: "Fă cererile de urmărire să necesite aprobare" @@ -137,14 +145,21 @@ emojiUrl: "URL-ul emoji-ului" addEmoji: "Adaugă un emoji" settingGuide: "Setări recomandate" cacheRemoteFiles: "Ține fișierele externe in cache" -cacheRemoteFilesDescription: "Când această setare este dezactivată, fișierele externe sunt încărcate direct din instanța externă. Dezactivarea va scădea utilizarea spațiului de stocare, dar va crește traficul, deoarece thumbnail-urile nu vor fi generate." +cacheRemoteFilesDescription: "Când această setare este dezactivată, fișierele externe + sunt încărcate direct din instanța externă. Dezactivarea va scădea utilizarea spațiului + de stocare, dar va crește traficul, deoarece thumbnail-urile nu vor fi generate." flagAsBot: "Marchează acest cont ca bot" -flagAsBotDescription: "Activează această opțiune dacă acest cont este controlat de un program. Daca e activată, aceasta va juca rolul unui indicator pentru dezvoltatori pentru a preveni interacțiunea în lanțuri infinite cu ceilalți boți și ajustează sistemele interne al Firefish pentru a trata acest cont drept un bot." +flagAsBotDescription: "Activează această opțiune dacă acest cont este controlat de + un program. Daca e activată, aceasta va juca rolul unui indicator pentru dezvoltatori + pentru a preveni interacțiunea în lanțuri infinite cu ceilalți boți și ajustează + sistemele interne al Firefish pentru a trata acest cont drept un bot." flagAsCat: "Marchează acest cont ca pisică" flagAsCatDescription: "Activează această opțiune dacă acest cont este o pisică." flagShowTimelineReplies: "Arată răspunsurile în cronologie" -flagShowTimelineRepliesDescription: "Dacă e activată vor fi arătate în cronologie răspunsurile utilizatorilor către alte notele altor utilizatori." -autoAcceptFollowed: "Aprobă automat cererile de urmărire de la utilizatorii pe care îi urmărești" +flagShowTimelineRepliesDescription: "Dacă e activată vor fi arătate în cronologie + răspunsurile utilizatorilor către alte notele altor utilizatori." +autoAcceptFollowed: "Aprobă automat cererile de urmărire de la utilizatorii pe care + îi urmărești" addAccount: "Adaugă un cont" loginFailed: "Autentificare eșuată" showOnRemote: "Vezi mai multe pe instanța externă" @@ -156,7 +171,11 @@ searchWith: "Caută: {q}" youHaveNoLists: "Nu ai nici o listă" followConfirm: "Ești sigur ca vrei să urmărești pe {name}?" proxyAccount: "Cont proxy" -proxyAccountDescription: "Un cont proxy este un cont care se comportă ca un urmăritor extern pentru utilizatorii puși sub anumite condiții. De exemplu, când un cineva adaugă un utilizator extern intr-o listă, activitatea utilizatorului extern nu va fi adusă în instanță daca nici un utilizator local nu urmărește acel utilizator, așa că în schimb contul proxy îl va urmări." +proxyAccountDescription: "Un cont proxy este un cont care se comportă ca un urmăritor + extern pentru utilizatorii puși sub anumite condiții. De exemplu, când un cineva + adaugă un utilizator extern intr-o listă, activitatea utilizatorului extern nu va + fi adusă în instanță daca nici un utilizator local nu urmărește acel utilizator, + așa că în schimb contul proxy îl va urmări." host: "Gazdă" selectUser: "Selectează un utilizator" recipient: "Destinatar" @@ -186,11 +205,14 @@ instanceInfo: "Informații despre instanță" statistics: "Statistici" clearQueue: "Șterge coada" clearQueueConfirmTitle: "Ești sigur că vrei să cureți coada?" -clearQueueConfirmText: "Orice notă rămasă în coadă nu va fi federată. De obicei această operație nu este necesară." +clearQueueConfirmText: "Orice notă rămasă în coadă nu va fi federată. De obicei această + operație nu este necesară." clearCachedFiles: "Golește cache-ul" -clearCachedFilesConfirm: "Ești sigur că vrei să ștergi toate fișierele externe din cache?" +clearCachedFilesConfirm: "Ești sigur că vrei să ștergi toate fișierele externe din + cache?" blockedInstances: "Instanțe blocate" -blockedInstancesDescription: "Scrie hostname-urile instanțelor pe care dorești să le blochezi. Instanțele listate nu vor mai putea să comunice cu această instanță." +blockedInstancesDescription: "Scrie hostname-urile instanțelor pe care dorești să + le blochezi. Instanțele listate nu vor mai putea să comunice cu această instanță." muteAndBlock: "Amuțiri și Blocări" mutedUsers: "Utilizatori amuțiți" blockedUsers: "Utilizatori blocați" @@ -238,7 +260,8 @@ saved: "Salvat" messaging: "Chat" upload: "Încarcă" keepOriginalUploading: "Păstrează imaginea originală" -keepOriginalUploadingDescription: "Salvează imaginea originala încărcată fără modificări. Dacă e oprită, o versiune pentru afișarea pe web va fi generată la încărcare." +keepOriginalUploadingDescription: "Salvează imaginea originala încărcată fără modificări. + Dacă e oprită, o versiune pentru afișarea pe web va fi generată la încărcare." fromDrive: "Din Drive" fromUrl: "Din URL" uploadFromUrl: "Încarcă dintr-un URL" @@ -254,7 +277,8 @@ agreeTo: "Sunt de acord cu {0}" tos: "Termenii de utilizare" start: "Să începem" home: "Acasă" -remoteUserCaution: "Deoarece acest utilizator este dintr-o instanță externă, informația afișată poate fi incompletă." +remoteUserCaution: "Deoarece acest utilizator este dintr-o instanță externă, informația + afișată poate fi incompletă." activity: "Activitate" images: "Imagini" birthday: "Zi de naștere" @@ -287,7 +311,8 @@ unableToDelete: "Nu se poate șterge" inputNewFileName: "Introdu un nou nume de fișier" inputNewDescription: "Introdu o descriere nouă" inputNewFolderName: "Introdu un nume de folder nou" -circularReferenceFolder: "Destinația folderului este un subfolder al folderului pe care dorești să îl muți." +circularReferenceFolder: "Destinația folderului este un subfolder al folderului pe + care dorești să îl muți." hasChildFilesOrFolders: "Acest folder nu este gol, așa că nu poate fi șters." copyUrl: "Copiază URL" rename: "Redenumește" @@ -318,7 +343,8 @@ yearX: "{year}" pages: "Pagini" enableLocalTimeline: "Activează cronologia locală" enableGlobalTimeline: "Activeaza cronologia globală" -disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate cronologiile, chiar dacă nu sunt activate." +disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate + cronologiile, chiar dacă nu sunt activate." registration: "Inregistrare" enableRegistration: "Activează înregistrările pentru utilizatori noi" invite: "Invită" @@ -330,9 +356,11 @@ bannerUrl: "URL-ul imaginii de banner" backgroundImageUrl: "URL-ul imaginii de fundal" basicInfo: "Informații de bază" pinnedUsers: "Utilizatori fixați" -pinnedUsersDescription: "Scrie utilizatorii, separați prin pauză de rând, care vor fi fixați pe pagina \"Explorează\"." +pinnedUsersDescription: "Scrie utilizatorii, separați prin pauză de rând, care vor + fi fixați pe pagina \"Explorează\"." pinnedPages: "Pagini fixate" -pinnedPagesDescription: "Introdu linkurile Paginilor pe care le vrei fixate in vâruful paginii acestei instanțe, separate de pauze de rând." +pinnedPagesDescription: "Introdu linkurile Paginilor pe care le vrei fixate in vâruful + paginii acestei instanțe, separate de pauze de rând." pinnedClipId: "ID-ul clip-ului pe care să îl fixezi" pinnedNotes: "Notă fixată" hcaptcha: "hCaptcha" @@ -343,14 +371,17 @@ recaptcha: "reCAPTCHA" enableRecaptcha: "Activează reCAPTCHA" recaptchaSiteKey: "Site key" recaptchaSecretKey: "Secret key" -avoidMultiCaptchaConfirm: "Folosirea mai multor sisteme Captcha poate cauza interferență între acestea. Ai dori să dezactivezi alte sisteme Captcha acum active? Dacă preferi să rămână activate, apasă Anulare." +avoidMultiCaptchaConfirm: "Folosirea mai multor sisteme Captcha poate cauza interferență + între acestea. Ai dori să dezactivezi alte sisteme Captcha acum active? Dacă preferi + să rămână activate, apasă Anulare." antennas: "Antene" manageAntennas: "Gestionează Antenele" name: "Nume" antennaSource: "Sursa antenei" antennaKeywords: "Cuvinte cheie ascultate" antennaExcludeKeywords: "Cuvinte cheie excluse" -antennaKeywordsDescription: "Separă cu spații pentru o condiție ȘI sau cu o întrerupere de rând pentru o condiție SAU." +antennaKeywordsDescription: "Separă cu spații pentru o condiție ȘI sau cu o întrerupere + de rând pentru o condiție SAU." notifyAntenna: "Notifică-mă pentru note noi" withFileAntenna: "Doar note cu fișiere" enableServiceworker: "Activează ServiceWorker" @@ -437,7 +468,8 @@ strongPassword: "Parolă puternică" passwordMatched: "Se potrivește!" passwordNotMatched: "Nu se potrivește" signinWith: "Autentifică-te cu {x}" -signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse sunt incorecte." +signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse + sunt incorecte." tapSecurityKey: "Apasă pe cheia ta de securitate." or: "Sau" language: "Limbă" @@ -478,19 +510,26 @@ showFeaturedNotesInTimeline: "Arată notele recomandate în cronologii" objectStorage: "Object Storage" useObjectStorage: "Folosește Object Storage" objectStorageBaseUrl: "URL de bază" -objectStorageBaseUrlDesc: "URL-ul este folosit pentru referință. Specifică URL-ul CDN-ului sau Proxy-ului tău dacă folosești unul. Pentru S3 folosește 'https://.s3.amazonaws.com' și pentru GCS sau servicii echivalente folosește 'https://storage.googleapis.com/', etc." +objectStorageBaseUrlDesc: "URL-ul este folosit pentru referință. Specifică URL-ul + CDN-ului sau Proxy-ului tău dacă folosești unul. Pentru S3 folosește 'https://.s3.amazonaws.com' + și pentru GCS sau servicii echivalente folosește 'https://storage.googleapis.com/', + etc." objectStorageBucket: "Bucket" objectStorageBucketDesc: "Te rog specifică numele bucket-ului furnizorului tău." objectStoragePrefix: "Prefix" objectStoragePrefixDesc: "Fișierele vor fi stocate sub directoare cu acest prefix." objectStorageEndpoint: "Endpoint" -objectStorageEndpointDesc: "Lasă acest câmp gol dacă folosești AWS S3, dacă nu specifică endpoint-ul ca '' sau ':', depinzând de ce serviciu folosești." +objectStorageEndpointDesc: "Lasă acest câmp gol dacă folosești AWS S3, dacă nu specifică + endpoint-ul ca '' sau ':', depinzând de ce serviciu folosești." objectStorageRegion: "Regiune" -objectStorageRegionDesc: "Specifică o regiune precum 'xx-east-1'. Dacă serviciul tău nu face distincția între regiuni lasă acest câmp gol sau introdu 'us-east-1'." +objectStorageRegionDesc: "Specifică o regiune precum 'xx-east-1'. Dacă serviciul tău + nu face distincția între regiuni lasă acest câmp gol sau introdu 'us-east-1'." objectStorageUseSSL: "Folosește SSl" -objectStorageUseSSLDesc: "Oprește această opțiune dacă nu vei folosi HTTPS pentru conexiunile API-ului" +objectStorageUseSSLDesc: "Oprește această opțiune dacă nu vei folosi HTTPS pentru + conexiunile API-ului" objectStorageUseProxy: "Conectează-te prin Proxy" -objectStorageUseProxyDesc: "Oprește această opțiune dacă vei nu folosi un Proxy pentru conexiunile API-ului" +objectStorageUseProxyDesc: "Oprește această opțiune dacă vei nu folosi un Proxy pentru + conexiunile API-ului" objectStorageSetPublicRead: "Setează \"public-read\" pentru încărcare" serverLogs: "Loguri server" deleteAll: "Șterge tot" @@ -518,7 +557,9 @@ sort: "Sortează" ascendingOrder: "Crescător" descendingOrder: "Descrescător" scratchpad: "Scratchpad" -scratchpadDescription: "Scratchpad-ul oferă un mediu de experimentare în AiScript. Poți scrie, executa și verifica rezultatele acestuia interacționând cu Firefish în el." +scratchpadDescription: "Scratchpad-ul oferă un mediu de experimentare în AiScript. + Poți scrie, executa și verifica rezultatele acestuia interacționând cu Firefish + în el." output: "Ieșire" script: "Script" disablePagesScript: "Dezactivează AiScript în Pagini" @@ -526,11 +567,14 @@ updateRemoteUser: "Actualizează informațiile utilizatorului extern" deleteAllFiles: "Șterge toate fișierele" deleteAllFilesConfirm: "Ești sigur că vrei să ștergi toate fișierele?" removeAllFollowing: "Dezurmărește toți utilizatorii urmăriți" -removeAllFollowingDescription: "Asta va dez-urmări toate conturile din {host}. Te rog execută asta numai dacă instanța, de ex., nu mai există." +removeAllFollowingDescription: "Asta va dez-urmări toate conturile din {host}. Te + rog execută asta numai dacă instanța, de ex., nu mai există." userSuspended: "Acest utilizator a fost suspendat." userSilenced: "Acest utilizator a fost setat silențios." yourAccountSuspendedTitle: "Acest cont a fost suspendat" -yourAccountSuspendedDescription: "Acest cont a fost suspendat din cauza încălcării termenilor de serviciu al serverului sau ceva similar. Contactează administratorul dacă ai dori să afli un motiv mai detaliat. Te rog nu crea un cont nou." +yourAccountSuspendedDescription: "Acest cont a fost suspendat din cauza încălcării + termenilor de serviciu al serverului sau ceva similar. Contactează administratorul + dacă ai dori să afli un motiv mai detaliat. Te rog nu crea un cont nou." menu: "Meniu" divider: "Separator" addItem: "Adaugă element" @@ -569,12 +613,14 @@ permission: "Permisiuni" enableAll: "Actevează tot" disableAll: "Dezactivează tot" tokenRequested: "Acordă acces la cont" -pluginTokenRequestedDescription: "Acest plugin va putea să folosească permisiunile setate aici." +pluginTokenRequestedDescription: "Acest plugin va putea să folosească permisiunile + setate aici." notificationType: "Tipul notificării" edit: "Editează" emailServer: "Server email" enableEmail: "Activează distribuția de emailuri" -emailConfigInfo: "Folosit pentru a confirma emailul tău în timpul logări dacă îți uiți parola" +emailConfigInfo: "Folosit pentru a confirma emailul tău în timpul logări dacă îți + uiți parola" email: "Email" emailAddress: "Adresă de email" smtpConfig: "Configurare Server SMTP" @@ -582,13 +628,15 @@ smtpHost: "Gazdă" smtpPort: "Port" smtpUser: "Nume de utilizator" smtpPass: "Parolă" -emptyToDisableSmtpAuth: "Lasă username-ul și parola necompletate pentru a dezactiva verificarea SMTP" +emptyToDisableSmtpAuth: "Lasă username-ul și parola necompletate pentru a dezactiva + verificarea SMTP" smtpSecure: "Folosește SSL/TLS implicit pentru conecțiunile SMTP" smtpSecureInfo: "Oprește opțiunea asta dacă STARTTLS este folosit" testEmail: "Testează livrarea emailurilor" wordMute: "Cuvinte pe mut" regexpError: "Eroare de Expresie Regulată" -regexpErrorDescription: "A apărut o eroare în expresia regulată pe linia {line} al cuvintelor {tab} setate pe mut:" +regexpErrorDescription: "A apărut o eroare în expresia regulată pe linia {line} al + cuvintelor {tab} setate pe mut:" instanceMute: "Instanțe pe mut" userSaysSomething: "{name} a spus ceva" makeActive: "Activează" @@ -604,10 +652,13 @@ create: "Crează" notificationSetting: "Setări notificări" notificationSettingDesc: "Selectează tipurile de notificări care să fie arătate" useGlobalSetting: "Folosește setările globale" -useGlobalSettingDesc: "Dacă opțiunea e pornită, notificările contului tău vor fi folosite. Dacă e oprită, configurația va fi individuală." +useGlobalSettingDesc: "Dacă opțiunea e pornită, notificările contului tău vor fi folosite. + Dacă e oprită, configurația va fi individuală." other: "Altele" regenerateLoginToken: "Regenerează token de login" -regenerateLoginTokenDescription: "Regenerează token-ul folosit intern în timpul logări. În mod normal asta nu este necesar. Odată regenerat, toate dispozitivele vor fi delogate." +regenerateLoginTokenDescription: "Regenerează token-ul folosit intern în timpul logări. + În mod normal asta nu este necesar. Odată regenerat, toate dispozitivele vor fi + delogate." setMultipleBySeparatingWithSpace: "Separă mai multe intrări cu spații." fileIdOrUrl: "Introdu ID sau URL" behavior: "Comportament" @@ -615,13 +666,15 @@ sample: "exemplu" abuseReports: "Rapoarte" reportAbuse: "Raportează" reportAbuseOf: "Raportează {name}" -fillAbuseReportDescription: "Te rog scrie detaliile legate de acest raport. Dacă este despre o notă specifică, te rog introdu URL-ul ei." +fillAbuseReportDescription: "Te rog scrie detaliile legate de acest raport. Dacă este + despre o notă specifică, te rog introdu URL-ul ei." abuseReported: "Raportul tău a fost trimis. Mulțumim." reporter: "Raportorul" reporteeOrigin: "Originea raportatului" reporterOrigin: "Originea raportorului" forwardReport: "Redirecționează raportul către instanța externă" -forwardReportIsAnonymous: "În locul contului tău, va fi afișat un cont anonim, de sistem, ca raportor către instanța externă." +forwardReportIsAnonymous: "În locul contului tău, va fi afișat un cont anonim, de + sistem, ca raportor către instanța externă." send: "Trimite" abuseMarkAsResolved: "Marchează raportul ca rezolvat" openInNewTab: "Deschide în tab nou" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 9de2c135b9..df9d183433 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -1375,9 +1375,6 @@ _widgets: userList: Список пользователей _userList: chooseList: Выберите список - meiliStatus: Состояние сервера - meiliSize: Размер индекса - meiliIndexCount: Индексированные посты serverInfo: Информация о сервере _cw: hide: "Спрятать" @@ -1951,11 +1948,6 @@ showUpdates: Показывать всплывающее окно при обн recommendedInstances: Рекомендованные серверы defaultReaction: Эмодзи реакция по умолчанию для выходящих и исходящих постов license: Лицензия -indexPosts: Индексировать посты -indexFrom: Индексировать начиная с идентификатора поста и далее -indexFromDescription: оставьте пустым для индексации каждого поста -indexNotice: Теперь индексирование. Вероятно, это займет некоторое время, пожалуйста, - не перезагружайте свой сервер по крайней мере в течение часа. customKaTeXMacro: Кастомные KaTex макросы enableCustomKaTeXMacro: Включить кастомные KaTeX макросы noteId: Идентификатор поста @@ -2094,7 +2086,6 @@ enableServerMachineStats: Включить статистику серверно enableIdenticonGeneration: Включить генерацию Identicon reactionPickerSkinTone: Предпочитаемый цвет кожи эмодзи sendModMail: Отправить сообщение о модерации -findOtherInstance: Найти другой сервер signupsDisabled: Регистрация на этом сервере сейчас отключена, но вы всегда можете зарегистрироваться на другом сервере! Если у вас есть код приглашения на этот сервер, пожалуйста, введите его ниже. diff --git a/locales/th-TH.yml b/locales/th-TH.yml index bcd97e9f64..6ae3201f01 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -1288,7 +1288,6 @@ customMOTD: ข้อความหน้าจอเริ่มต้นท swipeOnMobile: อนุญาตให้ปัดระหว่างหน้า breakFollowConfirm: คุณแน่ใจหรือไม่ที่จะลบผู้ติดตาม? defaultReaction: ค่าเริ่มต้นของปฏิกิริยาอีโมจิสำหรับโพสต์ขาออกและขาเข้า -findOtherInstance: ค้นหาเซิร์ฟเวอร์อื่น silenceThisInstance: ปิดเงียบสำหรับเซิร์ฟเวอร์นี้ antennaInstancesDescription: เขียนชื่อเซิร์ฟเวอร์ได้ 1 ชื่อต่อ 1 บรรทัด splash: หน้าจอเริ่มต้น @@ -1316,8 +1315,6 @@ customMOTDDescription: ข้อความหน้าจอเริ่มต คั่นด้วยการขึ้นบรรทัดใหม่เพื่อแสดงแบบสุ่มทุกครั้งที่ผู้ใช้โหลดเว็บหรือโหลดหน้าเว็บซ้ำ caption: คำอธิบายโดยอัตโนมัติ moveToLabel: 'บัญชีที่คุณจะย้ายไปยัง:' -indexFromDescription: เว้นว่างไว้เพื่อสร้างดัชนีทุกโพสต์ -indexNotice: ตอนนี้กำลังจัดทำดัชนี การดำเนินการนี้อาจใช้เวลาสักครู่ โปรดอย่ารีสตาร์ทเซิร์ฟเวอร์เป็นเวลาอย่างน้อยหนึ่งชั่วโมง noteId: โพสต์ ID apps: แอป enableRecommendedTimeline: เปิดใช้งาน ไทม์ไลน์ที่แนะนำ @@ -1371,9 +1368,7 @@ moveFromDescription: การดำเนินการนี้จะตั migrationConfirm: "คุณแน่ใจหรือไม่ว่าคุณต้องการย้ายบัญชีของคุณไปยัง {account} เมื่อคุณทำเช่นนี้ คุณจะไม่สามารถกู้คืนมาได้ และคุณจะไม่สามารถใช้บัญชีของคุณได้ตามปกติอีก\nนอกจากนี้ โปรดตรวจสอบให้แน่ใจว่าคุณได้ตั้งบัญชีปัจจุบันนี้เป็นบัญชีที่คุณจะย้ายออก" -indexFrom: จัดทำดัชนีตั้งแต่ Post ID เป็นต้นไป license: ใบอนุญาต -indexPosts: ดัชนีโพสต์ signupsDisabled: การลงชื่อสมัครใช้บนเซิร์ฟเวอร์นี้ถูกปิดใช้งานอยู่ในขณะนี้ แต่คุณสามารถสมัครที่เซิร์ฟเวอร์อื่นได้ตลอดเวลา หากคุณมีรหัสเชิญสำหรับเซิร์ฟเวอร์นี้ โปรดป้อนรหัสด้านล่าง customKaTeXMacroDescription: 'ตั้งค่ามาโครเพื่อเขียนนิพจน์ทางคณิตศาสตร์ได้อย่างง่ายดาย diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index fc0c236e0a..7a687dc7c4 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -158,7 +158,6 @@ _widgets: activity: Aktivite digitalClock: Dijital Saat unixClock: UNIX Saati - meiliIndexCount: Indexlenmiş gönderiler calendar: Takvim trends: Popüler memo: Yapışkan Notlar @@ -166,13 +165,11 @@ _widgets: federation: Federasyon instanceCloud: Sunucu Bulutu postForm: Gönderi Formu - meiliSize: Index boyutu slideshow: Slayt Gösterisi button: Düğme clock: Saat rss: RSS Okuyucu serverInfo: Sunucu Bilgisi - meiliStatus: Sunucu Durumu jobQueue: İş Sırası serverMetric: Sunucu Bilgileri _profile: @@ -473,7 +470,6 @@ activeEmailValidationDescription: Tek kullanımlık adreslerin kontrol edilmesi sağlar. İşaretlenmediğinde, yalnızca e-postanın biçimi doğrulanır. move: Taşı defaultReaction: Giden ve gelen gönderiler için varsayılan emoji tepkisi -indexPosts: Dizin Gönderileri youGotNewFollower: takip etti receiveFollowRequest: Takip isteği alındı followRequestAccepted: Takip isteği onaylandı @@ -1084,7 +1080,6 @@ check: Kontrol Et driveCapOverrideLabel: Bu kullanıcı için drive kapasitesini değiştirin numberOfPageCache: Önbelleğe alınan sayfa sayısı license: Lisans -indexFrom: Post ID'den itibaren dizin xl: XL notificationSetting: Bildirim ayarları fillAbuseReportDescription: Lütfen bu raporla ilgili ayrıntıları doldurun. Belirli @@ -1159,9 +1154,6 @@ migrationConfirm: "Hesabınızı {account} hesabına taşımak istediğinizden k emin misiniz? Bunu yaptığınızda, geri alamazsınız ve hesabınızı bir daha normal şekilde kullanamazsınız.\nAyrıca, lütfen bu cari hesabı, taşındığınız hesap olarak ayarladığınızdan emin olun." -indexFromDescription: Her gönderiyi dizine eklemek için boş bırakın -indexNotice: Şimdi indeksleniyor. Bu muhtemelen biraz zaman alacaktır, lütfen sunucunuzu - en az bir saat yeniden başlatmayın. customKaTeXMacro: Özel KaTeX makroları directNotes: Özel Mesajlar import: İçeri Aktar @@ -1292,7 +1284,6 @@ _emailUnavailable: used: Bu mail zaten kullanılıyor format: Bu mail adresi yanlış apps: Uygulamalar -findOtherInstance: Başka bir sunucu bul showWithSparkles: Parıltılarla göster showPopup: Kullanıcıları pop-up ile bilgilendirin silencedWarning: Bu sayfa, bu kullanıcılar yöneticinizin susturduğu sunuculardan olduğu diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 0905848e6a..5e73078a98 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -1199,14 +1199,11 @@ _widgets: aiscript: "Консоль AiScript" _userList: chooseList: Оберіть список - meiliStatus: Стан сервера - meiliSize: Розмір індексу rssTicker: RSS-тікер instanceCloud: Хмара серверів unixClock: Годинник UNIX userList: Список користувачів serverInfo: Інформація про сервер - meiliIndexCount: Індексовані записи _cw: hide: "Сховати" show: "Показати більше" @@ -1977,15 +1974,9 @@ caption: Автоматичний опис showAdminUpdates: Вказати, що доступна нова версія Firefish (тільки для адміністратора) defaultReaction: Емодзі реакція за замовчуванням для вихідних і вхідних записів license: Ліцензія -indexPosts: Індексувати пости -indexFrom: Індексувати записи з ID -indexFromDescription: Залиште порожнім, щоб індексувати кожен запис -indexNotice: Зараз відбувається індексація. Це, ймовірно, займе деякий час, будь ласка, - не перезавантажуйте сервер принаймні годину. signupsDisabled: Реєстрація на цьому сервері наразі відключена, але ви завжди можете зареєструватися на іншому сервері! Якщо у вас є код запрошення на цей сервер, будь ласка, введіть його нижче. -findOtherInstance: Знайти інший сервер customKaTeXMacro: Користувацькі макроси KaTeX enableCustomKaTeXMacro: Увімкнути користувацькі макроси KaTeX apps: Додатки diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 2c7790d7c8..527258bdad 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -1437,9 +1437,6 @@ _widgets: userList: Danh sách người dùng _userList: chooseList: Chọn một danh sách - meiliSize: Kích cỡ chỉ mục - meiliIndexCount: Tút đã lập chỉ mục - meiliStatus: Trạng thái máy chủ serverInfo: Thông tin máy chủ _cw: hide: "Ẩn" @@ -1911,7 +1908,6 @@ renoteMute: Ẩn lượt chia sẻ renoteUnmute: Bỏ ẩn lượt chia sẻ searchPlaceholder: Lướt Firefish edited: Đã sửa {date} {time} -findOtherInstance: Tìm máy chủ khác noThankYou: Từ chối _filters: withFile: Có file @@ -2048,8 +2044,6 @@ hiddenTagsDescription: 'Liệt kê các hashtag (không có #) mà bạn muốn noInstances: Không có máy chủ nào manageGroups: Quản lý nhóm accessibility: Khả năng tiếp cận -indexNotice: Đang lập chỉ mục. Quá trình này có thể mất một lúc, vui lòng không khởi - động lại máy chủ của bạn sau ít nhất một giờ. breakFollowConfirm: Bạn có chắc muốn xóa người theo dõi? caption: Caption tự động objectStorageS3ForcePathStyle: Sử dụng URL điểm cuối dựa trên đường dẫn @@ -2069,7 +2063,6 @@ updateAvailable: Có bản cập nhật mới! swipeOnDesktop: Cho phép vuốt kiểu điện thoại trên máy tính moveFromLabel: 'Tài khoản cũ của bạn:' defaultReaction: Biểu cảm mặc định cho những tút đã đăng và sắp đăng -indexFromDescription: Để trống để lập chỉ mục toàn bộ donationLink: Liên kết tới trang tài trợ deletePasskeys: Xóa passkey delete2faConfirm: Thao tác này sẽ xóa 2FA trên tài khoản này một cách không thể phục @@ -2086,8 +2079,6 @@ audio: Âm thanh selectInstance: Chọn máy chủ userSaysSomethingReason: '{name} cho biết {reason}' pushNotification: Thông báo đẩy -indexPosts: Chỉ mục tút -indexFrom: Chỉ mục từ Post ID customKaTeXMacro: Tùy chỉnh macro KaTeX license: Giấy phép cw: Nội dung ẩn diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 1aa187e0a9..11ef5d7303 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -31,12 +31,12 @@ uploading: "正在上传..." save: "保存" users: "用户" addUser: "添加用户" -favorite: "添加到书签" -favorites: "书签" +favorite: "添加到收藏" +favorites: "收藏" unfavorite: "取消收藏" -favorited: "已添加到书签。" -alreadyFavorited: "书签中已存在。" -cantFavorite: "无法添加到书签。" +favorited: "已添加到收藏。" +alreadyFavorited: "收藏中已存在。" +cantFavorite: "无法添加到收藏。" pin: "置顶" unpin: "取消置顶" copyContent: "复制内容" @@ -50,6 +50,7 @@ copyUsername: "复制用户名" searchUser: "搜索用户" reply: "回复" replies: "回复" +toReply: "回复" loadMore: "加载更多" showMore: "查看更多" showLess: "关闭" @@ -70,8 +71,9 @@ exportRequested: "导出请求已提交,这可能需要花一些时间,导 importRequested: "导入请求已提交,这可能需要花一点时间。" lists: "列表" noLists: "列表为空" -note: "发帖" +note: "帖子" notes: "帖子" +toPost: "发帖" following: "关注中" followers: "关注者" followsYou: "关注了您" @@ -103,6 +105,7 @@ cantRenote: "此帖子无法被转发。" cantReRenote: "转发无法被再次转发。" quote: "引用" quotes: "引用" +toQuote: "引用" pinnedNote: "已置顶的帖子" pinned: "置顶" you: "您" @@ -146,9 +149,9 @@ addEmoji: "添加表情符号" settingGuide: "推荐配置" cacheRemoteFiles: "缓存远程文件" cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程服务器载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。" -flagAsBot: "这是一个机器人账号" -flagAsBotDescription: "如果此账号由程序控制,请启用此项。启用后,此标志可以帮助其它开发人员防止机器人之间产生无限互动的行为,并让 Firefish - 的内部系统将此账号识别为机器人。" +flagAsBot: "标记此账号为自动化账号" +flagAsBotDescription: "如果此账号由程序控制,请启用此项。启用后,此标志可以帮助其它开发人员防止自动化账号之间产生无限互动的行为,并让 Firefish + 的内部系统将此账号识别为自动化账号。" flagAsCat: "将这个账号设定为一只猫😺" flagAsCatDescription: "您会长出猫耳朵并像猫一样说话!" flagShowTimelineReplies: "在时间线上显示帖子的回复" @@ -264,7 +267,7 @@ agreeTo: "我同意 {0}" tos: "服务条款" start: "开始" home: "首页" -remoteUserCaution: "由于此用户来自其它服务器,显示的信息可能不完整。" +remoteUserCaution: "由于此用户来自其它服务器,显示的信息不完整。" activity: "活动" images: "图片" birthday: "生日" @@ -589,6 +592,7 @@ tokenRequested: "允许访问账号" pluginTokenRequestedDescription: "此插件将能够拥有这里设置的权限。" notificationType: "通知类型" edit: "编辑" +toEdit: "编辑" emailServer: "邮件服务器" enableEmail: "启用发送邮件功能" emailConfigInfo: "用于确认电子邮件和密码重置" @@ -685,7 +689,7 @@ disableShowingAnimatedImages: "不播放动画" verificationEmailSent: "已发送确认电子邮件。请访问电子邮件中的链接以完成验证。" notSet: "未设置" emailVerified: "电子邮件地址已验证" -noteFavoritesCount: "加入书签的帖子数" +noteFavoritesCount: "加入收藏的帖子数" pageLikesCount: "页面点赞次数" pageLikedCount: "页面被点赞次数" contact: "联系人" @@ -869,7 +873,7 @@ recommended: "推荐" check: "检查" driveCapOverrideLabel: "修改此用户的网盘容量" driveCapOverrideCaption: "输入 0 或以下的值将容量重置为默认值。" -requireAdminForView: "需要使用管理员账号登录才能查看。" +requireAdminForView: "您需要使用管理员账号登录才能查看。" isSystemAccount: "该账号由系统自动创建。请不要修改、编辑、删除或以其它方式篡改这个账号,否则可能会破坏您的服务器。" typeToConfirm: "输入 {x} 以确认操作" deleteAccount: "删除账号" @@ -904,9 +908,9 @@ account: "账号" move: "迁移" customKaTeXMacro: "自定义 KaTeX 宏" customKaTeXMacroDescription: "使用宏来轻松的输入数学表达式吧!宏的用法与 LaTeX 中的命令定义相同。您可以使用 \\newcommand{\\ - name}{content} 或 \\newcommand{\\name}[number of arguments]{content} 来输入数学表达式。举个例子,\\ - newcommand{\\add}[2]{#1 + #2} 会将 \\add{3}{foo} 展开为 3 + foo。此外,宏名称外的花括号 {} 可以被替换为圆括号 - () 和方括号 [],这会影响用于参数的括号。每行只能够定义一个宏,无法在中间换行,且无效的行将被忽略。只支持简单字符串替换功能,不支持高级语法,如条件分支等。" + name}{content} 或 \\newcommand{\\name}[number of arguments]{content} 来输入数学表达式。举个例子, + \\newcommand{\\add}[2]{#1 + #2} 会将 \\add{3}{foo} 展开为 3 + foo 。此外,宏名称外的花括号 {} 可以被替换为圆括号 + () 和方括号 [] ,这会影响用于参数的括号。每行只能够定义一个宏,您无法在中间换行。无效的行将被忽略。只支持简单字符串替换功能,不支持高级语法,如条件分支等。" enableCustomKaTeXMacro: "启用自定义 KaTeX 宏" _sensitiveMediaDetection: description: "可以使用机器学习技术自动检测敏感媒体,以便进行审核。服务器负载将略微增加。" @@ -1127,6 +1131,7 @@ _wordMute: lang: "语言" hard: "硬过滤" mutedNotes: "已过滤的帖子" + mutePatterns: 静音表达式 _instanceMute: instanceMuteDescription: "静音列出服务器中的所有帖子和转帖,包括服务器的用户回复。" instanceMuteDescription2: "设置时用换行符来分隔" @@ -1258,7 +1263,7 @@ _2fa: step2: "然后,扫描屏幕上显示的二维码。" step2Url: "如果您使用的是桌面程序,您也可以输入这个URL:" step3: "输入您的应用提供的令牌以完成设置。" - step4: "从现在开始,任何登录操作都将要求您提供这样一个登录令牌。" + step4: "从现在开始,任何登录操作都将要求您提供这样一个令牌。" securityKeyInfo: "除了指纹或 PIN 身份验证外,您还可以通过支持 FIDO2 的硬件安全密钥设置身份验证,以进一步保护您的账号。" token: 2FA 令牌 step3Title: 输入验证码 @@ -1276,8 +1281,8 @@ _permissions: "write:blocks": "编辑屏蔽名单" "read:drive": "查看网盘" "write:drive": "管理网盘文件" - "read:favorites": "查看收藏夹" - "write:favorites": "编辑收藏夹" + "read:favorites": "查看收藏" + "write:favorites": "编辑收藏" "read:following": "查看关注信息" "write:following": "关注/取消关注其它账号" "read:messaging": "查看聊天消息" @@ -1350,9 +1355,6 @@ _widgets: aiscript: "AiScript 控制台" aichan: "小蓝" userList: 用户列表 - meiliStatus: 服务器状态 - meiliIndexCount: 已索引的帖子 - meiliSize: 索引大小 serverInfo: 服务器信息 _userList: chooseList: 选择列表 @@ -1403,7 +1405,7 @@ _postForm: b: "发生了什么?" c: "您有什么想法?" d: "您想要发布些什么吗?" - e: "请写下来吧" + e: "请写下来吧..." f: "等待您的发布..." _profile: name: "昵称" @@ -1914,13 +1916,11 @@ _skinTones: mediumDark: 中等偏深 isModerator: 监察员 isAdmin: 管理员 -findOtherInstance: 寻找其它服务器 moveFromDescription: 这将为您的旧账号设置一个别名,以便您可以从该旧账号迁移到当前账号。在从旧账号迁移之前执行此操作。请输入格式如 @person@server.com 的账号标签 -indexPosts: 索引帖子 -signupsDisabled: 该服务器目前关闭注册,但您随时可以在另一台服务器上注册!如果您有该服务器的邀请码,请在下面输入。 +signupsDisabled: 该服务器目前关闭注册。如果您有该服务器的邀请码,请在下面输入。 silencedWarning: 显示这个页面是因为这些用户来自您的管理员设置的禁言服务器,所以他们有可能是垃圾信息。 -isBot: 这个账号是一个机器人 +isBot: 这个账号是一个自动化账号 moveAccountDescription: 这个过程是不可逆的。在迁移之前,请确保您已在新账号上为当前账号设置了别名。请输入格式如 @person@server.com 账号标签 moveFromLabel: 您要迁移出的旧账号: @@ -1931,13 +1931,13 @@ moveTo: 将当前账号迁移至新账号 moveToLabel: 您要迁移到的目标账号: moveAccount: 迁移账号! migrationConfirm: "您确实确定要将账号迁移到 {account} 吗?此操作无法撤消,并且您将无法再次正常使用旧账号。\n另外,请确保您已将此当前账号设置为要移出的账号。" -indexFromDescription: 留空以索引每个帖子 noteId: 帖子 ID moveFrom: 从旧账号迁移至此账号 defaultReaction: 发出和收到帖子的默认表情符号反应 -indexNotice: 现在开始索引。这可能需要一段时间,请至少一个小时内不要重新启动服务器。 -indexFrom: 从帖子 ID 开始的索引 -sendModMail: 发送审核通知 +sendModMail: 发送管理通知 +moderationNote: "管理笔记" +ipFirstAcknowledged: "首次获取此 IP 地址的日期" +driveCapacityOverride: "网盘容量变更" isLocked: 该账号设置了关注请求 _filters: notesBefore: 帖子早于 @@ -1993,3 +1993,66 @@ openServerInfo: 点击帖子上的服务器滚动条时显示服务器信息 clickToShowPatterns: 点击显示模块模式 private: "秘密" privateDescription: "仅你可见" +_iconSets: + regular: 标准 + duotone: 双色 + fill: 填满 + bold: 加粗 + light: 减细 +emojiModPerm: 自定义表情符号管理权限 +squareCatAvatars: 猫模式账号显示圆形头像 +makePrivate: 设为私有 +makePrivateConfirm: 此操作将向远程服务器发送删除请求并将可见性更改为私有。是否继续? +_emojiModPerm: + add: 添加 + mod: 添加和编辑 + unauthorized: 未授权 + full: 全部允许 +moreUrls: 置顶页面 +enablePullToRefresh: 启用 “下拉刷新” +pullToRefreshThreshold: 触发下拉刷新所需的距离 +pullDownToReload: 下拉刷新 +releaseToReload: 释放刷新 +reloading: 刷新中 +attachedToNotes: 带有此附件的帖子 +showAttachedNotes: 显示有此附件的帖子 +iconSet: 图标样式 +moreUrlsDescription: "请您使用以下形式输入要固定到左下角帮助菜单的页面,每行一个:\n\"显示名称\": https://example.com/" +useCdn: 从 CDN 获取资源 +useCdnDescription: 从 JSDelivr CDN(而不是 Firefish 服务器)加载一些静态资源,例如 Twemoji。 +showBigPostButton: 在发帖表单上显示一个巨大的发帖按钮 +suggested: 建议 +noLanguage: 无语言 +showPreviewByDefault: 默认以发布形式显示预览 +preventMisclick: 预防误触 +hideFollowButtons: 隐藏会误触的关注按钮 +forMobile: 移动设备 +replaceChatButtonWithAccountButton: 将聊天按钮替换为帐户切换按钮 +replaceWidgetsButtonWithReloadButton: 将小部件按钮替换为重新加载按钮 +searchEngine: 搜索栏 MFM 中使用的搜索引擎 +postSearch: 在此服务器上搜索帖子 +enableTimelineStreaming: 自动更新时间线 +emojiModPermDescription: "添加:允许该用户添加新的自定义表情符号,并为新添加的自定义表情符号设置标签/类别/授权。\n添加和编辑:在 “添加” + 权限的基础上,允许该用户编辑现有自定义表情符号的名称/类别/标签/授权。\n全部允许:在 “添加和编辑” 权限的基础上,允许该用户删除现有的自定义表情符号。" +replyMute: 静音回复 +replyUnmute: 取消静音回复 +searchWords: 要搜索的关键词 / 要查询的用户 ID 或 URL +searchRange: 发表于(可选) +searchUsers: 发布者(可选) +searchUsersDescription: "要搜索特定用户/服务器的帖子,请输入 ID(@user@example.com,或 @user 对于本地用户)或域名(example.com)。\n + \n如果您输入 'me' (不带引号),您的所有帖子(包括不公开的帖子、仅限关注者的帖子、直接帖子和秘密帖子)都会被搜索。\n\n如果您输入 'local' (不带引号),结果将被过滤以仅包含来自该服务器的帖子。" +searchPostsWithFiles: 只带有文件的帖子 +searchCwAndAlt: 包括内容警告和文件描述 +publishTimelines: 为访客发布时间线 +publishTimelinesDescription: 如果启用,在用户登出时本地和全局时间线也会显示在 {url} 上。 +searchWordsDescription: "在此处输入搜索词以搜索帖子。交集搜索关键词之间使用空格进行区分,并集搜索关键词之间使用 OR 进行区分。\n例如 + '早上 晚上' 将查找包含 '早上' 和 '晚上' 的帖子,而 '早上 OR 晚上' 将查找包含 '早上' 或 '晚上' (以及同时包含两者)的帖子。\n您还可以组合交集/并集条件,例如 + '(早上 OR 晚上) 困了' 。\n如果您想搜索单词序列(例如一个英语句子),您必须将其放在双引号中,例如 \"Today I learned\" 以区分于交集搜索。\n + \n如果您想转到特定的用户页面或帖子页面,请在此字段中输入用户 ID 或 URL,然后单击 “查询” 按钮。 单击 “搜索” 将搜索字面包含用户 ID/URL + 的帖子。" +searchRangeDescription: "如果您要过滤时间段,请按以下格式输入:20220615-20231031\n\n如果您省略年份(例如 0105-0106 + 或 20231105-0110),它将被解释为当前年份。\n\n您还可以省略开始日期或结束日期。 例如 -0102 将过滤搜索结果以仅显示今年 1 月 2 日之前发布的帖子,而 + 20231026- 将过滤结果以仅显示 2023 年 10 月 26 日之后发布的帖子。" +messagingUnencryptedInfo: "Firefish 上的聊天没有经过端到端加密,请不要在聊天中分享您的敏感信息。" +noAltTextWarning: 有些附件没有描述。您是否忘记写描述了? +showNoAltTextWarning: 当您尝试发布没有描述的帖子附件时显示警告 diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index ae89e38ae8..06fda725f8 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -50,6 +50,7 @@ copyUsername: "複製使用者名稱" searchUser: "搜尋使用者" reply: "回覆" replies: "回覆" +toReply: "回覆" loadMore: "載入更多" showMore: "載入更多" showLess: "關閉" @@ -72,6 +73,7 @@ lists: "清單" noLists: "你沒有任何清單" note: "貼文" notes: "貼文" +toPost: "發貼文" following: "追隨中" followers: "追隨者" followsYou: "追隨你的人" @@ -103,6 +105,7 @@ cantRenote: "無法轉發此貼文。" cantReRenote: "無法轉發之前已經轉發過的內容。" quote: "引用" quotes: "引用" +toQuote: "引用" pinnedNote: "已置頂的貼文" pinned: "置頂" you: "您" @@ -585,6 +588,7 @@ tokenRequested: "允許存取帳戶" pluginTokenRequestedDescription: "此外掛將擁有在此設定的權限。" notificationType: "通知形式" edit: "編輯" +toEdit: "編輯" emailServer: "電郵伺服器" enableEmail: "啟用發送電郵功能" emailConfigInfo: "用於確認電郵地址及密碼重置" @@ -789,7 +793,7 @@ previewNoteText: "預覽文本" customCss: "自定義 CSS" customCssWarn: "這個設定必須由具備相關知識的人員操作,不當的設定可能导致客戶端無法正常使用。" global: "公開" -squareAvatars: "大頭貼以方形顯示" +squareAvatars: "以方形顯示非貓使用者的大頭貼" sent: "發送" received: "收取" searchResult: "搜尋結果" @@ -831,7 +835,7 @@ voteConfirm: "確定投給「{choice}」?" hide: "隱藏" leaveGroup: "離開群組" leaveGroupConfirm: "確定離開「{name}」?" -useDrawerReactionPickerForMobile: "在移動設備上使用抽屜顯示" +useDrawerReactionPickerForMobile: "在手機版使用抽屜顯示" welcomeBackWithName: "歡迎回來,{name}" clickToFinishEmailVerification: "點擊 [{ok}] 完成電子郵件地址認證。" overridedDeviceKind: "裝置類型" @@ -1123,6 +1127,7 @@ _wordMute: langDescription: 將指定語言的貼文從時間軸中隱藏。 muteLangs: 被靜音的語言 muteLangsDescription: OR條件以空格或換行進行分隔。 + mutePatterns: 靜音表達式 _instanceMute: instanceMuteDescription: "將設定的伺服器的所有貼文及轉發靜音。對被靜音伺服器的使用者的回覆也將被靜音。" instanceMuteDescription2: "設定時以換行進行分隔" @@ -1337,7 +1342,7 @@ _widgets: unixClock: "UNIX時間" federation: "聯邦宇宙" instanceCloud: "伺服器雲" - postForm: "發佈窗口" + postForm: "發文介面" slideshow: "幻燈片" button: "按鈕" onlineUsers: "線上的使用者" @@ -1349,9 +1354,6 @@ _widgets: userList: 使用者列表 _userList: chooseList: 選擇一個清單 - meiliIndexCount: 編入索引的帖子 - meiliStatus: 伺服器狀態 - meiliSize: 索引大小 _cw: hide: "隱藏" show: "瀏覽更多" @@ -1872,15 +1874,12 @@ _experiments: enablePostImports: 啟用匯入貼文的功能 postImportsCaption: 允許使用者從舊有的Firefish・Misskey・Mastodon・Akkoma・Pleroma帳號匯入貼文。在伺服器佇列堵塞時匯入貼文可能會導致載入速度變慢。 -findOtherInstance: 找找另一個伺服器 noGraze: 瀏覽器擴充元件 "Graze for Mastodon" 會與Firefish發生衝突,請停用該擴充元件。 userSaysSomethingReasonRenote: '{name} 轉發了包含 {reason} 的貼文' pushNotificationNotSupported: 你的瀏覽器或伺服器不支援推送通知 accessibility: 輔助功能 userSaysSomethingReasonReply: '{name} 回覆了包含 {reason} 的貼文' hiddenTags: 隱藏主題標籤 -indexPosts: 索引貼文 -indexNotice: 現在開始索引。 這可能需要一段時間,請不要在一個小時內重啟你的伺服器。 deleted: 已刪除 editNote: 編輯貼文 edited: '於 {date} {time} 編輯' @@ -1925,16 +1924,14 @@ sendModMail: 發送審核通知 enableIdenticonGeneration: 啟用Identicon生成 enableServerMachineStats: 啟用伺服器硬體統計資訊 reactionPickerSkinTone: 首選表情符號膚色 -indexFromDescription: 留空以索引每個貼文 preventAiLearning: 防止 AI 機器人抓取 preventAiLearningDescription: 請求第三方 AI 語言模型不要研究您上傳的內容,例如貼文和圖像。 -indexFrom: 建立此貼文ID以後的索引 isLocked: 該帳戶已獲得以下批准 isModerator: 板主 isAdmin: 管理員 isPatron: Firefish 項目贊助者 silencedWarning: 顯示此頁面是因為這些使用者來自您伺服器管理員已靜音的伺服器,因此他們可能是垃圾訊息。 -signupsDisabled: 此伺服器目前停止註冊,但您隨時可以在另一台伺服器上註冊!如果您有此伺服器的邀請碼,請在下面輸入。 +signupsDisabled: 此伺服器目前停止註冊。如果您有此伺服器的邀請碼,請在下面輸入。 showPopup: 通過彈出式視窗通知使用者 showWithSparkles: 讓標題閃閃發光 youHaveUnreadAnnouncements: 您有未讀的公告 @@ -2010,3 +2007,50 @@ private: "祕密" privateDescription: "僅你可見" makePrivate: "設為祕密" makePrivateConfirm: "此操作將向遠端伺服器發送刪除請求,並將貼文的公開範圍設為「祕密」。是否繼續?" +squareCatAvatars: 以方形顯示貓咪使用者的大頭貼 +showBigPostButton: 放大發文介面中的貼文按鈕 +emojiModPerm: 自訂表情符號的管理權限 +emojiModPermDescription: "新增: 允許新增自訂表情符號,並允許設定尚未設定標籤/類別/授權條款的現有自訂表情符號。\n新增及編輯: 除了「新增」的權限之外,也允許編輯現有自訂表情符號的標籤/類別/授權條款\n + 全部允許: 除了「新增及編輯」的權限之外,也允許刪除現有的自訂表情符號。" +_emojiModPerm: + full: 全部允許 + unauthorized: 不允許 + add: 新增 + mod: 新增及編輯 +replyMute: 靜音回覆貼文 +useCdn: 從 CDN 獲取資源 +useCdnDescription: 從 JSDelivr CDN(而非此 Firefish 伺服器)載入 Twemoji 等的靜態資源。 +replyUnmute: 解除靜音回覆貼文 +suggested: 建議 +noLanguage: 無語言 +forMobile: 手機版 +replaceChatButtonWithAccountButton: 將頁面下方的「傳送訊息按鈕」替換成「切換帳戶按鈕」 +replaceWidgetsButtonWithReloadButton: 將頁面下方的「小工具按鈕」替換成「重新整理按鈕」 +postSearch: 在此伺服器搜尋貼文 +searchWords: 搜尋關鍵字 / 查詢的ID或URL +searchEngine: MFM搜尋欄使用的搜尋引擎 +enablePullToRefresh: 啟用「下拉重新整理」 +pullToRefreshThreshold: 觸發下拉重新整理所需的距離 +pullDownToReload: 下拉重新整理 +releaseToReload: 放開以重新整理 +reloading: 重新整理中 +enableTimelineStreaming: 自動更新時間軸 +searchUsers: 發文者(選填) +searchRange: 日期範圍(選填) +searchPostsWithFiles: 僅帶有附件的貼文 +searchCwAndAlt: 包含內容警告及替代文字 +publishTimelines: 允許未登入的使用者查看時間軸 +publishTimelinesDescription: 啟用後,未登入的使用者可於 {url} 查看本地時間軸及公開時間軸。 +searchWordsDescription: "請在此欄位輸入欲搜尋的關鍵字。以空格分隔關鍵字以進行AND搜尋,在關鍵字之間插入「OR」以進行OR搜尋。\n舉例來說,輸入「早上 + 晚上」會搜尋包含「早上」和「晚上」的貼文,「早上 OR 晚上」會搜尋包含「早上」或「晚上」(或兩者皆包含)的貼文。\n您也可以同時進行AND搜尋及OR搜尋,例如「(早上 + OR 晚上) 想睡覺」。\n如欲搜尋包含空白的字串,請使用雙引號 (\") 以與AND搜尋進行區別,例如「\"Today I learned\"」。\n\n如欲前往特定使用者或貼文的頁面,請在此欄位輸入使用者ID(@user@example.com)或貼文的URL,並點擊「查詢」按鈕。點擊「搜尋」按鈕則會搜尋字面上包含輸入的ID或URL的貼文。" +searchUsersDescription: "如欲搜尋特定使用者的貼文,請以「@user@example.com(本地使用者則為 @user)」的格式輸入發文者的ID,或輸入網域名稱(example.com)以搜尋特定伺服器的貼文。\n\ + \n輸入「me」以搜尋自己的所有貼文(包含不在主頁顯示、追隨者、指定使用者、祕密貼文)。\n\n輸入「local」以搜尋本地伺服器的貼文。" +searchRangeDescription: "如欲搜尋特定期間的貼文,請以「20220615-20231031」的格式輸入日期範圍。\n\n今年的日期可省略年份(例如0105-0106、20231105-0110)。\n\ + \n開始日期和結果日期可擇一省略。舉例來說,「-0102」表示僅搜尋今年1月2日為止的貼文,「20231026-」表示僅搜尋2023年10月26日以後的貼文。" +noAltTextWarning: 有些附件沒有說明,您是否忘記寫了? +moderationNote: 管理員備註 +ipFirstAcknowledged: 首次取得此 IP 位址的日期 +driveCapacityOverride: 雲端硬碟容量變更 +showNoAltTextWarning: 在嘗試發佈包含沒有替代文字的貼文時顯示警告 +messagingUnencryptedInfo: Firefish 上的聊天沒有經過點對點加密,請不要發送敏感資訊。 diff --git a/package.json b/package.json index a860ad932d..2756498452 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "firefish", - "version": "20240301", + "version": "20240319", "repository": { "type": "git", "url": "https://firefish.dev/firefish/firefish.git" }, - "packageManager": "pnpm@8.15.4", + "packageManager": "pnpm@8.15.5", "private": true, "scripts": { "rebuild": "pnpm run clean && pnpm run build", @@ -14,14 +14,11 @@ "start:container": "pnpm run gulp && pnpm run migrate && pnpm run start", "start:test": "pnpm --filter backend run start:test", "init": "pnpm run migrate", - "migrate": "pnpm --filter backend run migrate", - "revertmigration": "pnpm --filter backend run revertmigration", + "migrate": "pnpm --filter backend run migration:run", + "revertmigration": "pnpm --filter backend run migration:revert", "gulp": "gulp build", "watch": "pnpm run dev", "dev": "pnpm node ./scripts/dev.mjs", - "dev:up": "pnpm node ./scripts/dev-up.mjs", - "dev:down": "pnpm node ./scripts/dev-down.mjs", - "dev:init": "pnpm run dev:down && pnpm run dev:up", "dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start", "lint": "pnpm -r --parallel run lint", "debug": "pnpm run build:debug && pnpm run start", @@ -32,28 +29,24 @@ "clean": "pnpm node ./scripts/clean-built.mjs", "clean-npm": "pnpm node ./scripts/clean-npm.mjs", "clean-cargo": "pnpm node ./scripts/clean-cargo.mjs", - "clean-all": "pnpm run clean && pnpm run clean-cargo && pnpm run clean-npm", - "entities": "pnpm node ./scripts/regenerate-sea-orm-entities.mjs" + "clean-all": "pnpm run clean && pnpm run clean-cargo && pnpm run clean-npm" }, "dependencies": { "js-yaml": "4.1.0", "gulp": "4.0.2", "gulp-cssnano": "2.1.3", - "gulp-rename": "2.0.0", "gulp-replace": "1.1.4", "gulp-terser": "2.1.0" }, "devDependencies": { - "@biomejs/biome": "1.5.3", - "@biomejs/cli-darwin-arm64": "^1.5.3", - "@biomejs/cli-darwin-x64": "^1.5.3", - "@biomejs/cli-linux-arm64": "^1.5.3", - "@biomejs/cli-linux-x64": "^1.5.3", - "@types/gulp": "4.0.17", - "@types/gulp-rename": "2.0.6", - "@types/node": "20.11.21", + "@biomejs/biome": "1.6.2", + "@biomejs/cli-darwin-arm64": "^1.6.2", + "@biomejs/cli-darwin-x64": "^1.6.2", + "@biomejs/cli-linux-arm64": "^1.6.2", + "@biomejs/cli-linux-x64": "^1.6.2", + "@types/node": "20.11.30", "execa": "8.0.1", - "pnpm": "8.15.4", - "typescript": "5.3.3" + "pnpm": "8.15.5", + "typescript": "5.4.3" } } diff --git a/packages/backend-rs/Cargo.lock b/packages/backend-rs/Cargo.lock index 38ca51f3da..99e3b27428 100644 --- a/packages/backend-rs/Cargo.lock +++ b/packages/backend-rs/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -44,9 +44,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -80,9 +80,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arrayvec" @@ -157,18 +157,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -180,16 +180,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atomic-write-file" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" -dependencies = [ - "nix", - "rand", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -205,7 +195,6 @@ dependencies = [ "cfg-if", "chrono", "cuid2", - "derive_more", "jsonschema", "napi", "napi-build", @@ -220,14 +209,13 @@ dependencies = [ "serde_json", "thiserror", "tokio", - "utoipa", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -290,9 +278,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -338,15 +326,15 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", "syn_derive", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytecheck" @@ -384,18 +372,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -411,9 +396,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", @@ -421,14 +406,14 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] name = "clap" -version = "4.5.0" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" dependencies = [ "clap_builder", "clap_derive", @@ -436,9 +421,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -448,14 +433,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -476,12 +461,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "convert_case" version = "0.6.0" @@ -558,12 +537,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -616,19 +595,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", -] - [[package]] name = "diff" version = "0.1.13" @@ -655,9 +621,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" @@ -892,9 +858,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -924,7 +890,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.8", + "ahash 0.8.11", "allocator-api2", ] @@ -947,10 +913,16 @@ dependencies = [ ] [[package]] -name = "hermit-abi" -version = "0.3.5" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -987,9 +959,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1078,13 +1050,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.3" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", - "serde", ] [[package]] @@ -1095,7 +1066,7 @@ checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -1130,9 +1101,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1143,7 +1114,7 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978" dependencies = [ - "ahash 0.8.8", + "ahash 0.8.11", "anyhow", "base64", "bytecount", @@ -1193,12 +1164,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.4", ] [[package]] @@ -1236,9 +1207,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "md-5" @@ -1279,9 +1250,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1290,11 +1261,11 @@ dependencies = [ [[package]] name = "napi" -version = "2.15.1" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43792514b0c95c5beec42996da0c1b39265b02b75c97baa82d163d3ef55cbfa7" +checksum = "54a63d0570e4c3e0daf7a8d380563610e159f538e20448d6c911337246f40e84" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "ctor", "napi-derive", "napi-sys", @@ -1304,37 +1275,37 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.1.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" +checksum = "2f9130fccc5f763cf2069b34a089a18f0d0883c66aceb81f2fad541a3d823c43" [[package]] name = "napi-derive" -version = "2.15.1" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d56bb899c164ab1be5e542ae7db8b26750c864bf2eef07295f17754e6358777" +checksum = "05bb7c37e3c1dda9312fdbe4a9fc7507fca72288ba154ec093e2d49114e727ce" dependencies = [ "cfg-if", - "convert_case 0.6.0", + "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] name = "napi-derive-backend" -version = "1.0.60" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cf2d74ac66fd1cccb646be75fdd1c1dce8acfe20a68f61566a31da0d3eb9786" +checksum = "f785a8b8d7b83e925f5aa6d2ae3c159d17fe137ac368dc185bef410e7acdaeb4" dependencies = [ - "convert_case 0.6.0", + "convert_case", "once_cell", "proc-macro2", "quote", "regex", "semver", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -1346,17 +1317,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -1523,11 +1483,11 @@ version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec4c6225c69b4ca778c0aea097321a64c421cf4577b331c61b229267edabb6f8" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -1576,7 +1536,7 @@ dependencies = [ "regex", "regex-syntax 0.7.5", "structmeta", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -1635,9 +1595,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "powerfmt" @@ -1696,9 +1656,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1779,9 +1739,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -1791,9 +1751,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1823,9 +1783,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.24" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64", "bytes", @@ -1859,16 +1819,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1942,22 +1903,13 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -1996,9 +1948,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schemars" @@ -2047,18 +1999,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bd3534a9978d0aa7edd2808dc1f8f31c4d0ecd31ddf71d997b3c98e9f3c9114" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] name = "sea-orm" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6632f499b80cc6aaa781b302e4c9fae663e0e3dcf2640e9d80034d5b10731efe" +checksum = "c8814e37dc25de54398ee62228323657520b7f29713b8e238649385dbe473ee0" dependencies = [ "async-stream", "async-trait", @@ -2084,15 +2036,15 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec13bfb4c4aef208f68dbea970dd40d13830c868aa8dcb4e106b956e6bb4f2fa" +checksum = "5e115c6b078e013aa963cc2d38c196c2c40b05f03d0ac872fe06b6e0d5265603" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "sea-bae", - "syn 2.0.48", + "syn 2.0.53", "unicode-ident", ] @@ -2137,28 +2089,28 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -2174,9 +2126,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -2263,18 +2215,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2315,9 +2267,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2328,11 +2280,11 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" dependencies = [ - "ahash 0.8.8", + "ahash 0.8.11", "atoi", "bigdecimal", "byteorder", @@ -2340,7 +2292,6 @@ dependencies = [ "chrono", "crc", "crossbeam-queue", - "dotenvy", "either", "event-listener", "futures-channel", @@ -2376,9 +2327,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" dependencies = [ "proc-macro2", "quote", @@ -2389,14 +2340,13 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" dependencies = [ - "atomic-write-file", "dotenvy", "either", - "heck", + "heck 0.4.1", "hex", "once_cell", "proc-macro2", @@ -2416,14 +2366,14 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64", "bigdecimal", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "bytes", "chrono", @@ -2463,14 +2413,14 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64", "bigdecimal", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "chrono", "crc", @@ -2494,7 +2444,6 @@ dependencies = [ "rust_decimal", "serde", "serde_json", - "sha1", "sha2", "smallvec", "sqlx-core", @@ -2508,9 +2457,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ "atoi", "chrono", @@ -2564,7 +2513,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -2575,7 +2524,7 @@ checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -2603,9 +2552,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -2621,7 +2570,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -2659,9 +2608,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", @@ -2671,22 +2620,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -2762,14 +2711,14 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -2833,7 +2782,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] @@ -2871,9 +2820,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -2919,35 +2868,11 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "utoipa" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "272ebdfbc99111033031d2f10e018836056e4d2c8e2acda76450ec7974269fa7" -dependencies = [ - "indexmap", - "serde", - "serde_json", - "utoipa-gen", -] - -[[package]] -name = "utoipa-gen" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c9f4d08338c1bfa70dde39412a040a884c6f318b3d09aaaf3437a1e52027fc" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "serde", ] @@ -2980,10 +2905,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.91" +name = "wasite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2991,24 +2922,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -3018,9 +2949,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3028,28 +2959,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -3063,9 +2994,13 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "whoami" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +dependencies = [ + "redox_syscall", + "wasite", +] [[package]] name = "windows-core" @@ -3073,7 +3008,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -3091,7 +3026,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -3111,17 +3046,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -3132,9 +3067,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -3144,9 +3079,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -3156,9 +3091,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -3168,9 +3103,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -3180,9 +3115,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -3192,9 +3127,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -3204,9 +3139,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" @@ -3259,7 +3194,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.53", ] [[package]] diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index 38d88cf3e7..3aecbef10a 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -12,33 +12,31 @@ napi = ["dep:napi", "dep:napi-derive"] crate-type = ["cdylib", "lib"] [dependencies] -async-trait = "0.1.75" +async-trait = "0.1.78" cfg-if = "1.0.0" -chrono = "0.4.31" +chrono = "0.4.35" cuid2 = "0.1.2" -derive_more = "0.99.17" jsonschema = "0.17.1" once_cell = "1.19.0" parse-display = "0.8.2" rand = "0.8.5" schemars = { version = "0.8.16", features = ["chrono"] } -sea-orm = { version = "0.12.10", features = ["sqlx-postgres", "runtime-tokio-rustls"] } -serde = { version = "1.0.193", features = ["derive"] } -serde_json = "1.0.108" -thiserror = "1.0.52" -tokio = { version = "1.35.1", features = ["full"] } -utoipa = "4.1.0" +sea-orm = { version = "0.12.15", features = ["sqlx-postgres", "runtime-tokio-rustls"] } +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.114" +thiserror = "1.0.58" +tokio = { version = "1.36.0", features = ["full"] } # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix -napi = { version = "2.14.1", default-features = false, features = ["napi6", "tokio_rt"], optional = true } -napi-derive = { version = "2.14.5", optional = true } +napi = { version = "2.16.0", default-features = false, features = ["napi9", "tokio_rt"], optional = true } +napi-derive = { version = "2.16.0", optional = true } basen = "0.1.0" [dev-dependencies] pretty_assertions = "1.4.0" [build-dependencies] -napi-build = "2.1.0" +napi-build = "2.1.2" [profile.release] lto = true diff --git a/packages/backend-rs/Makefile b/packages/backend-rs/Makefile new file mode 100644 index 0000000000..9411ab9d0d --- /dev/null +++ b/packages/backend-rs/Makefile @@ -0,0 +1,11 @@ +.PHONY: regenerate-entities +regenerate-entities: + sea-orm-cli generate entity \ + --output-dir='src/model/entity' \ + --database-url='postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@localhost:25432/$(POSTGRES_DB)' + +index.js: + NODE_OPTIONS='--max_old_space_size=3072' pnpm run build:debug + [ -f built/index.js ] + rm --force index.js + cp built/index.js index.js diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js new file mode 100644 index 0000000000..94960878f3 --- /dev/null +++ b/packages/backend-rs/index.js @@ -0,0 +1,305 @@ +/* tslint:disable */ +/* eslint-disable */ +/* prettier-ignore */ + +/* auto-generated by NAPI-RS */ + +const { existsSync, readFileSync } = require('fs') +const { join } = require('path') + +const { platform, arch } = process + +let nativeBinding = null +let localFileExisted = false +let loadError = null + +function isMusl() { + // For Node 10 + if (!process.report || typeof process.report.getReport !== 'function') { + try { + const lddPath = require('child_process').execSync('which ldd').toString().trim() + return readFileSync(lddPath, 'utf8').includes('musl') + } catch (e) { + return true + } + } else { + const { glibcVersionRuntime } = process.report.getReport().header + return !glibcVersionRuntime + } +} + +switch (platform) { + case 'android': + switch (arch) { + case 'arm64': + localFileExisted = existsSync(join(__dirname, 'backend-rs.android-arm64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.android-arm64.node') + } else { + nativeBinding = require('backend-rs-android-arm64') + } + } catch (e) { + loadError = e + } + break + case 'arm': + localFileExisted = existsSync(join(__dirname, 'backend-rs.android-arm-eabi.node')) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.android-arm-eabi.node') + } else { + nativeBinding = require('backend-rs-android-arm-eabi') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Android ${arch}`) + } + break + case 'win32': + switch (arch) { + case 'x64': + localFileExisted = existsSync( + join(__dirname, 'backend-rs.win32-x64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.win32-x64-msvc.node') + } else { + nativeBinding = require('backend-rs-win32-x64-msvc') + } + } catch (e) { + loadError = e + } + break + case 'ia32': + localFileExisted = existsSync( + join(__dirname, 'backend-rs.win32-ia32-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.win32-ia32-msvc.node') + } else { + nativeBinding = require('backend-rs-win32-ia32-msvc') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'backend-rs.win32-arm64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.win32-arm64-msvc.node') + } else { + nativeBinding = require('backend-rs-win32-arm64-msvc') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Windows: ${arch}`) + } + break + case 'darwin': + localFileExisted = existsSync(join(__dirname, 'backend-rs.darwin-universal.node')) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.darwin-universal.node') + } else { + nativeBinding = require('backend-rs-darwin-universal') + } + break + } catch {} + switch (arch) { + case 'x64': + localFileExisted = existsSync(join(__dirname, 'backend-rs.darwin-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.darwin-x64.node') + } else { + nativeBinding = require('backend-rs-darwin-x64') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'backend-rs.darwin-arm64.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.darwin-arm64.node') + } else { + nativeBinding = require('backend-rs-darwin-arm64') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on macOS: ${arch}`) + } + break + case 'freebsd': + if (arch !== 'x64') { + throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) + } + localFileExisted = existsSync(join(__dirname, 'backend-rs.freebsd-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.freebsd-x64.node') + } else { + nativeBinding = require('backend-rs-freebsd-x64') + } + } catch (e) { + loadError = e + } + break + case 'linux': + switch (arch) { + case 'x64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-x64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-x64-musl.node') + } else { + nativeBinding = require('backend-rs-linux-x64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-x64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-x64-gnu.node') + } else { + nativeBinding = require('backend-rs-linux-x64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-arm64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-arm64-musl.node') + } else { + nativeBinding = require('backend-rs-linux-arm64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-arm64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-arm64-gnu.node') + } else { + nativeBinding = require('backend-rs-linux-arm64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm': + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-arm-gnueabihf.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-arm-gnueabihf.node') + } else { + nativeBinding = require('backend-rs-linux-arm-gnueabihf') + } + } catch (e) { + loadError = e + } + break + case 'riscv64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-riscv64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-riscv64-musl.node') + } else { + nativeBinding = require('backend-rs-linux-riscv64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-riscv64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-riscv64-gnu.node') + } else { + nativeBinding = require('backend-rs-linux-riscv64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 's390x': + localFileExisted = existsSync( + join(__dirname, 'backend-rs.linux-s390x-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./backend-rs.linux-s390x-gnu.node') + } else { + nativeBinding = require('backend-rs-linux-s390x-gnu') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Linux: ${arch}`) + } + break + default: + throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`) +} + +if (!nativeBinding) { + if (loadError) { + throw loadError + } + throw new Error(`Failed to load native binding`) +} + +const { nativeRandomStr, IdConvertType, convertId, nativeGetTimestamp, nativeCreateId, nativeInitIdGenerator } = nativeBinding + +module.exports.nativeRandomStr = nativeRandomStr +module.exports.IdConvertType = IdConvertType +module.exports.convertId = convertId +module.exports.nativeGetTimestamp = nativeGetTimestamp +module.exports.nativeCreateId = nativeCreateId +module.exports.nativeInitIdGenerator = nativeInitIdGenerator diff --git a/packages/backend-rs/package.json b/packages/backend-rs/package.json index 72c76c6e57..94f1517448 100644 --- a/packages/backend-rs/package.json +++ b/packages/backend-rs/package.json @@ -21,10 +21,9 @@ ] } }, - "license": "MIT", "devDependencies": { "@napi-rs/cli": "2.18.0", - "ava": "6.1.1" + "ava": "6.1.2" }, "ava": { "timeout": "3m" diff --git a/packages/backend-rs/src/model/entity/abuse_user_report.rs b/packages/backend-rs/src/model/entity/abuse_user_report.rs index 719699bc9c..51b18eba56 100644 --- a/packages/backend-rs/src/model/entity/abuse_user_report.rs +++ b/packages/backend-rs/src/model/entity/abuse_user_report.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/access_token.rs b/packages/backend-rs/src/model/entity/access_token.rs index d1f46daa32..4f37c58307 100644 --- a/packages/backend-rs/src/model/entity/access_token.rs +++ b/packages/backend-rs/src/model/entity/access_token.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/ad.rs b/packages/backend-rs/src/model/entity/ad.rs index 13c2a0e732..4ffbf53456 100644 --- a/packages/backend-rs/src/model/entity/ad.rs +++ b/packages/backend-rs/src/model/entity/ad.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/announcement.rs b/packages/backend-rs/src/model/entity/announcement.rs index ff98cfb863..999673adb5 100644 --- a/packages/backend-rs/src/model/entity/announcement.rs +++ b/packages/backend-rs/src/model/entity/announcement.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/announcement_read.rs b/packages/backend-rs/src/model/entity/announcement_read.rs index cbc0f9d719..a91214fd81 100644 --- a/packages/backend-rs/src/model/entity/announcement_read.rs +++ b/packages/backend-rs/src/model/entity/announcement_read.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/antenna.rs b/packages/backend-rs/src/model/entity/antenna.rs index 7c0f4b7392..c48579d41e 100644 --- a/packages/backend-rs/src/model/entity/antenna.rs +++ b/packages/backend-rs/src/model/entity/antenna.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::AntennaSrcEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/app.rs b/packages/backend-rs/src/model/entity/app.rs index ff1e378fcf..86db6e99a1 100644 --- a/packages/backend-rs/src/model/entity/app.rs +++ b/packages/backend-rs/src/model/entity/app.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/attestation_challenge.rs b/packages/backend-rs/src/model/entity/attestation_challenge.rs index 65598cb70c..1ed507af33 100644 --- a/packages/backend-rs/src/model/entity/attestation_challenge.rs +++ b/packages/backend-rs/src/model/entity/attestation_challenge.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/auth_session.rs b/packages/backend-rs/src/model/entity/auth_session.rs index 6347ff2ea8..81cabf219a 100644 --- a/packages/backend-rs/src/model/entity/auth_session.rs +++ b/packages/backend-rs/src/model/entity/auth_session.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/blocking.rs b/packages/backend-rs/src/model/entity/blocking.rs index 440189fac5..3a00281850 100644 --- a/packages/backend-rs/src/model/entity/blocking.rs +++ b/packages/backend-rs/src/model/entity/blocking.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/channel.rs b/packages/backend-rs/src/model/entity/channel.rs index 1ebf7bc9d5..dcad55ddda 100644 --- a/packages/backend-rs/src/model/entity/channel.rs +++ b/packages/backend-rs/src/model/entity/channel.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/channel_following.rs b/packages/backend-rs/src/model/entity/channel_following.rs index eee89c3a5e..ca7af1e1ba 100644 --- a/packages/backend-rs/src/model/entity/channel_following.rs +++ b/packages/backend-rs/src/model/entity/channel_following.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/channel_note_pining.rs b/packages/backend-rs/src/model/entity/channel_note_pining.rs index c9494209e9..61befb8cf9 100644 --- a/packages/backend-rs/src/model/entity/channel_note_pining.rs +++ b/packages/backend-rs/src/model/entity/channel_note_pining.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/clip.rs b/packages/backend-rs/src/model/entity/clip.rs index e401f69e3b..23f748a6dd 100644 --- a/packages/backend-rs/src/model/entity/clip.rs +++ b/packages/backend-rs/src/model/entity/clip.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/clip_note.rs b/packages/backend-rs/src/model/entity/clip_note.rs index f4b73bf10d..be6f01ac0a 100644 --- a/packages/backend-rs/src/model/entity/clip_note.rs +++ b/packages/backend-rs/src/model/entity/clip_note.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/drive_file.rs b/packages/backend-rs/src/model/entity/drive_file.rs index 1a7a0f35b1..249d711796 100644 --- a/packages/backend-rs/src/model/entity/drive_file.rs +++ b/packages/backend-rs/src/model/entity/drive_file.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; @@ -64,6 +64,8 @@ pub enum Relation { DriveFolder, #[sea_orm(has_many = "super::messaging_message::Entity")] MessagingMessage, + #[sea_orm(has_many = "super::note_file::Entity")] + NoteFile, #[sea_orm(has_many = "super::page::Entity")] Page, #[sea_orm( @@ -94,6 +96,12 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteFile.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::Page.def() diff --git a/packages/backend-rs/src/model/entity/drive_folder.rs b/packages/backend-rs/src/model/entity/drive_folder.rs index 0084e7444b..f0c3bfc3ad 100644 --- a/packages/backend-rs/src/model/entity/drive_folder.rs +++ b/packages/backend-rs/src/model/entity/drive_folder.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/emoji.rs b/packages/backend-rs/src/model/entity/emoji.rs index ea95982fbd..36aad826cc 100644 --- a/packages/backend-rs/src/model/entity/emoji.rs +++ b/packages/backend-rs/src/model/entity/emoji.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/follow_request.rs b/packages/backend-rs/src/model/entity/follow_request.rs index 7356ec35fc..b71814ebd5 100644 --- a/packages/backend-rs/src/model/entity/follow_request.rs +++ b/packages/backend-rs/src/model/entity/follow_request.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/following.rs b/packages/backend-rs/src/model/entity/following.rs index 735700f5a2..d0fe6d1a87 100644 --- a/packages/backend-rs/src/model/entity/following.rs +++ b/packages/backend-rs/src/model/entity/following.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/gallery_like.rs b/packages/backend-rs/src/model/entity/gallery_like.rs index af63727231..edb0bb5a3f 100644 --- a/packages/backend-rs/src/model/entity/gallery_like.rs +++ b/packages/backend-rs/src/model/entity/gallery_like.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/gallery_post.rs b/packages/backend-rs/src/model/entity/gallery_post.rs index 15b3ccc930..ab8f1dab42 100644 --- a/packages/backend-rs/src/model/entity/gallery_post.rs +++ b/packages/backend-rs/src/model/entity/gallery_post.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/hashtag.rs b/packages/backend-rs/src/model/entity/hashtag.rs index 28ab13189d..b98ec49bcb 100644 --- a/packages/backend-rs/src/model/entity/hashtag.rs +++ b/packages/backend-rs/src/model/entity/hashtag.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/instance.rs b/packages/backend-rs/src/model/entity/instance.rs index 2cfa4ec604..408ad56ce9 100644 --- a/packages/backend-rs/src/model/entity/instance.rs +++ b/packages/backend-rs/src/model/entity/instance.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/messaging_message.rs b/packages/backend-rs/src/model/entity/messaging_message.rs index f6508063db..adce4351af 100644 --- a/packages/backend-rs/src/model/entity/messaging_message.rs +++ b/packages/backend-rs/src/model/entity/messaging_message.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs index e2a5edcaef..3d5d8ac226 100644 --- a/packages/backend-rs/src/model/entity/meta.rs +++ b/packages/backend-rs/src/model/entity/meta.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; @@ -69,8 +69,8 @@ pub struct Model { pub sw_private_key: Option, #[sea_orm(column_name = "pinnedUsers")] pub pinned_users: Vec, - #[sea_orm(column_name = "ToSUrl")] - pub to_s_url: Option, + #[sea_orm(column_name = "tosUrl")] + pub tos_url: Option, #[sea_orm(column_name = "repositoryUrl")] pub repository_url: String, #[sea_orm(column_name = "feedbackUrl")] @@ -93,7 +93,7 @@ pub struct Model { pub object_storage_secret_key: Option, #[sea_orm(column_name = "objectStoragePort")] pub object_storage_port: Option, - #[sea_orm(column_name = "objectStorageUseSSL")] + #[sea_orm(column_name = "objectStorageUseSsl")] pub object_storage_use_ssl: bool, #[sea_orm(column_name = "proxyAccountId")] pub proxy_account_id: Option, @@ -139,7 +139,7 @@ pub struct Model { pub enable_ip_logging: bool, #[sea_orm(column_name = "enableActiveEmailValidation")] pub enable_active_email_validation: bool, - #[sea_orm(column_name = "customMOTD")] + #[sea_orm(column_name = "customMotd")] pub custom_motd: Vec, #[sea_orm(column_name = "customSplashIcons")] pub custom_splash_icons: Vec, diff --git a/packages/backend-rs/src/model/entity/migrations.rs b/packages/backend-rs/src/model/entity/migrations.rs index 41e5d2fda0..04b79bcbae 100644 --- a/packages/backend-rs/src/model/entity/migrations.rs +++ b/packages/backend-rs/src/model/entity/migrations.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/mod.rs b/packages/backend-rs/src/model/entity/mod.rs index 38be7561b1..ffb21352d2 100644 --- a/packages/backend-rs/src/model/entity/mod.rs +++ b/packages/backend-rs/src/model/entity/mod.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 pub mod prelude; @@ -35,6 +35,7 @@ pub mod muting; pub mod note; pub mod note_edit; pub mod note_favorite; +pub mod note_file; pub mod note_reaction; pub mod note_thread_muting; pub mod note_unread; diff --git a/packages/backend-rs/src/model/entity/moderation_log.rs b/packages/backend-rs/src/model/entity/moderation_log.rs index 9cd6e7362e..1e2807dd4d 100644 --- a/packages/backend-rs/src/model/entity/moderation_log.rs +++ b/packages/backend-rs/src/model/entity/moderation_log.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/muted_note.rs b/packages/backend-rs/src/model/entity/muted_note.rs index 713e5fb882..60d5d01742 100644 --- a/packages/backend-rs/src/model/entity/muted_note.rs +++ b/packages/backend-rs/src/model/entity/muted_note.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::MutedNoteReasonEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/muting.rs b/packages/backend-rs/src/model/entity/muting.rs index 9e19aacb32..023439e4a9 100644 --- a/packages/backend-rs/src/model/entity/muting.rs +++ b/packages/backend-rs/src/model/entity/muting.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/note.rs b/packages/backend-rs/src/model/entity/note.rs index 4774cae952..271ea1fa65 100644 --- a/packages/backend-rs/src/model/entity/note.rs +++ b/packages/backend-rs/src/model/entity/note.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::NoteVisibilityEnum; use sea_orm::entity::prelude::*; @@ -100,6 +100,8 @@ pub enum Relation { NoteEdit, #[sea_orm(has_many = "super::note_favorite::Entity")] NoteFavorite, + #[sea_orm(has_many = "super::note_file::Entity")] + NoteFile, #[sea_orm(has_many = "super::note_reaction::Entity")] NoteReaction, #[sea_orm(has_many = "super::note_unread::Entity")] @@ -164,6 +166,12 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteFile.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::NoteReaction.def() diff --git a/packages/backend-rs/src/model/entity/note_edit.rs b/packages/backend-rs/src/model/entity/note_edit.rs index 3b3ceb13df..a403560b39 100644 --- a/packages/backend-rs/src/model/entity/note_edit.rs +++ b/packages/backend-rs/src/model/entity/note_edit.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/note_favorite.rs b/packages/backend-rs/src/model/entity/note_favorite.rs index a4ed5136c7..d202da3ff6 100644 --- a/packages/backend-rs/src/model/entity/note_favorite.rs +++ b/packages/backend-rs/src/model/entity/note_favorite.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/note_file.rs b/packages/backend-rs/src/model/entity/note_file.rs new file mode 100644 index 0000000000..00281e64e3 --- /dev/null +++ b/packages/backend-rs/src/model/entity/note_file.rs @@ -0,0 +1,48 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "note_file")] +pub struct Model { + #[sea_orm(column_name = "serialNo", primary_key)] + pub serial_no: i64, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_name = "fileId")] + pub file_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::drive_file::Entity", + from = "Column::FileId", + to = "super::drive_file::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + DriveFile, + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFile.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend-rs/src/model/entity/note_reaction.rs b/packages/backend-rs/src/model/entity/note_reaction.rs index b35400741d..f99a23900a 100644 --- a/packages/backend-rs/src/model/entity/note_reaction.rs +++ b/packages/backend-rs/src/model/entity/note_reaction.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/note_thread_muting.rs b/packages/backend-rs/src/model/entity/note_thread_muting.rs index e4d4ddf19c..7bb30b5262 100644 --- a/packages/backend-rs/src/model/entity/note_thread_muting.rs +++ b/packages/backend-rs/src/model/entity/note_thread_muting.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/note_unread.rs b/packages/backend-rs/src/model/entity/note_unread.rs index 0e0d4e0c79..7823bcbf0d 100644 --- a/packages/backend-rs/src/model/entity/note_unread.rs +++ b/packages/backend-rs/src/model/entity/note_unread.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/note_watching.rs b/packages/backend-rs/src/model/entity/note_watching.rs index 1175813f08..58079e20cf 100644 --- a/packages/backend-rs/src/model/entity/note_watching.rs +++ b/packages/backend-rs/src/model/entity/note_watching.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/notification.rs b/packages/backend-rs/src/model/entity/notification.rs index 5fcbdf6818..ca4919bb30 100644 --- a/packages/backend-rs/src/model/entity/notification.rs +++ b/packages/backend-rs/src/model/entity/notification.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::NotificationTypeEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/page.rs b/packages/backend-rs/src/model/entity/page.rs index ceaa75ec6f..df312fda00 100644 --- a/packages/backend-rs/src/model/entity/page.rs +++ b/packages/backend-rs/src/model/entity/page.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::PageVisibilityEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/page_like.rs b/packages/backend-rs/src/model/entity/page_like.rs index abc51e75fa..a1c9e81963 100644 --- a/packages/backend-rs/src/model/entity/page_like.rs +++ b/packages/backend-rs/src/model/entity/page_like.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/password_reset_request.rs b/packages/backend-rs/src/model/entity/password_reset_request.rs index 1765ad0365..55100dc0c5 100644 --- a/packages/backend-rs/src/model/entity/password_reset_request.rs +++ b/packages/backend-rs/src/model/entity/password_reset_request.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/poll.rs b/packages/backend-rs/src/model/entity/poll.rs index be8eb8f3e9..8d5dbee0f2 100644 --- a/packages/backend-rs/src/model/entity/poll.rs +++ b/packages/backend-rs/src/model/entity/poll.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::PollNotevisibilityEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/poll_vote.rs b/packages/backend-rs/src/model/entity/poll_vote.rs index 9625eb651d..ce5f517c53 100644 --- a/packages/backend-rs/src/model/entity/poll_vote.rs +++ b/packages/backend-rs/src/model/entity/poll_vote.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/prelude.rs b/packages/backend-rs/src/model/entity/prelude.rs index 10d3795362..57fff023db 100644 --- a/packages/backend-rs/src/model/entity/prelude.rs +++ b/packages/backend-rs/src/model/entity/prelude.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 pub use super::abuse_user_report::Entity as AbuseUserReport; pub use super::access_token::Entity as AccessToken; @@ -33,6 +33,7 @@ pub use super::muting::Entity as Muting; pub use super::note::Entity as Note; pub use super::note_edit::Entity as NoteEdit; pub use super::note_favorite::Entity as NoteFavorite; +pub use super::note_file::Entity as NoteFile; pub use super::note_reaction::Entity as NoteReaction; pub use super::note_thread_muting::Entity as NoteThreadMuting; pub use super::note_unread::Entity as NoteUnread; diff --git a/packages/backend-rs/src/model/entity/promo_note.rs b/packages/backend-rs/src/model/entity/promo_note.rs index a3793479bc..a9fe33e607 100644 --- a/packages/backend-rs/src/model/entity/promo_note.rs +++ b/packages/backend-rs/src/model/entity/promo_note.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/promo_read.rs b/packages/backend-rs/src/model/entity/promo_read.rs index 77c288deaf..5f587ad829 100644 --- a/packages/backend-rs/src/model/entity/promo_read.rs +++ b/packages/backend-rs/src/model/entity/promo_read.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/registration_ticket.rs b/packages/backend-rs/src/model/entity/registration_ticket.rs index 85defb9934..7581ae95e2 100644 --- a/packages/backend-rs/src/model/entity/registration_ticket.rs +++ b/packages/backend-rs/src/model/entity/registration_ticket.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/registry_item.rs b/packages/backend-rs/src/model/entity/registry_item.rs index 6c8b1c897a..c7b81331af 100644 --- a/packages/backend-rs/src/model/entity/registry_item.rs +++ b/packages/backend-rs/src/model/entity/registry_item.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/relay.rs b/packages/backend-rs/src/model/entity/relay.rs index 278317a13a..6073c943e0 100644 --- a/packages/backend-rs/src/model/entity/relay.rs +++ b/packages/backend-rs/src/model/entity/relay.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::RelayStatusEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/renote_muting.rs b/packages/backend-rs/src/model/entity/renote_muting.rs index 9518730f23..8b7df4a140 100644 --- a/packages/backend-rs/src/model/entity/renote_muting.rs +++ b/packages/backend-rs/src/model/entity/renote_muting.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/reply_muting.rs b/packages/backend-rs/src/model/entity/reply_muting.rs index bab6e17576..429bbe7566 100644 --- a/packages/backend-rs/src/model/entity/reply_muting.rs +++ b/packages/backend-rs/src/model/entity/reply_muting.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs index 7abdaab060..5e3666c352 100644 --- a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs +++ b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/signin.rs b/packages/backend-rs/src/model/entity/signin.rs index f6f8c2b7c1..b0624b00b0 100644 --- a/packages/backend-rs/src/model/entity/signin.rs +++ b/packages/backend-rs/src/model/entity/signin.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/sw_subscription.rs b/packages/backend-rs/src/model/entity/sw_subscription.rs index 280939d380..ecebc06ff1 100644 --- a/packages/backend-rs/src/model/entity/sw_subscription.rs +++ b/packages/backend-rs/src/model/entity/sw_subscription.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/used_username.rs b/packages/backend-rs/src/model/entity/used_username.rs index 38d6f9694f..8972a20718 100644 --- a/packages/backend-rs/src/model/entity/used_username.rs +++ b/packages/backend-rs/src/model/entity/used_username.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user.rs b/packages/backend-rs/src/model/entity/user.rs index 8e9729daf3..8f673089a8 100644 --- a/packages/backend-rs/src/model/entity/user.rs +++ b/packages/backend-rs/src/model/entity/user.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::UserEmojimodpermEnum; use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_group.rs b/packages/backend-rs/src/model/entity/user_group.rs index 1f8cc4e048..c412ada09c 100644 --- a/packages/backend-rs/src/model/entity/user_group.rs +++ b/packages/backend-rs/src/model/entity/user_group.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_group_invitation.rs b/packages/backend-rs/src/model/entity/user_group_invitation.rs index 4ffa751c9b..0a60a97ed3 100644 --- a/packages/backend-rs/src/model/entity/user_group_invitation.rs +++ b/packages/backend-rs/src/model/entity/user_group_invitation.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_group_invite.rs b/packages/backend-rs/src/model/entity/user_group_invite.rs index a7c2934587..6aaa5396d5 100644 --- a/packages/backend-rs/src/model/entity/user_group_invite.rs +++ b/packages/backend-rs/src/model/entity/user_group_invite.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_group_joining.rs b/packages/backend-rs/src/model/entity/user_group_joining.rs index 4a2635f8d2..040e0f2a36 100644 --- a/packages/backend-rs/src/model/entity/user_group_joining.rs +++ b/packages/backend-rs/src/model/entity/user_group_joining.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_ip.rs b/packages/backend-rs/src/model/entity/user_ip.rs index f1697785f9..7a79d4448f 100644 --- a/packages/backend-rs/src/model/entity/user_ip.rs +++ b/packages/backend-rs/src/model/entity/user_ip.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_keypair.rs b/packages/backend-rs/src/model/entity/user_keypair.rs index f94caaf856..7a22f44a91 100644 --- a/packages/backend-rs/src/model/entity/user_keypair.rs +++ b/packages/backend-rs/src/model/entity/user_keypair.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_list.rs b/packages/backend-rs/src/model/entity/user_list.rs index 60b3a5b9f3..832c65869f 100644 --- a/packages/backend-rs/src/model/entity/user_list.rs +++ b/packages/backend-rs/src/model/entity/user_list.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_list_joining.rs b/packages/backend-rs/src/model/entity/user_list_joining.rs index a7063adb83..db0cdca6b4 100644 --- a/packages/backend-rs/src/model/entity/user_list_joining.rs +++ b/packages/backend-rs/src/model/entity/user_list_joining.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_note_pining.rs b/packages/backend-rs/src/model/entity/user_note_pining.rs index 3a09d49932..b9ced3f3c2 100644 --- a/packages/backend-rs/src/model/entity/user_note_pining.rs +++ b/packages/backend-rs/src/model/entity/user_note_pining.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_pending.rs b/packages/backend-rs/src/model/entity/user_pending.rs index 2775c30d3d..b96c5e6368 100644 --- a/packages/backend-rs/src/model/entity/user_pending.rs +++ b/packages/backend-rs/src/model/entity/user_pending.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_profile.rs b/packages/backend-rs/src/model/entity/user_profile.rs index daccf57d1e..f806f1d07b 100644 --- a/packages/backend-rs/src/model/entity/user_profile.rs +++ b/packages/backend-rs/src/model/entity/user_profile.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use super::sea_orm_active_enums::UserProfileFfvisibilityEnum; use super::sea_orm_active_enums::UserProfileMutingnotificationtypesEnum; @@ -71,6 +71,8 @@ pub struct Model { pub prevent_ai_learning: bool, #[sea_orm(column_name = "isIndexable")] pub is_indexable: bool, + #[sea_orm(column_name = "mutedPatterns")] + pub muted_patterns: Vec, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/packages/backend-rs/src/model/entity/user_publickey.rs b/packages/backend-rs/src/model/entity/user_publickey.rs index 4e0674ba9d..b4181de196 100644 --- a/packages/backend-rs/src/model/entity/user_publickey.rs +++ b/packages/backend-rs/src/model/entity/user_publickey.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/user_security_key.rs b/packages/backend-rs/src/model/entity/user_security_key.rs index 023653d3bc..e4d6b86b67 100644 --- a/packages/backend-rs/src/model/entity/user_security_key.rs +++ b/packages/backend-rs/src/model/entity/user_security_key.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/model/entity/webhook.rs b/packages/backend-rs/src/model/entity/webhook.rs index f1063b84ba..bce26e11d9 100644 --- a/packages/backend-rs/src/model/entity/webhook.rs +++ b/packages/backend-rs/src/model/entity/webhook.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12 +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; diff --git a/packages/backend-rs/src/util/id.rs b/packages/backend-rs/src/util/id.rs index 2fd94e9019..9d1427e65d 100644 --- a/packages/backend-rs/src/util/id.rs +++ b/packages/backend-rs/src/util/id.rs @@ -21,7 +21,7 @@ const TIME_2000: i64 = 946_684_800_000; const TIMESTAMP_LENGTH: u16 = 8; /// Initializes Cuid2 generator. Must be called before any [create_id]. -pub fn init_id<'a>(length: u16, fingerprint: &'a str) { +pub fn init_id(length: u16, fingerprint: &str) { FINGERPRINT.get_or_init(move || format!("{}{}", fingerprint, cuid2::create_id())); GENERATOR.get_or_init(move || { cuid2::CuidConstructor::new() diff --git a/packages/backend/.swcrc b/packages/backend/.swcrc index e87bd7cf47..08aca7562a 100644 --- a/packages/backend/.swcrc +++ b/packages/backend/.swcrc @@ -14,11 +14,9 @@ "keepImportAssertions": true, "emitAssertForImportAttributes": true }, - "baseUrl": ".", + "baseUrl": "src", "paths": { - "@/*": [ - "./src/*" - ] + "@/*": ["*"] }, "target": "es2022" }, diff --git a/packages/backend/migration/1557476068003-PinnedUsers.js b/packages/backend/migration/1557476068003-PinnedUsers.js deleted file mode 100644 index 6f348836ad..0000000000 --- a/packages/backend/migration/1557476068003-PinnedUsers.js +++ /dev/null @@ -1,10 +0,0 @@ -export class PinnedUsers1557476068003 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "pinnedUsers" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedUsers"`); - } -} diff --git a/packages/backend/migration/1558266512381-UserListJoining.js b/packages/backend/migration/1558266512381-UserListJoining.js deleted file mode 100644 index 3597e51f76..0000000000 --- a/packages/backend/migration/1558266512381-UserListJoining.js +++ /dev/null @@ -1,10 +0,0 @@ -export class UserListJoining1558266512381 { - async up(queryRunner) { - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_90f7da835e4c10aca6853621e1" ON "user_list_joining" ("userId", "userListId") `, - ); - } - async down(queryRunner) { - await queryRunner.query(`DROP INDEX "IDX_90f7da835e4c10aca6853621e1"`); - } -} diff --git a/packages/backend/migration/1562422242907-PasswordLessLogin.js b/packages/backend/migration/1562422242907-PasswordLessLogin.js deleted file mode 100644 index 8e1280830b..0000000000 --- a/packages/backend/migration/1562422242907-PasswordLessLogin.js +++ /dev/null @@ -1,12 +0,0 @@ -export class PasswordLessLogin1562422242907 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD COLUMN "usePasswordLessLogin" boolean DEFAULT false NOT NULL`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" DROP COLUMN "usePasswordLessLogin"`, - ); - } -} diff --git a/packages/backend/migration/1562448332510-PageTitleHideOption.js b/packages/backend/migration/1562448332510-PageTitleHideOption.js deleted file mode 100644 index 9a1b42f4bb..0000000000 --- a/packages/backend/migration/1562448332510-PageTitleHideOption.js +++ /dev/null @@ -1,12 +0,0 @@ -export class PageTitleHideOption1562448332510 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "page" ADD "hideTitleWhenPinned" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "page" DROP COLUMN "hideTitleWhenPinned"`, - ); - } -} diff --git a/packages/backend/migration/1565634203341-room.js b/packages/backend/migration/1565634203341-room.js deleted file mode 100644 index 1023c0a31a..0000000000 --- a/packages/backend/migration/1565634203341-room.js +++ /dev/null @@ -1,10 +0,0 @@ -export class room1565634203341 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "room" jsonb NOT NULL DEFAULT '{}'`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "room"`); - } -} diff --git a/packages/backend/migration/1571220798684-CustomEmojiCategory.js b/packages/backend/migration/1571220798684-CustomEmojiCategory.js deleted file mode 100644 index 4d75313328..0000000000 --- a/packages/backend/migration/1571220798684-CustomEmojiCategory.js +++ /dev/null @@ -1,14 +0,0 @@ -export class CustomEmojiCategory1571220798684 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "emoji" ADD "category" character varying(128)`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "emoji" DROP COLUMN "category"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1576269851876-TalkFederationId.js b/packages/backend/migration/1576269851876-TalkFederationId.js deleted file mode 100644 index f0aed7dd83..0000000000 --- a/packages/backend/migration/1576269851876-TalkFederationId.js +++ /dev/null @@ -1,17 +0,0 @@ -export class TalkFederationId1576269851876 { - constructor() { - this.name = "TalkFederationId1576269851876"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "messaging_message" ADD "uri" character varying(512)`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "messaging_message" DROP COLUMN "uri"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1576869585998-ProxyRemoteFiles.js b/packages/backend/migration/1576869585998-ProxyRemoteFiles.js deleted file mode 100644 index 5565f64b6d..0000000000 --- a/packages/backend/migration/1576869585998-ProxyRemoteFiles.js +++ /dev/null @@ -1,17 +0,0 @@ -export class ProxyRemoteFiles1576869585998 { - constructor() { - this.name = "ProxyRemoteFiles1576869585998"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT false`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1580543501339-v12-13.js b/packages/backend/migration/1580543501339-v12-13.js deleted file mode 100644 index fd4d131518..0000000000 --- a/packages/backend/migration/1580543501339-v12-13.js +++ /dev/null @@ -1,14 +0,0 @@ -export class v12131580543501339 { - constructor() { - this.name = "v12131580543501339"; - } - async up(queryRunner) { - await queryRunner.query( - `CREATE INDEX "IDX_NOTE_TAGS" ON "note" USING gin ("tags")`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query(`DROP INDEX "IDX_NOTE_TAGS"`, undefined); - } -} diff --git a/packages/backend/migration/1581708415836-drive-user-folder-id-index.js b/packages/backend/migration/1581708415836-drive-user-folder-id-index.js deleted file mode 100644 index 41902dc53f..0000000000 --- a/packages/backend/migration/1581708415836-drive-user-folder-id-index.js +++ /dev/null @@ -1,17 +0,0 @@ -export class driveUserFolderIdIndex1581708415836 { - constructor() { - this.name = "driveUserFolderIdIndex1581708415836"; - } - async up(queryRunner) { - await queryRunner.query( - `CREATE INDEX "IDX_55720b33a61a7c806a8215b825" ON "drive_file" ("userId", "folderId", "id") `, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `DROP INDEX "IDX_55720b33a61a7c806a8215b825"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1582210532752-antenna-exclude.js b/packages/backend/migration/1582210532752-antenna-exclude.js deleted file mode 100644 index 5a394270ef..0000000000 --- a/packages/backend/migration/1582210532752-antenna-exclude.js +++ /dev/null @@ -1,17 +0,0 @@ -export class antennaExclude1582210532752 { - constructor() { - this.name = "antennaExclude1582210532752"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "antenna" ADD "excludeKeywords" jsonb NOT NULL DEFAULT '[]'`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "antenna" DROP COLUMN "excludeKeywords"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1585772678853-ap-url.js b/packages/backend/migration/1585772678853-ap-url.js deleted file mode 100644 index 18cc4588e6..0000000000 --- a/packages/backend/migration/1585772678853-ap-url.js +++ /dev/null @@ -1,14 +0,0 @@ -export class apUrl1585772678853 { - constructor() { - this.name = "apUrl1585772678853"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "note" ADD "url" character varying(512)`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "url"`, undefined); - } -} diff --git a/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js b/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js deleted file mode 100644 index 89694f84b2..0000000000 --- a/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js +++ /dev/null @@ -1,17 +0,0 @@ -export class AddObjectStorageUseProxy1586624197029 { - constructor() { - this.name = "AddObjectStorageUseProxy1586624197029"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "objectStorageUseProxy" boolean NOT NULL DEFAULT true`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "objectStorageUseProxy"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1586708940386-pageAiScript.js b/packages/backend/migration/1586708940386-pageAiScript.js deleted file mode 100644 index 25eb710988..0000000000 --- a/packages/backend/migration/1586708940386-pageAiScript.js +++ /dev/null @@ -1,17 +0,0 @@ -export class pageAiScript1586708940386 { - constructor() { - this.name = "pageAiScript1586708940386"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "page" ADD "script" character varying(16384) NOT NULL DEFAULT ''`, - undefined, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "page" DROP COLUMN "script"`, - undefined, - ); - } -} diff --git a/packages/backend/migration/1595075960584-blurhash.js b/packages/backend/migration/1595075960584-blurhash.js deleted file mode 100644 index 50660cd055..0000000000 --- a/packages/backend/migration/1595075960584-blurhash.js +++ /dev/null @@ -1,13 +0,0 @@ -export class blurhash1595075960584 { - constructor() { - this.name = "blurhash1595075960584"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "drive_file" ADD "blurhash" character varying(128)`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "blurhash"`); - } -} diff --git a/packages/backend/migration/1595676934834-instance-icon-url.js b/packages/backend/migration/1595676934834-instance-icon-url.js deleted file mode 100644 index c228b14b6c..0000000000 --- a/packages/backend/migration/1595676934834-instance-icon-url.js +++ /dev/null @@ -1,13 +0,0 @@ -export class instanceIconUrl1595676934834 { - constructor() { - this.name = "instanceIconUrl1595676934834"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "instance" ADD "iconUrl" character varying(256) DEFAULT null`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "iconUrl"`); - } -} diff --git a/packages/backend/migration/1596786425167-channel2.js b/packages/backend/migration/1596786425167-channel2.js deleted file mode 100644 index ae871f5ff6..0000000000 --- a/packages/backend/migration/1596786425167-channel2.js +++ /dev/null @@ -1,15 +0,0 @@ -export class channel21596786425167 { - constructor() { - this.name = "channel21596786425167"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "channel_following" DROP COLUMN "readCursor"`, - ); - } -} diff --git a/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js b/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js deleted file mode 100644 index 81540d5e8c..0000000000 --- a/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js +++ /dev/null @@ -1,15 +0,0 @@ -export class objectStorageSetPublicRead1597230137744 { - constructor() { - this.name = "objectStorageSetPublicRead1597230137744"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "objectStorageSetPublicRead" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "objectStorageSetPublicRead"`, - ); - } -} diff --git a/packages/backend/migration/1597385880794-add-sensitive-index.js b/packages/backend/migration/1597385880794-add-sensitive-index.js deleted file mode 100644 index d7c818bbfe..0000000000 --- a/packages/backend/migration/1597385880794-add-sensitive-index.js +++ /dev/null @@ -1,13 +0,0 @@ -export class addSensitiveIndex1597385880794 { - constructor() { - this.name = "addSensitiveIndex1597385880794"; - } - async up(queryRunner) { - await queryRunner.query( - `CREATE INDEX "IDX_a7eba67f8b3fa27271e85d2e26" ON "drive_file" ("isSensitive") `, - ); - } - async down(queryRunner) { - await queryRunner.query(`DROP INDEX "IDX_a7eba67f8b3fa27271e85d2e26"`); - } -} diff --git a/packages/backend/migration/1603776877564-instance-theme-color.js b/packages/backend/migration/1603776877564-instance-theme-color.js deleted file mode 100644 index 9bb3d65c0e..0000000000 --- a/packages/backend/migration/1603776877564-instance-theme-color.js +++ /dev/null @@ -1,13 +0,0 @@ -export class instanceThemeColor1603776877564 { - constructor() { - this.name = "instanceThemeColor1603776877564"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "instance" ADD "themeColor" character varying(64) DEFAULT null`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "themeColor"`); - } -} diff --git a/packages/backend/migration/1603781553011-instance-favicon.js b/packages/backend/migration/1603781553011-instance-favicon.js deleted file mode 100644 index 4b2442692f..0000000000 --- a/packages/backend/migration/1603781553011-instance-favicon.js +++ /dev/null @@ -1,13 +0,0 @@ -export class instanceFavicon1603781553011 { - constructor() { - this.name = "instanceFavicon1603781553011"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "instance" ADD "faviconUrl" character varying(256) DEFAULT null`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "faviconUrl"`); - } -} diff --git a/packages/backend/migration/1604821689616-delete-auto-watch.js b/packages/backend/migration/1604821689616-delete-auto-watch.js deleted file mode 100644 index 6a8333ce16..0000000000 --- a/packages/backend/migration/1604821689616-delete-auto-watch.js +++ /dev/null @@ -1,15 +0,0 @@ -export class deleteAutoWatch1604821689616 { - constructor() { - this.name = "deleteAutoWatch1604821689616"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" DROP COLUMN "autoWatch"`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "autoWatch" boolean NOT NULL DEFAULT false`, - ); - } -} diff --git a/packages/backend/migration/1605408848373-clip-description.js b/packages/backend/migration/1605408848373-clip-description.js deleted file mode 100644 index 99cda65346..0000000000 --- a/packages/backend/migration/1605408848373-clip-description.js +++ /dev/null @@ -1,13 +0,0 @@ -export class clipDescription1605408848373 { - constructor() { - this.name = "clipDescription1605408848373"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "clip" ADD "description" character varying(2048) DEFAULT null`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "clip" DROP COLUMN "description"`); - } -} diff --git a/packages/backend/migration/1607151207216-instance-pinned-clip.js b/packages/backend/migration/1607151207216-instance-pinned-clip.js deleted file mode 100644 index 655b4c7fbd..0000000000 --- a/packages/backend/migration/1607151207216-instance-pinned-clip.js +++ /dev/null @@ -1,13 +0,0 @@ -export class instancePinnedClip1607151207216 { - constructor() { - this.name = "instancePinnedClip1607151207216"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "pinnedClipId" character varying(32)`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedClipId"`); - } -} diff --git a/packages/backend/migration/1610283021566-registry3.js b/packages/backend/migration/1610283021566-registry3.js deleted file mode 100644 index a1d55b2dc1..0000000000 --- a/packages/backend/migration/1610283021566-registry3.js +++ /dev/null @@ -1,15 +0,0 @@ -export class registry31610283021566 { - constructor() { - this.name = "registry31610283021566"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "registry_item" ALTER COLUMN "value" DROP NOT NULL`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "registry_item" ALTER COLUMN "value" SET NOT NULL`, - ); - } -} diff --git a/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js b/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js deleted file mode 100644 index b65ca2a577..0000000000 --- a/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js +++ /dev/null @@ -1,15 +0,0 @@ -export class objectStorageS3ForcePathStyle1611547387175 { - constructor() { - this.name = "objectStorageS3ForcePathStyle1611547387175"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "objectStorageS3ForcePathStyle" boolean NOT NULL DEFAULT true`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "objectStorageS3ForcePathStyle"`, - ); - } -} diff --git a/packages/backend/migration/1612619156584-announcement-email.js b/packages/backend/migration/1612619156584-announcement-email.js deleted file mode 100644 index a3b7292f8a..0000000000 --- a/packages/backend/migration/1612619156584-announcement-email.js +++ /dev/null @@ -1,15 +0,0 @@ -export class announcementEmail1612619156584 { - constructor() { - this.name = "announcementEmail1612619156584"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "receiveAnnouncementEmail" boolean NOT NULL DEFAULT true`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" DROP COLUMN "receiveAnnouncementEmail"`, - ); - } -} diff --git a/packages/backend/migration/1613181457597-user-lang.js b/packages/backend/migration/1613181457597-user-lang.js deleted file mode 100644 index aa5bf7de8d..0000000000 --- a/packages/backend/migration/1613181457597-user-lang.js +++ /dev/null @@ -1,13 +0,0 @@ -export class userLang1613181457597 { - constructor() { - this.name = "userLang1613181457597"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "lang" character varying(32)`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); - } -} diff --git a/packages/backend/migration/1618639857000-user-hide-online-status.js b/packages/backend/migration/1618639857000-user-hide-online-status.js deleted file mode 100644 index 8d76326084..0000000000 --- a/packages/backend/migration/1618639857000-user-hide-online-status.js +++ /dev/null @@ -1,15 +0,0 @@ -export class userHideOnlineStatus1618639857000 { - constructor() { - this.name = "userHideOnlineStatus1618639857000"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user" ADD "hideOnlineStatus" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user" DROP COLUMN "hideOnlineStatus"`, - ); - } -} diff --git a/packages/backend/migration/1620364649428-ad2.js b/packages/backend/migration/1620364649428-ad2.js deleted file mode 100644 index a61c3ef088..0000000000 --- a/packages/backend/migration/1620364649428-ad2.js +++ /dev/null @@ -1,13 +0,0 @@ -export class ad21620364649428 { - constructor() { - this.name = "ad21620364649428"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "ad" ADD "ratio" integer NOT NULL DEFAULT '1'`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "ratio"`); - } -} diff --git a/packages/backend/migration/1629024377804-deepl-integration.js b/packages/backend/migration/1629024377804-deepl-integration.js deleted file mode 100644 index 1dd5465fba..0000000000 --- a/packages/backend/migration/1629024377804-deepl-integration.js +++ /dev/null @@ -1,13 +0,0 @@ -export class deeplIntegration1629024377804 { - constructor() { - this.name = "deeplIntegration1629024377804"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "deeplAuthKey" character varying(128)`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplAuthKey"`); - } -} diff --git a/packages/backend/migration/1629288472000-fix-channel-userId.js b/packages/backend/migration/1629288472000-fix-channel-userId.js deleted file mode 100644 index e02549b11a..0000000000 --- a/packages/backend/migration/1629288472000-fix-channel-userId.js +++ /dev/null @@ -1,15 +0,0 @@ -export class fixChannelUserId1629288472000 { - constructor() { - this.name = "fixChannelUserId1629288472000"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "channel" ALTER COLUMN "userId" DROP NOT NULL;`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "channel" ALTER COLUMN "userId" SET NOT NULL;`, - ); - } -} diff --git a/packages/backend/migration/1629778475000-deepl-integration2.js b/packages/backend/migration/1629778475000-deepl-integration2.js deleted file mode 100644 index 138e00d247..0000000000 --- a/packages/backend/migration/1629778475000-deepl-integration2.js +++ /dev/null @@ -1,13 +0,0 @@ -export class deeplIntegration21629778475000 { - constructor() { - this.name = "deeplIntegration21629778475000"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "deeplIsPro" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplIsPro"`); - } -} diff --git a/packages/backend/migration/1633068642000-email-required-for-signup.js b/packages/backend/migration/1633068642000-email-required-for-signup.js deleted file mode 100644 index 45c0894a75..0000000000 --- a/packages/backend/migration/1633068642000-email-required-for-signup.js +++ /dev/null @@ -1,15 +0,0 @@ -export class emailRequiredForSignup1633068642000 { - constructor() { - this.name = "emailRequiredForSignup1633068642000"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "emailRequiredForSignup" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "emailRequiredForSignup"`, - ); - } -} diff --git a/packages/backend/migration/1634486652000-user-public-reactions.js b/packages/backend/migration/1634486652000-user-public-reactions.js deleted file mode 100644 index 95b957f11c..0000000000 --- a/packages/backend/migration/1634486652000-user-public-reactions.js +++ /dev/null @@ -1,15 +0,0 @@ -export class userPublicReactions1634486652000 { - constructor() { - this.name = "userPublicReactions1634486652000"; - } - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "publicReactions" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" DROP COLUMN "publicReactions"`, - ); - } -} diff --git a/packages/backend/migration/1634902659689-delete-log.js b/packages/backend/migration/1634902659689-delete-log.js deleted file mode 100644 index fc148f0988..0000000000 --- a/packages/backend/migration/1634902659689-delete-log.js +++ /dev/null @@ -1,9 +0,0 @@ -export class deleteLog1634902659689 { - constructor() { - this.name = "deleteLog1634902659689"; - } - async up(queryRunner) { - await queryRunner.query(`DROP TABLE "log"`); - } - async down(queryRunner) {} -} diff --git a/packages/backend/migration/1636697408073-remove-via-mobile.js b/packages/backend/migration/1636697408073-remove-via-mobile.js deleted file mode 100644 index f862760249..0000000000 --- a/packages/backend/migration/1636697408073-remove-via-mobile.js +++ /dev/null @@ -1,13 +0,0 @@ -export class removeViaMobile1636697408073 { - name = "removeViaMobile1636697408073"; - - async up(queryRunner) { - await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "viaMobile"`); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "note" ADD "viaMobile" boolean NOT NULL DEFAULT false`, - ); - } -} diff --git a/packages/backend/migration/1637320813000-forwarded-report.js b/packages/backend/migration/1637320813000-forwarded-report.js deleted file mode 100644 index 18ec172063..0000000000 --- a/packages/backend/migration/1637320813000-forwarded-report.js +++ /dev/null @@ -1,15 +0,0 @@ -export class forwardedReport1637320813000 { - name = "forwardedReport1637320813000"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "abuse_user_report" ADD "forwarded" boolean NOT NULL DEFAULT false`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "abuse_user_report" DROP COLUMN "forwarded"`, - ); - } -} diff --git a/packages/backend/migration/1642613870898-drive-file-webpublic-type.js b/packages/backend/migration/1642613870898-drive-file-webpublic-type.js deleted file mode 100644 index df5ab7899b..0000000000 --- a/packages/backend/migration/1642613870898-drive-file-webpublic-type.js +++ /dev/null @@ -1,15 +0,0 @@ -export class driveFileWebpublicType1642613870898 { - name = "driveFileWebpublicType1642613870898"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "drive_file" ADD "webpublicType" character varying(128)`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "drive_file" DROP COLUMN "webpublicType"`, - ); - } -} diff --git a/packages/backend/migration/1644395759931-instance-theme-color.js b/packages/backend/migration/1644395759931-instance-theme-color.js deleted file mode 100644 index 1e0ee04bc2..0000000000 --- a/packages/backend/migration/1644395759931-instance-theme-color.js +++ /dev/null @@ -1,13 +0,0 @@ -export class instanceThemeColor1644395759931 { - name = "instanceThemeColor1644395759931"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "themeColor" character varying(512)`, - ); - } - - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "themeColor"`); - } -} diff --git a/packages/backend/migration/1645340161439-remove-max-note-text-length.js b/packages/backend/migration/1645340161439-remove-max-note-text-length.js deleted file mode 100644 index d17ef8c124..0000000000 --- a/packages/backend/migration/1645340161439-remove-max-note-text-length.js +++ /dev/null @@ -1,15 +0,0 @@ -export class removeMaxNoteTextLength1645340161439 { - name = "removeMaxNoteTextLength1645340161439"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "maxNoteTextLength"`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "maxNoteTextLength" integer NOT NULL DEFAULT '500'`, - ); - } -} diff --git a/packages/backend/migration/1656772790599-user-moderation-note.js b/packages/backend/migration/1656772790599-user-moderation-note.js deleted file mode 100644 index 11d3124aeb..0000000000 --- a/packages/backend/migration/1656772790599-user-moderation-note.js +++ /dev/null @@ -1,15 +0,0 @@ -export class userModerationNote1656772790599 { - name = "userModerationNote1656772790599"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "moderationNote" character varying(8192) NOT NULL DEFAULT ''`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" DROP COLUMN "moderationNote"`, - ); - } -} diff --git a/packages/backend/migration/1657346559800-active-email-validation.js b/packages/backend/migration/1657346559800-active-email-validation.js deleted file mode 100644 index 4e3fd3f820..0000000000 --- a/packages/backend/migration/1657346559800-active-email-validation.js +++ /dev/null @@ -1,15 +0,0 @@ -export class activeEmailValidation1657346559800 { - name = "activeEmailValidation1657346559800"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "enableActiveEmailValidation" boolean NOT NULL DEFAULT true`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "enableActiveEmailValidation"`, - ); - } -} diff --git a/packages/backend/migration/1658939464003CustomMOTD.js b/packages/backend/migration/1658939464003CustomMOTD.js deleted file mode 100644 index ee1b182e5d..0000000000 --- a/packages/backend/migration/1658939464003CustomMOTD.js +++ /dev/null @@ -1,10 +0,0 @@ -export class CustomMOTD1658939464003 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "customMOTD" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "customMOTD"`); - } -} diff --git a/packages/backend/migration/1658941974648CustomSplashIcons.js b/packages/backend/migration/1658941974648CustomSplashIcons.js deleted file mode 100644 index 5c6a874d0f..0000000000 --- a/packages/backend/migration/1658941974648CustomSplashIcons.js +++ /dev/null @@ -1,12 +0,0 @@ -export class CustomSplashIcons1658941974648 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "customSplashIcons" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "customSplashIcons"`, - ); - } -} diff --git a/packages/backend/migration/1660068273737GuestTimeline.js b/packages/backend/migration/1660068273737GuestTimeline.js deleted file mode 100644 index 9a42f602da..0000000000 --- a/packages/backend/migration/1660068273737GuestTimeline.js +++ /dev/null @@ -1,13 +0,0 @@ -export class GuestTimeline1660068273737 { - name = "GuestTimeline1660068273737"; - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "enableGuestTimeline" boolean NOT NULL DEFAULT false`, - ); - } - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "enableGuestTimeline"`, - ); - } -} diff --git a/packages/backend/migration/1668828368510PageDraft.js b/packages/backend/migration/1668828368510PageDraft.js deleted file mode 100644 index a5cc88b26e..0000000000 --- a/packages/backend/migration/1668828368510PageDraft.js +++ /dev/null @@ -1,10 +0,0 @@ -export class Page1668828368510 { - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "page" ADD "isPublic" boolean NOT NULL DEFAULT true`, - ); - } - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "isPublic"`); - } -} diff --git a/packages/backend/migration/1668831378728FixCalckeyAgain.js b/packages/backend/migration/1668831378728FixCalckeyAgain.js deleted file mode 100644 index 33db2b15a7..0000000000 --- a/packages/backend/migration/1668831378728FixCalckeyAgain.js +++ /dev/null @@ -1,15 +0,0 @@ -export class FixFirefishAgain1668831378728 { - name = "FixFirefishAgain1668831378728"; - - async up(queryRunner) { - await queryRunner.query( - `UPDATE "meta" SET "useStarForReactionFallback" = TRUE`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `UPDATE "meta" SET "useStarForReactionFallback" = FALSE`, - ); - } -} diff --git a/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js b/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js deleted file mode 100644 index 101972a68c..0000000000 --- a/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js +++ /dev/null @@ -1,15 +0,0 @@ -export class whetherPushNotifyToSendReadMessage1669138716634 { - name = "whetherPushNotifyToSendReadMessage1669138716634"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "sw_subscription" ADD "sendReadMessage" boolean NOT NULL DEFAULT false`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "sw_subscription" DROP COLUMN "sendReadMessage"`, - ); - } -} diff --git a/packages/backend/migration/1673336077243-PollChoiceLength.js b/packages/backend/migration/1673336077243-PollChoiceLength.js deleted file mode 100644 index a0e3350162..0000000000 --- a/packages/backend/migration/1673336077243-PollChoiceLength.js +++ /dev/null @@ -1,15 +0,0 @@ -export class PollChoiceLength1673336077243 { - name = "PollChoiceLength1673336077243"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(256) array`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(128) array`, - ); - } -} diff --git a/packages/backend/migration/1677935903517-DriveComment.js b/packages/backend/migration/1677935903517-DriveComment.js deleted file mode 100644 index 571958f294..0000000000 --- a/packages/backend/migration/1677935903517-DriveComment.js +++ /dev/null @@ -1,15 +0,0 @@ -export class DriveComment1677935903517 { - name = "DriveComment1677935903517"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(8192)`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(512)`, - ); - } -} diff --git a/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js b/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js deleted file mode 100644 index f3de7ce278..0000000000 --- a/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js +++ /dev/null @@ -1,13 +0,0 @@ -export class addPropsForCustomEmoji1678945242650 { - name = "addPropsForCustomEmoji1678945242650"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "emoji" ADD "license" character varying(1024)`, - ); - } - - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "license"`); - } -} diff --git a/packages/backend/migration/1682891890317-InstanceSilence.js b/packages/backend/migration/1682891890317-InstanceSilence.js deleted file mode 100644 index babe64883a..0000000000 --- a/packages/backend/migration/1682891890317-InstanceSilence.js +++ /dev/null @@ -1,13 +0,0 @@ -export class InstanceSilence1682891890317 { - name = "InstanceSilence1682891890317"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "silencedHosts" character varying(256) array NOT NULL DEFAULT '{}'`, - ); - } - - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "silencedHosts"`); - } -} diff --git a/packages/backend/migration/1682891891317-AddHiddenPosts.js b/packages/backend/migration/1682891891317-AddHiddenPosts.js deleted file mode 100644 index 827470f88e..0000000000 --- a/packages/backend/migration/1682891891317-AddHiddenPosts.js +++ /dev/null @@ -1,15 +0,0 @@ -export class AddHiddenPosts1682891891317 { - name = "AddHiddenPosts1682891891317"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TYPE note_visibility_enum ADD VALUE IF NOT EXISTS 'hidden'`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TYPE note_visibility_enum REMOVE VALUE IF EXISTS 'hidden'`, - ); - } -} diff --git a/packages/backend/migration/1683682889948-PreventAiLearning.js b/packages/backend/migration/1683682889948-PreventAiLearning.js deleted file mode 100644 index afb892ed5d..0000000000 --- a/packages/backend/migration/1683682889948-PreventAiLearning.js +++ /dev/null @@ -1,15 +0,0 @@ -export class PreventAiLearning1683682889948 { - name = "PreventAiLearning1683682889948"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD "preventAiLearning" boolean NOT NULL DEFAULT true`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" DROP COLUMN "preventAiLearning"`, - ); - } -} diff --git a/packages/backend/migration/1683980686995-ExperimentalFeatures.js b/packages/backend/migration/1683980686995-ExperimentalFeatures.js deleted file mode 100644 index a289a9ecdc..0000000000 --- a/packages/backend/migration/1683980686995-ExperimentalFeatures.js +++ /dev/null @@ -1,16 +0,0 @@ -export class ExperimentalFeatures1683980686995 { - name = "ExperimentalFeatures1683980686995"; - - async up(queryRunner) { - await queryRunner.query(` - ALTER TABLE "meta" - ADD "experimentalFeatures" jsonb NOT NULL DEFAULT '{}' - `); - } - - async down(queryRunner) { - await queryRunner.query(` - ALTER TABLE "meta" DROP COLUMN "experimentalFeatures" - `); - } -} diff --git a/packages/backend/migration/1684206886988-remove-showTimelineReplies.js b/packages/backend/migration/1684206886988-remove-showTimelineReplies.js deleted file mode 100644 index e5f8483c7f..0000000000 --- a/packages/backend/migration/1684206886988-remove-showTimelineReplies.js +++ /dev/null @@ -1,15 +0,0 @@ -export class RemoveShowTimelineReplies1684206886988 { - name = "RemoveShowTimelineReplies1684206886988"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user" ADD "showTimelineReplies" boolean NOT NULL DEFAULT false`, - ); - } -} diff --git a/packages/backend/migration/1689136347561-donation-link.js b/packages/backend/migration/1689136347561-donation-link.js deleted file mode 100644 index dbe0ed7c8e..0000000000 --- a/packages/backend/migration/1689136347561-donation-link.js +++ /dev/null @@ -1,15 +0,0 @@ -export class DonationLink1689136347561 { - name = "DonationLink1689136347561"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" ADD "donationLink" character varying(256)`, - ); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "meta" DROP COLUMN "DonationLink1689136347561"`, - ); - } -} diff --git a/packages/backend/migration/1695334243217-add-post-lang.js b/packages/backend/migration/1695334243217-add-post-lang.js deleted file mode 100644 index 7e8618953a..0000000000 --- a/packages/backend/migration/1695334243217-add-post-lang.js +++ /dev/null @@ -1,13 +0,0 @@ -export class AddPostLang1695334243217 { - name = "AddPostLang1695334243217"; - - async up(queryRunner) { - await queryRunner.query( - `ALTER TABLE "note" ADD "lang" character varying(10)`, - ); - } - - async down(queryRunner) { - await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "lang"`); - } -} diff --git a/packages/backend/migration/1699305365258-more-urls.js b/packages/backend/migration/1699305365258-more-urls.js deleted file mode 100644 index 6ef1dcd2b3..0000000000 --- a/packages/backend/migration/1699305365258-more-urls.js +++ /dev/null @@ -1,13 +0,0 @@ -export class MoreUrls1699305365258 { - name = "MoreUrls1699305365258"; - - async up(queryRunner) { - queryRunner.query( - `ALTER TABLE "meta" ADD "moreUrls" jsonb NOT NULL DEFAULT '[]'`, - ); - } - - async down(queryRunner) { - queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "moreUrls"`); - } -} diff --git a/packages/backend/migration/1708452631156-drop-user-profile-language.js b/packages/backend/migration/1708452631156-drop-user-profile-language.js deleted file mode 100644 index 37e701ef15..0000000000 --- a/packages/backend/migration/1708452631156-drop-user-profile-language.js +++ /dev/null @@ -1,13 +0,0 @@ -export class DropUserProfileLanguage1708452631156 { - name = "DropUserProfileLanguage1708452631156"; - - async up(queryRunner) { - await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); - } - - async down(queryRunner) { - await queryRunner.query( - `ALTER TABLE "user_profile" ADD COLUMN "lang" character varying(32)`, - ); - } -} diff --git a/packages/backend/migration/1709129810501-fix-note-url-index.js b/packages/backend/migration/1709129810501-fix-note-url-index.js deleted file mode 100644 index 3c13f65359..0000000000 --- a/packages/backend/migration/1709129810501-fix-note-url-index.js +++ /dev/null @@ -1,11 +0,0 @@ -export class FixNoteUrlIndex1709129810501 { - name = "FixNoteUrlIndex1709129810501"; - - async up(queryRunner) { - await queryRunner.query(`DROP INDEX "IDX_note_url"`); - await queryRunner.query(`CREATE INDEX "IDX_note_url" ON "note" ("url")`); - } - async down(queryRunner) { - /* You don't revert this migration */ - } -} diff --git a/packages/backend/package.json b/packages/backend/package.json index d5786f16ec..e86663a9d8 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -6,8 +6,9 @@ "scripts": { "start": "pnpm node ./built/index.js", "start:test": "NODE_ENV=test pnpm node ./built/index.js", - "migrate": "typeorm migration:run -d ormconfig.js", - "revertmigration": "typeorm migration:revert -d ormconfig.js", + "migration:run": "typeorm migration:run --dataSource ./built/ormconfig.js", + "migration:revert": "typeorm migration:revert --dataSource ./built/ormconfig.js", + "migration:new": "pnpm node ./scripts/create-migration.mjs", "check:connect": "node ./check_connect.js", "build": "pnpm swc src --out-dir built --source-maps false --copy-files --strip-leading-paths", "build:debug": "pnpm swc src --out-dir built --source-maps true --copy-files --strip-leading-paths", @@ -21,25 +22,24 @@ "@swc/core-android-arm64": "1.3.11" }, "dependencies": { - "@bull-board/api": "5.14.2", - "@bull-board/koa": "5.14.2", - "@bull-board/ui": "5.14.2", + "@bull-board/api": "5.15.1", + "@bull-board/koa": "5.15.1", + "@bull-board/ui": "5.15.1", "@discordapp/twemoji": "^15.0.2", - "@elastic/elasticsearch": "8.12.2", "@koa/cors": "5.0.0", "@koa/multer": "3.0.2", "@koa/router": "12.0.1", "@ladjs/koa-views": "9.0.0", "@peertube/http-signature": "1.7.0", - "@redocly/openapi-core": "1.9.1", + "@redocly/openapi-core": "1.10.5", "@sinonjs/fake-timers": "11.2.2", "@twemoji/parser": "^15.0.0", - "adm-zip": "^0.5.10", + "adm-zip": "^0.5.12", "ajv": "8.12.0", - "archiver": "6.0.2", + "archiver": "7.0.1", "argon2": "^0.40.1", - "aws-sdk": "2.1567.0", - "axios": "^1.6.7", + "aws-sdk": "2.1584.0", + "axios": "^1.6.8", "backend-rs": "workspace:*", "bcryptjs": "2.4.3", "blurhash": "2.0.5", @@ -51,17 +51,18 @@ "cli-highlight": "2.1.11", "color-convert": "2.0.1", "content-disposition": "0.5.4", - "date-fns": "3.3.1", + "date-fns": "3.6.0", "decompress": "^4.2.1", "deep-email-validator": "0.1.21", + "deepl-node": "1.12.0", "escape-regexp": "0.0.1", "feed": "4.2.2", "file-type": "19.0.0", "fluent-ffmpeg": "2.1.2", "form-data": "^4.0.0", - "got": "14.2.0", + "got": "14.2.1", "gunzip-maybe": "^1.4.2", - "happy-dom": "^13.6.2", + "happy-dom": "^14.3.1", "hpagent": "1.2.0", "ioredis": "5.3.2", "ip-cidr": "4.0.0", @@ -70,7 +71,7 @@ "json5": "2.2.3", "jsonld": "8.3.2", "jsrsasign": "11.1.0", - "koa": "2.15.0", + "koa": "2.15.2", "koa-body": "^6.0.1", "koa-bodyparser": "4.4.1", "koa-favicon": "2.1.0", @@ -81,14 +82,13 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "megalodon": "workspace:*", - "meilisearch": "0.37.0", "mfm-js": "0.24.0", "mime-types": "2.1.35", "msgpackr": "^1.10.1", "multer": "1.4.5-lts.1", "nested-property": "4.0.0", "node-fetch": "3.3.2", - "nodemailer": "6.9.10", + "nodemailer": "6.9.13", "opencc-js": "^1.0.5", "os-utils": "0.0.14", "otpauth": "^9.2.2", @@ -100,27 +100,26 @@ "punycode": "2.3.1", "pureimage": "0.4.13", "qrcode": "1.5.3", - "qs": "6.11.2", + "qs": "6.12.0", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.20.9", - "redis-semaphore": "5.5.0", + "re2": "1.20.10", + "redis-semaphore": "5.5.1", "reflect-metadata": "0.2.1", "rename": "1.0.4", "rndstr": "1.0.0", "rss-parser": "3.13.0", - "sanitize-html": "2.12.1", + "sanitize-html": "2.13.0", "semver": "7.6.0", - "sharp": "0.33.2", - "sonic-channel": "^1.3.1", + "sharp": "0.33.3", "stringz": "2.1.0", "summaly": "2.7.0", "syslog-pro": "1.0.0", - "systeminformation": "5.22.0", + "systeminformation": "5.22.6", "tar-stream": "^3.1.7", "tesseract.js": "^5.0.5", "tinycolor2": "1.6.0", - "tmp": "0.2.2", + "tmp": "0.2.3", "typeorm": "0.3.20", "ulid": "2.3.0", "uuid": "9.0.1", @@ -130,7 +129,7 @@ }, "devDependencies": { "@swc/cli": "0.3.10", - "@swc/core": "1.4.2", + "@swc/core": "1.4.8", "@types/adm-zip": "^0.5.5", "@types/bcryptjs": "2.4.6", "@types/color-convert": "^2.0.3", @@ -139,7 +138,7 @@ "@types/fluent-ffmpeg": "2.1.24", "@types/js-yaml": "4.0.9", "@types/jsonld": "1.5.13", - "@types/jsrsasign": "10.5.12", + "@types/jsrsasign": "10.5.13", "@types/koa": "2.15.0", "@types/koa-bodyparser": "4.3.12", "@types/koa-cors": "0.0.6", @@ -151,17 +150,17 @@ "@types/koa__multer": "2.0.7", "@types/koa__router": "12.0.4", "@types/mocha": "10.0.6", - "@types/node": "20.11.21", + "@types/node": "20.11.30", "@types/node-fetch": "2.6.11", "@types/nodemailer": "6.4.14", "@types/oauth": "0.9.4", "@types/opencc-js": "^1.0.3", - "@types/pg": "^8.11.2", + "@types/pg": "^8.11.4", "@types/probe-image-size": "^7.2.4", "@types/pug": "2.0.10", "@types/punycode": "2.1.4", "@types/qrcode": "1.5.5", - "@types/qs": "6.9.12", + "@types/qs": "6.9.14", "@types/random-seed": "0.3.5", "@types/ratelimiter": "3.4.6", "@types/rename": "1.0.7", @@ -177,8 +176,6 @@ "@types/ws": "8.5.10", "cross-env": "7.0.3", "eslint": "^8.57.0", - "execa": "8.0.1", - "json5-loader": "4.0.1", "mocha": "10.3.0", "pug": "3.0.2", "strict-event-emitter-types": "2.0.0", @@ -186,8 +183,8 @@ "ts-loader": "9.5.1", "ts-node": "10.9.2", "tsconfig-paths": "4.2.0", - "typescript": "5.3.3", - "webpack": "^5.90.3", + "typescript": "5.4.3", + "webpack": "^5.91.0", "ws": "8.16.0" } } diff --git a/packages/backend/scripts/create-migration.mjs b/packages/backend/scripts/create-migration.mjs new file mode 100644 index 0000000000..5881ddb0e3 --- /dev/null +++ b/packages/backend/scripts/create-migration.mjs @@ -0,0 +1,11 @@ +import { execa } from "execa"; + +(async () => { + await execa( + "pnpm", + ["typeorm", "migration:create", `src/migration/${process.argv[2]}`], + { + stdio: "inherit", + }, + ); +})(); diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 9418f59e4c..e54a2889e2 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -71,7 +71,7 @@ function greet() { 136, 0, )( - " If you like Firefish, please consider starring or contributing to the repo. https://firefish.dev/firefish/firefish", + " If you like Firefish, please consider contributing to the repo. https://firefish.dev/firefish/firefish", ), ); @@ -149,7 +149,7 @@ function showNodejsVersion(): void { nodejsLogger.info(`Version ${process.version} detected.`); - const minVersion = "v18.16.0"; + const minVersion = "v18.17.0"; if (semver.lt(process.version, minVersion)) { nodejsLogger.error(`At least Node.js ${minVersion} required!`); process.exit(1); diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 0389bf83fb..882e429c79 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -37,27 +37,6 @@ export type Source = { user?: string; tls?: { [z: string]: string }; }; - elasticsearch: { - host: string; - port: number; - ssl?: boolean; - user?: string; - pass?: string; - index?: string; - }; - sonic: { - host: string; - port: number; - auth?: string; - collection?: string; - bucket?: string; - }; - meilisearch: { - host: string; - port: number; - apiKey?: string; - ssl: boolean; - }; proxy?: string; proxySmtp?: string; diff --git a/packages/backend/src/daemons/server-stats.ts b/packages/backend/src/daemons/server-stats.ts index dc7493381c..58a9b1491b 100644 --- a/packages/backend/src/daemons/server-stats.ts +++ b/packages/backend/src/daemons/server-stats.ts @@ -2,7 +2,6 @@ import si from "systeminformation"; import Xev from "xev"; import * as osUtils from "os-utils"; import { fetchMeta } from "@/misc/fetch-meta.js"; -import meilisearch from "@/db/meilisearch.js"; const ev = new Xev(); @@ -30,7 +29,6 @@ export default function () { const memStats = await mem(); const netStats = await net(); const fsStats = await fs(); - const meilisearchStats = await meilisearchStatus(); const stats = { cpu: roundCpu(cpu), @@ -47,7 +45,6 @@ export default function () { r: round(Math.max(0, fsStats.rIO_sec ?? 0)), w: round(Math.max(0, fsStats.wIO_sec ?? 0)), }, - meilisearch: meilisearchStats, }; ev.emit("serverStats", stats); log.unshift(stats); @@ -86,16 +83,3 @@ async function fs() { const data = await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 })); return data || { rIO_sec: 0, wIO_sec: 0 }; } - -// MEILI STAT -async function meilisearchStatus() { - if (meilisearch) { - return meilisearch.serverStats(); - } else { - return { - health: "unconfigured", - size: 0, - indexed_count: 0, - }; - } -} diff --git a/packages/backend/src/db/elasticsearch.ts b/packages/backend/src/db/elasticsearch.ts deleted file mode 100644 index 2640e7f918..0000000000 --- a/packages/backend/src/db/elasticsearch.ts +++ /dev/null @@ -1,65 +0,0 @@ -import * as elasticsearch from "@elastic/elasticsearch"; -import config from "@/config/index.js"; - -const index = { - settings: { - analysis: { - analyzer: { - ngram: { - tokenizer: "ngram", - }, - }, - }, - }, - mappings: { - properties: { - text: { - type: "text", - index: true, - analyzer: "ngram", - }, - userId: { - type: "keyword", - index: true, - }, - userHost: { - type: "keyword", - index: true, - }, - }, - }, -}; - -// Init ElasticSearch connection -const client = config.elasticsearch - ? new elasticsearch.Client({ - node: `${config.elasticsearch.ssl ? "https://" : "http://"}${ - config.elasticsearch.host - }:${config.elasticsearch.port}`, - auth: - config.elasticsearch.user && config.elasticsearch.pass - ? { - username: config.elasticsearch.user, - password: config.elasticsearch.pass, - } - : undefined, - pingTimeout: 30000, - }) - : null; - -if (client) { - client.indices - .exists({ - index: config.elasticsearch.index || "misskey_note", - }) - .then((exist) => { - if (!exist.body) { - client.indices.create({ - index: config.elasticsearch.index || "misskey_note", - body: index, - }); - } - }); -} - -export default client; diff --git a/packages/backend/src/db/meilisearch.ts b/packages/backend/src/db/meilisearch.ts deleted file mode 100644 index 1f294058e5..0000000000 --- a/packages/backend/src/db/meilisearch.ts +++ /dev/null @@ -1,451 +0,0 @@ -import { Health, Index, MeiliSearch, Stats } from "meilisearch"; -import { dbLogger } from "./logger.js"; - -import config from "@/config/index.js"; -import { Note } from "@/models/entities/note.js"; -import * as url from "url"; -import { ILocalUser } from "@/models/entities/user.js"; -import { Followings, Users } from "@/models/index.js"; - -const logger = dbLogger.createSubLogger("meilisearch", "gray", false); - -let posts: Index; -let client: MeiliSearch; - -const hasConfig = - config.meilisearch && - (config.meilisearch.host || - config.meilisearch.port || - config.meilisearch.apiKey); - -if (hasConfig) { - const host = hasConfig ? config.meilisearch.host ?? "localhost" : ""; - const port = hasConfig ? config.meilisearch.port ?? 7700 : 0; - const auth = hasConfig ? config.meilisearch.apiKey ?? "" : ""; - const ssl = hasConfig ? config.meilisearch.ssl ?? false : false; - - logger.info("Connecting to MeiliSearch"); - - client = new MeiliSearch({ - host: `${ssl ? "https" : "http"}://${host}:${port}`, - apiKey: auth, - }); - - posts = client.index("posts"); - - posts - .updateSearchableAttributes(["text"]) - .catch((e) => - logger.error(`Setting searchable attr failed, searches won't work: ${e}`), - ); - - posts - .updateFilterableAttributes([ - "userName", - "userHost", - "mediaAttachment", - "createdAt", - "userId", - ]) - .catch((e) => - logger.error( - `Setting filterable attr failed, advanced searches won't work: ${e}`, - ), - ); - - posts - .updateSortableAttributes(["createdAt"]) - .catch((e) => - logger.error( - `Setting sortable attr failed, placeholder searches won't sort properly: ${e}`, - ), - ); - - posts - .updateStopWords([ - "the", - "a", - "as", - "be", - "of", - "they", - "these", - "is", - "are", - "これ", - "それ", - "あれ", - "この", - "その", - "あの", - "ここ", - "そこ", - "あそこ", - "こちら", - "どこ", - "私", - "僕", - "俺", - "君", - "あなた", - "我々", - "私達", - "彼女", - "彼", - "です", - "ます", - "は", - "が", - "の", - "に", - "を", - "で", - "へ", - "から", - "まで", - "より", - "も", - "どの", - "と", - "それで", - "しかし", - ]) - .catch((e) => - logger.error( - `Failed to set Meilisearch stop words, database size will be larger: ${e}`, - ), - ); - - posts - .updateRankingRules([ - "sort", - "words", - "typo", - "proximity", - "attribute", - "exactness", - ]) - .catch((e) => { - logger.error("Failed to set ranking rules, sorting won't work properly."); - }); - - logger.info("Connected to MeiliSearch"); -} - -export type MeilisearchNote = { - id: string; - text: string; - userId: string; - userHost: string; - userName: string; - channelId: string; - mediaAttachment: string; - createdAt: number; -}; - -function timestampToUnix(timestamp: string) { - let unix = 0; - - // Only contains numbers => UNIX timestamp - if (/^\d+$/.test(timestamp)) { - unix = Number.parseInt(timestamp); - } - - if (unix === 0) { - // Try to parse the timestamp as JavaScript Date - const date = Date.parse(timestamp); - if (Number.isNaN(date)) return 0; - unix = date / 1000; - } - - return unix; -} - -export default hasConfig - ? { - search: async ( - query: string, - limit: number, - offset: number, - userCtx: ILocalUser | null, - overrideSort: string | null, - ) => { - /// Advanced search syntax - /// from:user => filter by user + optional domain - /// has:image/video/audio/text/file => filter by attachment types - /// domain:domain.com => filter by domain - /// before:Date => show posts made before Date - /// after: Date => show posts made after Date - /// "text" => get posts with exact text between quotes - /// filter:following => show results only from users you follow - /// filter:followers => show results only from followers - /// order:desc/asc => order results ascending or descending - - const constructedFilters: string[] = []; - let sortRules: string[] = []; - - const splitSearch = query.split(" "); - - // Detect search operators and remove them from the actual query - const filteredSearchTerms = ( - await Promise.all( - splitSearch.map(async (term) => { - if (term.startsWith("has:")) { - const fileType = term.slice(4); - constructedFilters.push(`mediaAttachment = "${fileType}"`); - return null; - } else if (term.startsWith("from:")) { - let user = term.slice(5); - - if (user.length === 0) return null; - - // Cut off leading @, those aren't saved in the DB - if (user.charAt(0) === "@") { - user = user.slice(1); - } - - // Determine if we got a webfinger address or a single username - if (user.split("@").length > 1) { - const splitUser = user.split("@"); - - const domain = splitUser.pop(); - user = splitUser.join("@"); - - constructedFilters.push( - `userName = ${user} AND userHost = ${domain}`, - ); - } else { - constructedFilters.push(`userName = ${user}`); - } - - return null; - } else if (term.startsWith("domain:")) { - const domain = term.slice(7); - if ( - domain.length === 0 || - domain === "local" || - domain === config.hostname - ) { - constructedFilters.push("userHost NOT EXISTS"); - return null; - } - constructedFilters.push(`userHost = ${domain}`); - return null; - } else if (term.startsWith("after:")) { - const timestamp = term.slice(6); - - const unix = timestampToUnix(timestamp); - - if (unix !== 0) constructedFilters.push(`createdAt > ${unix}`); - - return null; - } else if (term.startsWith("before:")) { - const timestamp = term.slice(7); - - const unix = timestampToUnix(timestamp); - if (unix !== 0) constructedFilters.push(`createdAt < ${unix}`); - - return null; - } else if (term.startsWith("filter:following")) { - // Check if we got a context user - if (userCtx) { - // Fetch user follows from DB - const followedUsers = await Followings.find({ - where: { - followerId: userCtx.id, - }, - select: { - followeeId: true, - }, - }); - const followIDs = followedUsers.map( - (user) => user.followeeId, - ); - - if (followIDs.length === 0) return null; - - constructedFilters.push(`userId IN [${followIDs.join(",")}]`); - } else { - logger.warn( - "search filtered to follows called without user context", - ); - } - - return null; - } else if (term.startsWith("filter:followers")) { - // Check if we got a context user - if (userCtx) { - // Fetch users follows from DB - const followedUsers = await Followings.find({ - where: { - followeeId: userCtx.id, - }, - select: { - followerId: true, - }, - }); - const followIDs = followedUsers.map( - (user) => user.followerId, - ); - - if (followIDs.length === 0) return null; - - constructedFilters.push(`userId IN [${followIDs.join(",")}]`); - } else { - logger.warn( - "search filtered to followers called without user context", - ); - } - - return null; - } else if (term.startsWith("order:desc")) { - sortRules.push("createdAt:desc"); - - return null; - } else if (term.startsWith("order:asc")) { - sortRules.push("createdAt:asc"); - - return null; - } - - return term; - }), - ) - ).filter((term) => term !== null); - - // An empty search term with defined filters means we have a placeholder search => https://www.meilisearch.com/docs/reference/api/search#placeholder-search - // These have to be ordered manually, otherwise the *oldest* posts are returned first, which we don't want - // If the user has defined a sort rule, don't mess with it - if ( - filteredSearchTerms.length === 0 && - constructedFilters.length > 0 && - sortRules.length === 0 - ) { - sortRules.push("createdAt:desc"); - } - - // More than one sorting rule doesn't make sense. We only keep the first one, otherwise weird stuff may happen. - if (sortRules.length > 1) { - sortRules = [sortRules[0]]; - } - - // An override sort takes precedence, user sorting is ignored here - if (overrideSort) { - sortRules = [overrideSort]; - } - - logger.info(`Searching for ${filteredSearchTerms.join(" ")}`); - logger.info(`Limit: ${limit}`); - logger.info(`Offset: ${offset}`); - logger.info(`Filters: ${constructedFilters}`); - logger.info(`Ordering: ${sortRules}`); - - return posts.search(filteredSearchTerms.join(" "), { - limit: limit, - offset: offset, - filter: constructedFilters, - sort: sortRules, - }); - }, - ingestNote: async (ingestNotes: Note | Note[]) => { - if (ingestNotes instanceof Note) { - ingestNotes = [ingestNotes]; - } - - const indexingBatch: MeilisearchNote[] = []; - - for (const note of ingestNotes) { - if (note.user === undefined) { - note.user = await Users.findOne({ - where: { - id: note.userId, - }, - }); - } - - let attachmentType = ""; - if (note.attachedFileTypes.length > 0) { - attachmentType = note.attachedFileTypes[0].split("/")[0]; - switch (attachmentType) { - case "image": - case "video": - case "audio": - case "text": - break; - default: - attachmentType = "file"; - break; - } - } - - indexingBatch.push({ - id: note.id.toString(), - text: note.text ? note.text : "", - userId: note.userId, - userHost: - note.userHost !== "" - ? note.userHost - : url.parse(config.host).host, - channelId: note.channelId ? note.channelId : "", - mediaAttachment: attachmentType, - userName: note.user?.username ?? "UNKNOWN", - createdAt: note.createdAt.getTime() / 1000, // division by 1000 is necessary because Node returns in ms-accuracy - }); - } - - return posts - .addDocuments(indexingBatch, { - primaryKey: "id", - }) - .then(() => - logger.info(`sent ${indexingBatch.length} posts for indexing`), - ); - }, - serverStats: async () => { - const health: Health = await client.health(); - const stats: Stats = await client.getStats(); - - return { - health: health.status, - size: stats.databaseSize, - indexed_count: stats.indexes["posts"].numberOfDocuments, - }; - }, - deleteNotes: async (note: Note | Note[] | string | string[]) => { - if (note instanceof Note) { - note = [note]; - } - if (typeof note === "string") { - note = [note]; - } - - const deletionBatch = note - .map((n) => { - if (n instanceof Note) { - return n.id; - } - - if (n.length > 0) return n; - - logger.error( - `Failed to delete note from Meilisearch, invalid post ID: ${JSON.stringify( - n, - )}`, - ); - - throw new Error( - `Invalid note ID passed to meilisearch deleteNote: ${JSON.stringify( - n, - )}`, - ); - }) - .filter((el) => el !== null); - - await posts.deleteDocuments(deletionBatch as string[]).then(() => { - logger.info( - `submitted ${deletionBatch.length} large batch for deletion`, - ); - }); - }, - } - : null; diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index b14f028e8b..b6c3f0db8f 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -73,6 +73,7 @@ import { UserPending } from "@/models/entities/user-pending.js"; import { Webhook } from "@/models/entities/webhook.js"; import { UserIp } from "@/models/entities/user-ip.js"; import { NoteEdit } from "@/models/entities/note-edit.js"; +import { NoteFile } from "@/models/entities/note-file.js"; import { entities as charts } from "@/services/chart/entities.js"; import { dbLogger } from "./logger.js"; @@ -143,6 +144,7 @@ export const entities = [ Note, NoteEdit, NoteFavorite, + NoteFile, NoteReaction, NoteWatching, NoteThreadMuting, diff --git a/packages/backend/src/db/sonic.ts b/packages/backend/src/db/sonic.ts deleted file mode 100644 index 032982f083..0000000000 --- a/packages/backend/src/db/sonic.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as SonicChannel from "sonic-channel"; -import { dbLogger } from "./logger.js"; - -import config from "@/config/index.js"; - -const logger = dbLogger.createSubLogger("sonic", "gray", false); - -const handlers = (type: string): SonicChannel.Handlers => ({ - connected: () => { - logger.succ(`Connected to Sonic ${type}`); - }, - disconnected: (error) => { - logger.warn(`Disconnected from Sonic ${type}, error: ${error}`); - }, - error: (error) => { - logger.warn(`Sonic ${type} error: ${error}`); - }, - retrying: () => { - logger.info(`Sonic ${type} retrying`); - }, - timeout: () => { - logger.warn(`Sonic ${type} timeout`); - }, -}); - -const hasConfig = - config.sonic && (config.sonic.host || config.sonic.port || config.sonic.auth); - -if (hasConfig) { - logger.info("Connecting to Sonic"); -} - -const host = hasConfig ? config.sonic.host ?? "localhost" : ""; -const port = hasConfig ? config.sonic.port ?? 1491 : 0; -const auth = hasConfig ? config.sonic.auth ?? "SecretPassword" : ""; -const collection = hasConfig ? config.sonic.collection ?? "main" : ""; -const bucket = hasConfig ? config.sonic.bucket ?? "default" : ""; - -export default hasConfig - ? { - search: new SonicChannel.Search({ host, port, auth }).connect( - handlers("search"), - ), - ingest: new SonicChannel.Ingest({ host, port, auth }).connect( - handlers("ingest"), - ), - - collection, - bucket, - } - : null; diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index ab4c90b33e..284a360dd7 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -3,10 +3,10 @@ */ import { EventEmitter } from "node:events"; -import boot from "./boot/index.js"; import { inspect } from "node:util"; +import boot from "./boot/index.js"; -Error.stackTraceLimit = Infinity; +Error.stackTraceLimit = Number.POSITIVE_INFINITY; EventEmitter.defaultMaxListeners = 128; boot().catch((err) => { diff --git a/packages/backend/migration/1000000000000-Init.js b/packages/backend/src/migration/1000000000000-Init.ts similarity index 99% rename from packages/backend/migration/1000000000000-Init.js rename to packages/backend/src/migration/1000000000000-Init.ts index a72f53841c..ae88514d18 100644 --- a/packages/backend/migration/1000000000000-Init.js +++ b/packages/backend/src/migration/1000000000000-Init.ts @@ -1,5 +1,7 @@ -export class Init1000000000000 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Init1000000000000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "log_level_enum" AS ENUM('error', 'warning', 'info', 'success', 'debug')`, ); @@ -712,7 +714,7 @@ export class Init1000000000000 { `ALTER TABLE "user_profile" ADD CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9"`, ); diff --git a/packages/backend/migration/1556348509290-Pages.js b/packages/backend/src/migration/1556348509290-Pages.ts similarity index 92% rename from packages/backend/migration/1556348509290-Pages.js rename to packages/backend/src/migration/1556348509290-Pages.ts index 696b2acbec..66d00f7405 100644 --- a/packages/backend/migration/1556348509290-Pages.js +++ b/packages/backend/src/migration/1556348509290-Pages.ts @@ -1,5 +1,7 @@ -export class Pages1556348509290 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Pages1556348509290 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "page_visibility_enum" AS ENUM('public', 'followers', 'specified')`, ); @@ -31,7 +33,7 @@ export class Pages1556348509290 { `ALTER TABLE "page" ADD CONSTRAINT "FK_3126dd7c502c9e4d7597ef7ef10" FOREIGN KEY ("eyeCatchingImageId") REFERENCES "drive_file"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "page" DROP CONSTRAINT "FK_3126dd7c502c9e4d7597ef7ef10"`, ); diff --git a/packages/backend/migration/1556746559567-UserProfile.js b/packages/backend/src/migration/1556746559567-UserProfile.ts similarity index 72% rename from packages/backend/migration/1556746559567-UserProfile.js rename to packages/backend/src/migration/1556746559567-UserProfile.ts index d229ec519f..015df00331 100644 --- a/packages/backend/migration/1556746559567-UserProfile.js +++ b/packages/backend/src/migration/1556746559567-UserProfile.ts @@ -1,5 +1,7 @@ -export class UserProfile1556746559567 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UserProfile1556746559567 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ALTER COLUMN "githubId" TYPE VARCHAR(64) USING "githubId"::VARCHAR(64)`, ); @@ -7,7 +9,7 @@ export class UserProfile1556746559567 { `ALTER TABLE "user_profile" ALTER COLUMN "discordExpiresDate" TYPE VARCHAR(64) USING "discordExpiresDate"::VARCHAR(64)`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE "user_profile" SET github = FALSE, discord = FALSE`, ); diff --git a/packages/backend/src/migration/1557476068003-PinnedUsers.ts b/packages/backend/src/migration/1557476068003-PinnedUsers.ts new file mode 100644 index 0000000000..f7c279744d --- /dev/null +++ b/packages/backend/src/migration/1557476068003-PinnedUsers.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PinnedUsers1557476068003 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "pinnedUsers" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedUsers"`); + } +} diff --git a/packages/backend/migration/1557761316509-AddSomeUrls.js b/packages/backend/src/migration/1557761316509-AddSomeUrls.ts similarity index 72% rename from packages/backend/migration/1557761316509-AddSomeUrls.js rename to packages/backend/src/migration/1557761316509-AddSomeUrls.ts index 9839fe010b..e0af30240f 100644 --- a/packages/backend/migration/1557761316509-AddSomeUrls.js +++ b/packages/backend/src/migration/1557761316509-AddSomeUrls.ts @@ -1,5 +1,7 @@ -export class AddSomeUrls1557761316509 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddSomeUrls1557761316509 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "ToSUrl" character varying(512)`, ); @@ -10,7 +12,7 @@ export class AddSomeUrls1557761316509 { `ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://codeberg.org/firefish/firefish/issues'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "feedbackUrl"`); await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "repositoryUrl"`); await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "ToSUrl"`); diff --git a/packages/backend/migration/1557932705754-ObjectStorageSetting.js b/packages/backend/src/migration/1557932705754-ObjectStorageSetting.ts similarity index 88% rename from packages/backend/migration/1557932705754-ObjectStorageSetting.js rename to packages/backend/src/migration/1557932705754-ObjectStorageSetting.ts index 5fcc98fe15..cc8e36003b 100644 --- a/packages/backend/migration/1557932705754-ObjectStorageSetting.js +++ b/packages/backend/src/migration/1557932705754-ObjectStorageSetting.ts @@ -1,5 +1,7 @@ -export class ObjectStorageSetting1557932705754 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ObjectStorageSetting1557932705754 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "useObjectStorage" boolean NOT NULL DEFAULT false`, ); @@ -31,7 +33,7 @@ export class ObjectStorageSetting1557932705754 { `ALTER TABLE "meta" ADD "objectStorageUseSSL" boolean NOT NULL DEFAULT true`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "objectStorageUseSSL"`, ); diff --git a/packages/backend/migration/1558072954435-PageLike.js b/packages/backend/src/migration/1558072954435-PageLike.ts similarity index 86% rename from packages/backend/migration/1558072954435-PageLike.js rename to packages/backend/src/migration/1558072954435-PageLike.ts index e919e02ddb..80c8da95b0 100644 --- a/packages/backend/migration/1558072954435-PageLike.js +++ b/packages/backend/src/migration/1558072954435-PageLike.ts @@ -1,5 +1,7 @@ -export class PageLike1558072954435 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PageLike1558072954435 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "page_like" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "pageId" character varying(32) NOT NULL, CONSTRAINT "PK_813f034843af992d3ae0f43c64c" PRIMARY KEY ("id"))`, ); @@ -19,7 +21,7 @@ export class PageLike1558072954435 { `ALTER TABLE "page_like" ADD CONSTRAINT "FK_cf8782626dced3176038176a847" FOREIGN KEY ("pageId") REFERENCES "page"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "page_like" DROP CONSTRAINT "FK_cf8782626dced3176038176a847"`, ); diff --git a/packages/backend/migration/1558103093633-UserGroup.js b/packages/backend/src/migration/1558103093633-UserGroup.ts similarity index 94% rename from packages/backend/migration/1558103093633-UserGroup.js rename to packages/backend/src/migration/1558103093633-UserGroup.ts index dc581a24ef..20e008b62c 100644 --- a/packages/backend/migration/1558103093633-UserGroup.js +++ b/packages/backend/src/migration/1558103093633-UserGroup.ts @@ -1,5 +1,7 @@ -export class UserGroup1558103093633 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UserGroup1558103093633 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "user_group" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(256) NOT NULL, "userId" character varying(32) NOT NULL, "isPrivate" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_3c29fba6fe013ec8724378ce7c9" PRIMARY KEY ("id"))`, ); @@ -46,7 +48,7 @@ export class UserGroup1558103093633 { `ALTER TABLE "user_group_joining" ADD CONSTRAINT "FK_67dc758bc0566985d1b3d399865" FOREIGN KEY ("userGroupId") REFERENCES "user_group"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_group_joining" DROP CONSTRAINT "FK_67dc758bc0566985d1b3d399865"`, ); diff --git a/packages/backend/migration/1558257926829-UserGroupInvite.js b/packages/backend/src/migration/1558257926829-UserGroupInvite.ts similarity index 88% rename from packages/backend/migration/1558257926829-UserGroupInvite.js rename to packages/backend/src/migration/1558257926829-UserGroupInvite.ts index ed137fdb2e..f65e8d17a3 100644 --- a/packages/backend/migration/1558257926829-UserGroupInvite.js +++ b/packages/backend/src/migration/1558257926829-UserGroupInvite.ts @@ -1,5 +1,7 @@ -export class UserGroupInvite1558257926829 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UserGroupInvite1558257926829 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "user_group_invite" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "userGroupId" character varying(32) NOT NULL, CONSTRAINT "PK_3893884af0d3a5f4d01e7921a97" PRIMARY KEY ("id"))`, ); @@ -22,7 +24,7 @@ export class UserGroupInvite1558257926829 { `ALTER TABLE "user_group_invite" ADD CONSTRAINT "FK_e10924607d058004304611a436a" FOREIGN KEY ("userGroupId") REFERENCES "user_group"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_group_invite" DROP CONSTRAINT "FK_e10924607d058004304611a436a"`, ); diff --git a/packages/backend/src/migration/1558266512381-UserListJoining.ts b/packages/backend/src/migration/1558266512381-UserListJoining.ts new file mode 100644 index 0000000000..b531ba038a --- /dev/null +++ b/packages/backend/src/migration/1558266512381-UserListJoining.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UserListJoining1558266512381 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_90f7da835e4c10aca6853621e1" ON "user_list_joining" ("userId", "userListId") `, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_90f7da835e4c10aca6853621e1"`); + } +} diff --git a/packages/backend/migration/1561706992953-webauthn.js b/packages/backend/src/migration/1561706992953-webauthn.ts similarity index 91% rename from packages/backend/migration/1561706992953-webauthn.js rename to packages/backend/src/migration/1561706992953-webauthn.ts index f860d2c11b..2fa6798237 100644 --- a/packages/backend/migration/1561706992953-webauthn.js +++ b/packages/backend/src/migration/1561706992953-webauthn.ts @@ -1,5 +1,7 @@ -export class webauthn1561706992953 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class webauthn1561706992953 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "attestation_challenge" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "challenge" character varying(64) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "registrationChallenge" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_d0ba6786e093f1bcb497572a6b5" PRIMARY KEY ("id", "userId"))`, ); @@ -28,7 +30,7 @@ export class webauthn1561706992953 { `ALTER TABLE "user_security_key" ADD CONSTRAINT "FK_ff9ca3b5f3ee3d0681367a9b447" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_security_key" DROP CONSTRAINT "FK_ff9ca3b5f3ee3d0681367a9b447"`, ); diff --git a/packages/backend/migration/1561873850023-ChartIndexes.js b/packages/backend/src/migration/1561873850023-ChartIndexes.ts similarity index 98% rename from packages/backend/migration/1561873850023-ChartIndexes.js rename to packages/backend/src/migration/1561873850023-ChartIndexes.ts index ba46da1e41..ad907b84f9 100644 --- a/packages/backend/migration/1561873850023-ChartIndexes.js +++ b/packages/backend/src/migration/1561873850023-ChartIndexes.ts @@ -1,5 +1,7 @@ -export class ChartIndexes1561873850023 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ChartIndexes1561873850023 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc" ON "__chart__active_users" ("date") `, ); @@ -271,7 +273,7 @@ export class ChartIndexes1561873850023 { `CREATE INDEX "IDX_a770a57c70e668cc61590c9161" ON "__chart__users" ("span", "date", "group") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_a770a57c70e668cc61590c9161"`); await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`); await queryRunner.query(`DROP INDEX "IDX_f091abb24193d50c653c6b77fc"`); diff --git a/packages/backend/src/migration/1562422242907-PasswordLessLogin.ts b/packages/backend/src/migration/1562422242907-PasswordLessLogin.ts new file mode 100644 index 0000000000..cf8d974b4a --- /dev/null +++ b/packages/backend/src/migration/1562422242907-PasswordLessLogin.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PasswordLessLogin1562422242907 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD COLUMN "usePasswordLessLogin" boolean DEFAULT false NOT NULL`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" DROP COLUMN "usePasswordLessLogin"`, + ); + } +} diff --git a/packages/backend/migration/1562444565093-PinnedPage.js b/packages/backend/src/migration/1562444565093-PinnedPage.ts similarity index 76% rename from packages/backend/migration/1562444565093-PinnedPage.js rename to packages/backend/src/migration/1562444565093-PinnedPage.ts index dcb342d3fc..eb953d05c7 100644 --- a/packages/backend/migration/1562444565093-PinnedPage.js +++ b/packages/backend/src/migration/1562444565093-PinnedPage.ts @@ -1,5 +1,7 @@ -export class PinnedPage1562444565093 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PinnedPage1562444565093 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ADD "pinnedPageId" character varying(32)`, ); @@ -10,7 +12,7 @@ export class PinnedPage1562444565093 { `ALTER TABLE "user_profile" ADD CONSTRAINT "FK_6dc44f1ceb65b1e72bacef2ca27" FOREIGN KEY ("pinnedPageId") REFERENCES "page"("id") ON DELETE SET NULL ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP CONSTRAINT "FK_6dc44f1ceb65b1e72bacef2ca27"`, ); diff --git a/packages/backend/src/migration/1562448332510-PageTitleHideOption.ts b/packages/backend/src/migration/1562448332510-PageTitleHideOption.ts new file mode 100644 index 0000000000..5744b2578e --- /dev/null +++ b/packages/backend/src/migration/1562448332510-PageTitleHideOption.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PageTitleHideOption1562448332510 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "page" ADD "hideTitleWhenPinned" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "page" DROP COLUMN "hideTitleWhenPinned"`, + ); + } +} diff --git a/packages/backend/migration/1562869971568-ModerationLog.js b/packages/backend/src/migration/1562869971568-ModerationLog.ts similarity index 78% rename from packages/backend/migration/1562869971568-ModerationLog.js rename to packages/backend/src/migration/1562869971568-ModerationLog.ts index f652b067b4..66e7bca25a 100644 --- a/packages/backend/migration/1562869971568-ModerationLog.js +++ b/packages/backend/src/migration/1562869971568-ModerationLog.ts @@ -1,5 +1,7 @@ -export class ModerationLog1562869971568 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ModerationLog1562869971568 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "moderation_log" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "type" character varying(128) NOT NULL, "info" jsonb NOT NULL, CONSTRAINT "PK_d0adca6ecfd068db83e4526cc26" PRIMARY KEY ("id"))`, ); @@ -10,7 +12,7 @@ export class ModerationLog1562869971568 { `ALTER TABLE "moderation_log" ADD CONSTRAINT "FK_a08ad074601d204e0f69da9a954" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "moderation_log" DROP CONSTRAINT "FK_a08ad074601d204e0f69da9a954"`, ); diff --git a/packages/backend/migration/1563757595828-UsedUsername.js b/packages/backend/src/migration/1563757595828-UsedUsername.ts similarity index 55% rename from packages/backend/migration/1563757595828-UsedUsername.js rename to packages/backend/src/migration/1563757595828-UsedUsername.ts index 2cf5d8c740..bb82b91a5d 100644 --- a/packages/backend/migration/1563757595828-UsedUsername.js +++ b/packages/backend/src/migration/1563757595828-UsedUsername.ts @@ -1,10 +1,12 @@ -export class UsedUsername1563757595828 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UsedUsername1563757595828 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "used_username" ("username" character varying(128) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT "PK_78fd79d2d24c6ac2f4cc9a31a5d" PRIMARY KEY ("username"))`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP TABLE "used_username"`); } } diff --git a/packages/backend/src/migration/1565634203341-room.ts b/packages/backend/src/migration/1565634203341-room.ts new file mode 100644 index 0000000000..e3023fcf31 --- /dev/null +++ b/packages/backend/src/migration/1565634203341-room.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class room1565634203341 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "room" jsonb NOT NULL DEFAULT '{}'`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "room"`); + } +} diff --git a/packages/backend/src/migration/1571220798684-CustomEmojiCategory.ts b/packages/backend/src/migration/1571220798684-CustomEmojiCategory.ts new file mode 100644 index 0000000000..c3d9ea8765 --- /dev/null +++ b/packages/backend/src/migration/1571220798684-CustomEmojiCategory.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CustomEmojiCategory1571220798684 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "emoji" ADD "category" character varying(128)`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "emoji" DROP COLUMN "category"`, + undefined, + ); + } +} diff --git a/packages/backend/migration/1572760203493-nodeinfo.js b/packages/backend/src/migration/1572760203493-nodeinfo.ts similarity index 89% rename from packages/backend/migration/1572760203493-nodeinfo.js rename to packages/backend/src/migration/1572760203493-nodeinfo.ts index eea87c82c8..e346a44779 100644 --- a/packages/backend/migration/1572760203493-nodeinfo.js +++ b/packages/backend/src/migration/1572760203493-nodeinfo.ts @@ -1,5 +1,7 @@ -export class nodeinfo1572760203493 { - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class nodeinfo1572760203493 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "instance" DROP COLUMN "system"`, undefined, @@ -37,7 +39,7 @@ export class nodeinfo1572760203493 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "instance" DROP COLUMN "infoUpdatedAt"`, undefined, diff --git a/packages/backend/src/migration/1576269851876-TalkFederationId.ts b/packages/backend/src/migration/1576269851876-TalkFederationId.ts new file mode 100644 index 0000000000..02671f78e3 --- /dev/null +++ b/packages/backend/src/migration/1576269851876-TalkFederationId.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class TalkFederationId1576269851876 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "messaging_message" ADD "uri" character varying(512)`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "messaging_message" DROP COLUMN "uri"`, + undefined, + ); + } +} diff --git a/packages/backend/src/migration/1576869585998-ProxyRemoteFiles.ts b/packages/backend/src/migration/1576869585998-ProxyRemoteFiles.ts new file mode 100644 index 0000000000..e260da2195 --- /dev/null +++ b/packages/backend/src/migration/1576869585998-ProxyRemoteFiles.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ProxyRemoteFiles1576869585998 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT false`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`, + undefined, + ); + } +} diff --git a/packages/backend/migration/1579267006611-v12.js b/packages/backend/src/migration/1579267006611-v12.ts similarity index 93% rename from packages/backend/migration/1579267006611-v12.js rename to packages/backend/src/migration/1579267006611-v12.ts index f1d906465e..50cc491a6d 100644 --- a/packages/backend/migration/1579267006611-v12.js +++ b/packages/backend/src/migration/1579267006611-v12.ts @@ -1,8 +1,7 @@ -export class v121579267006611 { - constructor() { - this.name = "v121579267006611"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v121579267006611 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "announcement" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "text" character varying(8192) NOT NULL, "title" character varying(256) NOT NULL, "imageUrl" character varying(1024), CONSTRAINT "PK_e0ef0550174fd1099a308fd18a0" PRIMARY KEY ("id"))`, undefined, @@ -48,7 +47,7 @@ export class v121579267006611 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement_read" DROP CONSTRAINT "FK_603a7b1e7aa0533c6c88e9bfafe"`, undefined, diff --git a/packages/backend/migration/1579270193251-v12-2.js b/packages/backend/src/migration/1579270193251-v12-2.ts similarity index 51% rename from packages/backend/migration/1579270193251-v12-2.js rename to packages/backend/src/migration/1579270193251-v12-2.ts index 6bbcdcc152..d78a93828e 100644 --- a/packages/backend/migration/1579270193251-v12-2.js +++ b/packages/backend/src/migration/1579270193251-v12-2.ts @@ -1,14 +1,13 @@ -export class v1221579270193251 { - constructor() { - this.name = "v1221579270193251"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1221579270193251 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement_read" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement_read" DROP COLUMN "createdAt"`, undefined, diff --git a/packages/backend/migration/1579282808087-v12-3.js b/packages/backend/src/migration/1579282808087-v12-3.ts similarity index 50% rename from packages/backend/migration/1579282808087-v12-3.js rename to packages/backend/src/migration/1579282808087-v12-3.ts index d5a9a86b52..367fe78bcb 100644 --- a/packages/backend/migration/1579282808087-v12-3.js +++ b/packages/backend/src/migration/1579282808087-v12-3.ts @@ -1,14 +1,13 @@ -export class v1231579282808087 { - constructor() { - this.name = "v1231579282808087"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1231579282808087 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement" ADD "updatedAt" TIMESTAMP WITH TIME ZONE`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement" DROP COLUMN "updatedAt"`, undefined, diff --git a/packages/backend/migration/1579544426412-v12-4.js b/packages/backend/src/migration/1579544426412-v12-4.ts similarity index 72% rename from packages/backend/migration/1579544426412-v12-4.js rename to packages/backend/src/migration/1579544426412-v12-4.ts index efd6ee61bb..c84eea3e93 100644 --- a/packages/backend/migration/1579544426412-v12-4.js +++ b/packages/backend/src/migration/1579544426412-v12-4.ts @@ -1,8 +1,7 @@ -export class v1241579544426412 { - constructor() { - this.name = "v1241579544426412"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1241579544426412 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "notification" ADD "followRequestId" character varying(32)`, undefined, @@ -12,7 +11,7 @@ export class v1241579544426412 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "notification" DROP CONSTRAINT "FK_bd7fab507621e635b32cd31892c"`, undefined, diff --git a/packages/backend/migration/1579977526288-v12-5.js b/packages/backend/src/migration/1579977526288-v12-5.ts similarity index 96% rename from packages/backend/migration/1579977526288-v12-5.js rename to packages/backend/src/migration/1579977526288-v12-5.ts index f71c287551..b619451d90 100644 --- a/packages/backend/migration/1579977526288-v12-5.js +++ b/packages/backend/src/migration/1579977526288-v12-5.ts @@ -1,8 +1,7 @@ -export class v1251579977526288 { - constructor() { - this.name = "v1251579977526288"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1251579977526288 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "clip" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, "isPublic" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_f0685dac8d4dd056d7255670b75" PRIMARY KEY ("id"))`, undefined, @@ -85,7 +84,7 @@ export class v1251579977526288 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna_note" DROP CONSTRAINT "FK_0d775946662d2575dfd2068a5f5"`, undefined, diff --git a/packages/backend/migration/1579993013959-v12-6.js b/packages/backend/src/migration/1579993013959-v12-6.ts similarity index 74% rename from packages/backend/migration/1579993013959-v12-6.js rename to packages/backend/src/migration/1579993013959-v12-6.ts index fc954c3612..af84e04651 100644 --- a/packages/backend/migration/1579993013959-v12-6.js +++ b/packages/backend/src/migration/1579993013959-v12-6.ts @@ -1,8 +1,7 @@ -export class v1261579993013959 { - constructor() { - this.name = "v1261579993013959"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1261579993013959 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna" DROP COLUMN "hasNewNote"`, undefined, @@ -16,7 +15,7 @@ export class v1261579993013959 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "IDX_9937ea48d7ae97ffb4f3f063a4"`, undefined, diff --git a/packages/backend/migration/1580069531114-v12-7.js b/packages/backend/src/migration/1580069531114-v12-7.ts similarity index 86% rename from packages/backend/migration/1580069531114-v12-7.js rename to packages/backend/src/migration/1580069531114-v12-7.ts index c4214ddf13..e45ba5129a 100644 --- a/packages/backend/migration/1580069531114-v12-7.js +++ b/packages/backend/src/migration/1580069531114-v12-7.ts @@ -1,8 +1,7 @@ -export class v1271580069531114 { - constructor() { - this.name = "v1271580069531114"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1271580069531114 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna" ADD "users" character varying(1024) array NOT NULL DEFAULT '{}'::varchar[]`, undefined, @@ -25,7 +24,7 @@ export class v1271580069531114 { ); await queryRunner.query(`DROP TYPE "antenna_src_enum_old"`, undefined); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "antenna_src_enum_old" AS ENUM('home', 'all', 'list')`, undefined, diff --git a/packages/backend/migration/1580148575182-v12-8.js b/packages/backend/src/migration/1580148575182-v12-8.ts similarity index 69% rename from packages/backend/migration/1580148575182-v12-8.js rename to packages/backend/src/migration/1580148575182-v12-8.ts index 11b792b7ea..60e0487148 100644 --- a/packages/backend/migration/1580148575182-v12-8.js +++ b/packages/backend/src/migration/1580148575182-v12-8.ts @@ -1,8 +1,7 @@ -export class v1281580148575182 { - constructor() { - this.name = "v1281580148575182"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1281580148575182 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note" DROP CONSTRAINT "FK_ec5c201576192ba8904c345c5cc"`, undefined, @@ -12,7 +11,7 @@ export class v1281580148575182 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note" ADD "appId" character varying(32)`, undefined, diff --git a/packages/backend/migration/1580154400017-v12-9.js b/packages/backend/src/migration/1580154400017-v12-9.ts similarity index 50% rename from packages/backend/migration/1580154400017-v12-9.js rename to packages/backend/src/migration/1580154400017-v12-9.ts index 19f8be0958..1b4d390e5a 100644 --- a/packages/backend/migration/1580154400017-v12-9.js +++ b/packages/backend/src/migration/1580154400017-v12-9.ts @@ -1,14 +1,13 @@ -export class v1291580154400017 { - constructor() { - this.name = "v1291580154400017"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v1291580154400017 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna" ADD "withReplies" boolean NOT NULL DEFAULT false`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna" DROP COLUMN "withReplies"`, undefined, diff --git a/packages/backend/migration/1580276619901-v12-10.js b/packages/backend/src/migration/1580276619901-v12-10.ts similarity index 77% rename from packages/backend/migration/1580276619901-v12-10.js rename to packages/backend/src/migration/1580276619901-v12-10.ts index e5dd1db5e5..80c48f45aa 100644 --- a/packages/backend/migration/1580276619901-v12-10.js +++ b/packages/backend/src/migration/1580276619901-v12-10.ts @@ -1,8 +1,7 @@ -export class v12101580276619901 { - constructor() { - this.name = "v12101580276619901"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v12101580276619901 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`TRUNCATE TABLE "notification"`, undefined); await queryRunner.query( `ALTER TABLE "notification" DROP COLUMN "type"`, @@ -17,7 +16,7 @@ export class v12101580276619901 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "notification" DROP COLUMN "type"`, undefined, diff --git a/packages/backend/migration/1580331224276-v12-11.js b/packages/backend/src/migration/1580331224276-v12-11.ts similarity index 74% rename from packages/backend/migration/1580331224276-v12-11.js rename to packages/backend/src/migration/1580331224276-v12-11.ts index c31dca1758..b83e020258 100644 --- a/packages/backend/migration/1580331224276-v12-11.js +++ b/packages/backend/src/migration/1580331224276-v12-11.ts @@ -1,8 +1,7 @@ -export class v12111580331224276 { - constructor() { - this.name = "v12111580331224276"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v12111580331224276 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "instance" DROP COLUMN "isMarkedAsClosed"`, undefined, @@ -16,7 +15,7 @@ export class v12111580331224276 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "IDX_34500da2e38ac393f7bb6b299c"`, undefined, diff --git a/packages/backend/migration/1580508795118-v12-12.js b/packages/backend/src/migration/1580508795118-v12-12.ts similarity index 94% rename from packages/backend/migration/1580508795118-v12-12.js rename to packages/backend/src/migration/1580508795118-v12-12.ts index 6df1b8f8a9..263889aa8c 100644 --- a/packages/backend/migration/1580508795118-v12-12.js +++ b/packages/backend/src/migration/1580508795118-v12-12.ts @@ -1,8 +1,7 @@ -export class v12121580508795118 { - constructor() { - this.name = "v12121580508795118"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v12121580508795118 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "twitter"`, undefined, @@ -72,7 +71,7 @@ export class v12121580508795118 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "integrations"`, undefined, diff --git a/packages/backend/src/migration/1580543501339-v12-13.ts b/packages/backend/src/migration/1580543501339-v12-13.ts new file mode 100644 index 0000000000..a0e3e4f1ec --- /dev/null +++ b/packages/backend/src/migration/1580543501339-v12-13.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v12131580543501339 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_NOTE_TAGS" ON "note" USING gin ("tags")`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_NOTE_TAGS"`, undefined); + } +} diff --git a/packages/backend/migration/1580864313253-v12-14.js b/packages/backend/src/migration/1580864313253-v12-14.ts similarity index 81% rename from packages/backend/migration/1580864313253-v12-14.js rename to packages/backend/src/migration/1580864313253-v12-14.ts index 47f778e1d7..c8eefaefdf 100644 --- a/packages/backend/migration/1580864313253-v12-14.js +++ b/packages/backend/src/migration/1580864313253-v12-14.ts @@ -1,8 +1,7 @@ -export class v12141580864313253 { - constructor() { - this.name = "v12141580864313253"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class v12141580864313253 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" RENAME COLUMN "proxyAccount" TO "proxyAccountId"`, undefined, @@ -20,7 +19,7 @@ export class v12141580864313253 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP CONSTRAINT "FK_ab1bc0c1e209daa77b8e8d212ad"`, undefined, diff --git a/packages/backend/migration/1581526429287-user-group-invitation.js b/packages/backend/src/migration/1581526429287-user-group-invitation.ts similarity index 94% rename from packages/backend/migration/1581526429287-user-group-invitation.js rename to packages/backend/src/migration/1581526429287-user-group-invitation.ts index e327816ea7..811b10777e 100644 --- a/packages/backend/migration/1581526429287-user-group-invitation.js +++ b/packages/backend/src/migration/1581526429287-user-group-invitation.ts @@ -1,8 +1,7 @@ -export class userGroupInvitation1581526429287 { - constructor() { - this.name = "userGroupInvitation1581526429287"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userGroupInvitation1581526429287 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "user_group_invitation" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "userGroupId" character varying(32) NOT NULL, CONSTRAINT "PK_160c63ec02bf23f6a5c5e8140d6" PRIMARY KEY ("id"))`, undefined, @@ -56,7 +55,7 @@ export class userGroupInvitation1581526429287 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "notification" DROP CONSTRAINT "FK_8fe87814e978053a53b1beb7e98"`, undefined, diff --git a/packages/backend/migration/1581695816408-user-group-antenna.js b/packages/backend/src/migration/1581695816408-user-group-antenna.ts similarity index 89% rename from packages/backend/migration/1581695816408-user-group-antenna.js rename to packages/backend/src/migration/1581695816408-user-group-antenna.ts index 28112767e7..2428e682c9 100644 --- a/packages/backend/migration/1581695816408-user-group-antenna.js +++ b/packages/backend/src/migration/1581695816408-user-group-antenna.ts @@ -1,8 +1,7 @@ -export class userGroupAntenna1581695816408 { - constructor() { - this.name = "userGroupAntenna1581695816408"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userGroupAntenna1581695816408 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna" ADD "userGroupJoiningId" character varying(32)`, undefined, @@ -33,7 +32,7 @@ export class userGroupAntenna1581695816408 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "antenna" DROP CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb"`, undefined, diff --git a/packages/backend/src/migration/1581708415836-drive-user-folder-id-index.ts b/packages/backend/src/migration/1581708415836-drive-user-folder-id-index.ts new file mode 100644 index 0000000000..0d2b38905a --- /dev/null +++ b/packages/backend/src/migration/1581708415836-drive-user-folder-id-index.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class driveUserFolderIdIndex1581708415836 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_55720b33a61a7c806a8215b825" ON "drive_file" ("userId", "folderId", "id") `, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DROP INDEX "IDX_55720b33a61a7c806a8215b825"`, + undefined, + ); + } +} diff --git a/packages/backend/migration/1581979837262-promo.js b/packages/backend/src/migration/1581979837262-promo.ts similarity index 91% rename from packages/backend/migration/1581979837262-promo.js rename to packages/backend/src/migration/1581979837262-promo.ts index 39e79965b7..c8dc2d1fed 100644 --- a/packages/backend/migration/1581979837262-promo.js +++ b/packages/backend/src/migration/1581979837262-promo.ts @@ -1,8 +1,7 @@ -export class promo1581979837262 { - constructor() { - this.name = "promo1581979837262"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class promo1581979837262 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "promo_note" ("noteId" character varying(32) NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, CONSTRAINT "REL_e263909ca4fe5d57f8d4230dd5" UNIQUE ("noteId"), CONSTRAINT "PK_e263909ca4fe5d57f8d4230dd5c" PRIMARY KEY ("noteId"))`, undefined, @@ -36,7 +35,7 @@ export class promo1581979837262 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "promo_read" DROP CONSTRAINT "FK_a46a1a603ecee695d7db26da5f4"`, undefined, diff --git a/packages/backend/migration/1582019042083-featured-injecttion.js b/packages/backend/src/migration/1582019042083-featured-injecttion.ts similarity index 50% rename from packages/backend/migration/1582019042083-featured-injecttion.js rename to packages/backend/src/migration/1582019042083-featured-injecttion.ts index 61b7d0c272..3890b84d71 100644 --- a/packages/backend/migration/1582019042083-featured-injecttion.js +++ b/packages/backend/src/migration/1582019042083-featured-injecttion.ts @@ -1,14 +1,13 @@ -export class featuredInjecttion1582019042083 { - constructor() { - this.name = "featuredInjecttion1582019042083"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class featuredInjecttion1582019042083 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ADD "injectFeaturedNote" boolean NOT NULL DEFAULT true`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "injectFeaturedNote"`, undefined, diff --git a/packages/backend/src/migration/1582210532752-antenna-exclude.ts b/packages/backend/src/migration/1582210532752-antenna-exclude.ts new file mode 100644 index 0000000000..f78a8124cd --- /dev/null +++ b/packages/backend/src/migration/1582210532752-antenna-exclude.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class antennaExclude1582210532752 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "antenna" ADD "excludeKeywords" jsonb NOT NULL DEFAULT '[]'`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "antenna" DROP COLUMN "excludeKeywords"`, + undefined, + ); + } +} diff --git a/packages/backend/migration/1582875306439-note-reaction-length.js b/packages/backend/src/migration/1582875306439-note-reaction-length.ts similarity index 52% rename from packages/backend/migration/1582875306439-note-reaction-length.js rename to packages/backend/src/migration/1582875306439-note-reaction-length.ts index 2c9b726732..e52a1b1ac3 100644 --- a/packages/backend/migration/1582875306439-note-reaction-length.js +++ b/packages/backend/src/migration/1582875306439-note-reaction-length.ts @@ -1,14 +1,13 @@ -export class noteReactionLength1582875306439 { - constructor() { - this.name = "noteReactionLength1582875306439"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class noteReactionLength1582875306439 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(130)`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(128)`, undefined, diff --git a/packages/backend/migration/1585361548360-miauth.js b/packages/backend/src/migration/1585361548360-miauth.ts similarity index 92% rename from packages/backend/migration/1585361548360-miauth.js rename to packages/backend/src/migration/1585361548360-miauth.ts index 2e052cb89a..5283ebbafc 100644 --- a/packages/backend/migration/1585361548360-miauth.js +++ b/packages/backend/src/migration/1585361548360-miauth.ts @@ -1,8 +1,7 @@ -export class miauth1585361548360 { - constructor() { - this.name = "miauth1585361548360"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class miauth1585361548360 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "access_token" ADD "lastUsedAt" TIMESTAMP WITH TIME ZONE DEFAULT null`, undefined, @@ -52,7 +51,7 @@ export class miauth1585361548360 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "access_token" DROP CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560"`, undefined, diff --git a/packages/backend/migration/1585385921215-custom-notification.js b/packages/backend/src/migration/1585385921215-custom-notification.ts similarity index 95% rename from packages/backend/migration/1585385921215-custom-notification.js rename to packages/backend/src/migration/1585385921215-custom-notification.ts index 23142cd3a8..0016065fab 100644 --- a/packages/backend/migration/1585385921215-custom-notification.js +++ b/packages/backend/src/migration/1585385921215-custom-notification.ts @@ -1,8 +1,7 @@ -export class customNotification1585385921215 { - constructor() { - this.name = "customNotification1585385921215"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class customNotification1585385921215 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "notification" ADD "customBody" character varying(2048)`, undefined, @@ -76,7 +75,7 @@ export class customNotification1585385921215 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "notification" DROP CONSTRAINT "FK_e22bf6bda77b6adc1fd9e75c8c9"`, undefined, diff --git a/packages/backend/src/migration/1585772678853-ap-url.ts b/packages/backend/src/migration/1585772678853-ap-url.ts new file mode 100644 index 0000000000..f985a60292 --- /dev/null +++ b/packages/backend/src/migration/1585772678853-ap-url.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class apUrl1585772678853 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "note" ADD "url" character varying(512)`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "url"`, undefined); + } +} diff --git a/packages/backend/src/migration/1586624197029-AddObjectStorageUseProxy.ts b/packages/backend/src/migration/1586624197029-AddObjectStorageUseProxy.ts new file mode 100644 index 0000000000..e6c29ecac6 --- /dev/null +++ b/packages/backend/src/migration/1586624197029-AddObjectStorageUseProxy.ts @@ -0,0 +1,18 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddObjectStorageUseProxy1586624197029 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "objectStorageUseProxy" boolean NOT NULL DEFAULT true`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "objectStorageUseProxy"`, + undefined, + ); + } +} diff --git a/packages/backend/migration/1586641139527-remote-reaction.js b/packages/backend/src/migration/1586641139527-remote-reaction.ts similarity index 53% rename from packages/backend/migration/1586641139527-remote-reaction.js rename to packages/backend/src/migration/1586641139527-remote-reaction.ts index d7390544c4..f66245efca 100644 --- a/packages/backend/migration/1586641139527-remote-reaction.js +++ b/packages/backend/src/migration/1586641139527-remote-reaction.ts @@ -1,14 +1,13 @@ -export class remoteReaction1586641139527 { - constructor() { - this.name = "remoteReaction1586641139527"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class remoteReaction1586641139527 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(260)`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(130)`, undefined, diff --git a/packages/backend/src/migration/1586708940386-pageAiScript.ts b/packages/backend/src/migration/1586708940386-pageAiScript.ts new file mode 100644 index 0000000000..4849525f4e --- /dev/null +++ b/packages/backend/src/migration/1586708940386-pageAiScript.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class pageAiScript1586708940386 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "page" ADD "script" character varying(16384) NOT NULL DEFAULT ''`, + undefined, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "page" DROP COLUMN "script"`, + undefined, + ); + } +} diff --git a/packages/backend/migration/1588044505511-hCaptcha.js b/packages/backend/src/migration/1588044505511-hCaptcha.ts similarity index 73% rename from packages/backend/migration/1588044505511-hCaptcha.js rename to packages/backend/src/migration/1588044505511-hCaptcha.ts index 29ba87370f..b3008b8628 100644 --- a/packages/backend/migration/1588044505511-hCaptcha.js +++ b/packages/backend/src/migration/1588044505511-hCaptcha.ts @@ -1,8 +1,7 @@ -export class hCaptcha1588044505511 { - constructor() { - this.name = "hCaptcha1588044505511"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class hCaptcha1588044505511 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "enableHcaptcha" boolean NOT NULL DEFAULT false`, undefined, @@ -16,7 +15,7 @@ export class hCaptcha1588044505511 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "hcaptchaSecretKey"`, undefined, diff --git a/packages/backend/migration/1589023282116-pubRelay.js b/packages/backend/src/migration/1589023282116-pubRelay.ts similarity index 76% rename from packages/backend/migration/1589023282116-pubRelay.js rename to packages/backend/src/migration/1589023282116-pubRelay.ts index a1a2299192..fb684f90e1 100644 --- a/packages/backend/migration/1589023282116-pubRelay.js +++ b/packages/backend/src/migration/1589023282116-pubRelay.ts @@ -1,8 +1,7 @@ -export class pubRelay1589023282116 { - constructor() { - this.name = "pubRelay1589023282116"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class pubRelay1589023282116 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "relay_status_enum" AS ENUM('requesting', 'accepted', 'rejected')`, undefined, @@ -16,7 +15,7 @@ export class pubRelay1589023282116 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "IDX_0d9a1738f2cf7f3b1c3334dfab"`, undefined, diff --git a/packages/backend/src/migration/1595075960584-blurhash.ts b/packages/backend/src/migration/1595075960584-blurhash.ts new file mode 100644 index 0000000000..d8dfaf5c9d --- /dev/null +++ b/packages/backend/src/migration/1595075960584-blurhash.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class blurhash1595075960584 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" ADD "blurhash" character varying(128)`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "blurhash"`); + } +} diff --git a/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js b/packages/backend/src/migration/1595077605646-blurhash-for-avatar-banner.ts similarity index 73% rename from packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js rename to packages/backend/src/migration/1595077605646-blurhash-for-avatar-banner.ts index 612ab648cb..7454b5bfb3 100644 --- a/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js +++ b/packages/backend/src/migration/1595077605646-blurhash-for-avatar-banner.ts @@ -1,8 +1,9 @@ -export class blurhashForAvatarBanner1595077605646 { - constructor() { - this.name = "blurhashForAvatarBanner1595077605646"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class blurhashForAvatarBanner1595077605646 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarColor"`); await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerColor"`); await queryRunner.query( @@ -12,7 +13,7 @@ export class blurhashForAvatarBanner1595077605646 { `ALTER TABLE "user" ADD "bannerBlurhash" character varying(128)`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerBlurhash"`); await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`); await queryRunner.query( diff --git a/packages/backend/src/migration/1595676934834-instance-icon-url.ts b/packages/backend/src/migration/1595676934834-instance-icon-url.ts new file mode 100644 index 0000000000..30f6a940cd --- /dev/null +++ b/packages/backend/src/migration/1595676934834-instance-icon-url.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instanceIconUrl1595676934834 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "instance" ADD "iconUrl" character varying(256) DEFAULT null`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "iconUrl"`); + } +} diff --git a/packages/backend/migration/1595771249699-word-mute.js b/packages/backend/src/migration/1595771249699-word-mute.ts similarity index 89% rename from packages/backend/migration/1595771249699-word-mute.js rename to packages/backend/src/migration/1595771249699-word-mute.ts index 0a8a63294d..ed08678947 100644 --- a/packages/backend/migration/1595771249699-word-mute.js +++ b/packages/backend/src/migration/1595771249699-word-mute.ts @@ -1,8 +1,7 @@ -export class wordMute1595771249699 { - constructor() { - this.name = "wordMute1595771249699"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class wordMute1595771249699 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "muted_note" ("id" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, CONSTRAINT "PK_897e2eff1c0b9b64e55ca1418a4" PRIMARY KEY ("id"))`, ); @@ -31,7 +30,7 @@ export class wordMute1595771249699 { `ALTER TABLE "muted_note" ADD CONSTRAINT "FK_d8e07aa18c2d64e86201601aec1" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "muted_note" DROP CONSTRAINT "FK_d8e07aa18c2d64e86201601aec1"`, ); diff --git a/packages/backend/migration/1595782306083-word-mute2.js b/packages/backend/src/migration/1595782306083-word-mute2.ts similarity index 70% rename from packages/backend/migration/1595782306083-word-mute2.js rename to packages/backend/src/migration/1595782306083-word-mute2.ts index 61f06b3474..1e7063caef 100644 --- a/packages/backend/migration/1595782306083-word-mute2.js +++ b/packages/backend/src/migration/1595782306083-word-mute2.ts @@ -1,8 +1,7 @@ -export class wordMute21595782306083 { - constructor() { - this.name = "wordMute21595782306083"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class wordMute21595782306083 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "muted_note_reason_enum" AS ENUM('word', 'manual', 'spam', 'other')`, ); @@ -13,7 +12,7 @@ export class wordMute21595782306083 { `CREATE INDEX "IDX_636e977ff90b23676fb5624b25" ON "muted_note" ("reason") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_636e977ff90b23676fb5624b25"`); await queryRunner.query(`ALTER TABLE "muted_note" DROP COLUMN "reason"`); await queryRunner.query(`DROP TYPE "muted_note_reason_enum"`); diff --git a/packages/backend/migration/1596548170836-channel.js b/packages/backend/src/migration/1596548170836-channel.ts similarity index 96% rename from packages/backend/migration/1596548170836-channel.js rename to packages/backend/src/migration/1596548170836-channel.ts index 2aaaf95503..02ecf958a3 100644 --- a/packages/backend/migration/1596548170836-channel.js +++ b/packages/backend/src/migration/1596548170836-channel.ts @@ -1,8 +1,7 @@ -export class channel1596548170836 { - constructor() { - this.name = "channel1596548170836"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class channel1596548170836 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "channel" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "lastNotedAt" TIMESTAMP WITH TIME ZONE, "userId" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, "description" character varying(2048), "bannerId" character varying(32), "notesCount" integer NOT NULL DEFAULT 0, "usersCount" integer NOT NULL DEFAULT 0, CONSTRAINT "PK_590f33ee6ee7d76437acf362e39" PRIMARY KEY ("id"))`, ); @@ -73,7 +72,7 @@ export class channel1596548170836 { `ALTER TABLE "channel_note_pining" ADD CONSTRAINT "FK_10b19ef67d297ea9de325cd4502" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "channel_note_pining" DROP CONSTRAINT "FK_10b19ef67d297ea9de325cd4502"`, ); diff --git a/packages/backend/src/migration/1596786425167-channel2.ts b/packages/backend/src/migration/1596786425167-channel2.ts new file mode 100644 index 0000000000..d825f9cae5 --- /dev/null +++ b/packages/backend/src/migration/1596786425167-channel2.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class channel21596786425167 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "channel_following" DROP COLUMN "readCursor"`, + ); + } +} diff --git a/packages/backend/src/migration/1597230137744-objectStorageSetPublicRead.ts b/packages/backend/src/migration/1597230137744-objectStorageSetPublicRead.ts new file mode 100644 index 0000000000..f5faacb53e --- /dev/null +++ b/packages/backend/src/migration/1597230137744-objectStorageSetPublicRead.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class objectStorageSetPublicRead1597230137744 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "objectStorageSetPublicRead" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "objectStorageSetPublicRead"`, + ); + } +} diff --git a/packages/backend/migration/1597236229720-IncludingNotificationTypes.js b/packages/backend/src/migration/1597236229720-IncludingNotificationTypes.ts similarity index 70% rename from packages/backend/migration/1597236229720-IncludingNotificationTypes.js rename to packages/backend/src/migration/1597236229720-IncludingNotificationTypes.ts index ce02148d28..679fc0ff9a 100644 --- a/packages/backend/migration/1597236229720-IncludingNotificationTypes.js +++ b/packages/backend/src/migration/1597236229720-IncludingNotificationTypes.ts @@ -1,8 +1,9 @@ -export class IncludingNotificationTypes1597236229720 { - constructor() { - this.name = "IncludingNotificationTypes1597236229720"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class IncludingNotificationTypes1597236229720 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "user_profile_includingnotificationtypes_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`, ); @@ -10,7 +11,7 @@ export class IncludingNotificationTypes1597236229720 { `ALTER TABLE "user_profile" ADD "includingNotificationTypes" "user_profile_includingnotificationtypes_enum" array`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "includingNotificationTypes"`, ); diff --git a/packages/backend/src/migration/1597385880794-add-sensitive-index.ts b/packages/backend/src/migration/1597385880794-add-sensitive-index.ts new file mode 100644 index 0000000000..432e7e9fe8 --- /dev/null +++ b/packages/backend/src/migration/1597385880794-add-sensitive-index.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class addSensitiveIndex1597385880794 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_a7eba67f8b3fa27271e85d2e26" ON "drive_file" ("isSensitive") `, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_a7eba67f8b3fa27271e85d2e26"`); + } +} diff --git a/packages/backend/migration/1597459042300-channel-unread.js b/packages/backend/src/migration/1597459042300-channel-unread.ts similarity index 85% rename from packages/backend/migration/1597459042300-channel-unread.js rename to packages/backend/src/migration/1597459042300-channel-unread.ts index 4975a84f92..4216323a90 100644 --- a/packages/backend/migration/1597459042300-channel-unread.js +++ b/packages/backend/src/migration/1597459042300-channel-unread.ts @@ -1,8 +1,7 @@ -export class channelUnread1597459042300 { - constructor() { - this.name = "channelUnread1597459042300"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class channelUnread1597459042300 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`TRUNCATE TABLE "note_unread"`, undefined); await queryRunner.query( `ALTER TABLE "channel_following" DROP COLUMN "readCursor"`, @@ -26,7 +25,7 @@ export class channelUnread1597459042300 { `CREATE INDEX "IDX_6a57f051d82c6d4036c141e107" ON "note_unread" ("noteChannelId") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_6a57f051d82c6d4036c141e107"`); await queryRunner.query(`DROP INDEX "IDX_29e8c1d579af54d4232939f994"`); await queryRunner.query(`DROP INDEX "IDX_89a29c9237b8c3b6b3cbb4cb30"`); diff --git a/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js b/packages/backend/src/migration/1597893996136-ChannelNoteIdDescIndex.ts similarity index 61% rename from packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js rename to packages/backend/src/migration/1597893996136-ChannelNoteIdDescIndex.ts index 5a31d51e8b..981514347a 100644 --- a/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js +++ b/packages/backend/src/migration/1597893996136-ChannelNoteIdDescIndex.ts @@ -1,14 +1,13 @@ -export class ChannelNoteIdDescIndex1597893996136 { - constructor() { - this.name = "ChannelNoteIdDescIndex1597893996136"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ChannelNoteIdDescIndex1597893996136 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_f22169eb10657bded6d875ac8f"`); await queryRunner.query( `CREATE INDEX "IDX_note_on_channelId_and_id_desc" ON "note" ("channelId", "id" desc)`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_note_on_channelId_and_id_desc"`); await queryRunner.query( `CREATE INDEX "IDX_f22169eb10657bded6d875ac8f" ON "note" ("channelId") `, diff --git a/packages/backend/migration/1600353287890-mutingNotificationTypes.js b/packages/backend/src/migration/1600353287890-mutingNotificationTypes.ts similarity index 83% rename from packages/backend/migration/1600353287890-mutingNotificationTypes.js rename to packages/backend/src/migration/1600353287890-mutingNotificationTypes.ts index 2a317b3f9f..ae47d53a4c 100644 --- a/packages/backend/migration/1600353287890-mutingNotificationTypes.js +++ b/packages/backend/src/migration/1600353287890-mutingNotificationTypes.ts @@ -1,8 +1,9 @@ -export class mutingNotificationTypes1600353287890 { - constructor() { - this.name = "mutingNotificationTypes1600353287890"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class mutingNotificationTypes1600353287890 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "includingNotificationTypes"`, ); @@ -16,7 +17,7 @@ export class mutingNotificationTypes1600353287890 { `ALTER TABLE "user_profile" ADD "mutingNotificationTypes" "user_profile_mutingnotificationtypes_enum" array NOT NULL DEFAULT '{}'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "mutingNotificationTypes"`, ); diff --git a/packages/backend/migration/1603094348345-refine-abuse-user-report.js b/packages/backend/src/migration/1603094348345-refine-abuse-user-report.ts similarity index 90% rename from packages/backend/migration/1603094348345-refine-abuse-user-report.js rename to packages/backend/src/migration/1603094348345-refine-abuse-user-report.ts index 1aaf2685e5..0ed047783b 100644 --- a/packages/backend/migration/1603094348345-refine-abuse-user-report.js +++ b/packages/backend/src/migration/1603094348345-refine-abuse-user-report.ts @@ -1,8 +1,7 @@ -export class refineAbuseUserReport1603094348345 { - constructor() { - this.name = "refineAbuseUserReport1603094348345"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class refineAbuseUserReport1603094348345 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_d049123c413e68ca52abe734203"`, ); @@ -30,7 +29,7 @@ export class refineAbuseUserReport1603094348345 { `ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_08b883dd5fdd6f9c4c1572b36de" FOREIGN KEY ("assigneeId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_08b883dd5fdd6f9c4c1572b36de"`, ); diff --git a/packages/backend/migration/1603095701770-refine-abuse-user-report2.js b/packages/backend/src/migration/1603095701770-refine-abuse-user-report2.ts similarity index 76% rename from packages/backend/migration/1603095701770-refine-abuse-user-report2.js rename to packages/backend/src/migration/1603095701770-refine-abuse-user-report2.ts index 301a8e5382..e87685c465 100644 --- a/packages/backend/migration/1603095701770-refine-abuse-user-report2.js +++ b/packages/backend/src/migration/1603095701770-refine-abuse-user-report2.ts @@ -1,8 +1,7 @@ -export class refineAbuseUserReport21603095701770 { - constructor() { - this.name = "refineAbuseUserReport21603095701770"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class refineAbuseUserReport21603095701770 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "abuse_user_report" ADD "targetUserHost" character varying(128)`, ); @@ -16,7 +15,7 @@ export class refineAbuseUserReport21603095701770 { `CREATE INDEX "IDX_f8d8b93740ad12c4ce8213a199" ON "abuse_user_report" ("reporterHost") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_f8d8b93740ad12c4ce8213a199"`); await queryRunner.query(`DROP INDEX "IDX_4ebbf7f93cdc10e8d1ef2fc6cd"`); await queryRunner.query( diff --git a/packages/backend/src/migration/1603776877564-instance-theme-color.ts b/packages/backend/src/migration/1603776877564-instance-theme-color.ts new file mode 100644 index 0000000000..6bde772fe6 --- /dev/null +++ b/packages/backend/src/migration/1603776877564-instance-theme-color.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instanceThemeColor1603776877564 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "instance" ADD "themeColor" character varying(64) DEFAULT null`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "themeColor"`); + } +} diff --git a/packages/backend/src/migration/1603781553011-instance-favicon.ts b/packages/backend/src/migration/1603781553011-instance-favicon.ts new file mode 100644 index 0000000000..1753f6449a --- /dev/null +++ b/packages/backend/src/migration/1603781553011-instance-favicon.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instanceFavicon1603781553011 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "instance" ADD "faviconUrl" character varying(256) DEFAULT null`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "faviconUrl"`); + } +} diff --git a/packages/backend/src/migration/1604821689616-delete-auto-watch.ts b/packages/backend/src/migration/1604821689616-delete-auto-watch.ts new file mode 100644 index 0000000000..514087721b --- /dev/null +++ b/packages/backend/src/migration/1604821689616-delete-auto-watch.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class deleteAutoWatch1604821689616 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" DROP COLUMN "autoWatch"`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "autoWatch" boolean NOT NULL DEFAULT false`, + ); + } +} diff --git a/packages/backend/src/migration/1605408848373-clip-description.ts b/packages/backend/src/migration/1605408848373-clip-description.ts new file mode 100644 index 0000000000..7cd98d8f8a --- /dev/null +++ b/packages/backend/src/migration/1605408848373-clip-description.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class clipDescription1605408848373 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "clip" ADD "description" character varying(2048) DEFAULT null`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "clip" DROP COLUMN "description"`); + } +} diff --git a/packages/backend/migration/1605408971051-comments.js b/packages/backend/src/migration/1605408971051-comments.ts similarity index 99% rename from packages/backend/migration/1605408971051-comments.js rename to packages/backend/src/migration/1605408971051-comments.ts index 363fec5cdd..b846d0526c 100644 --- a/packages/backend/migration/1605408971051-comments.js +++ b/packages/backend/src/migration/1605408971051-comments.ts @@ -1,8 +1,7 @@ -export class comments1605408971051 { - constructor() { - this.name = "comments1605408971051"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class comments1605408971051 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `COMMENT ON COLUMN "log"."createdAt" IS 'The created date of the Log.'`, ); @@ -621,7 +620,7 @@ export class comments1605408971051 { `COMMENT ON COLUMN "channel_note_pining"."createdAt" IS 'The created date of the ChannelNotePining.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `COMMENT ON COLUMN "channel_note_pining"."createdAt" IS NULL`, ); diff --git a/packages/backend/migration/1605585339718-instance-pinned-pages.js b/packages/backend/src/migration/1605585339718-instance-pinned-pages.ts similarity index 53% rename from packages/backend/migration/1605585339718-instance-pinned-pages.js rename to packages/backend/src/migration/1605585339718-instance-pinned-pages.ts index 09e1617641..480839fce9 100644 --- a/packages/backend/migration/1605585339718-instance-pinned-pages.js +++ b/packages/backend/src/migration/1605585339718-instance-pinned-pages.ts @@ -1,13 +1,12 @@ -export class instancePinnedPages1605585339718 { - constructor() { - this.name = "instancePinnedPages1605585339718"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instancePinnedPages1605585339718 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "pinnedPages" character varying(512) array NOT NULL DEFAULT '{"/featured", "/channels", "/explore", "/pages", "/about-misskey"}'::varchar[]`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedPages"`); } } diff --git a/packages/backend/migration/1605965516823-instance-images.js b/packages/backend/src/migration/1605965516823-instance-images.ts similarity index 61% rename from packages/backend/migration/1605965516823-instance-images.js rename to packages/backend/src/migration/1605965516823-instance-images.ts index ed9a26a655..2f024a5d38 100644 --- a/packages/backend/migration/1605965516823-instance-images.js +++ b/packages/backend/src/migration/1605965516823-instance-images.ts @@ -1,8 +1,7 @@ -export class instanceImages1605965516823 { - constructor() { - this.name = "instanceImages1605965516823"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instanceImages1605965516823 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "backgroundImageUrl" character varying(512)`, ); @@ -10,7 +9,7 @@ export class instanceImages1605965516823 { `ALTER TABLE "meta" ADD "logoImageUrl" character varying(512)`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "logoImageUrl"`); await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "backgroundImageUrl"`, diff --git a/packages/backend/migration/1606191203881-no-crawle.js b/packages/backend/src/migration/1606191203881-no-crawle.ts similarity index 65% rename from packages/backend/migration/1606191203881-no-crawle.js rename to packages/backend/src/migration/1606191203881-no-crawle.ts index 4e7e822771..7ca2ff30ba 100644 --- a/packages/backend/migration/1606191203881-no-crawle.js +++ b/packages/backend/src/migration/1606191203881-no-crawle.ts @@ -1,8 +1,7 @@ -export class noCrawle1606191203881 { - constructor() { - this.name = "noCrawle1606191203881"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class noCrawle1606191203881 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ADD "noCrawle" boolean NOT NULL DEFAULT false`, ); @@ -10,7 +9,7 @@ export class noCrawle1606191203881 { `COMMENT ON COLUMN "user_profile"."noCrawle" IS 'Whether reject index by crawler.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `COMMENT ON COLUMN "user_profile"."noCrawle" IS 'Whether reject index by crawler.'`, ); diff --git a/packages/backend/src/migration/1607151207216-instance-pinned-clip.ts b/packages/backend/src/migration/1607151207216-instance-pinned-clip.ts new file mode 100644 index 0000000000..1d77c69563 --- /dev/null +++ b/packages/backend/src/migration/1607151207216-instance-pinned-clip.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instancePinnedClip1607151207216 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "pinnedClipId" character varying(32)`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedClipId"`); + } +} diff --git a/packages/backend/migration/1607353487793-isExplorable.js b/packages/backend/src/migration/1607353487793-isExplorable.ts similarity index 71% rename from packages/backend/migration/1607353487793-isExplorable.js rename to packages/backend/src/migration/1607353487793-isExplorable.ts index d654ee121f..3518ab769c 100644 --- a/packages/backend/migration/1607353487793-isExplorable.js +++ b/packages/backend/src/migration/1607353487793-isExplorable.ts @@ -1,8 +1,7 @@ -export class isExplorable1607353487793 { - constructor() { - this.name = "isExplorable1607353487793"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class isExplorable1607353487793 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "isExplorable" boolean NOT NULL DEFAULT true`, ); @@ -13,7 +12,7 @@ export class isExplorable1607353487793 { `CREATE INDEX "IDX_d5a1b83c7cab66f167e6888188" ON "user" ("isExplorable") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_d5a1b83c7cab66f167e6888188"`); await queryRunner.query( `COMMENT ON COLUMN "user"."isExplorable" IS 'Whether the User is explorable.'`, diff --git a/packages/backend/migration/1610277136869-registry.js b/packages/backend/src/migration/1610277136869-registry.ts similarity index 87% rename from packages/backend/migration/1610277136869-registry.js rename to packages/backend/src/migration/1610277136869-registry.ts index 023519302e..dea40bce5b 100644 --- a/packages/backend/migration/1610277136869-registry.js +++ b/packages/backend/src/migration/1610277136869-registry.ts @@ -1,8 +1,7 @@ -export class registry1610277136869 { - constructor() { - this.name = "registry1610277136869"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class registry1610277136869 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "registry_item" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "key" character varying(1024) NOT NULL, "scope" character varying(1024) array NOT NULL DEFAULT '{}'::varchar[], "domain" character varying(512), CONSTRAINT "PK_64b3f7e6008b4d89b826cd3af95" PRIMARY KEY ("id")); COMMENT ON COLUMN "registry_item"."createdAt" IS 'The created date of the RegistryItem.'; COMMENT ON COLUMN "registry_item"."updatedAt" IS 'The updated date of the RegistryItem.'; COMMENT ON COLUMN "registry_item"."userId" IS 'The owner ID.'; COMMENT ON COLUMN "registry_item"."key" IS 'The key of the RegistryItem.'`, ); @@ -19,7 +18,7 @@ export class registry1610277136869 { `ALTER TABLE "registry_item" ADD CONSTRAINT "FK_fb9d21ba0abb83223263df6bcb3" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "registry_item" DROP CONSTRAINT "FK_fb9d21ba0abb83223263df6bcb3"`, ); diff --git a/packages/backend/migration/1610277585759-registry2.js b/packages/backend/src/migration/1610277585759-registry2.ts similarity index 64% rename from packages/backend/migration/1610277585759-registry2.js rename to packages/backend/src/migration/1610277585759-registry2.ts index a2c1fb01bf..98287e6b68 100644 --- a/packages/backend/migration/1610277585759-registry2.js +++ b/packages/backend/src/migration/1610277585759-registry2.ts @@ -1,8 +1,7 @@ -export class registry21610277585759 { - constructor() { - this.name = "registry21610277585759"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class registry21610277585759 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "registry_item" ADD "value" jsonb NOT NULL DEFAULT '{}'`, ); @@ -10,7 +9,7 @@ export class registry21610277585759 { `COMMENT ON COLUMN "registry_item"."value" IS 'The value of the RegistryItem.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `COMMENT ON COLUMN "registry_item"."value" IS 'The value of the RegistryItem.'`, ); diff --git a/packages/backend/src/migration/1610283021566-registry3.ts b/packages/backend/src/migration/1610283021566-registry3.ts new file mode 100644 index 0000000000..11d094c2a8 --- /dev/null +++ b/packages/backend/src/migration/1610283021566-registry3.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class registry31610283021566 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "registry_item" ALTER COLUMN "value" DROP NOT NULL`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "registry_item" ALTER COLUMN "value" SET NOT NULL`, + ); + } +} diff --git a/packages/backend/migration/1611354329133-followersUri.js b/packages/backend/src/migration/1611354329133-followersUri.ts similarity index 69% rename from packages/backend/migration/1611354329133-followersUri.js rename to packages/backend/src/migration/1611354329133-followersUri.ts index c7ca5c895b..e67c14c290 100644 --- a/packages/backend/migration/1611354329133-followersUri.js +++ b/packages/backend/src/migration/1611354329133-followersUri.ts @@ -1,8 +1,7 @@ -export class followersUri1611354329133 { - constructor() { - this.name = "followersUri1611354329133"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class followersUri1611354329133 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "followersUri" varchar(512) DEFAULT NULL`, ); @@ -10,7 +9,7 @@ export class followersUri1611354329133 { `COMMENT ON COLUMN "user"."followersUri" IS 'The URI of the user Follower Collection. It will be null if the origin of the user is local.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `COMMENT ON COLUMN "user"."followersUri" IS 'The URI of the user Follower Collection. It will be null if the origin of the user is local.'`, ); diff --git a/packages/backend/migration/1611397665007-gallery.js b/packages/backend/src/migration/1611397665007-gallery.ts similarity index 94% rename from packages/backend/migration/1611397665007-gallery.js rename to packages/backend/src/migration/1611397665007-gallery.ts index 1f36acbc17..3f80989ca1 100644 --- a/packages/backend/migration/1611397665007-gallery.js +++ b/packages/backend/src/migration/1611397665007-gallery.ts @@ -1,8 +1,7 @@ -export class gallery1611397665007 { - constructor() { - this.name = "gallery1611397665007"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class gallery1611397665007 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "gallery_post" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "title" character varying(256) NOT NULL, "description" character varying(2048), "userId" character varying(32) NOT NULL, "fileIds" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], "isSensitive" boolean NOT NULL DEFAULT false, "likedCount" integer NOT NULL DEFAULT '0', "tags" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], CONSTRAINT "PK_8e90d7b6015f2c4518881b14753" PRIMARY KEY ("id")); COMMENT ON COLUMN "gallery_post"."createdAt" IS 'The created date of the GalleryPost.'; COMMENT ON COLUMN "gallery_post"."updatedAt" IS 'The updated date of the GalleryPost.'; COMMENT ON COLUMN "gallery_post"."userId" IS 'The ID of author.'; COMMENT ON COLUMN "gallery_post"."isSensitive" IS 'Whether the post is sensitive.'`, ); @@ -46,7 +45,7 @@ export class gallery1611397665007 { `ALTER TABLE "gallery_like" ADD CONSTRAINT "FK_b1cb568bfe569e47b7051699fc8" FOREIGN KEY ("postId") REFERENCES "gallery_post"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "gallery_like" DROP CONSTRAINT "FK_b1cb568bfe569e47b7051699fc8"`, ); diff --git a/packages/backend/src/migration/1611547387175-objectStorageS3ForcePathStyle.ts b/packages/backend/src/migration/1611547387175-objectStorageS3ForcePathStyle.ts new file mode 100644 index 0000000000..d28b00b3c9 --- /dev/null +++ b/packages/backend/src/migration/1611547387175-objectStorageS3ForcePathStyle.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class objectStorageS3ForcePathStyle1611547387175 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "objectStorageS3ForcePathStyle" boolean NOT NULL DEFAULT true`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "objectStorageS3ForcePathStyle"`, + ); + } +} diff --git a/packages/backend/src/migration/1612619156584-announcement-email.ts b/packages/backend/src/migration/1612619156584-announcement-email.ts new file mode 100644 index 0000000000..7788d2ae50 --- /dev/null +++ b/packages/backend/src/migration/1612619156584-announcement-email.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class announcementEmail1612619156584 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "receiveAnnouncementEmail" boolean NOT NULL DEFAULT true`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" DROP COLUMN "receiveAnnouncementEmail"`, + ); + } +} diff --git a/packages/backend/migration/1613155914446-emailNotificationTypes.js b/packages/backend/src/migration/1613155914446-emailNotificationTypes.ts similarity index 52% rename from packages/backend/migration/1613155914446-emailNotificationTypes.js rename to packages/backend/src/migration/1613155914446-emailNotificationTypes.ts index e64aada7b3..228c3024a8 100644 --- a/packages/backend/migration/1613155914446-emailNotificationTypes.js +++ b/packages/backend/src/migration/1613155914446-emailNotificationTypes.ts @@ -1,13 +1,12 @@ -export class emailNotificationTypes1613155914446 { - constructor() { - this.name = "emailNotificationTypes1613155914446"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class emailNotificationTypes1613155914446 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ADD "emailNotificationTypes" jsonb NOT NULL DEFAULT '["follow","receiveFollowRequest","groupInvited"]'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "emailNotificationTypes"`, ); diff --git a/packages/backend/src/migration/1613181457597-user-lang.ts b/packages/backend/src/migration/1613181457597-user-lang.ts new file mode 100644 index 0000000000..424fc20e94 --- /dev/null +++ b/packages/backend/src/migration/1613181457597-user-lang.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userLang1613181457597 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "lang" character varying(32)`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); + } +} diff --git a/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js b/packages/backend/src/migration/1613503367223-use-bigint-for-driveUsage.ts similarity index 53% rename from packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js rename to packages/backend/src/migration/1613503367223-use-bigint-for-driveUsage.ts index a8f1e33bfc..7d7f29de65 100644 --- a/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js +++ b/packages/backend/src/migration/1613503367223-use-bigint-for-driveUsage.ts @@ -1,13 +1,12 @@ -export class useBigintForDriveUsage1613503367223 { - constructor() { - this.name = "useBigintForDriveUsage1613503367223"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class useBigintForDriveUsage1613503367223 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "instance" ALTER COLUMN "driveUsage" TYPE bigint`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "driveUsage"`); await queryRunner.query( `ALTER TABLE "instance" ADD "driveUsage" integer NOT NULL DEFAULT 0`, diff --git a/packages/backend/migration/1615965918224-chart-v2.js b/packages/backend/src/migration/1615965918224-chart-v2.ts similarity index 98% rename from packages/backend/migration/1615965918224-chart-v2.js rename to packages/backend/src/migration/1615965918224-chart-v2.ts index 0460a57f55..4b41f399b7 100644 --- a/packages/backend/migration/1615965918224-chart-v2.js +++ b/packages/backend/src/migration/1615965918224-chart-v2.ts @@ -1,8 +1,7 @@ -export class chartV21615965918224 { - constructor() { - this.name = "chartV21615965918224"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class chartV21615965918224 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `DELETE FROM "__chart__active_users" WHERE "span" = 'day'`, ); @@ -218,7 +217,7 @@ export class chartV21615965918224 { `ALTER TABLE "__chart__users" DROP COLUMN "unique"`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__users" ADD "unique" jsonb NOT NULL DEFAULT '{}'`, ); diff --git a/packages/backend/migration/1615966519402-chart-v2-2.js b/packages/backend/src/migration/1615966519402-chart-v2-2.ts similarity index 84% rename from packages/backend/migration/1615966519402-chart-v2-2.js rename to packages/backend/src/migration/1615966519402-chart-v2-2.ts index ce75961035..12fb427b1b 100644 --- a/packages/backend/migration/1615966519402-chart-v2-2.js +++ b/packages/backend/src/migration/1615966519402-chart-v2-2.ts @@ -1,8 +1,7 @@ -export class chartV221615966519402 { - constructor() { - this.name = "chartV221615966519402"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class chartV221615966519402 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__active_users" ADD "___local_users" character varying array NOT NULL DEFAULT '{}'::varchar[]`, ); @@ -19,7 +18,7 @@ export class chartV221615966519402 { `ALTER TABLE "__chart__test_unique" ADD "___foo" character varying array NOT NULL DEFAULT '{}'::varchar[]`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__test_unique" DROP COLUMN "___foo"`, ); diff --git a/packages/backend/migration/1618637372000-user-last-active-date.js b/packages/backend/src/migration/1618637372000-user-last-active-date.ts similarity index 61% rename from packages/backend/migration/1618637372000-user-last-active-date.js rename to packages/backend/src/migration/1618637372000-user-last-active-date.ts index 0211c256bc..df75243246 100644 --- a/packages/backend/migration/1618637372000-user-last-active-date.js +++ b/packages/backend/src/migration/1618637372000-user-last-active-date.ts @@ -1,8 +1,7 @@ -export class userLastActiveDate1618637372000 { - constructor() { - this.name = "userLastActiveDate1618637372000"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userLastActiveDate1618637372000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "lastActiveDate" TIMESTAMP WITH TIME ZONE DEFAULT NULL`, ); @@ -10,7 +9,7 @@ export class userLastActiveDate1618637372000 { `CREATE INDEX "IDX_seoignmeoprigmkpodgrjmkpormg" ON "user" ("lastActiveDate") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_seoignmeoprigmkpodgrjmkpormg"`); await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "lastActiveDate"`); } diff --git a/packages/backend/src/migration/1618639857000-user-hide-online-status.ts b/packages/backend/src/migration/1618639857000-user-hide-online-status.ts new file mode 100644 index 0000000000..523b602ffc --- /dev/null +++ b/packages/backend/src/migration/1618639857000-user-hide-online-status.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userHideOnlineStatus1618639857000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" ADD "hideOnlineStatus" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" DROP COLUMN "hideOnlineStatus"`, + ); + } +} diff --git a/packages/backend/migration/1619942102890-password-reset.js b/packages/backend/src/migration/1619942102890-password-reset.ts similarity index 82% rename from packages/backend/migration/1619942102890-password-reset.js rename to packages/backend/src/migration/1619942102890-password-reset.ts index e3adeb95e7..d456dafdd7 100644 --- a/packages/backend/migration/1619942102890-password-reset.js +++ b/packages/backend/src/migration/1619942102890-password-reset.ts @@ -1,8 +1,7 @@ -export class passwordReset1619942102890 { - constructor() { - this.name = "passwordReset1619942102890"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class passwordReset1619942102890 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "password_reset_request" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "token" character varying(256) NOT NULL, "userId" character varying(32) NOT NULL, CONSTRAINT "PK_fcf4b02eae1403a2edaf87fd074" PRIMARY KEY ("id"))`, ); @@ -16,7 +15,7 @@ export class passwordReset1619942102890 { `ALTER TABLE "password_reset_request" ADD CONSTRAINT "FK_4bb7fd4a34492ae0e6cc8d30ac8" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "password_reset_request" DROP CONSTRAINT "FK_4bb7fd4a34492ae0e6cc8d30ac8"`, ); diff --git a/packages/backend/migration/1620019354680-ad.js b/packages/backend/src/migration/1620019354680-ad.ts similarity index 81% rename from packages/backend/migration/1620019354680-ad.js rename to packages/backend/src/migration/1620019354680-ad.ts index e39b381013..5b7eed9fa3 100644 --- a/packages/backend/migration/1620019354680-ad.js +++ b/packages/backend/src/migration/1620019354680-ad.ts @@ -1,8 +1,7 @@ -export class ad1620019354680 { - constructor() { - this.name = "ad1620019354680"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ad1620019354680 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "ad" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "place" character varying(32) NOT NULL, "priority" character varying(32) NOT NULL, "url" character varying(1024) NOT NULL, "imageUrl" character varying(1024) NOT NULL, "memo" character varying(8192) NOT NULL, CONSTRAINT "PK_0193d5ef09746e88e9ea92c634d" PRIMARY KEY ("id")); COMMENT ON COLUMN "ad"."createdAt" IS 'The created date of the Ad.'; COMMENT ON COLUMN "ad"."expiresAt" IS 'The expired date of the Ad.'`, ); @@ -13,7 +12,7 @@ export class ad1620019354680 { `CREATE INDEX "IDX_2da24ce20ad209f1d9dc032457" ON "ad" ("expiresAt") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_2da24ce20ad209f1d9dc032457"`); await queryRunner.query(`DROP INDEX "IDX_1129c2ef687fc272df040bafaa"`); await queryRunner.query(`DROP TABLE "ad"`); diff --git a/packages/backend/src/migration/1620364649428-ad2.ts b/packages/backend/src/migration/1620364649428-ad2.ts new file mode 100644 index 0000000000..321dd36610 --- /dev/null +++ b/packages/backend/src/migration/1620364649428-ad2.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ad21620364649428 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "ad" ADD "ratio" integer NOT NULL DEFAULT '1'`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "ratio"`); + } +} diff --git a/packages/backend/migration/1621479946000-add-note-indexes.js b/packages/backend/src/migration/1621479946000-add-note-indexes.ts similarity index 63% rename from packages/backend/migration/1621479946000-add-note-indexes.js rename to packages/backend/src/migration/1621479946000-add-note-indexes.ts index f9ffbbff17..ceb34f0838 100644 --- a/packages/backend/migration/1621479946000-add-note-indexes.js +++ b/packages/backend/src/migration/1621479946000-add-note-indexes.ts @@ -1,8 +1,7 @@ -export class addNoteIndexes1621479946000 { - constructor() { - this.name = "addNoteIndexes1621479946000"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class addNoteIndexes1621479946000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE INDEX "IDX_NOTE_MENTIONS" ON "note" USING gin ("mentions")`, undefined, @@ -12,7 +11,7 @@ export class addNoteIndexes1621479946000 { undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_NOTE_MENTIONS"`, undefined); await queryRunner.query( `DROP INDEX "IDX_NOTE_VISIBLE_USER_IDS"`, diff --git a/packages/backend/migration/1622679304522-user-profile-description-length.js b/packages/backend/src/migration/1622679304522-user-profile-description-length.ts similarity index 52% rename from packages/backend/migration/1622679304522-user-profile-description-length.js rename to packages/backend/src/migration/1622679304522-user-profile-description-length.ts index 7c761c92a1..5552ac169f 100644 --- a/packages/backend/migration/1622679304522-user-profile-description-length.js +++ b/packages/backend/src/migration/1622679304522-user-profile-description-length.ts @@ -1,14 +1,15 @@ -export class userProfileDescriptionLength1622679304522 { - constructor() { - this.name = "userProfileDescriptionLength1622679304522"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userProfileDescriptionLength1622679304522 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(2048)`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(1024)`, undefined, diff --git a/packages/backend/migration/1622681548499-log-message-length.js b/packages/backend/src/migration/1622681548499-log-message-length.ts similarity index 50% rename from packages/backend/migration/1622681548499-log-message-length.js rename to packages/backend/src/migration/1622681548499-log-message-length.ts index 9dfb7ed3d2..f2c88cef5e 100644 --- a/packages/backend/migration/1622681548499-log-message-length.js +++ b/packages/backend/src/migration/1622681548499-log-message-length.ts @@ -1,14 +1,13 @@ -export class logMessageLength1622681548499 { - constructor() { - this.name = "logMessageLength1622681548499"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class logMessageLength1622681548499 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(2048)`, undefined, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(1024)`, undefined, diff --git a/packages/backend/migration/1626509500668-fix-remote-file-proxy.js b/packages/backend/src/migration/1626509500668-fix-remote-file-proxy.ts similarity index 78% rename from packages/backend/migration/1626509500668-fix-remote-file-proxy.js rename to packages/backend/src/migration/1626509500668-fix-remote-file-proxy.ts index f79cfb0066..2fea0a8436 100644 --- a/packages/backend/migration/1626509500668-fix-remote-file-proxy.js +++ b/packages/backend/src/migration/1626509500668-fix-remote-file-proxy.ts @@ -1,8 +1,7 @@ -export class fixRemoteFileProxy1626509500668 { - constructor() { - this.name = "fixRemoteFileProxy1626509500668"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class fixRemoteFileProxy1626509500668 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarUrl"`); await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerUrl"`); await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`); @@ -11,7 +10,7 @@ export class fixRemoteFileProxy1626509500668 { `ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT false`, ); diff --git a/packages/backend/migration/1626733991004-allowlist-secure-mode.js b/packages/backend/src/migration/1626733991004-allowlist-secure-mode.ts similarity index 68% rename from packages/backend/migration/1626733991004-allowlist-secure-mode.js rename to packages/backend/src/migration/1626733991004-allowlist-secure-mode.ts index 6d2dd6842f..3282d7d989 100644 --- a/packages/backend/migration/1626733991004-allowlist-secure-mode.js +++ b/packages/backend/src/migration/1626733991004-allowlist-secure-mode.ts @@ -1,6 +1,7 @@ -export class allowlistSecureMode1626733991004 { - name = "allowlistSecureMode1626733991004"; - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class allowlistSecureMode1626733991004 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "allowedHosts" character varying(256) [] default '{}'`, ); @@ -12,7 +13,7 @@ export class allowlistSecureMode1626733991004 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "allowedHosts"`); await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "secureMode"`); await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "privateMode"`); diff --git a/packages/backend/migration/1629004542760-chart-reindex.js b/packages/backend/src/migration/1629004542760-chart-reindex.ts similarity index 98% rename from packages/backend/migration/1629004542760-chart-reindex.js rename to packages/backend/src/migration/1629004542760-chart-reindex.ts index 8cc564b32e..503f0b2b11 100644 --- a/packages/backend/migration/1629004542760-chart-reindex.js +++ b/packages/backend/src/migration/1629004542760-chart-reindex.ts @@ -1,8 +1,7 @@ -export class chartReindex1629004542760 { - constructor() { - this.name = "chartReindex1629004542760"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class chartReindex1629004542760 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `DELETE FROM "__chart__active_users" a USING "__chart__active_users" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`, ); @@ -181,7 +180,7 @@ export class chartReindex1629004542760 { `CREATE UNIQUE INDEX "IDX_66feba81e1795d176d06c0b1e6" ON "__chart__users" ("date") WHERE "group" IS NULL`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_66feba81e1795d176d06c0b1e6"`); await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`); await queryRunner.query(`DROP INDEX "IDX_dab383a36f3c9db4a0c9b02cf3"`); diff --git a/packages/backend/src/migration/1629024377804-deepl-integration.ts b/packages/backend/src/migration/1629024377804-deepl-integration.ts new file mode 100644 index 0000000000..5d8ec48e57 --- /dev/null +++ b/packages/backend/src/migration/1629024377804-deepl-integration.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class deeplIntegration1629024377804 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "deeplAuthKey" character varying(128)`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplAuthKey"`); + } +} diff --git a/packages/backend/src/migration/1629288472000-fix-channel-userId.ts b/packages/backend/src/migration/1629288472000-fix-channel-userId.ts new file mode 100644 index 0000000000..e75ec7cf5a --- /dev/null +++ b/packages/backend/src/migration/1629288472000-fix-channel-userId.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class fixChannelUserId1629288472000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "channel" ALTER COLUMN "userId" DROP NOT NULL;`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "channel" ALTER COLUMN "userId" SET NOT NULL;`, + ); + } +} diff --git a/packages/backend/migration/1629512953000-user-is-deleted.js b/packages/backend/src/migration/1629512953000-user-is-deleted.ts similarity index 55% rename from packages/backend/migration/1629512953000-user-is-deleted.js rename to packages/backend/src/migration/1629512953000-user-is-deleted.ts index 448535276f..82b4dcfd4c 100644 --- a/packages/backend/migration/1629512953000-user-is-deleted.js +++ b/packages/backend/src/migration/1629512953000-user-is-deleted.ts @@ -1,8 +1,7 @@ -export class isUserDeleted1629512953000 { - constructor() { - this.name = "isUserDeleted1629512953000"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class isUserDeleted1629512953000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "isDeleted" boolean NOT NULL DEFAULT false`, ); @@ -10,7 +9,7 @@ export class isUserDeleted1629512953000 { `COMMENT ON COLUMN "user"."isDeleted" IS 'Whether the User is deleted.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isDeleted"`); } } diff --git a/packages/backend/src/migration/1629778475000-deepl-integration2.ts b/packages/backend/src/migration/1629778475000-deepl-integration2.ts new file mode 100644 index 0000000000..5457685538 --- /dev/null +++ b/packages/backend/src/migration/1629778475000-deepl-integration2.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class deeplIntegration21629778475000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "deeplIsPro" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplIsPro"`); + } +} diff --git a/packages/backend/migration/1629833361000-AddShowTLReplies.js b/packages/backend/src/migration/1629833361000-AddShowTLReplies.ts similarity index 60% rename from packages/backend/migration/1629833361000-AddShowTLReplies.js rename to packages/backend/src/migration/1629833361000-AddShowTLReplies.ts index 78e9f417b7..cd321ec1db 100644 --- a/packages/backend/migration/1629833361000-AddShowTLReplies.js +++ b/packages/backend/src/migration/1629833361000-AddShowTLReplies.ts @@ -1,8 +1,7 @@ -export class addShowTLReplies1629833361000 { - constructor() { - this.name = "addShowTLReplies1629833361000"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class addShowTLReplies1629833361000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "showTimelineReplies" boolean NOT NULL DEFAULT false`, ); @@ -10,7 +9,7 @@ export class addShowTLReplies1629833361000 { `COMMENT ON COLUMN "user"."showTimelineReplies" IS 'Whether to show users replying to other users in the timeline.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`, ); diff --git a/packages/backend/migration/1629968054000_userInstanceBlocks.js b/packages/backend/src/migration/1629968054000_userInstanceBlocks.ts similarity index 58% rename from packages/backend/migration/1629968054000_userInstanceBlocks.js rename to packages/backend/src/migration/1629968054000_userInstanceBlocks.ts index 666aaba284..3b8703f7b4 100644 --- a/packages/backend/migration/1629968054000_userInstanceBlocks.js +++ b/packages/backend/src/migration/1629968054000_userInstanceBlocks.ts @@ -1,8 +1,7 @@ -export class userInstanceBlocks1629968054000 { - constructor() { - this.name = "userInstanceBlocks1629968054000"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userInstanceBlocks1629968054000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ADD "mutedInstances" jsonb NOT NULL DEFAULT '[]'`, ); @@ -10,7 +9,7 @@ export class userInstanceBlocks1629968054000 { `COMMENT ON COLUMN "user_profile"."mutedInstances" IS 'List of instances muted by the user.'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "mutedInstances"`, ); diff --git a/packages/backend/src/migration/1633068642000-email-required-for-signup.ts b/packages/backend/src/migration/1633068642000-email-required-for-signup.ts new file mode 100644 index 0000000000..6fcfca58db --- /dev/null +++ b/packages/backend/src/migration/1633068642000-email-required-for-signup.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class emailRequiredForSignup1633068642000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "emailRequiredForSignup" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "emailRequiredForSignup"`, + ); + } +} diff --git a/packages/backend/migration/1633071909016-user-pending.js b/packages/backend/src/migration/1633071909016-user-pending.ts similarity index 72% rename from packages/backend/migration/1633071909016-user-pending.js rename to packages/backend/src/migration/1633071909016-user-pending.ts index b37e51629d..cd6ad492cc 100644 --- a/packages/backend/migration/1633071909016-user-pending.js +++ b/packages/backend/src/migration/1633071909016-user-pending.ts @@ -1,8 +1,7 @@ -export class userPending1633071909016 { - constructor() { - this.name = "userPending1633071909016"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userPending1633071909016 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "user_pending" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "code" character varying(128) NOT NULL, "username" character varying(128) NOT NULL, "email" character varying(128) NOT NULL, "password" character varying(128) NOT NULL, CONSTRAINT "PK_d4c84e013c98ec02d19b8fbbafa" PRIMARY KEY ("id"))`, ); @@ -10,7 +9,7 @@ export class userPending1633071909016 { `CREATE UNIQUE INDEX "IDX_4e5c4c99175638ec0761714ab0" ON "user_pending" ("code") `, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "IDX_4e5c4c99175638ec0761714ab0"`); await queryRunner.query(`DROP TABLE "user_pending"`); } diff --git a/packages/backend/src/migration/1634486652000-user-public-reactions.ts b/packages/backend/src/migration/1634486652000-user-public-reactions.ts new file mode 100644 index 0000000000..73695334d7 --- /dev/null +++ b/packages/backend/src/migration/1634486652000-user-public-reactions.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userPublicReactions1634486652000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "publicReactions" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" DROP COLUMN "publicReactions"`, + ); + } +} diff --git a/packages/backend/src/migration/1634902659689-delete-log.ts b/packages/backend/src/migration/1634902659689-delete-log.ts new file mode 100644 index 0000000000..859a17c569 --- /dev/null +++ b/packages/backend/src/migration/1634902659689-delete-log.ts @@ -0,0 +1,8 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class deleteLog1634902659689 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "log"`); + } + async down(queryRunner: QueryRunner): Promise {} +} diff --git a/packages/backend/migration/1635500777168-note-thread-mute.js b/packages/backend/src/migration/1635500777168-note-thread-mute.ts similarity index 87% rename from packages/backend/migration/1635500777168-note-thread-mute.js rename to packages/backend/src/migration/1635500777168-note-thread-mute.ts index 5fcfa40c07..6d55632cb4 100644 --- a/packages/backend/migration/1635500777168-note-thread-mute.js +++ b/packages/backend/src/migration/1635500777168-note-thread-mute.ts @@ -1,8 +1,7 @@ -export class noteThreadMute1635500777168 { - constructor() { - this.name = "noteThreadMute1635500777168"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class noteThreadMute1635500777168 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "note_thread_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "threadId" character varying(256) NOT NULL, CONSTRAINT "PK_ec5936d94d1a0369646d12a3a47" PRIMARY KEY ("id"))`, ); @@ -25,7 +24,7 @@ export class noteThreadMute1635500777168 { `ALTER TABLE "note_thread_muting" ADD CONSTRAINT "FK_29c11c7deb06615076f8c95b80a" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "note_thread_muting" DROP CONSTRAINT "FK_29c11c7deb06615076f8c95b80a"`, ); diff --git a/packages/backend/migration/1636197624383-ff-visibility.js b/packages/backend/src/migration/1636197624383-ff-visibility.ts similarity index 66% rename from packages/backend/migration/1636197624383-ff-visibility.js rename to packages/backend/src/migration/1636197624383-ff-visibility.ts index a3af8f7186..09a323d1f1 100644 --- a/packages/backend/migration/1636197624383-ff-visibility.js +++ b/packages/backend/src/migration/1636197624383-ff-visibility.ts @@ -1,8 +1,7 @@ -export class ffVisibility1636197624383 { - constructor() { - this.name = "ffVisibility1636197624383"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ffVisibility1636197624383 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "public"."user_profile_ffvisibility_enum" AS ENUM('public', 'followers', 'private')`, ); @@ -10,7 +9,7 @@ export class ffVisibility1636197624383 { `ALTER TABLE "user_profile" ADD "ffVisibility" "public"."user_profile_ffvisibility_enum" NOT NULL DEFAULT 'public'`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" DROP COLUMN "ffVisibility"`, ); diff --git a/packages/backend/src/migration/1636697408073-remove-via-mobile.ts b/packages/backend/src/migration/1636697408073-remove-via-mobile.ts new file mode 100644 index 0000000000..a02143c4e9 --- /dev/null +++ b/packages/backend/src/migration/1636697408073-remove-via-mobile.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class removeViaMobile1636697408073 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "viaMobile"`); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "note" ADD "viaMobile" boolean NOT NULL DEFAULT false`, + ); + } +} diff --git a/packages/backend/src/migration/1637320813000-forwarded-report.ts b/packages/backend/src/migration/1637320813000-forwarded-report.ts new file mode 100644 index 0000000000..7acd9ed0a6 --- /dev/null +++ b/packages/backend/src/migration/1637320813000-forwarded-report.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class forwardedReport1637320813000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "abuse_user_report" ADD "forwarded" boolean NOT NULL DEFAULT false`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "abuse_user_report" DROP COLUMN "forwarded"`, + ); + } +} diff --git a/packages/backend/migration/1639325650583-chart-v3.js b/packages/backend/src/migration/1639325650583-chart-v3.ts similarity index 99% rename from packages/backend/migration/1639325650583-chart-v3.js rename to packages/backend/src/migration/1639325650583-chart-v3.ts index 011708c0fe..04267abc55 100644 --- a/packages/backend/migration/1639325650583-chart-v3.js +++ b/packages/backend/src/migration/1639325650583-chart-v3.ts @@ -1,7 +1,7 @@ -export class chartV31639325650583 { - name = "chartV31639325650583"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV31639325650583 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `DELETE FROM "__chart__per_user_drive" WHERE "group" IS NULL`, ); @@ -266,7 +266,7 @@ export class chartV31639325650583 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__per_user_drive" DROP CONSTRAINT "UQ_30bf67687f483ace115c5ca6429"`, ); diff --git a/packages/backend/migration/1642611822809-emoji-url.js b/packages/backend/src/migration/1642611822809-emoji-url.ts similarity index 62% rename from packages/backend/migration/1642611822809-emoji-url.js rename to packages/backend/src/migration/1642611822809-emoji-url.ts index e1852c0025..97b88e0866 100644 --- a/packages/backend/migration/1642611822809-emoji-url.js +++ b/packages/backend/src/migration/1642611822809-emoji-url.ts @@ -1,7 +1,7 @@ -export class emojiUrl1642611822809 { - name = "emojiUrl1642611822809"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class emojiUrl1642611822809 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "emoji" RENAME COLUMN "url" TO "originalUrl"`, ); @@ -10,7 +10,7 @@ export class emojiUrl1642611822809 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "publicUrl"`); await queryRunner.query( `ALTER TABLE "emoji" RENAME COLUMN "originalUrl" TO "url"`, diff --git a/packages/backend/src/migration/1642613870898-drive-file-webpublic-type.ts b/packages/backend/src/migration/1642613870898-drive-file-webpublic-type.ts new file mode 100644 index 0000000000..97457f6ad3 --- /dev/null +++ b/packages/backend/src/migration/1642613870898-drive-file-webpublic-type.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class driveFileWebpublicType1642613870898 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" ADD "webpublicType" character varying(128)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" DROP COLUMN "webpublicType"`, + ); + } +} diff --git a/packages/backend/migration/1643963705770-chart-v4.js b/packages/backend/src/migration/1643963705770-chart-v4.ts similarity index 96% rename from packages/backend/migration/1643963705770-chart-v4.js rename to packages/backend/src/migration/1643963705770-chart-v4.ts index 1e7233cc72..081be2e9ce 100644 --- a/packages/backend/migration/1643963705770-chart-v4.js +++ b/packages/backend/src/migration/1643963705770-chart-v4.ts @@ -1,7 +1,7 @@ -export class chartV41643963705770 { - name = "chartV41643963705770"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV41643963705770 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__instance" DROP COLUMN "___drive_totalUsage"`, ); @@ -82,7 +82,7 @@ export class chartV41643963705770 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__hashtag" DROP COLUMN "___remote_users"`, ); diff --git a/packages/backend/migration/1643966656277-chart-v5.js b/packages/backend/src/migration/1643966656277-chart-v5.ts similarity index 90% rename from packages/backend/migration/1643966656277-chart-v5.js rename to packages/backend/src/migration/1643966656277-chart-v5.ts index 826f28ee34..c4ef29408e 100644 --- a/packages/backend/migration/1643966656277-chart-v5.js +++ b/packages/backend/src/migration/1643966656277-chart-v5.ts @@ -1,7 +1,7 @@ -export class chartV51643966656277 { - name = "chartV51643966656277"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV51643966656277 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__active_users" ADD "unique_temp___local_users" character varying array NOT NULL DEFAULT '{}'`, ); @@ -28,7 +28,7 @@ export class chartV51643966656277 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__hashtag" DROP COLUMN "unique_temp___remote_users"`, ); diff --git a/packages/backend/migration/1643967331284-chart-v6.js b/packages/backend/src/migration/1643967331284-chart-v6.ts similarity index 99% rename from packages/backend/migration/1643967331284-chart-v6.js rename to packages/backend/src/migration/1643967331284-chart-v6.ts index 9dfbf24bec..b82cc31f48 100644 --- a/packages/backend/migration/1643967331284-chart-v6.js +++ b/packages/backend/src/migration/1643967331284-chart-v6.ts @@ -1,7 +1,7 @@ -export class chartV61643967331284 { - name = "chartV61643967331284"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV61643967331284 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" ALTER COLUMN "___instance_total" SET DEFAULT '0'`, ); @@ -502,7 +502,7 @@ export class chartV61643967331284 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__per_user_drive" ALTER COLUMN "___decSize" DROP DEFAULT`, ); diff --git a/packages/backend/migration/1644010796173-convert-hard-mutes.js b/packages/backend/src/migration/1644010796173-convert-hard-mutes.ts similarity index 86% rename from packages/backend/migration/1644010796173-convert-hard-mutes.js rename to packages/backend/src/migration/1644010796173-convert-hard-mutes.ts index 39c5b080fd..7579427d26 100644 --- a/packages/backend/migration/1644010796173-convert-hard-mutes.js +++ b/packages/backend/src/migration/1644010796173-convert-hard-mutes.ts @@ -1,9 +1,9 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + import RE2 from "re2"; -export class convertHardMutes1644010796173 { - name = "convertHardMutes1644010796173"; - - async up(queryRunner) { +export class convertHardMutes1644010796173 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { let entries = await queryRunner.query( `SELECT "userId", "mutedWords" FROM "user_profile" WHERE "userHost" IS NULL`, ); @@ -40,7 +40,7 @@ export class convertHardMutes1644010796173 { } } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { let entries = await queryRunner.query( `SELECT "userId", "mutedWords" FROM "user_profile"`, ); diff --git a/packages/backend/migration/1644058404077-chart-v7.js b/packages/backend/src/migration/1644058404077-chart-v7.ts similarity index 99% rename from packages/backend/migration/1644058404077-chart-v7.js rename to packages/backend/src/migration/1644058404077-chart-v7.ts index ab48c9ab38..7441b002a9 100644 --- a/packages/backend/migration/1644058404077-chart-v7.js +++ b/packages/backend/src/migration/1644058404077-chart-v7.ts @@ -1,7 +1,7 @@ -export class chartV71644058404077 { - name = "chartV71644058404077"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV71644058404077 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE "__chart__federation" SET "___instance_total"=2147483647 WHERE "___instance_total" > 2147483647`, ); @@ -967,7 +967,7 @@ export class chartV71644058404077 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" ALTER COLUMN "___instance_total" TYPE bigint USING "___instance_total"::bigint`, ); diff --git a/packages/backend/migration/1644059847460-chart-v8.js b/packages/backend/src/migration/1644059847460-chart-v8.ts similarity index 88% rename from packages/backend/migration/1644059847460-chart-v8.js rename to packages/backend/src/migration/1644059847460-chart-v8.ts index f9357c8ca1..fef309bcbe 100644 --- a/packages/backend/migration/1644059847460-chart-v8.js +++ b/packages/backend/src/migration/1644059847460-chart-v8.ts @@ -1,7 +1,7 @@ -export class chartV81644059847460 { - name = "chartV81644059847460"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV81644059847460 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE "__chart__active_users" SET "___local_users"=2147483647 WHERE "___local_users" > 2147483647`, ); @@ -29,7 +29,7 @@ export class chartV81644059847460 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__active_users" ALTER COLUMN "___local_users" TYPE bigint USING "___local_users"::bigint`, ); diff --git a/packages/backend/migration/1644060125705-chart-v9.js b/packages/backend/src/migration/1644060125705-chart-v9.ts similarity index 88% rename from packages/backend/migration/1644060125705-chart-v9.js rename to packages/backend/src/migration/1644060125705-chart-v9.ts index 7d7934e319..c55282ed32 100644 --- a/packages/backend/migration/1644060125705-chart-v9.js +++ b/packages/backend/src/migration/1644060125705-chart-v9.ts @@ -1,7 +1,7 @@ -export class chartV91644060125705 { - name = "chartV91644060125705"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV91644060125705 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE "__chart__hashtag" SET "___local_users"=2147483647 WHERE "___local_users" > 2147483647`, ); @@ -29,7 +29,7 @@ export class chartV91644060125705 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__hashtag" ALTER COLUMN "___local_users" TYPE bigint USING "___local_users"::bigint`, ); diff --git a/packages/backend/migration/1644073149413-chart-v10.js b/packages/backend/src/migration/1644073149413-chart-v10.ts similarity index 93% rename from packages/backend/migration/1644073149413-chart-v10.js rename to packages/backend/src/migration/1644073149413-chart-v10.ts index 8038dad156..7bcf105b99 100644 --- a/packages/backend/migration/1644073149413-chart-v10.js +++ b/packages/backend/src/migration/1644073149413-chart-v10.ts @@ -1,7 +1,7 @@ -export class chartV101644073149413 { - name = "chartV101644073149413"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV101644073149413 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "__chart__ap_request" ("id" SERIAL NOT NULL, "date" integer NOT NULL, "___deliverFailed" integer NOT NULL DEFAULT '0', "___deliverSucceeded" integer NOT NULL DEFAULT '0', "___inboxReceived" integer NOT NULL DEFAULT '0', CONSTRAINT "UQ_e56f4beac5746d44bc3e19c80d0" UNIQUE ("date"), CONSTRAINT "PK_56a25cd447c7ee08876b3baf8d8" PRIMARY KEY ("id"))`, ); @@ -40,7 +40,7 @@ export class chartV101644073149413 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__federation" DROP COLUMN "___inboxInstances"`, ); diff --git a/packages/backend/migration/1644095659741-chart-v11.js b/packages/backend/src/migration/1644095659741-chart-v11.ts similarity index 97% rename from packages/backend/migration/1644095659741-chart-v11.js rename to packages/backend/src/migration/1644095659741-chart-v11.ts index 8db122d4f1..d5e7fb5f87 100644 --- a/packages/backend/migration/1644095659741-chart-v11.js +++ b/packages/backend/src/migration/1644095659741-chart-v11.ts @@ -1,7 +1,7 @@ -export class chartV111644095659741 { - name = "chartV111644095659741"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV111644095659741 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__active_users" DROP COLUMN "___local_users"`, ); @@ -124,7 +124,7 @@ export class chartV111644095659741 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__active_users" DROP COLUMN "___registeredOutsideYear"`, ); diff --git a/packages/backend/migration/1644328606241-chart-v12.js b/packages/backend/src/migration/1644328606241-chart-v12.ts similarity index 89% rename from packages/backend/migration/1644328606241-chart-v12.js rename to packages/backend/src/migration/1644328606241-chart-v12.ts index ea363e12fd..b2a3378bbd 100644 --- a/packages/backend/migration/1644328606241-chart-v12.js +++ b/packages/backend/src/migration/1644328606241-chart-v12.ts @@ -1,7 +1,7 @@ -export class chartV121644328606241 { - name = "chartV121644328606241"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV121644328606241 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__notes" ADD "___local_diffs_withFile" integer NOT NULL DEFAULT '0'`, ); @@ -28,7 +28,7 @@ export class chartV121644328606241 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__per_user_notes" DROP COLUMN "___diffs_withFile"`, ); diff --git a/packages/backend/migration/1644331238153-chart-v13.js b/packages/backend/src/migration/1644331238153-chart-v13.ts similarity index 80% rename from packages/backend/migration/1644331238153-chart-v13.js rename to packages/backend/src/migration/1644331238153-chart-v13.ts index cbb1830f50..6a5aa75ad7 100644 --- a/packages/backend/migration/1644331238153-chart-v13.js +++ b/packages/backend/src/migration/1644331238153-chart-v13.ts @@ -1,7 +1,7 @@ -export class chartV131644331238153 { - name = "chartV131644331238153"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV131644331238153 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" ADD "unique_temp___stalled" character varying array NOT NULL DEFAULT '{}'`, ); @@ -16,7 +16,7 @@ export class chartV131644331238153 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__federation" DROP COLUMN "___stalled"`, ); diff --git a/packages/backend/migration/1644344266289-chart-v14.js b/packages/backend/src/migration/1644344266289-chart-v14.ts similarity index 94% rename from packages/backend/migration/1644344266289-chart-v14.js rename to packages/backend/src/migration/1644344266289-chart-v14.ts index 6e6c030833..bbbd8e3096 100644 --- a/packages/backend/migration/1644344266289-chart-v14.js +++ b/packages/backend/src/migration/1644344266289-chart-v14.ts @@ -1,7 +1,7 @@ -export class chartV141644344266289 { - name = "chartV141644344266289"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV141644344266289 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__active_users" DROP COLUMN "unique_temp___users"`, ); @@ -58,7 +58,7 @@ export class chartV141644344266289 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__active_users" DROP COLUMN "___write"`, ); diff --git a/packages/backend/src/migration/1644395759931-instance-theme-color.ts b/packages/backend/src/migration/1644395759931-instance-theme-color.ts new file mode 100644 index 0000000000..e0391fbde2 --- /dev/null +++ b/packages/backend/src/migration/1644395759931-instance-theme-color.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class instanceThemeColor1644395759931 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "themeColor" character varying(512)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "themeColor"`); + } +} diff --git a/packages/backend/migration/1644481657998-chart-v15.js b/packages/backend/src/migration/1644481657998-chart-v15.ts similarity index 90% rename from packages/backend/migration/1644481657998-chart-v15.js rename to packages/backend/src/migration/1644481657998-chart-v15.ts index a8e1b89cb1..54572997a3 100644 --- a/packages/backend/migration/1644481657998-chart-v15.js +++ b/packages/backend/src/migration/1644481657998-chart-v15.ts @@ -1,7 +1,7 @@ -export class chartV151644481657998 { - name = "chartV151644481657998"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartV151644481657998 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" DROP COLUMN "___instance_total"`, ); @@ -34,7 +34,7 @@ export class chartV151644481657998 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__federation" DROP COLUMN "___pub"`, ); diff --git a/packages/backend/migration/1644551208096-following-indexes.js b/packages/backend/src/migration/1644551208096-following-indexes.ts similarity index 63% rename from packages/backend/migration/1644551208096-following-indexes.js rename to packages/backend/src/migration/1644551208096-following-indexes.ts index b06f764e58..5838124844 100644 --- a/packages/backend/migration/1644551208096-following-indexes.js +++ b/packages/backend/src/migration/1644551208096-following-indexes.ts @@ -1,7 +1,7 @@ -export class followingIndexes1644551208096 { - name = "followingIndexes1644551208096"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class followingIndexes1644551208096 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE INDEX "IDX_4ccd2239268ebbd1b35e318754" ON "following" ("followerHost") `, ); @@ -10,7 +10,7 @@ export class followingIndexes1644551208096 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "public"."IDX_fcdafee716dfe9c3b5fde90f30"`, ); diff --git a/packages/backend/src/migration/1645340161439-remove-max-note-text-length.ts b/packages/backend/src/migration/1645340161439-remove-max-note-text-length.ts new file mode 100644 index 0000000000..ac673ea936 --- /dev/null +++ b/packages/backend/src/migration/1645340161439-remove-max-note-text-length.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class removeMaxNoteTextLength1645340161439 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "maxNoteTextLength"`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "maxNoteTextLength" integer NOT NULL DEFAULT '500'`, + ); + } +} diff --git a/packages/backend/migration/1645599900873-federation-chart-pubsub.js b/packages/backend/src/migration/1645599900873-federation-chart-pubsub.ts similarity index 64% rename from packages/backend/migration/1645599900873-federation-chart-pubsub.js rename to packages/backend/src/migration/1645599900873-federation-chart-pubsub.ts index 58e2b4c00d..6f80b79a22 100644 --- a/packages/backend/migration/1645599900873-federation-chart-pubsub.js +++ b/packages/backend/src/migration/1645599900873-federation-chart-pubsub.ts @@ -1,7 +1,7 @@ -export class federationChartPubsub1645599900873 { - name = "federationChartPubsub1645599900873"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class federationChartPubsub1645599900873 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" ADD "___pubsub" smallint NOT NULL DEFAULT '0'`, ); @@ -10,7 +10,7 @@ export class federationChartPubsub1645599900873 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__federation" DROP COLUMN "___pubsub"`, ); diff --git a/packages/backend/migration/1646143552768-instance-default-theme.js b/packages/backend/src/migration/1646143552768-instance-default-theme.ts similarity index 61% rename from packages/backend/migration/1646143552768-instance-default-theme.js rename to packages/backend/src/migration/1646143552768-instance-default-theme.ts index d97efcaa6e..a22bdc2792 100644 --- a/packages/backend/migration/1646143552768-instance-default-theme.js +++ b/packages/backend/src/migration/1646143552768-instance-default-theme.ts @@ -1,7 +1,7 @@ -export class instanceDefaultTheme1646143552768 { - name = "instanceDefaultTheme1646143552768"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class instanceDefaultTheme1646143552768 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "defaultLightTheme" character varying(8192)`, ); @@ -10,7 +10,7 @@ export class instanceDefaultTheme1646143552768 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "defaultDarkTheme"`, ); diff --git a/packages/backend/migration/1646387162108-mute-expires-at.js b/packages/backend/src/migration/1646387162108-mute-expires-at.ts similarity index 61% rename from packages/backend/migration/1646387162108-mute-expires-at.js rename to packages/backend/src/migration/1646387162108-mute-expires-at.ts index 52fe101bd1..2a15d20405 100644 --- a/packages/backend/migration/1646387162108-mute-expires-at.js +++ b/packages/backend/src/migration/1646387162108-mute-expires-at.ts @@ -1,7 +1,7 @@ -export class muteExpiresAt1646387162108 { - name = "muteExpiresAt1646387162108"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class muteExpiresAt1646387162108 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "muting" ADD "expiresAt" TIMESTAMP WITH TIME ZONE`, ); @@ -10,7 +10,7 @@ export class muteExpiresAt1646387162108 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "public"."IDX_c1fd1c3dfb0627aa36c253fd14"`, ); diff --git a/packages/backend/migration/1646549089451-poll-ended-notification.js b/packages/backend/src/migration/1646549089451-poll-ended-notification.ts similarity index 83% rename from packages/backend/migration/1646549089451-poll-ended-notification.js rename to packages/backend/src/migration/1646549089451-poll-ended-notification.ts index cc96a62a7e..651b0a4b92 100644 --- a/packages/backend/migration/1646549089451-poll-ended-notification.js +++ b/packages/backend/src/migration/1646549089451-poll-ended-notification.ts @@ -1,7 +1,7 @@ -export class pollEndedNotification1646549089451 { - name = "pollEndedNotification1646549089451"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class pollEndedNotification1646549089451 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TYPE "public"."notification_type_enum" RENAME TO "notification_type_enum_old"`, ); @@ -14,7 +14,7 @@ export class pollEndedNotification1646549089451 { await queryRunner.query(`DROP TYPE "public"."notification_type_enum_old"`); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "public"."notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`, ); diff --git a/packages/backend/migration/1646633030285-chart-federation-active.js b/packages/backend/src/migration/1646633030285-chart-federation-active.ts similarity index 64% rename from packages/backend/migration/1646633030285-chart-federation-active.js rename to packages/backend/src/migration/1646633030285-chart-federation-active.ts index 3cb2dffe3f..92b1358a1f 100644 --- a/packages/backend/migration/1646633030285-chart-federation-active.js +++ b/packages/backend/src/migration/1646633030285-chart-federation-active.ts @@ -1,7 +1,7 @@ -export class chartFederationActive1646633030285 { - name = "chartFederationActive1646633030285"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartFederationActive1646633030285 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" ADD "___active" smallint NOT NULL DEFAULT '0'`, ); @@ -10,7 +10,7 @@ export class chartFederationActive1646633030285 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__federation" DROP COLUMN "___active"`, ); diff --git a/packages/backend/migration/1646655454495-remove-instance-drive-columns.js b/packages/backend/src/migration/1646655454495-remove-instance-drive-columns.ts similarity index 59% rename from packages/backend/migration/1646655454495-remove-instance-drive-columns.js rename to packages/backend/src/migration/1646655454495-remove-instance-drive-columns.ts index 12f56bc2d7..ca969b34da 100644 --- a/packages/backend/migration/1646655454495-remove-instance-drive-columns.js +++ b/packages/backend/src/migration/1646655454495-remove-instance-drive-columns.ts @@ -1,12 +1,14 @@ -export class removeInstanceDriveColumns1646655454495 { - name = "removeInstanceDriveColumns1646655454495"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class removeInstanceDriveColumns1646655454495 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "driveUsage"`); await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "driveFiles"`); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "instance" ADD "driveFiles" integer NOT NULL DEFAULT '0'`, ); diff --git a/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js b/packages/backend/src/migration/1646732390560-chart-federation-active-sub-pub.ts similarity index 84% rename from packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js rename to packages/backend/src/migration/1646732390560-chart-federation-active-sub-pub.ts index e34b9a22e9..18d01f5f94 100644 --- a/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js +++ b/packages/backend/src/migration/1646732390560-chart-federation-active-sub-pub.ts @@ -1,7 +1,9 @@ -export class chartFederationActiveSubPub1646732390560 { - name = "chartFederationActiveSubPub1646732390560"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class chartFederationActiveSubPub1646732390560 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart__federation" DROP COLUMN "___active"`, ); @@ -22,7 +24,7 @@ export class chartFederationActiveSubPub1646732390560 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "__chart_day__federation" DROP COLUMN "___pubActive"`, ); diff --git a/packages/backend/migration/1648548247382-webhook.js b/packages/backend/src/migration/1648548247382-webhook.ts similarity index 87% rename from packages/backend/migration/1648548247382-webhook.js rename to packages/backend/src/migration/1648548247382-webhook.ts index 3e7160e2b2..409ddc6bcd 100644 --- a/packages/backend/migration/1648548247382-webhook.js +++ b/packages/backend/src/migration/1648548247382-webhook.ts @@ -1,7 +1,7 @@ -export class webhook1648548247382 { - name = "webhook1648548247382"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class webhook1648548247382 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "webhook" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, "on" character varying(128) array NOT NULL DEFAULT '{}', "url" character varying(1024) NOT NULL, "secret" character varying(1024) NOT NULL, "active" boolean NOT NULL DEFAULT true, CONSTRAINT "PK_e6765510c2d078db49632b59020" PRIMARY KEY ("id")); COMMENT ON COLUMN "webhook"."createdAt" IS 'The created date of the Antenna.'; COMMENT ON COLUMN "webhook"."userId" IS 'The owner ID.'; COMMENT ON COLUMN "webhook"."name" IS 'The name of the Antenna.'`, ); @@ -19,7 +19,7 @@ export class webhook1648548247382 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "webhook" DROP CONSTRAINT "FK_f272c8c8805969e6a6449c77b3c"`, ); diff --git a/packages/backend/migration/1648816172177-webhook-2.js b/packages/backend/src/migration/1648816172177-webhook-2.ts similarity index 60% rename from packages/backend/migration/1648816172177-webhook-2.js rename to packages/backend/src/migration/1648816172177-webhook-2.ts index a4ab4ef8f8..c313a57bc2 100644 --- a/packages/backend/migration/1648816172177-webhook-2.js +++ b/packages/backend/src/migration/1648816172177-webhook-2.ts @@ -1,14 +1,14 @@ -export class webhook21648816172177 { - name = "webhook21648816172177"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class webhook21648816172177 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "webhook" ADD "latestSentAt" TIMESTAMP WITH TIME ZONE`, ); await queryRunner.query(`ALTER TABLE "webhook" ADD "latestStatus" integer`); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "webhook" DROP COLUMN "latestStatus"`); await queryRunner.query(`ALTER TABLE "webhook" DROP COLUMN "latestSentAt"`); } diff --git a/packages/backend/migration/1651224615271-foreign-key.js b/packages/backend/src/migration/1651224615271-foreign-key.ts similarity index 96% rename from packages/backend/migration/1651224615271-foreign-key.js rename to packages/backend/src/migration/1651224615271-foreign-key.ts index 7e6bc79623..c93ff28a26 100644 --- a/packages/backend/migration/1651224615271-foreign-key.js +++ b/packages/backend/src/migration/1651224615271-foreign-key.ts @@ -1,7 +1,7 @@ -export class foreignKeyReports1651224615271 { - name = "foreignKeyReports1651224615271"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class foreignKeyReports1651224615271 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await Promise.all([ queryRunner.query( `ALTER INDEX "public"."IDX_seoignmeoprigmkpodgrjmkpormg" RENAME TO "IDX_c8cc87bd0f2f4487d17c651fbf"`, @@ -104,7 +104,7 @@ export class foreignKeyReports1651224615271 { ]); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await Promise.all([ // There is no ALTER TYPE REMOVE VALUE query, so the reverse operation is a bit more complex queryRunner diff --git a/packages/backend/migration/1652859567549-uniform-themecolor.js b/packages/backend/src/migration/1652859567549-uniform-themecolor.ts similarity index 82% rename from packages/backend/migration/1652859567549-uniform-themecolor.js rename to packages/backend/src/migration/1652859567549-uniform-themecolor.ts index 8c91854d53..0943d6218d 100644 --- a/packages/backend/migration/1652859567549-uniform-themecolor.js +++ b/packages/backend/src/migration/1652859567549-uniform-themecolor.ts @@ -1,9 +1,9 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + import tinycolor from "tinycolor2"; -export class uniformThemecolor1652859567549 { - name = "uniformThemecolor1652859567549"; - - async up(queryRunner) { +export class uniformThemecolor1652859567549 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { const formatColor = (color) => { let tc = new tinycolor(color); if (tc.isValid()) { @@ -44,7 +44,7 @@ export class uniformThemecolor1652859567549 { }); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { // The original representation is not stored, so migrating back is not possible. // The new format also works in older versions so this is not a problem. } diff --git a/packages/backend/migration/1655368940105-nsfw-detection.js b/packages/backend/src/migration/1655368940105-nsfw-detection.ts similarity index 87% rename from packages/backend/migration/1655368940105-nsfw-detection.js rename to packages/backend/src/migration/1655368940105-nsfw-detection.ts index f1bcda50e5..ed5af1bfaa 100644 --- a/packages/backend/migration/1655368940105-nsfw-detection.js +++ b/packages/backend/src/migration/1655368940105-nsfw-detection.ts @@ -1,7 +1,7 @@ -export class nsfwDetection1655368940105 { - name = "nsfwDetection1655368940105"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class nsfwDetection1655368940105 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "drive_file" ADD "forceIsSensitive" boolean NOT NULL DEFAULT false`, ); @@ -25,7 +25,7 @@ export class nsfwDetection1655368940105 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "public"."IDX_fc2d74a6d7d8b11292a851d8f8"`, ); diff --git a/packages/backend/migration/1655371960534-nsfw-detection-2.js b/packages/backend/src/migration/1655371960534-nsfw-detection-2.ts similarity index 76% rename from packages/backend/migration/1655371960534-nsfw-detection-2.js rename to packages/backend/src/migration/1655371960534-nsfw-detection-2.ts index 236cd70913..4f0362449b 100644 --- a/packages/backend/migration/1655371960534-nsfw-detection-2.js +++ b/packages/backend/src/migration/1655371960534-nsfw-detection-2.ts @@ -1,7 +1,7 @@ -export class nsfwDetection21655371960534 { - name = "nsfwDetection21655371960534"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class nsfwDetection21655371960534 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "public"."meta_sensitiveimagedetectionsensitivity_enum" AS ENUM('medium', 'low', 'high')`, ); @@ -13,7 +13,7 @@ export class nsfwDetection21655371960534 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "disallowUploadWhenPredictedAsPorn"`, ); diff --git a/packages/backend/migration/1655388169582-nsfw-detection-3.js b/packages/backend/src/migration/1655388169582-nsfw-detection-3.ts similarity index 88% rename from packages/backend/migration/1655388169582-nsfw-detection-3.js rename to packages/backend/src/migration/1655388169582-nsfw-detection-3.ts index 6a6ceeafba..16cb039da5 100644 --- a/packages/backend/migration/1655388169582-nsfw-detection-3.js +++ b/packages/backend/src/migration/1655388169582-nsfw-detection-3.ts @@ -1,7 +1,7 @@ -export class nsfwDetection31655388169582 { - name = "nsfwDetection31655388169582"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class nsfwDetection31655388169582 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TYPE "public"."meta_sensitiveimagedetectionsensitivity_enum" RENAME TO "meta_sensitiveimagedetectionsensitivity_enum_old"`, ); @@ -22,7 +22,7 @@ export class nsfwDetection31655388169582 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "public"."meta_sensitiveimagedetectionsensitivity_enum_old" AS ENUM('medium', 'low', 'high')`, ); diff --git a/packages/backend/migration/1655393015659-nsfw-detection-4.js b/packages/backend/src/migration/1655393015659-nsfw-detection-4.ts similarity index 89% rename from packages/backend/migration/1655393015659-nsfw-detection-4.js rename to packages/backend/src/migration/1655393015659-nsfw-detection-4.ts index 3e45897327..e01e74e6a6 100644 --- a/packages/backend/migration/1655393015659-nsfw-detection-4.js +++ b/packages/backend/src/migration/1655393015659-nsfw-detection-4.ts @@ -1,7 +1,7 @@ -export class nsfwDetection41655393015659 { - name = "nsfwDetection41655393015659"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class nsfwDetection41655393015659 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "sensitiveImageDetection"`, ); @@ -28,7 +28,7 @@ export class nsfwDetection41655393015659 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "sensitiveMediaDetectionSensitivity"`, ); diff --git a/packages/backend/migration/1655813815729-driveCapacityOverrideMb.js b/packages/backend/src/migration/1655813815729-driveCapacityOverrideMb.ts similarity index 64% rename from packages/backend/migration/1655813815729-driveCapacityOverrideMb.js rename to packages/backend/src/migration/1655813815729-driveCapacityOverrideMb.ts index e43f0af5c1..8616fcb546 100644 --- a/packages/backend/migration/1655813815729-driveCapacityOverrideMb.js +++ b/packages/backend/src/migration/1655813815729-driveCapacityOverrideMb.ts @@ -1,7 +1,9 @@ -export class driveCapacityOverrideMb1655813815729 { - name = "driveCapacityOverrideMb1655813815729"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class driveCapacityOverrideMb1655813815729 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "driveCapacityOverrideMb" integer`, ); @@ -10,7 +12,7 @@ export class driveCapacityOverrideMb1655813815729 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `COMMENT ON COLUMN "user"."driveCapacityOverrideMb" IS 'Overrides user drive capacity limit'`, ); diff --git a/packages/backend/migration/1655918165614-user-ip.js b/packages/backend/src/migration/1655918165614-user-ip.ts similarity index 81% rename from packages/backend/migration/1655918165614-user-ip.js rename to packages/backend/src/migration/1655918165614-user-ip.ts index 2c5dc1c821..db980e4b5c 100644 --- a/packages/backend/migration/1655918165614-user-ip.js +++ b/packages/backend/src/migration/1655918165614-user-ip.ts @@ -1,7 +1,7 @@ -export class userIp1655918165614 { - name = "userIp1655918165614"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class userIp1655918165614 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "user_ip" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "ip" character varying(128) NOT NULL, CONSTRAINT "PK_2c44ddfbf7c0464d028dcef325e" PRIMARY KEY ("id"))`, ); @@ -16,7 +16,7 @@ export class userIp1655918165614 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_ip" DROP CONSTRAINT "FK_7f7f1c66f48e9a8e18a33bc5150"`, ); diff --git a/packages/backend/migration/1656122560740-file-ip.js b/packages/backend/src/migration/1656122560740-file-ip.ts similarity index 62% rename from packages/backend/migration/1656122560740-file-ip.js rename to packages/backend/src/migration/1656122560740-file-ip.ts index 534097adb3..52fdf1a64f 100644 --- a/packages/backend/migration/1656122560740-file-ip.js +++ b/packages/backend/src/migration/1656122560740-file-ip.ts @@ -1,7 +1,7 @@ -export class fileIp1656122560740 { - name = "fileIp1656122560740"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class fileIp1656122560740 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "drive_file" ADD "requestHeaders" jsonb DEFAULT '{}'`, ); @@ -10,7 +10,7 @@ export class fileIp1656122560740 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "requestIp"`); await queryRunner.query( `ALTER TABLE "drive_file" DROP COLUMN "requestHeaders"`, diff --git a/packages/backend/migration/1656251734807-nsfw-detection-5.js b/packages/backend/src/migration/1656251734807-nsfw-detection-5.ts similarity index 91% rename from packages/backend/migration/1656251734807-nsfw-detection-5.js rename to packages/backend/src/migration/1656251734807-nsfw-detection-5.ts index 7a2206e018..2a89eef228 100644 --- a/packages/backend/migration/1656251734807-nsfw-detection-5.js +++ b/packages/backend/src/migration/1656251734807-nsfw-detection-5.ts @@ -1,7 +1,7 @@ -export class nsfwDetection51656251734807 { - name = "nsfwDetection51656251734807"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class nsfwDetection51656251734807 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "public"."IDX_fc2d74a6d7d8b11292a851d8f8"`, ); @@ -40,7 +40,7 @@ export class nsfwDetection51656251734807 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `DROP INDEX "public"."IDX_8bdcd3dd2bddb78014999a16ce"`, ); diff --git a/packages/backend/migration/1656328812281-ip-2.js b/packages/backend/src/migration/1656328812281-ip-2.ts similarity index 68% rename from packages/backend/migration/1656328812281-ip-2.js rename to packages/backend/src/migration/1656328812281-ip-2.ts index ab4096e9c6..45f608be3d 100644 --- a/packages/backend/migration/1656328812281-ip-2.js +++ b/packages/backend/src/migration/1656328812281-ip-2.ts @@ -1,7 +1,7 @@ -export class ip21656328812281 { - name = "ip21656328812281"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class ip21656328812281 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_ip" DROP CONSTRAINT "FK_7f7f1c66f48e9a8e18a33bc5150"`, ); @@ -10,7 +10,7 @@ export class ip21656328812281 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableIpLogging"`); await queryRunner.query( `ALTER TABLE "user_ip" ADD CONSTRAINT "FK_7f7f1c66f48e9a8e18a33bc5150" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, diff --git a/packages/backend/migration/1656408772602-nsfw-detection-6.js b/packages/backend/src/migration/1656408772602-nsfw-detection-6.ts similarity index 51% rename from packages/backend/migration/1656408772602-nsfw-detection-6.js rename to packages/backend/src/migration/1656408772602-nsfw-detection-6.ts index 4ef237308f..f3e34b097d 100644 --- a/packages/backend/migration/1656408772602-nsfw-detection-6.js +++ b/packages/backend/src/migration/1656408772602-nsfw-detection-6.ts @@ -1,13 +1,13 @@ -export class nsfwDetection61656408772602 { - name = "nsfwDetection61656408772602"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class nsfwDetection61656408772602 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "enableSensitiveMediaDetectionForVideos" boolean NOT NULL DEFAULT false`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "enableSensitiveMediaDetectionForVideos"`, ); diff --git a/packages/backend/src/migration/1656772790599-user-moderation-note.ts b/packages/backend/src/migration/1656772790599-user-moderation-note.ts new file mode 100644 index 0000000000..b98db08132 --- /dev/null +++ b/packages/backend/src/migration/1656772790599-user-moderation-note.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class userModerationNote1656772790599 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "moderationNote" character varying(8192) NOT NULL DEFAULT ''`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" DROP COLUMN "moderationNote"`, + ); + } +} diff --git a/packages/backend/src/migration/1657346559800-active-email-validation.ts b/packages/backend/src/migration/1657346559800-active-email-validation.ts new file mode 100644 index 0000000000..e93f3f3a8c --- /dev/null +++ b/packages/backend/src/migration/1657346559800-active-email-validation.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class activeEmailValidation1657346559800 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "enableActiveEmailValidation" boolean NOT NULL DEFAULT true`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "enableActiveEmailValidation"`, + ); + } +} diff --git a/packages/backend/migration/1658203170545firefish.js b/packages/backend/src/migration/1658203170545firefish.ts similarity index 66% rename from packages/backend/migration/1658203170545firefish.js rename to packages/backend/src/migration/1658203170545firefish.ts index c66996d088..41df2367bc 100644 --- a/packages/backend/migration/1658203170545firefish.js +++ b/packages/backend/src/migration/1658203170545firefish.ts @@ -1,7 +1,7 @@ -export class calckey1658203170545 { - name = "calckey1658203170545"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class calckey1658203170545 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg/firefish/firefish'`, ); @@ -10,7 +10,7 @@ export class calckey1658203170545 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg/firefish/firefish'`, ); diff --git a/packages/backend/migration/1658656633972-note-replies-function.js b/packages/backend/src/migration/1658656633972-note-replies-function.ts similarity index 82% rename from packages/backend/migration/1658656633972-note-replies-function.js rename to packages/backend/src/migration/1658656633972-note-replies-function.ts index 810e238439..eab330a08d 100644 --- a/packages/backend/migration/1658656633972-note-replies-function.js +++ b/packages/backend/src/migration/1658656633972-note-replies-function.ts @@ -1,7 +1,7 @@ -export class noteRepliesFunction1658656633972 { - name = "noteRepliesFunction1658656633972"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class noteRepliesFunction1658656633972 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` CREATE OR REPLACE FUNCTION note_replies(start_id varchar, max_depth integer, max_breadth integer) RETURNS TABLE (id VARCHAR) AS $$ @@ -46,7 +46,7 @@ export class noteRepliesFunction1658656633972 { `); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP FUNCTION note_replies`); } } diff --git a/packages/backend/src/migration/1658939464003CustomMOTD.ts b/packages/backend/src/migration/1658939464003CustomMOTD.ts new file mode 100644 index 0000000000..e3247a274e --- /dev/null +++ b/packages/backend/src/migration/1658939464003CustomMOTD.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CustomMOTD1658939464003 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "customMOTD" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "customMOTD"`); + } +} diff --git a/packages/backend/src/migration/1658941974648CustomSplashIcons.ts b/packages/backend/src/migration/1658941974648CustomSplashIcons.ts new file mode 100644 index 0000000000..43ddaf281d --- /dev/null +++ b/packages/backend/src/migration/1658941974648CustomSplashIcons.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CustomSplashIcons1658941974648 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "customSplashIcons" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "customSplashIcons"`, + ); + } +} diff --git a/packages/backend/migration/1658981842728FixCalckey.js b/packages/backend/src/migration/1658981842728FixCalckey.ts similarity index 73% rename from packages/backend/migration/1658981842728FixCalckey.js rename to packages/backend/src/migration/1658981842728FixCalckey.ts index 96dfd77ac3..cac88cd7dd 100644 --- a/packages/backend/migration/1658981842728FixCalckey.js +++ b/packages/backend/src/migration/1658981842728FixCalckey.ts @@ -1,7 +1,7 @@ -export class FixFirefish1658981842728 { - name = "FixFirefish1658981842728"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class FixFirefish1658981842728 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE "meta" SET "useStarForReactionFallback" = TRUE;`, ); @@ -13,7 +13,7 @@ export class FixFirefish1658981842728 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE "meta" SET "useStarForReactionFallback" = FALSE;`, ); diff --git a/packages/backend/migration/1659042130648RecommendedTimeline.js b/packages/backend/src/migration/1659042130648RecommendedTimeline.ts similarity index 65% rename from packages/backend/migration/1659042130648RecommendedTimeline.js rename to packages/backend/src/migration/1659042130648RecommendedTimeline.ts index 01d28b2f38..6a0b9140e5 100644 --- a/packages/backend/migration/1659042130648RecommendedTimeline.js +++ b/packages/backend/src/migration/1659042130648RecommendedTimeline.ts @@ -1,6 +1,7 @@ -export class RecommendedTimeline1659042130648 { - name = "RecommendedTimeline1659042130648"; - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RecommendedTimeline1659042130648 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "disableRecommendedTimeline" boolean NOT NULL DEFAULT true`, ); @@ -8,7 +9,7 @@ export class RecommendedTimeline1659042130648 { `ALTER TABLE "meta" ADD "recommendedInstances" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "disableRecommendedTimeline"`, ); diff --git a/packages/backend/src/migration/1660068273737GuestTimeline.ts b/packages/backend/src/migration/1660068273737GuestTimeline.ts new file mode 100644 index 0000000000..4f6ddeb770 --- /dev/null +++ b/packages/backend/src/migration/1660068273737GuestTimeline.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class GuestTimeline1660068273737 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "enableGuestTimeline" boolean NOT NULL DEFAULT false`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "enableGuestTimeline"`, + ); + } +} diff --git a/packages/backend/migration/1665091090561-add-renote-muting.js b/packages/backend/src/migration/1665091090561-add-renote-muting.ts similarity index 71% rename from packages/backend/migration/1665091090561-add-renote-muting.js rename to packages/backend/src/migration/1665091090561-add-renote-muting.ts index 2c76aaff5f..f6787639dc 100644 --- a/packages/backend/migration/1665091090561-add-renote-muting.js +++ b/packages/backend/src/migration/1665091090561-add-renote-muting.ts @@ -1,9 +1,7 @@ -export class addRenoteMuting1665091090561 { - constructor() { - this.name = "addRenoteMuting1665091090561"; - } +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class addRenoteMuting1665091090561 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "renote_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_renoteMuting_id" PRIMARY KEY ("id"))`, ); @@ -18,5 +16,5 @@ export class addRenoteMuting1665091090561 { ); } - async down(queryRunner) {} + async down(queryRunner: QueryRunner): Promise {} } diff --git a/packages/backend/src/migration/1668828368510PageDraft.ts b/packages/backend/src/migration/1668828368510PageDraft.ts new file mode 100644 index 0000000000..265e4d68ae --- /dev/null +++ b/packages/backend/src/migration/1668828368510PageDraft.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Page1668828368510 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "page" ADD "isPublic" boolean NOT NULL DEFAULT true`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "isPublic"`); + } +} diff --git a/packages/backend/src/migration/1668831378728FixCalckeyAgain.ts b/packages/backend/src/migration/1668831378728FixCalckeyAgain.ts new file mode 100644 index 0000000000..0f127e9244 --- /dev/null +++ b/packages/backend/src/migration/1668831378728FixCalckeyAgain.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class FixFirefishAgain1668831378728 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `UPDATE "meta" SET "useStarForReactionFallback" = TRUE`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `UPDATE "meta" SET "useStarForReactionFallback" = FALSE`, + ); + } +} diff --git a/packages/backend/src/migration/1669138716634-whetherPushNotifyToSendReadMessage.ts b/packages/backend/src/migration/1669138716634-whetherPushNotifyToSendReadMessage.ts new file mode 100644 index 0000000000..38c7a31b85 --- /dev/null +++ b/packages/backend/src/migration/1669138716634-whetherPushNotifyToSendReadMessage.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class whetherPushNotifyToSendReadMessage1669138716634 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "sw_subscription" ADD "sendReadMessage" boolean NOT NULL DEFAULT false`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "sw_subscription" DROP COLUMN "sendReadMessage"`, + ); + } +} diff --git a/packages/backend/migration/1669288094000-AddMovedToAndKnownAs.js b/packages/backend/src/migration/1669288094000-AddMovedToAndKnownAs.ts similarity index 69% rename from packages/backend/migration/1669288094000-AddMovedToAndKnownAs.js rename to packages/backend/src/migration/1669288094000-AddMovedToAndKnownAs.ts index c34764e0b0..3bdc26b4c9 100644 --- a/packages/backend/migration/1669288094000-AddMovedToAndKnownAs.js +++ b/packages/backend/src/migration/1669288094000-AddMovedToAndKnownAs.ts @@ -1,7 +1,7 @@ -export class addMovedToAndKnownAs1669288094000 { - name = "addMovedToAndKnownAs1669288094000"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class addMovedToAndKnownAs1669288094000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user" ADD "movedToUri" character varying(512)`, ); @@ -14,7 +14,7 @@ export class addMovedToAndKnownAs1669288094000 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "movedToUri"`); await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "alsoKnownAs"`); } diff --git a/packages/backend/migration/1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.js b/packages/backend/src/migration/1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.ts similarity index 72% rename from packages/backend/migration/1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.js rename to packages/backend/src/migration/1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.ts index 96ed8e1d6b..26424d9c28 100644 --- a/packages/backend/migration/1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.js +++ b/packages/backend/src/migration/1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.ts @@ -1,7 +1,9 @@ -export class addFkAbuseUserReportTargetUserIdToUserId1671199573000 { - name = "addFkAbuseUserReportTargetUserIdToUserId1671199573000"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class addFkAbuseUserReportTargetUserIdToUserId1671199573000 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `DELETE FROM abuse_user_report WHERE NOT EXISTS (SELECT 1 FROM "user" WHERE "user"."id" = "abuse_user_report"."targetUserId")`, ); @@ -10,7 +12,7 @@ export class addFkAbuseUserReportTargetUserIdToUserId1671199573000 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE abuse_user_report DROP CONSTRAINT fk_7f4e851a35d81b64dda28eee0`, ); diff --git a/packages/backend/migration/1671388343000-CalckeyRepoMove.js b/packages/backend/src/migration/1671388343000-CalckeyRepoMove.ts similarity index 70% rename from packages/backend/migration/1671388343000-CalckeyRepoMove.js rename to packages/backend/src/migration/1671388343000-CalckeyRepoMove.ts index e11ddcb435..baf23963c4 100644 --- a/packages/backend/migration/1671388343000-CalckeyRepoMove.js +++ b/packages/backend/src/migration/1671388343000-CalckeyRepoMove.ts @@ -1,9 +1,9 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + /* "FirefishRepoMove1671388343000" is a class that updates the "useStarForReactionFallback" column in the "meta" table to TRUE */ -export class FirefishRepoMove1671388343000 { - name = "FirefishRepoMove1671388343000"; - - async up(queryRunner) { +export class FirefishRepoMove1671388343000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg/firefish/firefish'`, ); @@ -12,7 +12,7 @@ export class FirefishRepoMove1671388343000 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg/firefish/firefish'`, ); diff --git a/packages/backend/migration/1672882664294-DefaultReaction.js b/packages/backend/src/migration/1672882664294-DefaultReaction.ts similarity index 58% rename from packages/backend/migration/1672882664294-DefaultReaction.js rename to packages/backend/src/migration/1672882664294-DefaultReaction.ts index 6ce1146ecb..7874e571ef 100644 --- a/packages/backend/migration/1672882664294-DefaultReaction.js +++ b/packages/backend/src/migration/1672882664294-DefaultReaction.ts @@ -1,7 +1,7 @@ -export class DefaultReaction1672882664294 { - name = "DefaultReaction1672882664294"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class DefaultReaction1672882664294 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "defaultReaction" character varying(256) NOT NULL DEFAULT '⭐'`, ); @@ -10,7 +10,7 @@ export class DefaultReaction1672882664294 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultReaction"`); } } diff --git a/packages/backend/src/migration/1673336077243-PollChoiceLength.ts b/packages/backend/src/migration/1673336077243-PollChoiceLength.ts new file mode 100644 index 0000000000..5f5ffd722a --- /dev/null +++ b/packages/backend/src/migration/1673336077243-PollChoiceLength.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PollChoiceLength1673336077243 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(256) array`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(128) array`, + ); + } +} diff --git a/packages/backend/migration/1676093997212-AntennaInstances.js b/packages/backend/src/migration/1676093997212-AntennaInstances.ts similarity index 77% rename from packages/backend/migration/1676093997212-AntennaInstances.js rename to packages/backend/src/migration/1676093997212-AntennaInstances.ts index ffd428f7dc..63ac5ae29b 100644 --- a/packages/backend/migration/1676093997212-AntennaInstances.js +++ b/packages/backend/src/migration/1676093997212-AntennaInstances.ts @@ -1,7 +1,7 @@ -export class AntennaInstances1676093997212 { - name = "AntennaInstances1676093997212"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class AntennaInstances1676093997212 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TYPE "antenna_src_enum" ADD VALUE 'instances'`, ); @@ -10,7 +10,7 @@ export class AntennaInstances1676093997212 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DELETE FROM "antenna" WHERE "src" = 'instances'`); await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "instances"`); await queryRunner.query( diff --git a/packages/backend/src/migration/1677935903517-DriveComment.ts b/packages/backend/src/migration/1677935903517-DriveComment.ts new file mode 100644 index 0000000000..97d4bc4edf --- /dev/null +++ b/packages/backend/src/migration/1677935903517-DriveComment.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class DriveComment1677935903517 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(8192)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(512)`, + ); + } +} diff --git a/packages/backend/migration/1678426061773-tweak-varchar-length.js b/packages/backend/src/migration/1678426061773-tweak-varchar-length.ts similarity index 51% rename from packages/backend/migration/1678426061773-tweak-varchar-length.js rename to packages/backend/src/migration/1678426061773-tweak-varchar-length.ts index 00ddcaebea..dc20555723 100644 --- a/packages/backend/migration/1678426061773-tweak-varchar-length.js +++ b/packages/backend/src/migration/1678426061773-tweak-varchar-length.ts @@ -1,7 +1,7 @@ -export class tweakVarcharLength1678426061773 { - name = "tweakVarcharLength1678426061773"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class tweakVarcharLength1678426061773 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ALTER COLUMN "smtpUser" TYPE character varying(1024)`, undefined, @@ -12,5 +12,5 @@ export class tweakVarcharLength1678426061773 { ); } - async down(queryRunner) {} + async down(queryRunner: QueryRunner): Promise {} } diff --git a/packages/backend/src/migration/1678945242650-add-props-for-custom-emoji.ts b/packages/backend/src/migration/1678945242650-add-props-for-custom-emoji.ts new file mode 100644 index 0000000000..209dcbed70 --- /dev/null +++ b/packages/backend/src/migration/1678945242650-add-props-for-custom-emoji.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class addPropsForCustomEmoji1678945242650 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "emoji" ADD "license" character varying(1024)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "license"`); + } +} diff --git a/packages/backend/migration/1679269929000-fix-repo.js b/packages/backend/src/migration/1679269929000-fix-repo.ts similarity index 66% rename from packages/backend/migration/1679269929000-fix-repo.js rename to packages/backend/src/migration/1679269929000-fix-repo.ts index 2abcd71bb9..7c462bf626 100644 --- a/packages/backend/migration/1679269929000-fix-repo.js +++ b/packages/backend/src/migration/1679269929000-fix-repo.ts @@ -1,7 +1,7 @@ -export class FixRepo1679269929000 { - name = "FixRepo1679269929000"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class FixRepo1679269929000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg.org/firefish/firefish'`, ); @@ -10,7 +10,7 @@ export class FixRepo1679269929000 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg.org/firefish/firefish'`, ); diff --git a/packages/backend/migration/1680375641101-clean-charts.js b/packages/backend/src/migration/1680375641101-clean-charts.ts similarity index 73% rename from packages/backend/migration/1680375641101-clean-charts.js rename to packages/backend/src/migration/1680375641101-clean-charts.ts index bfb8aa9d92..9bc1356dcc 100644 --- a/packages/backend/migration/1680375641101-clean-charts.js +++ b/packages/backend/src/migration/1680375641101-clean-charts.ts @@ -1,8 +1,7 @@ -export class CleanCharts1680375641101 { - constructor() { - this.name = "CleanCharts1680375641101"; - } - async up(queryRunner) { +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CleanCharts1680375641101 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `delete from __chart__hashtag where ___local_users = 0 and ___remote_users = 0;`, ); @@ -14,7 +13,7 @@ export class CleanCharts1680375641101 { await queryRunner.query(`vacuum __chart_day__hashtag;`); await queryRunner.query(`COMMIT;`); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `delete from __chart__hashtag where ___local_users = 0 and ___remote_users = 0;`, ); diff --git a/packages/backend/migration/1680426269172-SpeakAsCat.js b/packages/backend/src/migration/1680426269172-SpeakAsCat.ts similarity index 61% rename from packages/backend/migration/1680426269172-SpeakAsCat.js rename to packages/backend/src/migration/1680426269172-SpeakAsCat.ts index 375098542c..24700fe44f 100644 --- a/packages/backend/migration/1680426269172-SpeakAsCat.js +++ b/packages/backend/src/migration/1680426269172-SpeakAsCat.ts @@ -1,7 +1,7 @@ -export class SpeakAsCat1680426269172 { - name = "SpeakAsCat1680426269172"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class SpeakAsCat1680426269172 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE "user" ADD "speakAsCat" boolean NOT NULL DEFAULT true @@ -12,7 +12,7 @@ export class SpeakAsCat1680426269172 { `); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE "user" DROP COLUMN "speakAsCat" `); diff --git a/packages/backend/migration/1682753227899-NoteEdit.js b/packages/backend/src/migration/1682753227899-NoteEdit.ts similarity index 85% rename from packages/backend/migration/1682753227899-NoteEdit.js rename to packages/backend/src/migration/1682753227899-NoteEdit.ts index 55a0de0206..6dae4efbdb 100644 --- a/packages/backend/migration/1682753227899-NoteEdit.js +++ b/packages/backend/src/migration/1682753227899-NoteEdit.ts @@ -1,7 +1,7 @@ -export class NoteEdit1682753227899 { - name = "NoteEdit1682753227899"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class NoteEdit1682753227899 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` CREATE TABLE "note_edit" ( "id" character varying(32) NOT NULL, @@ -39,7 +39,7 @@ export class NoteEdit1682753227899 { `); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE "note_edit" DROP CONSTRAINT "FK_702ad5ae993a672e4fbffbcd38c" `); diff --git a/packages/backend/migration/1682777547198-LibreTranslate.js b/packages/backend/src/migration/1682777547198-LibreTranslate.ts similarity index 63% rename from packages/backend/migration/1682777547198-LibreTranslate.js rename to packages/backend/src/migration/1682777547198-LibreTranslate.ts index dbaf483e6c..c8b66f0d9e 100644 --- a/packages/backend/migration/1682777547198-LibreTranslate.js +++ b/packages/backend/src/migration/1682777547198-LibreTranslate.ts @@ -1,7 +1,7 @@ -export class LibreTranslate1682777547198 { - name = "LibreTranslate1682777547198"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class LibreTranslate1682777547198 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE "meta" ADD "libreTranslateApiUrl" character varying(512) @@ -12,7 +12,7 @@ export class LibreTranslate1682777547198 { `); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE "meta" DROP COLUMN "libreTranslateApiKey" `); diff --git a/packages/backend/src/migration/1682891890317-InstanceSilence.ts b/packages/backend/src/migration/1682891890317-InstanceSilence.ts new file mode 100644 index 0000000000..ef36ad560d --- /dev/null +++ b/packages/backend/src/migration/1682891890317-InstanceSilence.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class InstanceSilence1682891890317 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "silencedHosts" character varying(256) array NOT NULL DEFAULT '{}'`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "silencedHosts"`); + } +} diff --git a/packages/backend/src/migration/1682891891317-AddHiddenPosts.ts b/packages/backend/src/migration/1682891891317-AddHiddenPosts.ts new file mode 100644 index 0000000000..f7f09ba44f --- /dev/null +++ b/packages/backend/src/migration/1682891891317-AddHiddenPosts.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddHiddenPosts1682891891317 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TYPE note_visibility_enum ADD VALUE IF NOT EXISTS 'hidden'`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TYPE note_visibility_enum REMOVE VALUE IF EXISTS 'hidden'`, + ); + } +} diff --git a/packages/backend/src/migration/1683682889948-PreventAiLearning.ts b/packages/backend/src/migration/1683682889948-PreventAiLearning.ts new file mode 100644 index 0000000000..3123715b28 --- /dev/null +++ b/packages/backend/src/migration/1683682889948-PreventAiLearning.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class PreventAiLearning1683682889948 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "preventAiLearning" boolean NOT NULL DEFAULT true`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" DROP COLUMN "preventAiLearning"`, + ); + } +} diff --git a/packages/backend/src/migration/1683980686995-ExperimentalFeatures.ts b/packages/backend/src/migration/1683980686995-ExperimentalFeatures.ts new file mode 100644 index 0000000000..b03408a00e --- /dev/null +++ b/packages/backend/src/migration/1683980686995-ExperimentalFeatures.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ExperimentalFeatures1683980686995 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "meta" + ADD "experimentalFeatures" jsonb NOT NULL DEFAULT '{}' + `); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "meta" DROP COLUMN "experimentalFeatures" + `); + } +} diff --git a/packages/backend/src/migration/1684206886988-remove-showTimelineReplies.ts b/packages/backend/src/migration/1684206886988-remove-showTimelineReplies.ts new file mode 100644 index 0000000000..f156f41707 --- /dev/null +++ b/packages/backend/src/migration/1684206886988-remove-showTimelineReplies.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RemoveShowTimelineReplies1684206886988 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" ADD "showTimelineReplies" boolean NOT NULL DEFAULT false`, + ); + } +} diff --git a/packages/backend/migration/1684494870830-EmojiSize.js b/packages/backend/src/migration/1684494870830-EmojiSize.ts similarity index 66% rename from packages/backend/migration/1684494870830-EmojiSize.js rename to packages/backend/src/migration/1684494870830-EmojiSize.ts index 6d42f1a614..987b7b77e2 100644 --- a/packages/backend/migration/1684494870830-EmojiSize.js +++ b/packages/backend/src/migration/1684494870830-EmojiSize.ts @@ -1,7 +1,7 @@ -export class EmojiSize1684494870830 { - name = "EmojiSize1684494870830"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class EmojiSize1684494870830 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "emoji" ADD "width" integer`); await queryRunner.query( `COMMENT ON COLUMN "emoji"."width" IS 'Image width'`, @@ -12,7 +12,7 @@ export class EmojiSize1684494870830 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "height"`); await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "width"`); } diff --git a/packages/backend/migration/1688280713783-add-meta-options.js b/packages/backend/src/migration/1688280713783-add-meta-options.ts similarity index 64% rename from packages/backend/migration/1688280713783-add-meta-options.js rename to packages/backend/src/migration/1688280713783-add-meta-options.ts index e97a95c423..c058b7dcc4 100644 --- a/packages/backend/migration/1688280713783-add-meta-options.js +++ b/packages/backend/src/migration/1688280713783-add-meta-options.ts @@ -1,7 +1,7 @@ -export class AddMetaOptions1688280713783 { - name = "AddMetaOptions1688280713783"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class AddMetaOptions1688280713783 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ADD "enableServerMachineStats" boolean NOT NULL DEFAULT false`, ); @@ -10,7 +10,7 @@ export class AddMetaOptions1688280713783 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" DROP COLUMN "enableIdenticonGeneration"`, ); diff --git a/packages/backend/migration/1688845537045-announcement-popup.js b/packages/backend/src/migration/1688845537045-announcement-popup.ts similarity index 63% rename from packages/backend/migration/1688845537045-announcement-popup.js rename to packages/backend/src/migration/1688845537045-announcement-popup.ts index 196590d3e3..c035051864 100644 --- a/packages/backend/migration/1688845537045-announcement-popup.js +++ b/packages/backend/src/migration/1688845537045-announcement-popup.ts @@ -1,7 +1,7 @@ -export class AnnouncementPopup1688845537045 { - name = "AnnouncementPopup1688845537045"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class AnnouncementPopup1688845537045 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement" ADD "showPopup" boolean NOT NULL DEFAULT false`, ); @@ -10,7 +10,7 @@ export class AnnouncementPopup1688845537045 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "announcement" DROP COLUMN "isGoodNews"`, ); diff --git a/packages/backend/src/migration/1689136347561-donation-link.ts b/packages/backend/src/migration/1689136347561-donation-link.ts new file mode 100644 index 0000000000..1abfa8e341 --- /dev/null +++ b/packages/backend/src/migration/1689136347561-donation-link.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class DonationLink1689136347561 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "donationLink" character varying(256)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "DonationLink1689136347561"`, + ); + } +} diff --git a/packages/backend/migration/1689739513827-firefish-repo.js b/packages/backend/src/migration/1689739513827-firefish-repo.ts similarity index 67% rename from packages/backend/migration/1689739513827-firefish-repo.js rename to packages/backend/src/migration/1689739513827-firefish-repo.ts index d2491f2139..dd34bcf183 100644 --- a/packages/backend/migration/1689739513827-firefish-repo.js +++ b/packages/backend/src/migration/1689739513827-firefish-repo.ts @@ -1,7 +1,7 @@ -export class FirefishRepo1689739513827 { - name = "FirefishRepo1689739513827"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class FirefishRepo1689739513827 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg.org/firefish/firefish'`, ); @@ -10,7 +10,7 @@ export class FirefishRepo1689739513827 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg.org/calckey/calckey'`, ); diff --git a/packages/backend/migration/1689957674000-firefish-repo.js b/packages/backend/src/migration/1689957674000-firefish-repo.ts similarity index 67% rename from packages/backend/migration/1689957674000-firefish-repo.js rename to packages/backend/src/migration/1689957674000-firefish-repo.ts index fb45538ddf..5ae1543f14 100644 --- a/packages/backend/migration/1689957674000-firefish-repo.js +++ b/packages/backend/src/migration/1689957674000-firefish-repo.ts @@ -1,7 +1,7 @@ -export class FirefishRepo1689957674000 { - name = "FirefishRepo1689957674000"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class FirefishRepo1689957674000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://git.joinfirefish.org/firefish/firefish'`, ); @@ -10,7 +10,7 @@ export class FirefishRepo1689957674000 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://codeberg.org/firefish/firefish'`, ); diff --git a/packages/backend/migration/1692374635734-IncreaseHostCharLimit.js b/packages/backend/src/migration/1692374635734-IncreaseHostCharLimit.ts similarity index 94% rename from packages/backend/migration/1692374635734-IncreaseHostCharLimit.js rename to packages/backend/src/migration/1692374635734-IncreaseHostCharLimit.ts index feb0d18a63..e4fe5cdc64 100644 --- a/packages/backend/migration/1692374635734-IncreaseHostCharLimit.js +++ b/packages/backend/src/migration/1692374635734-IncreaseHostCharLimit.ts @@ -1,7 +1,7 @@ -export class IncreaseHostCharLimit1692374635734 { - name = "IncreaseHostCharLimit1692374635734"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class IncreaseHostCharLimit1692374635734 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "drive_file" ALTER COLUMN "userHost" TYPE character varying(512)`, ); @@ -59,7 +59,7 @@ export class IncreaseHostCharLimit1692374635734 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "drive_file" ALTER COLUMN "userHost" TYPE character varying(128)`, ); diff --git a/packages/backend/migration/1692825433698-emoji-moderator.js b/packages/backend/src/migration/1692825433698-emoji-moderator.ts similarity index 64% rename from packages/backend/migration/1692825433698-emoji-moderator.js rename to packages/backend/src/migration/1692825433698-emoji-moderator.ts index 95ece9cbf1..d5d405e536 100644 --- a/packages/backend/migration/1692825433698-emoji-moderator.js +++ b/packages/backend/src/migration/1692825433698-emoji-moderator.ts @@ -1,7 +1,7 @@ -export class EmojiModerator1692825433698 { - name = "EmojiModerator1692825433698"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class EmojiModerator1692825433698 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TYPE "public"."user_emojimodperm_enum" AS ENUM('unauthorized', 'add', 'mod', 'full')`, ); @@ -10,7 +10,7 @@ export class EmojiModerator1692825433698 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "emojiModPerm"`); await queryRunner.query(`DROP TYPE "public"."user_emojimodperm_enum"`); } diff --git a/packages/backend/src/migration/1695334243217-add-post-lang.ts b/packages/backend/src/migration/1695334243217-add-post-lang.ts new file mode 100644 index 0000000000..df861e7639 --- /dev/null +++ b/packages/backend/src/migration/1695334243217-add-post-lang.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddPostLang1695334243217 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "note" ADD "lang" character varying(10)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "lang"`); + } +} diff --git a/packages/backend/src/migration/1698420787202-pgroonga.ts b/packages/backend/src/migration/1698420787202-pgroonga.ts new file mode 100644 index 0000000000..703872c1c4 --- /dev/null +++ b/packages/backend/src/migration/1698420787202-pgroonga.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Pgroonga1698420787202 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_f27f5d88941e57442be75ba9c8" ON "note" USING "pgroonga" ("text")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_065d4d8f3b5adb4a08841eae3c" ON "user" USING "pgroonga" ("name" pgroonga_varchar_full_text_search_ops_v2)`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_fcb770976ff8240af5799e3ffc" ON "user_profile" USING "pgroonga" ("description" pgroonga_varchar_full_text_search_ops_v2) `, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_fcb770976ff8240af5799e3ffc"`); + await queryRunner.query(`DROP INDEX "IDX_065d4d8f3b5adb4a08841eae3c"`); + await queryRunner.query(`DROP INDEX "IDX_f27f5d88941e57442be75ba9c8"`); + } +} diff --git a/packages/backend/src/migration/1699305365258-more-urls.ts b/packages/backend/src/migration/1699305365258-more-urls.ts new file mode 100644 index 0000000000..2fe2704126 --- /dev/null +++ b/packages/backend/src/migration/1699305365258-more-urls.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class MoreUrls1699305365258 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + queryRunner.query( + `ALTER TABLE "meta" ADD "moreUrls" jsonb NOT NULL DEFAULT '[]'`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "moreUrls"`); + } +} diff --git a/packages/backend/migration/1704851359889-add-reply-muting.js b/packages/backend/src/migration/1704851359889-add-reply-muting.ts similarity index 73% rename from packages/backend/migration/1704851359889-add-reply-muting.js rename to packages/backend/src/migration/1704851359889-add-reply-muting.ts index 65086a2a93..3db5da32de 100644 --- a/packages/backend/migration/1704851359889-add-reply-muting.js +++ b/packages/backend/src/migration/1704851359889-add-reply-muting.ts @@ -1,7 +1,7 @@ -export class AddReplyMuting1704851359889 { - name = "AddReplyMuting1704851359889"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class AddReplyMuting1704851359889 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE "reply_muting" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "muteeId" character varying(32) NOT NULL, "muterId" character varying(32) NOT NULL, CONSTRAINT "PK_replyMuting_id" PRIMARY KEY ("id"))`, ); @@ -15,7 +15,7 @@ export class AddReplyMuting1704851359889 { `CREATE INDEX "IDX_reply_muting_muterId" ON "muting" ("muterId")`, ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP TABLE "reply_muting"`); } } diff --git a/packages/backend/migration/1705848938166-remove-nsfw-detection.js b/packages/backend/src/migration/1705848938166-remove-nsfw-detection.ts similarity index 90% rename from packages/backend/migration/1705848938166-remove-nsfw-detection.js rename to packages/backend/src/migration/1705848938166-remove-nsfw-detection.ts index 3ba837104b..c150b4b10d 100644 --- a/packages/backend/migration/1705848938166-remove-nsfw-detection.js +++ b/packages/backend/src/migration/1705848938166-remove-nsfw-detection.ts @@ -1,7 +1,7 @@ -export class RemoveNsfwDetection1705848938166 { - name = "RemoveNsfwDetection1705848938166"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class RemoveNsfwDetection1705848938166 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "drive_file" DROP COLUMN "maybeSensitive"`, ); @@ -29,7 +29,7 @@ export class RemoveNsfwDetection1705848938166 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ADD "autoSensitive" boolean NOT NULL DEFAULT false`, ); diff --git a/packages/backend/migration/1705877093218-remove-native-utils-migration.js b/packages/backend/src/migration/1705877093218-remove-native-utils-migration.ts similarity index 82% rename from packages/backend/migration/1705877093218-remove-native-utils-migration.js rename to packages/backend/src/migration/1705877093218-remove-native-utils-migration.ts index bf6bec01b0..a155a4ff78 100644 --- a/packages/backend/migration/1705877093218-remove-native-utils-migration.js +++ b/packages/backend/src/migration/1705877093218-remove-native-utils-migration.ts @@ -1,11 +1,13 @@ -export class RemoveNativeUtilsMigration1705877093218 { - name = "RemoveNativeUtilsMigration1705877093218"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class RemoveNativeUtilsMigration1705877093218 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP TABLE IF EXISTS "reversi_game"`); await queryRunner.query(`DROP TABLE IF EXISTS "reversi_matching"`); await queryRunner.query( - `CREATE INDEX IF NOT EXISTS "IDX_note_url" ON "note" ("text")`, + `CREATE INDEX IF NOT EXISTS "IDX_note_url" ON "note" ("url")`, ); await queryRunner.query(`DROP TABLE IF EXISTS "antenna_note"`); await queryRunner.query( @@ -47,7 +49,7 @@ export class RemoveNativeUtilsMigration1705877093218 { await queryRunner.query(`DROP TABLE IF EXISTS "seaql_migrations"`); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `CREATE TABLE IF NOT EXISTS "seaql_migrations" (version character varying NOT NULL, applied_at bigint NOT NULL)`, ); @@ -103,10 +105,10 @@ export class RemoveNativeUtilsMigration1705877093218 { `CREATE INDEX "IDX_9937ea48d7ae97ffb4f3f063a4" ON "antenna_note" ("read")`, ); await queryRunner.query( - `ALTER TABLE "antenna_note" ADD CONSTRAINT IF NOT EXISTS "FK_0d775946662d2575dfd2068a5f5" FOREIGN KEY ("antennaId") REFERENCES "antenna"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "antenna_note" ADD CONSTRAINT "FK_0d775946662d2575dfd2068a5f5" FOREIGN KEY ("antennaId") REFERENCES "antenna"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( - `ALTER TABLE "antenna_note" ADD CONSTRAINT IF NOT EXISTS "FK_bd0397be22147e17210940e125b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "antenna_note" ADD CONSTRAINT "FK_bd0397be22147e17210940e125b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query(`DROP INDEX IF EXISTS "IDX_note_url"`); await queryRunner.query( @@ -122,10 +124,10 @@ export class RemoveNativeUtilsMigration1705877093218 { `CREATE INDEX IF NOT EXISTS "IDX_e247b23a3c9b45f89ec1299d06" ON "reversi_matching" ("childId")`, ); await queryRunner.query( - `ALTER TABLE "reversi_matching" ADD CONSTRAINT IF NOT EXISTS "FK_3b25402709dd9882048c2bbade0" FOREIGN KEY ("parentId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "reversi_matching" ADD CONSTRAINT "FK_3b25402709dd9882048c2bbade0" FOREIGN KEY ("parentId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( - `ALTER TABLE "reversi_matching" ADD CONSTRAINT IF NOT EXISTS "FK_e247b23a3c9b45f89ec1299d066" FOREIGN KEY ("childId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "reversi_matching" ADD CONSTRAINT "FK_e247b23a3c9b45f89ec1299d066" FOREIGN KEY ("childId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( `COMMENT ON COLUMN "reversi_matching"."createdAt" IS 'The created date of the ReversiMatching.'`, @@ -137,10 +139,10 @@ export class RemoveNativeUtilsMigration1705877093218 { `CREATE INDEX IF NOT EXISTS "IDX_b46ec40746efceac604142be1c" ON "reversi_game" ("createdAt")`, ); await queryRunner.query( - `ALTER TABLE "reversi_game" ADD CONSTRAINT IF NOT EXISTS "FK_f7467510c60a45ce5aca6292743" FOREIGN KEY ("user1Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "reversi_game" ADD CONSTRAINT "FK_f7467510c60a45ce5aca6292743" FOREIGN KEY ("user1Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( - `ALTER TABLE "reversi_game" ADD CONSTRAINT IF NOT EXISTS "FK_6649a4e8c5d5cf32fb03b5da9f6" FOREIGN KEY ("user2Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "reversi_game" ADD CONSTRAINT "FK_6649a4e8c5d5cf32fb03b5da9f6" FOREIGN KEY ("user2Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( `COMMENT ON COLUMN "reversi_game"."createdAt" IS 'The created date of the ReversiGame.'`, diff --git a/packages/backend/src/migration/1705944717480-rename-meta-columns.ts b/packages/backend/src/migration/1705944717480-rename-meta-columns.ts new file mode 100644 index 0000000000..b73bebe8e6 --- /dev/null +++ b/packages/backend/src/migration/1705944717480-rename-meta-columns.ts @@ -0,0 +1,27 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RenameMetaColumns1705944717480 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" RENAME COLUMN "customMOTD" TO "customMotd"`, + ); + await queryRunner.query( + `ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSSL" TO "objectStorageUseSsl"`, + ); + await queryRunner.query( + `ALTER TABLE "meta" RENAME COLUMN "ToSUrl" TO "tosUrl"`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" RENAME COLUMN "tosUrl" TO "ToSUrl"`, + ); + await queryRunner.query( + `ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSsl" TO "objectStorageUseSSL"`, + ); + await queryRunner.query( + `ALTER TABLE "meta" RENAME COLUMN "customMotd" TO "customMOTD"`, + ); + } +} diff --git a/packages/backend/src/migration/1706413792769-separate-hard-mute-words-and-patterns.ts b/packages/backend/src/migration/1706413792769-separate-hard-mute-words-and-patterns.ts new file mode 100644 index 0000000000..d2506616f7 --- /dev/null +++ b/packages/backend/src/migration/1706413792769-separate-hard-mute-words-and-patterns.ts @@ -0,0 +1,34 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class SeparateHardMuteWordsAndPatterns1706413792769 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD "mutedPatterns" text[] DEFAULT '{}'`, + ); + await queryRunner.query(` + UPDATE "user_profile" SET + "mutedPatterns" = ARRAY( + SELECT jsonb_array_elements_text(jsonb_path_query_array( + "mutedWords", + '$ ? (@.type() == "string")' + )) + ), + "mutedWords" = jsonb_path_query_array( + "mutedWords", + '$ ? (@.type() == "array")' + ) + `); + await queryRunner.query( + `ALTER TABLE "user_profile" ALTER "mutedPatterns" SET NOT NULL`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `UPDATE "user_profile" SET "mutedWords" = "mutedWords" || array_to_json("mutedPatterns")::jsonb`, + ); + await queryRunner.query(`ALTER TABLE "user_profile" DROP "mutedPatterns"`); + } +} diff --git a/packages/backend/migration/1707850084123-firefish-url-move.js b/packages/backend/src/migration/1707850084123-firefish-url-move.ts similarity index 66% rename from packages/backend/migration/1707850084123-firefish-url-move.js rename to packages/backend/src/migration/1707850084123-firefish-url-move.ts index c3b694eb7e..a9621ab392 100644 --- a/packages/backend/migration/1707850084123-firefish-url-move.js +++ b/packages/backend/src/migration/1707850084123-firefish-url-move.ts @@ -1,7 +1,7 @@ -export class FirefishUrlMove1707850084123 { - name = "FirefishUrlMove1707850084123"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class FirefishUrlMove1707850084123 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://firefish.dev/firefish/firefish'`, ); @@ -10,7 +10,7 @@ export class FirefishUrlMove1707850084123 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `UPDATE meta SET "repositoryUrl" = 'https://git.joinfirefish.org/firefish/firefish'`, ); diff --git a/packages/backend/src/migration/1708452631156-drop-user-profile-language.ts b/packages/backend/src/migration/1708452631156-drop-user-profile-language.ts new file mode 100644 index 0000000000..568542cb67 --- /dev/null +++ b/packages/backend/src/migration/1708452631156-drop-user-profile-language.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class DropUserProfileLanguage1708452631156 + implements MigrationInterface +{ + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD COLUMN "lang" character varying(32)`, + ); + } +} diff --git a/packages/backend/src/migration/1708872574733-index-alt-text-and-cw.ts b/packages/backend/src/migration/1708872574733-index-alt-text-and-cw.ts new file mode 100644 index 0000000000..b8072b717c --- /dev/null +++ b/packages/backend/src/migration/1708872574733-index-alt-text-and-cw.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class IndexAltTextAndCw1708872574733 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f" ON "note" USING "pgroonga" ("cw" pgroonga_varchar_full_text_search_ops_v2)`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_f4f7b93d05958527300d79ac82" ON "drive_file" USING "pgroonga" ("comment" pgroonga_varchar_full_text_search_ops_v2)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_f4f7b93d05958527300d79ac82"`); + await queryRunner.query(`DROP INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f"`); + } +} diff --git a/packages/backend/migration/1709047957489-remove-charts.js b/packages/backend/src/migration/1709047957489-remove-charts.ts similarity index 99% rename from packages/backend/migration/1709047957489-remove-charts.js rename to packages/backend/src/migration/1709047957489-remove-charts.ts index f480b8b4d0..f4d303a574 100644 --- a/packages/backend/migration/1709047957489-remove-charts.js +++ b/packages/backend/src/migration/1709047957489-remove-charts.ts @@ -1,7 +1,7 @@ -export class RemoveCharts1709047957489 { - name = "RemoveCharts1709047957489"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class RemoveCharts1709047957489 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP TABLE "__chart__ap_request" CASCADE`); await queryRunner.query(`DROP TABLE "__chart_day__ap_request" CASCADE`); await queryRunner.query(`DROP TABLE "__chart_day__drive" CASCADE`); @@ -35,7 +35,7 @@ export class RemoveCharts1709047957489 { await queryRunner.query(`DROP TABLE "__chart__users" CASCADE`); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query(` CREATE TABLE public.__chart__ap_request ( id integer NOT NULL, diff --git a/packages/backend/src/migration/1709129810501-fix-note-url-index.ts b/packages/backend/src/migration/1709129810501-fix-note-url-index.ts new file mode 100644 index 0000000000..b59119efa7 --- /dev/null +++ b/packages/backend/src/migration/1709129810501-fix-note-url-index.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class FixNoteUrlIndex1709129810501 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_note_url"`); + await queryRunner.query(`CREATE INDEX "IDX_note_url" ON "note" ("url")`); + } + async down(queryRunner: QueryRunner): Promise { + /* You don't revert this migration */ + } +} diff --git a/packages/backend/migration/1709251460718-change-default-configs.js b/packages/backend/src/migration/1709251460718-change-default-configs.ts similarity index 73% rename from packages/backend/migration/1709251460718-change-default-configs.js rename to packages/backend/src/migration/1709251460718-change-default-configs.ts index 8c50e482be..f9833450fd 100644 --- a/packages/backend/migration/1709251460718-change-default-configs.js +++ b/packages/backend/src/migration/1709251460718-change-default-configs.ts @@ -1,7 +1,7 @@ -export class ChangeDefaultConfigs1709251460718 { - name = "ChangeDefaultConfigs1709251460718"; +import { MigrationInterface, QueryRunner } from "typeorm"; - async up(queryRunner) { +export class ChangeDefaultConfigs1709251460718 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "meta" ALTER COLUMN "disableRegistration" SET DEFAULT true`, ); @@ -13,7 +13,7 @@ export class ChangeDefaultConfigs1709251460718 { ); } - async down(queryRunner) { + async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "user_profile" ALTER COLUMN "noCrawle" SET DEFAULT false`, ); diff --git a/packages/backend/src/migration/1710304584214-note-file.ts b/packages/backend/src/migration/1710304584214-note-file.ts new file mode 100644 index 0000000000..be0458d297 --- /dev/null +++ b/packages/backend/src/migration/1710304584214-note-file.ts @@ -0,0 +1,41 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class NoteFile1710304584214 implements MigrationInterface { + name = "NoteFile1710304584214"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "note_file" ( + "serialNo" bigserial PRIMARY KEY, + "noteId" varchar(32) NOT NULL, + "fileId" varchar(32) NOT NULL + )`, + ); + await queryRunner.query(` + INSERT INTO "note_file" ("noteId", "fileId") + SELECT "t"."id", "t"."fid" FROM ( + SELECT ROW_NUMBER() OVER () AS "rn", * FROM ( + SELECT "id", UNNEST("fileIds") AS "fid" FROM "note" + ) AS "s" + ) AS "t" + INNER JOIN "drive_file" ON "drive_file"."id" = "t"."fid" + ORDER BY "rn" + `); + await queryRunner.query( + `ALTER TABLE "note_file" ADD FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE`, + ); + await queryRunner.query( + `ALTER TABLE "note_file" ADD FOREIGN KEY ("fileId") REFERENCES "drive_file" ("id") ON DELETE CASCADE`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_note_file_noteId" ON "note_file" ("noteId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_note_file_fileId" ON "note_file" ("fileId")`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "note_file"`); + } +} diff --git a/packages/backend/src/migration/1710690239308-fix-muting-indices.ts b/packages/backend/src/migration/1710690239308-fix-muting-indices.ts new file mode 100644 index 0000000000..3dc24c2531 --- /dev/null +++ b/packages/backend/src/migration/1710690239308-fix-muting-indices.ts @@ -0,0 +1,57 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class FixMutingIndices1710690239308 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_renote_muting_createdAt"`); + await queryRunner.query(`DROP INDEX "IDX_renote_muting_muteeId"`); + await queryRunner.query(`DROP INDEX "IDX_renote_muting_muterId"`); + await queryRunner.query(`DROP INDEX "IDX_reply_muting_createdAt"`); + await queryRunner.query(`DROP INDEX "IDX_reply_muting_muteeId"`); + await queryRunner.query(`DROP INDEX "IDX_reply_muting_muterId"`); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_createdAt" ON "renote_muting" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_muteeId" ON "renote_muting" ("muteeId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_muterId" ON "renote_muting" ("muterId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_reply_muting_createdAt" ON "reply_muting" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_reply_muting_muteeId" ON "reply_muting" ("muteeId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_reply_muting_muterId" ON "reply_muting" ("muterId")`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_renote_muting_createdAt"`); + await queryRunner.query(`DROP INDEX "IDX_renote_muting_muteeId"`); + await queryRunner.query(`DROP INDEX "IDX_renote_muting_muterId"`); + await queryRunner.query(`DROP INDEX "IDX_reply_muting_createdAt"`); + await queryRunner.query(`DROP INDEX "IDX_reply_muting_muteeId"`); + await queryRunner.query(`DROP INDEX "IDX_reply_muting_muterId"`); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_createdAt" ON "muting" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_reply_muting_createdAt" ON "muting" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_reply_muting_muteeId" ON "muting" ("muteeId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_reply_muting_muterId" ON "muting" ("muterId")`, + ); + } +} diff --git a/packages/backend/src/misc/check-hit-antenna.ts b/packages/backend/src/misc/check-hit-antenna.ts index 1f4f2f2fae..b93cb459e8 100644 --- a/packages/backend/src/misc/check-hit-antenna.ts +++ b/packages/backend/src/misc/check-hit-antenna.ts @@ -1,15 +1,21 @@ import type { Antenna } from "@/models/entities/antenna.js"; import type { Note } from "@/models/entities/note.js"; import type { User } from "@/models/entities/user.js"; -import { Blockings, UserProfiles } from "@/models/index.js"; +import type { UserProfile } from "@/models/entities/user-profile.js"; +import { Blockings, Followings, UserProfiles } from "@/models/index.js"; import { getFullApAccount } from "@/misc/convert-host.js"; import * as Acct from "@/misc/acct.js"; +import { getWordHardMute } from "@/misc/check-word-mute.js"; import type { Packed } from "@/misc/schema.js"; import { Cache } from "@/misc/cache.js"; -import { getWordHardMute } from "@/misc/check-word-mute.js"; const blockingCache = new Cache("blocking", 60 * 5); -const mutedWordsCache = new Cache("mutedWords", 60 * 5); +const hardMutesCache = new Cache<{ + userId: UserProfile["userId"]; + mutedWords: UserProfile["mutedWords"]; + mutedPatterns: UserProfile["mutedPatterns"]; +}>("hardMutes", 60 * 5); +const followingCache = new Cache("following", 60 * 5); export async function checkHitAntenna( antenna: Antenna, @@ -17,11 +23,10 @@ export async function checkHitAntenna( noteUser: { id: User["id"]; username: string; host: string | null }, ): Promise { if (note.visibility === "specified") return false; - if (note.visibility === "home") return false; - if (!antenna.withReplies && note.replyId != null) return false; if (antenna.withFile) { if (note.fileIds && note.fileIds.length === 0) return false; } + if (!antenna.withReplies && note.replyId != null) return false; if (antenna.src === "users") { const accts = antenna.users.map((x) => { @@ -48,14 +53,19 @@ export async function checkHitAntenna( .map((xs) => xs.filter((x) => x !== "")) .filter((xs) => xs.length > 0); + let text = `${note.text ?? ""} ${note.cw ?? ""}`; + if (note.files != null) + text += ` ${note.files.map((f) => f.comment ?? "").join(" ")}`; + text = text.trim(); + if (keywords.length > 0) { if (note.text == null) return false; const matched = keywords.some((and) => and.every((keyword) => antenna.caseSensitive - ? note.text!.includes(keyword) - : note.text!.toLowerCase().includes(keyword.toLowerCase()), + ? text.includes(keyword) + : text.toLowerCase().includes(keyword.toLowerCase()), ), ); @@ -73,8 +83,8 @@ export async function checkHitAntenna( const matched = excludeKeywords.some((and) => and.every((keyword) => antenna.caseSensitive - ? note.text!.includes(keyword) - : note.text!.toLowerCase().includes(keyword.toLowerCase()), + ? note.text?.includes(keyword) + : note.text?.toLowerCase().includes(keyword.toLowerCase()), ), ); @@ -89,12 +99,34 @@ export async function checkHitAntenna( ); if (blockings.includes(antenna.userId)) return false; - const mutedWords = await mutedWordsCache.fetch(antenna.userId, () => - UserProfiles.findOneBy({ userId: antenna.userId }).then( - (profile) => profile?.mutedWords, - ), + if (note.visibility === "followers" || note.visibility === "home") { + const following = await followingCache.fetch(antenna.userId, () => + Followings.find({ + where: { followerId: antenna.userId }, + select: ["followeeId"], + }).then((relations) => relations.map((relation) => relation.followeeId)), + ); + if (!following.includes(note.userId)) return false; + } + + const mutes = await hardMutesCache.fetch(antenna.userId, () => + UserProfiles.findOneByOrFail({ + userId: antenna.userId, + }).then((profile) => { + return { + userId: antenna.userId, + mutedWords: profile.mutedWords, + mutedPatterns: profile.mutedPatterns, + }; + }), ); - if (await getWordHardMute(note, antenna.userId, mutedWords)) return false; + if ( + mutes.mutedWords != null && + mutes.mutedPatterns != null && + antenna.userId !== note.userId && + (await getWordHardMute(note, mutes.mutedWords, mutes.mutedPatterns)) + ) + return false; // TODO: eval expression diff --git a/packages/backend/src/misc/check-word-mute.ts b/packages/backend/src/misc/check-word-mute.ts index 5686aef2f7..f07f2a0fe5 100644 --- a/packages/backend/src/misc/check-word-mute.ts +++ b/packages/backend/src/misc/check-word-mute.ts @@ -6,11 +6,14 @@ type NoteLike = { text: Note["text"]; files?: Note["files"]; cw?: Note["cw"]; + reply?: NoteLike | null; + renote?: NoteLike | null; }; function checkWordMute( - note: NoteLike, - mutedWords: Array, + note: NoteLike | null | undefined, + mutedWords: string[][], + mutedPatterns: string[], ): boolean { if (note == null) return false; @@ -21,33 +24,33 @@ function checkWordMute( if (text === "") return false; - for (const mutePattern of mutedWords) { - if (Array.isArray(mutePattern)) { - // Clean up - const keywords = mutePattern.filter((keyword) => keyword !== ""); + for (const mutedWord of mutedWords) { + // Clean up + const keywords = mutedWord.filter((keyword) => keyword !== ""); - if ( - keywords.length > 0 && - keywords.every((keyword) => - text.toLowerCase().includes(keyword.toLowerCase()), - ) + if ( + keywords.length > 0 && + keywords.every((keyword) => + text.toLowerCase().includes(keyword.toLowerCase()), ) - return true; - } else { - // represents RegExp - const regexp = mutePattern.match(/^\/(.+)\/(.*)$/); + ) + return true; + } + for (const mutedPattern of mutedPatterns) { + // represents RegExp + const regexp = mutedPattern.match(/^\/(.+)\/(.*)$/); + + // This should never happen due to input sanitisation. + if (!regexp) { + console.warn(`Found invalid regex in word mutes: ${mutedPattern}`); + continue; + } + + try { + if (new RE2(regexp[1], regexp[2]).test(text)) return true; + } catch (err) { // This should never happen due to input sanitisation. - if (!regexp) { - console.warn(`Found invalid regex in word mutes: ${mutePattern}`); - continue; - } - - try { - if (new RE2(regexp[1], regexp[2]).test(text)) return true; - } catch (err) { - // This should never happen due to input sanitisation. - } } } @@ -55,17 +58,17 @@ function checkWordMute( } export async function getWordHardMute( - note: NoteLike, - meId: string | null | undefined, - mutedWords?: Array, + note: NoteLike | null, + mutedWords: string[][], + mutedPatterns: string[], ): Promise { - if (note.userId === meId || mutedWords == null) return false; + if (note == null || mutedWords == null || mutedPatterns == null) return false; if (mutedWords.length > 0) { return ( - checkWordMute(note, mutedWords) || - checkWordMute(note.reply, mutedWords) || - checkWordMute(note.renote, mutedWords) + checkWordMute(note, mutedWords, mutedPatterns) || + checkWordMute(note.reply, mutedWords, mutedPatterns) || + checkWordMute(note.renote, mutedWords, mutedPatterns) ); } diff --git a/packages/backend/src/misc/convert-host.ts b/packages/backend/src/misc/convert-host.ts index 856ce3c127..65cc3ca1f5 100644 --- a/packages/backend/src/misc/convert-host.ts +++ b/packages/backend/src/misc/convert-host.ts @@ -1,6 +1,10 @@ import { URL } from "node:url"; import config from "@/config/index.js"; import { toASCII } from "punycode"; +import Logger from "@/services/logger.js"; +import { inspect } from "node:util"; + +const logger = new Logger("convert-host"); export function getFullApAccount(username: string, host: string | null) { return host @@ -13,6 +17,20 @@ export function isSelfHost(host: string) { return toPuny(config.host) === toPuny(host); } +export function isSameOrigin(src: unknown): boolean | null { + if (typeof src !== "string") { + logger.debug(`unknown origin: ${inspect(src)}`); + return null; + } + try { + const u = new URL(src); + return u.origin === config.url; + } catch (e) { + logger.debug(inspect(e)); + return false; + } +} + export function extractDbHost(uri: string) { const url = new URL(uri); return toPuny(url.hostname); diff --git a/packages/backend/src/misc/fetch-meta.ts b/packages/backend/src/misc/fetch-meta.ts index b3a5e30ae4..fdc978b5a3 100644 --- a/packages/backend/src/misc/fetch-meta.ts +++ b/packages/backend/src/misc/fetch-meta.ts @@ -5,8 +5,8 @@ let cache: Meta; export function metaToPugArgs(meta: Meta): object { let motd = ["Loading..."]; - if (meta.customMOTD.length > 0) { - motd = meta.customMOTD; + if (meta.customMotd.length > 0) { + motd = meta.customMotd; } let splashIconUrl = meta.iconUrl; if (meta.customSplashIcons.length > 0) { diff --git a/packages/backend/src/misc/langmap.ts b/packages/backend/src/misc/langmap.ts index df3214e449..2506a36151 100644 --- a/packages/backend/src/misc/langmap.ts +++ b/packages/backend/src/misc/langmap.ts @@ -380,3 +380,4 @@ export const iso639Regional = { }; export const langmap = Object.assign({}, langmapNoRegion, iso639Regional); +export type PostLanguage = keyof typeof langmap; diff --git a/packages/backend/src/misc/schema.ts b/packages/backend/src/misc/schema.ts index 9d698527c4..016b7159c9 100644 --- a/packages/backend/src/misc/schema.ts +++ b/packages/backend/src/misc/schema.ts @@ -32,6 +32,7 @@ import { packedQueueCountSchema } from "@/models/schema/queue.js"; import { packedGalleryPostSchema } from "@/models/schema/gallery-post.js"; import { packedEmojiSchema } from "@/models/schema/emoji.js"; import { packedNoteEdit } from "@/models/schema/note-edit.js"; +import { packedNoteFileSchema } from "@/models/schema/note-file.js"; export const refs = { UserLite: packedUserLiteSchema, @@ -47,6 +48,7 @@ export const refs = { App: packedAppSchema, MessagingMessage: packedMessagingMessageSchema, Note: packedNoteSchema, + NoteFile: packedNoteFileSchema, NoteEdit: packedNoteEdit, NoteReaction: packedNoteReactionSchema, NoteFavorite: packedNoteFavoriteSchema, diff --git a/packages/backend/src/misc/translate.ts b/packages/backend/src/misc/translate.ts new file mode 100644 index 0000000000..8592d639db --- /dev/null +++ b/packages/backend/src/misc/translate.ts @@ -0,0 +1,88 @@ +import fetch from "node-fetch"; +import { Converter } from "opencc-js"; +import { getAgentByUrl } from "@/misc/fetch.js"; +import { fetchMeta } from "@/misc/fetch-meta.js"; +import type { PostLanguage } from "@/misc/langmap"; +import * as deepl from "deepl-node"; + +function convertChinese(convert: boolean, src: string) { + if (!convert) return src; + const converter = Converter({ from: "cn", to: "twp" }); + return converter(src); +} + +function stem(lang: PostLanguage): string { + let toReturn = lang as string; + if (toReturn.includes("-")) toReturn = toReturn.split("-")[0]; + if (toReturn.includes("_")) toReturn = toReturn.split("_")[0]; + return toReturn; +} + +export async function translate( + text: string, + from: PostLanguage | null, + to: PostLanguage, +) { + const instance = await fetchMeta(); + + if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) { + throw Error("No translator is set up on this server."); + } + + const source = from == null ? null : stem(from); + const target = stem(to); + + if (instance.libreTranslateApiUrl != null) { + const jsonBody = { + q: text, + source: source ?? "auto", + target, + format: "text", + api_key: instance.libreTranslateApiKey ?? "", + }; + + const url = new URL(instance.libreTranslateApiUrl); + if (url.pathname.endsWith("/")) { + url.pathname = url.pathname.slice(0, -1); + } + if (!url.pathname.endsWith("/translate")) { + url.pathname += "/translate"; + } + const res = await fetch(url.toString(), { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(jsonBody), + agent: getAgentByUrl, + }); + + const json = (await res.json()) as { + detectedLanguage?: { + confidence: number; + language: string; + }; + translatedText: string; + }; + + return { + sourceLang: source ?? json.detectedLanguage?.language, + text: convertChinese( + ["zh-hant", "zh-TW"].includes(to), + json.translatedText, + ), + }; + } + + const deeplTranslator = new deepl.Translator(instance.deeplAuthKey ?? ""); + const result = await deeplTranslator.translateText( + text, + source as deepl.SourceLanguageCode | null, + (target === "en" ? to : target) as deepl.TargetLanguageCode, + ); + + return { + sourceLang: source ?? result.detectedSourceLang, + text: convertChinese(["zh-hant", "zh-TW"].includes(to), result.text), + }; +} diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index 54f5a8ca28..3c4510b533 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -4,12 +4,17 @@ import { Index, JoinColumn, Column, + ManyToMany, ManyToOne, + OneToMany, + type Relation, } from "typeorm"; import { id } from "../id.js"; +import { Note } from "./note.js"; import { User } from "./user.js"; import { DriveFolder } from "./drive-folder.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; +import { NoteFile } from "./note-file.js"; @Entity() @Index(["userId", "folderId", "id"]) @@ -31,12 +36,6 @@ export class DriveFile { }) public userId: User["id"] | null; - @ManyToOne((type) => User, { - onDelete: "SET NULL", - }) - @JoinColumn() - public user: User | null; - @Index() @Column("varchar", { length: 512, @@ -70,6 +69,7 @@ export class DriveFile { }) public size: number; + @Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2 @Column("varchar", { length: DB_MAX_IMAGE_COMMENT_LENGTH, nullable: true, @@ -170,12 +170,6 @@ export class DriveFile { }) public folderId: DriveFolder["id"] | null; - @ManyToOne((type) => DriveFolder, { - onDelete: "SET NULL", - }) - @JoinColumn() - public folder: DriveFolder | null; - @Index() @Column("boolean", { default: false, @@ -204,4 +198,30 @@ export class DriveFile { nullable: true, }) public requestIp: string | null; + + //#region Relations + @OneToMany( + () => NoteFile, + (noteFile: NoteFile) => noteFile.file, + ) + public noteFiles: Relation; + + @ManyToMany( + () => Note, + (note: Note) => note.files, + ) + public notes: Relation; + + @ManyToOne(() => User, { + onDelete: "SET NULL", + }) + @JoinColumn() + public user: User | null; + + @ManyToOne(() => DriveFolder, { + onDelete: "SET NULL", + }) + @JoinColumn() + public folder: DriveFolder | null; + //#endregion Relations } diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index a14967185f..6030a969cc 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -61,6 +61,11 @@ export class Meta { }) public disableGlobalTimeline: boolean; + @Column("boolean", { + default: false, + }) + public enableGuestTimeline: boolean; + @Column("varchar", { length: 256, default: "⭐", @@ -93,7 +98,7 @@ export class Meta { array: true, default: "{}", }) - public customMOTD: string[]; + public customMotd: string[]; @Column("varchar", { length: 256, @@ -354,7 +359,7 @@ export class Meta { length: 512, nullable: true, }) - public ToSUrl: string | null; + public tosUrl: string | null; @Column("jsonb", { default: [], @@ -443,7 +448,7 @@ export class Meta { @Column("boolean", { default: true, }) - public objectStorageUseSSL: boolean; + public objectStorageUseSsl: boolean; @Column("boolean", { default: true, diff --git a/packages/backend/src/models/entities/note-file.ts b/packages/backend/src/models/entities/note-file.ts new file mode 100644 index 0000000000..7e7013e03a --- /dev/null +++ b/packages/backend/src/models/entities/note-file.ts @@ -0,0 +1,45 @@ +import { + Entity, + Index, + Column, + ManyToOne, + PrimaryGeneratedColumn, + type Relation, +} from "typeorm"; +import { Note } from "./note.js"; +import { DriveFile } from "./drive-file.js"; +import { id } from "../id.js"; + +@Entity() +export class NoteFile { + @PrimaryGeneratedColumn("increment") + public serialNo: number; + + @Index("IDX_note_file_noteId", { unique: false }) + @Column({ + ...id(), + nullable: false, + }) + public noteId: Note["id"]; + + @Index("IDX_note_file_fileId", { unique: false }) + @Column({ + ...id(), + nullable: false, + }) + public fileId: DriveFile["id"]; + + //#region Relations + @ManyToOne( + () => Note, + (note: Note) => note.noteFiles, + ) + public note: Relation; + + @ManyToOne( + () => DriveFile, + (file: DriveFile) => file.noteFiles, + ) + public file: Relation; + //#endregion Relations +} diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index 8f7958e83d..a31dd7dd46 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -2,15 +2,20 @@ import { Entity, Index, JoinColumn, + JoinTable, Column, PrimaryColumn, + ManyToMany, ManyToOne, + OneToMany, + type Relation, } from "typeorm"; import { User } from "./user.js"; -import type { DriveFile } from "./drive-file.js"; +import { DriveFile } from "./drive-file.js"; import { id } from "../id.js"; import { noteVisibilities } from "../../types.js"; import { Channel } from "./channel.js"; +import { NoteFile } from "./note-file.js"; @Entity() @Index("IDX_NOTE_TAGS", { synchronize: false }) @@ -34,12 +39,6 @@ export class Note { }) public replyId: Note["id"] | null; - @ManyToOne((type) => Note, { - onDelete: "CASCADE", - }) - @JoinColumn() - public reply: Note | null; - @Index() @Column({ ...id(), @@ -48,12 +47,6 @@ export class Note { }) public renoteId: Note["id"] | null; - @ManyToOne((type) => Note, { - onDelete: "CASCADE", - }) - @JoinColumn() - public renote: Note | null; - @Index() @Column("varchar", { length: 256, @@ -61,6 +54,7 @@ export class Note { }) public threadId: string | null; + @Index() // USING pgroonga @Column("text", { nullable: true, }) @@ -78,6 +72,7 @@ export class Note { }) public name: string | null; + @Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2 @Column("varchar", { length: 512, nullable: true, @@ -91,12 +86,6 @@ export class Note { }) public userId: User["id"]; - @ManyToOne((type) => User, { - onDelete: "CASCADE", - }) - @JoinColumn() - public user: User | null; - @Column("boolean", { default: false, }) @@ -149,6 +138,8 @@ export class Note { }) public score: number; + // FIXME: file id is not removed from this array even if the file is deleted + // TODO: drop this column and use note_files @Index() @Column({ ...id(), @@ -181,6 +172,7 @@ export class Note { }) public mentions: User["id"][]; + // FIXME: WHAT IS THIS @Column("text", { default: "[]", }) @@ -214,12 +206,55 @@ export class Note { }) public channelId: Channel["id"] | null; - @ManyToOne((type) => Channel, { + //#region Relations + @OneToMany( + () => NoteFile, + (noteFile: NoteFile) => noteFile.note, + ) + public noteFiles: Relation; + + @ManyToMany( + () => DriveFile, + (file: DriveFile) => file.notes, + ) + @JoinTable({ + name: "note_file", + joinColumn: { + name: "noteId", + referencedColumnName: "id", + }, + inverseJoinColumn: { + name: "fileId", + referencedColumnName: "id", + }, + }) + public files: Relation; + + @ManyToOne(() => Note, { + onDelete: "CASCADE", + }) + @JoinColumn() + public reply: Note | null; + + @ManyToOne(() => Note, { + onDelete: "CASCADE", + }) + @JoinColumn() + public renote: Note | null; + + @ManyToOne(() => Channel, { onDelete: "CASCADE", }) @JoinColumn() public channel: Channel | null; + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) + @JoinColumn() + public user: User | null; + //#endregion Relations + //#region Denormalized fields @Index() @Column("varchar", { diff --git a/packages/backend/src/models/entities/user-profile.ts b/packages/backend/src/models/entities/user-profile.ts index 56887035ce..2a99d58226 100644 --- a/packages/backend/src/models/entities/user-profile.ts +++ b/packages/backend/src/models/entities/user-profile.ts @@ -38,6 +38,7 @@ export class UserProfile { }) public birthday: string | null; + @Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2 @Column("varchar", { length: 2048, nullable: true, @@ -216,6 +217,12 @@ export class UserProfile { }) public mutedWords: string[][]; + @Column("text", { + array: true, + nullable: false, + }) + public mutedPatterns: string[]; + @Column("jsonb", { default: [], comment: "List of instances muted by the user.", diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts index 07aba7badf..6a2d3ee017 100644 --- a/packages/backend/src/models/entities/user.ts +++ b/packages/backend/src/models/entities/user.ts @@ -9,6 +9,8 @@ import { import { id } from "../id.js"; import { DriveFile } from "./drive-file.js"; +export type EmojiModPerm = "unauthorized" | "add" | "mod" | "full"; + @Entity() @Index(["usernameLower", "host"], { unique: true }) export class User { @@ -58,6 +60,7 @@ export class User { }) public usernameLower: string; + @Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2 @Column("varchar", { length: 128, nullable: true, @@ -187,7 +190,7 @@ export class User { enum: ["unauthorized", "add", "mod", "full"], default: "unauthorized", }) - public emojiModPerm: "unauthorized" | "add" | "mod" | "full"; + public emojiModPerm: EmojiModPerm; @Index() @Column("boolean", { diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index 8ae12a63df..5d4ff52198 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -66,12 +66,14 @@ import { InstanceRepository } from "./repositories/instance.js"; import { Webhook } from "./entities/webhook.js"; import { UserIp } from "./entities/user-ip.js"; import { NoteEdit } from "./entities/note-edit.js"; +import { NoteFileRepository } from "./repositories/note-file.js"; export const Announcements = db.getRepository(Announcement); export const AnnouncementReads = db.getRepository(AnnouncementRead); export const Apps = AppRepository; export const Notes = NoteRepository; export const NoteEdits = db.getRepository(NoteEdit); +export const NoteFiles = NoteFileRepository; export const NoteFavorites = NoteFavoriteRepository; export const NoteWatchings = db.getRepository(NoteWatching); export const NoteThreadMutings = db.getRepository(NoteThreadMuting); diff --git a/packages/backend/src/models/repositories/note-file.ts b/packages/backend/src/models/repositories/note-file.ts new file mode 100644 index 0000000000..f755fb5fea --- /dev/null +++ b/packages/backend/src/models/repositories/note-file.ts @@ -0,0 +1,4 @@ +import { db } from "@/db/postgre.js"; +import { NoteFile } from "@/models/entities/note-file.js"; + +export const NoteFileRepository = db.getRepository(NoteFile).extend({}); diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 28abe7a9cc..7c6105d2f2 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -494,9 +494,7 @@ export const UserRepository = db.getRepository(User).extend({ url: profile!.url, uri: user.uri, movedToUri: user.movedToUri - ? await this.userFromURI(user.movedToUri).catch( - () => user.movedToUri, - ) + ? await this.userFromURI(user.movedToUri).catch(() => null) : null, alsoKnownAs: user.alsoKnownAs, createdAt: user.createdAt.toISOString(), @@ -515,8 +513,8 @@ export const UserRepository = db.getRepository(User).extend({ location: profile!.location, birthday: profile!.birthday, fields: profile!.fields, - followersCount: followersCount || 0, - followingCount: followingCount || 0, + followersCount: followersCount ?? null, + followingCount: followingCount ?? null, notesCount: user.notesCount, pinnedNoteIds: pins.map((pin) => pin.noteId), pinnedNotes: Notes.packMany( @@ -530,8 +528,11 @@ export const UserRepository = db.getRepository(User).extend({ pinnedPage: profile!.pinnedPageId ? Pages.pack(profile!.pinnedPageId, me) : null, - publicReactions: profile!.publicReactions, - ffVisibility: profile!.ffVisibility, + // TODO: federate publicReactions + publicReactions: + user.host == null ? profile!.publicReactions : false, + // TODO: federate ffVisibility + ffVisibility: user.host == null ? profile!.ffVisibility : "private", twoFactorEnabled: profile!.twoFactorEnabled, usePasswordLessLogin: profile!.usePasswordLessLogin, securityKeys: UserSecurityKeys.countBy({ @@ -544,13 +545,13 @@ export const UserRepository = db.getRepository(User).extend({ ? { avatarId: user.avatarId, bannerId: user.bannerId, - injectFeaturedNote: profile!.injectFeaturedNote, - receiveAnnouncementEmail: profile!.receiveAnnouncementEmail, - alwaysMarkNsfw: profile!.alwaysMarkNsfw, - carefulBot: profile!.carefulBot, - autoAcceptFollowed: profile!.autoAcceptFollowed, - noCrawle: profile!.noCrawle, - preventAiLearning: profile!.preventAiLearning, + injectFeaturedNote: profile?.injectFeaturedNote, + receiveAnnouncementEmail: profile?.receiveAnnouncementEmail, + alwaysMarkNsfw: profile?.alwaysMarkNsfw, + carefulBot: profile?.carefulBot, + autoAcceptFollowed: profile?.autoAcceptFollowed, + noCrawle: profile?.noCrawle, + preventAiLearning: profile?.preventAiLearning, isExplorable: user.isExplorable, isDeleted: user.isDeleted, hideOnlineStatus: user.hideOnlineStatus, @@ -571,17 +572,18 @@ export const UserRepository = db.getRepository(User).extend({ hasUnreadNotification: this.getHasUnreadNotification(user.id), hasPendingReceivedFollowRequest: this.getHasPendingReceivedFollowRequest(user.id), - mutedWords: profile!.mutedWords, - mutedInstances: profile!.mutedInstances, - mutingNotificationTypes: profile!.mutingNotificationTypes, - emailNotificationTypes: profile!.emailNotificationTypes, + mutedWords: profile?.mutedWords, + mutedPatterns: profile?.mutedPatterns, + mutedInstances: profile?.mutedInstances, + mutingNotificationTypes: profile?.mutingNotificationTypes, + emailNotificationTypes: profile?.emailNotificationTypes, } : {}), ...(opts.includeSecrets ? { - email: profile!.email, - emailVerified: profile!.emailVerified, + email: profile?.email, + emailVerified: profile?.emailVerified, securityKeysList: UserSecurityKeys.find({ where: { userId: user.id, diff --git a/packages/backend/src/models/schema/note-file.ts b/packages/backend/src/models/schema/note-file.ts new file mode 100644 index 0000000000..c9b8a7e181 --- /dev/null +++ b/packages/backend/src/models/schema/note-file.ts @@ -0,0 +1,24 @@ +export const packedNoteFileSchema = { + type: "object", + properties: { + serialNo: { + type: "number", + optional: false, + nullable: false, + }, + noteId: { + type: "string", + optional: false, + nullable: false, + format: "id", + example: "xxxxxxxxxx", + }, + fileId: { + type: "string", + optional: false, + nullable: false, + format: "id", + example: "xxxxxxxxxx", + }, + }, +} as const; diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts index d6a5cd8b8d..bcdd718dd1 100644 --- a/packages/backend/src/models/schema/user.ts +++ b/packages/backend/src/models/schema/user.ts @@ -468,6 +468,16 @@ export const packedMeDetailedOnlySchema = { }, }, }, + mutedPatterns: { + type: "array", + nullable: false, + optional: false, + items: { + type: "string", + nullable: false, + optional: false, + }, + }, mutedInstances: { type: "array", nullable: true, diff --git a/packages/backend/ormconfig.js b/packages/backend/src/ormconfig.ts similarity index 67% rename from packages/backend/ormconfig.js rename to packages/backend/src/ormconfig.ts index 5f85cead8a..a1891e00df 100644 --- a/packages/backend/ormconfig.js +++ b/packages/backend/src/ormconfig.ts @@ -1,6 +1,6 @@ import { DataSource } from "typeorm"; -import config from "./built/config/index.js"; -import { entities } from "./built/db/postgre.js"; +import config from "./config/index.js"; +import { entities } from "./db/postgre.js"; export default new DataSource({ type: "postgres", @@ -11,5 +11,5 @@ export default new DataSource({ database: config.db.db, extra: config.db.extra, entities: entities, - migrations: ["migration/*.js"], + migrations: ["built/migration/*.js"], }); diff --git a/packages/backend/src/prelude/await-all.ts b/packages/backend/src/prelude/await-all.ts index ce11eb87b4..d81870a574 100644 --- a/packages/backend/src/prelude/await-all.ts +++ b/packages/backend/src/prelude/await-all.ts @@ -1,10 +1,12 @@ +import { unsafeCast } from "./unsafe-cast.js"; + export type Promiseable = { [K in keyof T]: Promise | T[K]; }; export async function awaitAll(obj: Promiseable): Promise { const target = {} as T; - const keys = Object.keys(obj) as unknown as (keyof T)[]; + const keys = unsafeCast<(keyof T)[]>(Object.keys(obj)); const values = Object.values(obj) as any[]; const resolvedValues = await Promise.all( diff --git a/packages/backend/src/prelude/unsafe-cast.ts b/packages/backend/src/prelude/unsafe-cast.ts new file mode 100644 index 0000000000..f7e251fa34 --- /dev/null +++ b/packages/backend/src/prelude/unsafe-cast.ts @@ -0,0 +1,4 @@ +// unsafe type cast +export function unsafeCast(val: unknown): T { + return val as T; +} diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index ced08fee3b..58a0ae7486 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -13,7 +13,6 @@ import processDb from "./processors/db/index.js"; import processObjectStorage from "./processors/object-storage/index.js"; import processSystemQueue from "./processors/system/index.js"; import processWebhookDeliver from "./processors/webhook-deliver.js"; -import processBackground from "./processors/background/index.js"; import { endedPollNotification } from "./processors/ended-poll-notification.js"; import { queueLogger } from "./logger.js"; import { getJobInfo } from "./get-job-info.js"; @@ -482,14 +481,6 @@ export function createCleanRemoteFilesJob() { ); } -export function createIndexAllNotesJob(data = {}) { - return backgroundQueue.add("indexAllNotes", data, { - removeOnComplete: true, - removeOnFail: false, - timeout: 1000 * 60 * 60 * 24, - }); -} - export function webhookDeliver( webhook: Webhook, type: (typeof webhookEventTypes)[number], @@ -526,7 +517,6 @@ export default function () { webhookDeliverQueue.process(64, processWebhookDeliver); processDb(dbQueue); processObjectStorage(objectStorageQueue); - processBackground(backgroundQueue); systemQueue.add( "cleanCharts", diff --git a/packages/backend/src/queue/processors/background/index-all-notes.ts b/packages/backend/src/queue/processors/background/index-all-notes.ts deleted file mode 100644 index 115f2147b6..0000000000 --- a/packages/backend/src/queue/processors/background/index-all-notes.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type Bull from "bull"; -import type { DoneCallback } from "bull"; - -import { queueLogger } from "../../logger.js"; -import { Notes } from "@/models/index.js"; -import { MoreThan } from "typeorm"; -import { index } from "@/services/note/create.js"; -import { Note } from "@/models/entities/note.js"; -import meilisearch from "@/db/meilisearch.js"; -import { inspect } from "node:util"; - -const logger = queueLogger.createSubLogger("index-all-notes"); - -export default async function indexAllNotes( - job: Bull.Job>, - done: DoneCallback, -): Promise { - logger.info("Indexing all notes..."); - - let cursor: string | null = (job.data.cursor as string) ?? null; - let indexedCount: number = (job.data.indexedCount as number) ?? 0; - let total: number = (job.data.total as number) ?? 0; - - let running = true; - const take = 10000; - const batch = 100; - while (running) { - logger.info( - `Querying for ${take} notes ${indexedCount}/${ - total ? total : "?" - } at ${cursor}`, - ); - - let notes: Note[] = []; - try { - notes = await Notes.find({ - where: { - ...(cursor ? { id: MoreThan(cursor) } : {}), - }, - take: take, - order: { - id: 1, - }, - relations: ["user"], - }); - } catch (e: any) { - logger.error(`Failed to query notes:\n${inspect(e)}`); - done(e); - break; - } - - if (notes.length === 0) { - await job.progress(100); - running = false; - break; - } - - try { - const count = await Notes.count(); - total = count; - await job.update({ indexedCount, cursor, total }); - } catch (e) {} - - for (let i = 0; i < notes.length; i += batch) { - const chunk = notes.slice(i, i + batch); - - if (meilisearch) { - await meilisearch.ingestNote(chunk); - } - - await Promise.all(chunk.map((note) => index(note, true))); - - indexedCount += chunk.length; - const pct = (indexedCount / total) * 100; - await job.update({ indexedCount, cursor, total }); - await job.progress(+pct.toFixed(1)); - logger.info(`Indexed notes ${indexedCount}/${total ? total : "?"}`); - } - cursor = notes[notes.length - 1].id; - await job.update({ indexedCount, cursor, total }); - - if (notes.length < take) { - running = false; - } - } - - done(); - logger.info("All notes have been indexed."); -} diff --git a/packages/backend/src/queue/processors/background/index.ts b/packages/backend/src/queue/processors/background/index.ts deleted file mode 100644 index 6674f954b0..0000000000 --- a/packages/backend/src/queue/processors/background/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type Bull from "bull"; -import indexAllNotes from "./index-all-notes.js"; - -const jobs = { - indexAllNotes, -} as Record>>; - -export default function (q: Bull.Queue) { - for (const [k, v] of Object.entries(jobs)) { - q.process(k, 16, v); - } -} diff --git a/packages/backend/src/queue/processors/db/delete-account.ts b/packages/backend/src/queue/processors/db/delete-account.ts index adb93484bd..b43cdd137c 100644 --- a/packages/backend/src/queue/processors/db/delete-account.ts +++ b/packages/backend/src/queue/processors/db/delete-account.ts @@ -7,7 +7,6 @@ import type { DriveFile } from "@/models/entities/drive-file.js"; import { MoreThan } from "typeorm"; import { deleteFileSync } from "@/services/drive/delete-file.js"; import { sendEmail } from "@/services/send-email.js"; -import meilisearch from "@/db/meilisearch.js"; const logger = queueLogger.createSubLogger("delete-account"); @@ -42,9 +41,6 @@ export async function deleteAccount( cursor = notes[notes.length - 1].id; await Notes.delete(notes.map((note) => note.id)); - if (meilisearch) { - await meilisearch.deleteNotes(notes); - } } logger.succ("All of notes deleted"); diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 19b8fe49e7..3dc54e1fb5 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -1,6 +1,5 @@ import promiseLimit from "promise-limit"; import * as mfm from "mfm-js"; -import config from "@/config/index.js"; import Resolver from "../resolver.js"; import post from "@/services/note/create.js"; import { extractMentionedUsers } from "@/services/note/create.js"; @@ -14,7 +13,7 @@ import { extractPollFromQuestion } from "./question.js"; import vote from "@/services/note/polls/vote.js"; import { apLogger } from "../logger.js"; import { DriveFile } from "@/models/entities/drive-file.js"; -import { extractDbHost, toPuny } from "@/misc/convert-host.js"; +import { extractDbHost, isSameOrigin, toPuny } from "@/misc/convert-host.js"; import { Emojis, Polls, @@ -234,7 +233,7 @@ export async function createNote( .catch(async (e) => { // トークだったらinReplyToのエラーは無視 const uri = getApId(note.inReplyTo); - if (uri.startsWith(`${config.url}/`)) { + if (isSameOrigin(uri)) { const id = uri.split("/").pop(); const talk = await MessagingMessages.findOneBy({ id }); if (talk) { @@ -439,7 +438,7 @@ export async function resolveNote( } //#endregion - if (uri.startsWith(config.url)) { + if (isSameOrigin(uri)) { throw new StatusError( "cannot resolve local note", 400, @@ -556,7 +555,7 @@ export async function updateNote(value: string | IObject, resolver?: Resolver) { if (!uri) throw new Error("Missing note uri"); // Skip if URI points to this server - if (uri.startsWith(`${config.url}/`)) throw new Error("uri points local"); + if (isSameOrigin(uri)) throw new Error("uri points local"); // A new resolver is created if not specified if (resolver == null) resolver = new Resolver(); diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 1b7bd41bbf..6546f041b8 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -19,7 +19,7 @@ import { UserNotePining } from "@/models/entities/user-note-pining.js"; import { genId } from "@/misc/gen-id.js"; import { UserPublickey } from "@/models/entities/user-publickey.js"; import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js"; -import { toPuny } from "@/misc/convert-host.js"; +import { isSameOrigin, toPuny } from "@/misc/convert-host.js"; import { UserProfile } from "@/models/entities/user-profile.js"; import { toArray } from "@/prelude/array.js"; import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js"; @@ -138,7 +138,7 @@ export async function fetchPerson( if (cached) return cached; // Fetch from the database if the URI points to this server - if (uri.startsWith(`${config.url}/`)) { + if (isSameOrigin(uri)) { const id = uri.split("/").pop(); const u = await Users.findOneBy({ id }); if (u) await uriPersonCache.set(uri, u); @@ -166,7 +166,7 @@ export async function createPerson( ): Promise { if (typeof uri !== "string") throw new Error("uri is not string"); - if (uri.startsWith(config.url)) { + if (isSameOrigin(uri)) { throw new StatusError( "cannot resolve local user", 400, @@ -419,7 +419,7 @@ export async function updatePerson( if (typeof uri !== "string") throw new Error("uri is not string"); // Skip if the URI points to this server - if (uri.startsWith(`${config.url}/`)) { + if (isSameOrigin(uri)) { return; } diff --git a/packages/backend/src/remote/activitypub/models/question.ts b/packages/backend/src/remote/activitypub/models/question.ts index 39963fddbf..59818654fd 100644 --- a/packages/backend/src/remote/activitypub/models/question.ts +++ b/packages/backend/src/remote/activitypub/models/question.ts @@ -1,10 +1,10 @@ -import config from "@/config/index.js"; import Resolver from "../resolver.js"; import type { IObject, IQuestion } from "../type.js"; import { getApId, isQuestion } from "../type.js"; import { apLogger } from "../logger.js"; import { Notes, Polls } from "@/models/index.js"; import type { IPoll } from "@/models/entities/poll.js"; +import { isSameOrigin } from "@/misc/convert-host.js"; export async function extractPollFromQuestion( source: string | IObject, @@ -57,7 +57,7 @@ export async function updateQuestion( const uri = typeof value === "string" ? value : getApId(value); // Skip if URI points to this server - if (uri.startsWith(`${config.url}/`)) throw new Error("uri points local"); + if (isSameOrigin(uri)) throw new Error("uri points local"); //#region Already registered with this server? const note = await Notes.findOneBy({ uri }); diff --git a/packages/backend/src/remote/activitypub/renderer/index.ts b/packages/backend/src/remote/activitypub/renderer/index.ts index 734d1198c9..2b6229b3e4 100644 --- a/packages/backend/src/remote/activitypub/renderer/index.ts +++ b/packages/backend/src/remote/activitypub/renderer/index.ts @@ -36,7 +36,7 @@ export const renderActivity = (x: any): IActivity | null => { PropertyValue: "schema:PropertyValue", value: "schema:value", // Firefish - firefish: "https://joinfirefish.org/ns#", + firefish: "https://firefish.dev/ns#", speakAsCat: "firefish:speakAsCat", // Misskey misskey: "https://misskey-hub.net/ns#", diff --git a/packages/backend/src/server/api/call.ts b/packages/backend/src/server/api/call.ts index 1fc42d43cf..2faef7b0e8 100644 --- a/packages/backend/src/server/api/call.ts +++ b/packages/backend/src/server/api/call.ts @@ -2,6 +2,7 @@ import { performance } from "perf_hooks"; import type Koa from "koa"; import type { CacheableLocalUser } from "@/models/entities/user.js"; import type { AccessToken } from "@/models/entities/access-token.js"; +import { v4 as uuid } from "uuid"; import { getIpHash } from "@/misc/get-ip-hash.js"; import { limiter } from "./limiter.js"; import type { IEndpointMeta } from "./endpoints.js"; @@ -177,20 +178,23 @@ export default async ( if (e instanceof ApiError) { throw e; } else { - apiLogger.error(`Internal error occurred in ${ep.name}: ${e.message}`, { - ep: ep.name, - ps: data, - e: { - message: e.message, - code: e.name, - stack: e.stack, + const errorId = uuid(); + apiLogger.error( + `Internal error occurred in ${ep.name}: ${e.message} (Event ID: ${errorId})`, + { + ep: ep.name, + ps: data, + e: { + message: e.message, + code: e.name, + stack: e.stack, + }, }, - }); + ); throw new ApiError(null, { e: { - message: e.message, + message: `Internal error (Event ID: ${errorId})`, code: e.name, - stack: e.stack, }, }); } diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 8184df5d23..52dd3382f7 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -51,7 +51,6 @@ import * as ep___admin_relays_list from "./endpoints/admin/relays/list.js"; import * as ep___admin_relays_remove from "./endpoints/admin/relays/remove.js"; import * as ep___admin_resetPassword from "./endpoints/admin/reset-password.js"; import * as ep___admin_resolveAbuseUserReport from "./endpoints/admin/resolve-abuse-user-report.js"; -import * as ep___admin_search_indexAll from "./endpoints/admin/search/index-all.js"; import * as ep___admin_sendEmail from "./endpoints/admin/send-email.js"; import * as ep___admin_sendModMail from "./endpoints/admin/send-mod-mail.js"; import * as ep___admin_serverInfo from "./endpoints/admin/server-info.js"; @@ -283,7 +282,7 @@ import * as ep___pages_update from "./endpoints/pages/update.js"; import * as ep___ping from "./endpoints/ping.js"; import * as ep___recommendedInstances from "./endpoints/recommended-instances.js"; import * as ep___pinnedUsers from "./endpoints/pinned-users.js"; -import * as ep___customMOTD from "./endpoints/custom-motd.js"; +import * as ep___customMotd from "./endpoints/custom-motd.js"; import * as ep___customSplashIcons from "./endpoints/custom-splash-icons.js"; import * as ep___latestVersion from "./endpoints/latest-version.js"; import * as ep___patrons from "./endpoints/patrons.js"; @@ -400,7 +399,6 @@ const eps = [ ["admin/relays/remove", ep___admin_relays_remove], ["admin/reset-password", ep___admin_resetPassword], ["admin/resolve-abuse-user-report", ep___admin_resolveAbuseUserReport], - ["admin/search/index-all", ep___admin_search_indexAll], ["admin/send-email", ep___admin_sendEmail], ["admin/send-mod-mail", ep___admin_sendModMail], ["admin/server-info", ep___admin_serverInfo], @@ -633,7 +631,7 @@ const eps = [ ["reply-mute/create", ep___reply_mute_create], ["reply-mute/delete", ep___reply_mute_delete], ["reply-mute/list", ep___reply_mute_list], - ["custom-motd", ep___customMOTD], + ["custom-motd", ep___customMotd], ["custom-splash-icons", ep___customSplashIcons], ["latest-version", ep___latestVersion], ["patrons", ep___patrons], diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts index 601cd95003..fd4ad9401a 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts @@ -89,7 +89,7 @@ export default define(meta, paramDef, async (ps, me) => { set.objectStorageSecretKey = config.objectStorage.secretKey; } if (typeof config.objectStorage.useSsl === "boolean") { - set.objectStorageUseSSL = config.objectStorage.useSsl; + set.objectStorageUseSsl = config.objectStorage.useSsl; } if (typeof config.objectStorage.connnectOverProxy === "boolean") { set.objectStorageUseProxy = config.objectStorage.connnectOverProxy; diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index b8b645bc32..a504055065 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -471,7 +471,7 @@ export default define(meta, paramDef, async () => { uri: config.url, description: instance.description, langs: instance.langs, - tosUrl: instance.ToSUrl, + tosUrl: instance.tosUrl, moreUrls: instance.moreUrls, repositoryUrl: instance.repositoryUrl, feedbackUrl: instance.feedbackUrl, @@ -479,6 +479,7 @@ export default define(meta, paramDef, async () => { disableLocalTimeline: instance.disableLocalTimeline, disableRecommendedTimeline: instance.disableRecommendedTimeline, disableGlobalTimeline: instance.disableGlobalTimeline, + enableGuestTimeline: instance.enableGuestTimeline, driveCapacityPerLocalUserMb: instance.localDriveCapacityMb, driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb, emailRequiredForSignup: instance.emailRequiredForSignup, @@ -508,7 +509,7 @@ export default define(meta, paramDef, async () => { defaultReaction: instance.defaultReaction, recommendedInstances: instance.recommendedInstances, pinnedUsers: instance.pinnedUsers, - customMOTD: instance.customMOTD, + customMOTD: instance.customMotd, customSplashIcons: instance.customSplashIcons, hiddenTags: instance.hiddenTags, blockedHosts: instance.blockedHosts, @@ -536,7 +537,7 @@ export default define(meta, paramDef, async () => { objectStoragePort: instance.objectStoragePort, objectStorageAccessKey: instance.objectStorageAccessKey, objectStorageSecretKey: instance.objectStorageSecretKey, - objectStorageUseSSL: instance.objectStorageUseSSL, + objectStorageUseSSL: instance.objectStorageUseSsl, objectStorageUseProxy: instance.objectStorageUseProxy, objectStorageSetPublicRead: instance.objectStorageSetPublicRead, objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle, diff --git a/packages/backend/src/server/api/endpoints/admin/search/index-all.ts b/packages/backend/src/server/api/endpoints/admin/search/index-all.ts deleted file mode 100644 index 531428849b..0000000000 --- a/packages/backend/src/server/api/endpoints/admin/search/index-all.ts +++ /dev/null @@ -1,28 +0,0 @@ -import define from "@/server/api/define.js"; -import { createIndexAllNotesJob } from "@/queue/index.js"; - -export const meta = { - tags: ["admin"], - - requireCredential: true, - requireModerator: true, -} as const; - -export const paramDef = { - type: "object", - properties: { - cursor: { - type: "string", - format: "misskey:id", - nullable: true, - default: null, - }, - }, - required: [], -} as const; - -export default define(meta, paramDef, async (ps, _me) => { - createIndexAllNotesJob({ - cursor: ps.cursor ?? undefined, - }); -}); diff --git a/packages/backend/src/server/api/endpoints/admin/set-emoji-moderator.ts b/packages/backend/src/server/api/endpoints/admin/set-emoji-moderator.ts index dfaf54ca7d..6633edbc8c 100644 --- a/packages/backend/src/server/api/endpoints/admin/set-emoji-moderator.ts +++ b/packages/backend/src/server/api/endpoints/admin/set-emoji-moderator.ts @@ -1,6 +1,8 @@ import define from "@/server/api/define.js"; import { Users } from "@/models/index.js"; import { publishInternalEvent } from "@/services/stream.js"; +import type { EmojiModPerm } from "@/models/entities/user.js"; +import { unsafeCast } from "@/prelude/unsafe-cast.js"; export const meta = { tags: ["admin"], @@ -31,12 +33,8 @@ export default define(meta, paramDef, async (ps) => { ); } - const _emojiModPerm = - (ps.emojiModPerm as "unauthorized" | "add" | "mod" | "full") ?? - "unauthorized"; - await Users.update(user.id, { - emojiModPerm: _emojiModPerm, + emojiModPerm: unsafeCast(ps.emojiModPerm), }); publishInternalEvent("userChangeModeratorState", { diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 164d6ae419..3ad255ddde 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -60,6 +60,7 @@ export default define(meta, paramDef, async (ps, me) => { injectFeaturedNote: profile.injectFeaturedNote, receiveAnnouncementEmail: profile.receiveAnnouncementEmail, mutedWords: profile.mutedWords, + mutedPatterns: profile.mutedPatterns, mutedInstances: profile.mutedInstances, mutingNotificationTypes: profile.mutingNotificationTypes, isModerator: user.isModerator, diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 765219fcdc..f0e831924a 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -17,6 +17,7 @@ export const paramDef = { disableLocalTimeline: { type: "boolean", nullable: true }, disableRecommendedTimeline: { type: "boolean", nullable: true }, disableGlobalTimeline: { type: "boolean", nullable: true }, + enableGuestTimeline: { type: "boolean", nullable: true }, defaultReaction: { type: "string", nullable: true }, recommendedInstances: { type: "array", @@ -206,6 +207,10 @@ export default define(meta, paramDef, async (ps, me) => { set.disableGlobalTimeline = ps.disableGlobalTimeline; } + if (typeof ps.enableGuestTimeline === "boolean") { + set.enableGuestTimeline = ps.enableGuestTimeline; + } + if (typeof ps.defaultReaction === "string") { set.defaultReaction = ps.defaultReaction; } @@ -215,7 +220,7 @@ export default define(meta, paramDef, async (ps, me) => { } if (Array.isArray(ps.customMOTD)) { - set.customMOTD = ps.customMOTD.filter(Boolean); + set.customMotd = ps.customMOTD.filter(Boolean); } if (Array.isArray(ps.customSplashIcons)) { @@ -426,7 +431,7 @@ export default define(meta, paramDef, async (ps, me) => { } if (ps.tosUrl !== undefined) { - set.ToSUrl = ps.tosUrl; + set.tosUrl = ps.tosUrl; } if (ps.moreUrls !== undefined) { @@ -482,7 +487,7 @@ export default define(meta, paramDef, async (ps, me) => { } if (ps.objectStorageUseSSL !== undefined) { - set.objectStorageUseSSL = ps.objectStorageUseSSL; + set.objectStorageUseSsl = ps.objectStorageUseSSL; } if (ps.objectStorageUseProxy !== undefined) { diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 1512cb9281..cbe0318525 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -111,8 +111,7 @@ export default define(meta, paramDef, async (ps, user) => { .leftJoinAndSelect("replyUser.banner", "replyUserBanner") .leftJoinAndSelect("renote.user", "renoteUser") .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") - .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") - .andWhere("note.visibility != 'home'"); + .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner"); generateVisibilityQuery(query, user); generateMutedUserQuery(query, user); diff --git a/packages/backend/src/server/api/endpoints/custom-motd.ts b/packages/backend/src/server/api/endpoints/custom-motd.ts index d61b31fed6..2939355b94 100644 --- a/packages/backend/src/server/api/endpoints/custom-motd.ts +++ b/packages/backend/src/server/api/endpoints/custom-motd.ts @@ -28,6 +28,6 @@ export const paramDef = { export default define(meta, paramDef, async () => { const meta = await fetchMeta(); - const motd = await Promise.all(meta.customMOTD.map((x) => x)); + const motd = await Promise.all(meta.customMotd.map((x) => x)); return motd; }); diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index d7974ce6cc..08bf885d49 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -120,6 +120,7 @@ export const paramDef = { ffVisibility: { type: "string", enum: ["public", "followers", "private"] }, pinnedPageId: { type: "string", format: "misskey:id", nullable: true }, mutedWords: { type: "array" }, + mutedPatterns: { type: "array", items: { type: "string" } }, mutedInstances: { type: "array", items: { @@ -159,23 +160,52 @@ export default define(meta, paramDef, async (ps, _user, token) => { profileUpdates.ffVisibility = ps.ffVisibility; if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; + if (ps.mutedPatterns !== undefined) { + for (const item of ps.mutedPatterns) { + const regexp = item.match(/^\/(.+)\/(.*)$/); + if (!regexp) throw new ApiError(meta.errors.invalidRegexp); + + try { + new RegExp(regexp[1], regexp[2]); + } catch (err) { + throw new ApiError(meta.errors.invalidRegexp); + } + + profileUpdates.mutedPatterns = profileUpdates.mutedPatterns ?? []; + profileUpdates.mutedPatterns.push(item); + } + } if (ps.mutedWords !== undefined) { - // validate regular expression syntax - ps.mutedWords - .filter((x) => !Array.isArray(x)) - .forEach((x) => { - const regexp = x.match(/^\/(.+)\/(.*)$/); - if (!regexp) throw new ApiError(meta.errors.invalidRegexp); + // for backward compatibility + for (const item of ps.mutedWords) { + if (Array.isArray(item)) continue; - try { - new RE2(regexp[1], regexp[2]); - } catch (err) { - throw new ApiError(meta.errors.invalidRegexp); - } - }); + const regexp = item.match(/^\/(.+)\/(.*)$/); + if (!regexp) throw new ApiError(meta.errors.invalidRegexp); - profileUpdates.mutedWords = ps.mutedWords; - profileUpdates.enableWordMute = ps.mutedWords.length > 0; + try { + new RegExp(regexp[1], regexp[2]); + } catch (err) { + throw new ApiError(meta.errors.invalidRegexp); + } + + profileUpdates.mutedPatterns = profileUpdates.mutedPatterns ?? []; + profileUpdates.mutedPatterns.push(item); + } + + profileUpdates.mutedWords = ps.mutedWords.filter((item) => + Array.isArray(item), + ); + } + if ( + profileUpdates.mutedWords !== undefined || + profileUpdates.mutedPatterns !== undefined + ) { + profileUpdates.enableWordMute = + (profileUpdates.mutedWords != null && + profileUpdates.mutedWords.length > 0) || + (profileUpdates.mutedPatterns != null && + profileUpdates.mutedPatterns.length > 0); } if (ps.mutedInstances !== undefined) profileUpdates.mutedInstances = ps.mutedInstances; diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 819fccc826..68a7008405 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -111,6 +111,11 @@ export const meta = { optional: false, nullable: false, }, + enableGuestTimeline: { + type: "boolean", + optional: false, + nullable: false, + }, driveCapacityPerLocalUserMb: { type: "number", optional: false, @@ -420,7 +425,7 @@ export default define(meta, paramDef, async (ps, me) => { uri: config.url, description: instance.description, langs: instance.langs, - tosUrl: instance.ToSUrl, + tosUrl: instance.tosUrl, moreUrls: instance.moreUrls, repositoryUrl: instance.repositoryUrl, feedbackUrl: instance.feedbackUrl, @@ -432,6 +437,7 @@ export default define(meta, paramDef, async (ps, me) => { disableLocalTimeline: instance.disableLocalTimeline, disableRecommendedTimeline: instance.disableRecommendedTimeline, disableGlobalTimeline: instance.disableGlobalTimeline, + enableGuestTimeline: instance.enableGuestTimeline, driveCapacityPerLocalUserMb: instance.localDriveCapacityMb, driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb, emailRequiredForSignup: instance.emailRequiredForSignup, @@ -506,8 +512,8 @@ export default define(meta, paramDef, async (ps, me) => { localTimeLine: !instance.disableLocalTimeline, recommendedTimeline: !instance.disableRecommendedTimeline, globalTimeLine: !instance.disableGlobalTimeline, + guestTimeline: instance.enableGuestTimeline, emailRequiredForSignup: instance.emailRequiredForSignup, - searchFilters: config.meilisearch ? true : false, hcaptcha: instance.enableHcaptcha, recaptcha: instance.enableRecaptcha, objectStorage: instance.useObjectStorage, diff --git a/packages/backend/src/server/api/endpoints/notes/edit.ts b/packages/backend/src/server/api/endpoints/notes/edit.ts index 8e818745fc..f8a7a626b7 100644 --- a/packages/backend/src/server/api/endpoints/notes/edit.ts +++ b/packages/backend/src/server/api/endpoints/notes/edit.ts @@ -1,5 +1,4 @@ import { In } from "typeorm"; -import { index } from "@/services/note/create.js"; import type { IRemoteUser, User } from "@/models/entities/user.js"; import { Users, @@ -626,8 +625,6 @@ export default define(meta, paramDef, async (ps, user) => { } if (publishing && user.isIndexable) { - index(note, true); - // Publish update event for the updated note details publishNoteStream(note.id, "updated", { updatedAt: update.updatedAt, diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 9374e0bac7..b159a91944 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -1,16 +1,12 @@ -import { FindManyOptions, In } from "typeorm"; import { Notes } from "@/models/index.js"; import { Note } from "@/models/entities/note.js"; -import config from "@/config/index.js"; -import es from "@/db/elasticsearch.js"; -import sonic from "@/db/sonic.js"; -import meilisearch, { MeilisearchNote } from "@/db/meilisearch.js"; import define from "@/server/api/define.js"; import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js"; import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js"; import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js"; import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import type { SelectQueryBuilder } from "typeorm"; export const meta = { tags: ["notes"], @@ -39,6 +35,8 @@ export const paramDef = { query: { type: "string" }, sinceId: { type: "string", format: "misskey:id" }, untilId: { type: "string", format: "misskey:id" }, + sinceDate: { type: "number", nullable: true }, + untilDate: { type: "number", nullable: true }, limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, offset: { type: "integer", default: 0 }, host: { @@ -52,6 +50,8 @@ export const paramDef = { nullable: true, default: null, }, + withFiles: { type: "boolean", nullable: true }, + searchCwAndAlt: { type: "boolean", nullable: true }, channelId: { type: "string", format: "misskey:id", @@ -69,12 +69,17 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, me) => { - if (es == null && sonic == null && meilisearch == null) { + async function search( + modifier?: (query: SelectQueryBuilder) => void, + ): Promise { const query = makePaginationQuery( Notes.createQueryBuilder("note"), ps.sinceId, ps.untilId, + ps.sinceDate ?? undefined, + ps.untilDate ?? undefined, ); + modifier?.(query); if (ps.userId != null) { query.andWhere("note.userId = :userId", { userId: ps.userId }); @@ -86,11 +91,32 @@ export default define(meta, paramDef, async (ps, me) => { }); } + query.innerJoinAndSelect("note.user", "user"); + + // "from: me": search all (public, home, followers, specified) my posts + // otherwise: search public indexable posts only + if (ps.userId == null || ps.userId !== me?.id) { + query + .andWhere("note.visibility = 'public'") + .andWhere("user.isIndexable = TRUE"); + } + + if (ps.userId != null) { + query.andWhere("note.userId = :userId", { userId: ps.userId }); + } + + if (ps.host === null) { + query.andWhere("note.userHost IS NULL"); + } + if (ps.host != null) { + query.andWhere("note.userHost = :userHost", { userHost: ps.host }); + } + + if (ps.withFiles === true) { + query.andWhere("note.fileIds != '{}'"); + } + query - .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` }) - .andWhere("note.visibility = 'public'") - .innerJoinAndSelect("note.user", "user") - .andWhere("user.isIndexable = TRUE") .leftJoinAndSelect("user.avatar", "avatar") .leftJoinAndSelect("user.banner", "banner") .leftJoinAndSelect("note.reply", "reply") @@ -106,245 +132,60 @@ export default define(meta, paramDef, async (ps, me) => { if (me) generateMutedUserQuery(query, me); if (me) generateBlockedUserQuery(query, me); - const notes: Note[] = await query.take(ps.limit).getMany(); - - return await Notes.packMany(notes, me); - } else if (sonic) { - let start = 0; - const chunkSize = 100; - - // Use sonic to fetch and step through all search results that could match the requirements - const ids = []; - while (true) { - const results = await sonic.search.query( - sonic.collection, - sonic.bucket, - ps.query, - { - limit: chunkSize, - offset: start, - }, - ); - - start += chunkSize; - - if (results.length === 0) { - break; - } - - const res = results - .map((k) => JSON.parse(k)) - .filter((key) => { - if (ps.userId && key.userId !== ps.userId) { - return false; - } - if (ps.channelId && key.channelId !== ps.channelId) { - return false; - } - if (ps.sinceId && key.id <= ps.sinceId) { - return false; - } - if (ps.untilId && key.id >= ps.untilId) { - return false; - } - return true; - }) - .map((key) => key.id); - - ids.push(...res); - } - - // Sort all the results by note id DESC (newest first) - ids.sort((a, b) => b - a); - - // Fetch the notes from the database until we have enough to satisfy the limit - start = 0; - const found = []; - while (found.length < ps.limit && start < ids.length) { - const chunk = ids.slice(start, start + chunkSize); - const notes: Note[] = await Notes.find({ - where: { - id: In(chunk), - }, - }); - - // The notes are checked for visibility and muted/blocked users when packed - found.push(...(await Notes.packMany(notes, me))); - start += chunkSize; - } - - // If we have more results than the limit, trim them - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; - } else if (meilisearch) { - let start = 0; - const chunkSize = 100; - const sortByDate = ps.order !== "relevancy"; - - type NoteResult = { - id: string; - createdAt: number; - }; - const extractedNotes: NoteResult[] = []; - - while (true) { - const searchRes = await meilisearch.search( - ps.query, - chunkSize, - start, - me, - sortByDate ? "createdAt:desc" : null, - ); - const results: MeilisearchNote[] = searchRes.hits as MeilisearchNote[]; - - start += chunkSize; - - if (results.length === 0) { - break; - } - - const res = results - .filter((key: MeilisearchNote) => { - if (ps.userId && key.userId !== ps.userId) { - return false; - } - if (ps.channelId && key.channelId !== ps.channelId) { - return false; - } - if (ps.sinceId && key.id <= ps.sinceId) { - return false; - } - if (ps.untilId && key.id >= ps.untilId) { - return false; - } - return true; - }) - .map((key) => { - return { - id: key.id, - createdAt: key.createdAt, - }; - }); - - extractedNotes.push(...res); - } - - // Fetch the notes from the database until we have enough to satisfy the limit - start = 0; - const found = []; - const noteIDs = extractedNotes.map((note) => note.id); - - // Index the ID => index number into a map, so we can restore the array ordering efficiently later - const idIndexMap = new Map(noteIDs.map((id, index) => [id, index])); - - while (found.length < ps.limit && start < noteIDs.length) { - const chunk = noteIDs.slice(start, start + chunkSize); - - let query: FindManyOptions = { - where: { - id: In(chunk), - }, - }; - - const notes: Note[] = await Notes.find(query); - - // Re-order the note result according to the noteIDs array (cannot be undefined, we map this earlier) - // @ts-ignore - notes.sort((a, b) => idIndexMap.get(a.id) - idIndexMap.get(b.id)); - - // The notes are checked for visibility and muted/blocked users when packed - found.push(...(await Notes.packMany(notes, me))); - start += chunkSize; - } - - // If we have more results than the limit, trim the results down - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; - } else { - const userQuery = - ps.userId != null - ? [ - { - term: { - userId: ps.userId, - }, - }, - ] - : []; - - const hostQuery = - ps.userId == null - ? ps.host === null - ? [ - { - bool: { - must_not: { - exists: { - field: "userHost", - }, - }, - }, - }, - ] - : ps.host !== undefined - ? [ - { - term: { - userHost: ps.host, - }, - }, - ] - : [] - : []; - - const result = await es.search({ - index: config.elasticsearch.index || "misskey_note", - body: { - size: ps.limit, - from: ps.offset, - query: { - bool: { - must: [ - { - simple_query_string: { - fields: ["text"], - query: ps.query.toLowerCase(), - default_operator: "and", - }, - }, - ...hostQuery, - ...userQuery, - ], - }, - }, - sort: [ - { - _doc: "desc", - }, - ], - }, - }); - - const hits = result.body.hits.hits.map((hit: any) => hit._id); - - if (hits.length === 0) return []; - - // Fetch found notes - const notes = await Notes.find({ - where: { - id: In(hits), - }, - order: { - id: -1, - }, - }); - - return await Notes.packMany(notes, me); + return await query.take(ps.limit).getMany(); } + + let notes: Note[]; + + if (ps.query != null) { + const q = sqlLikeEscape(ps.query); + + if (ps.searchCwAndAlt) { + // Whether we should return latest notes first + const isDescendingOrder = + (ps.sinceId == null || ps.untilId != null) && + (ps.sinceId != null || + ps.untilId != null || + ps.sinceDate == null || + ps.untilDate != null); + + const compare = isDescendingOrder + ? (lhs: Note, rhs: Note) => + Math.sign(rhs.createdAt.getTime() - lhs.createdAt.getTime()) + : (lhs: Note, rhs: Note) => + Math.sign(lhs.createdAt.getTime() - rhs.createdAt.getTime()); + + notes = [ + ...new Map( + ( + await Promise.all([ + search((query) => { + query.andWhere("note.text &@~ :q", { q }); + }), + search((query) => { + query.andWhere("note.cw &@~ :q", { q }); + }), + search((query) => { + query + .andWhere("drive_file.comment &@~ :q", { q }) + .innerJoin("note.files", "drive_file"); + }), + ]) + ) + .flatMap((e) => e) + .map((note) => [note.id, note]), + ).values(), + ] + .sort(compare) + .slice(0, ps.limit); + } else { + notes = await search((query) => { + query.andWhere("note.text &@~ :q", { q }); + }); + } + } else { + notes = await search(); + } + + return await Notes.packMany(notes, me); }); diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index d1de399936..094b7fed33 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -1,11 +1,7 @@ -import { URLSearchParams } from "node:url"; -import fetch from "node-fetch"; -import config from "@/config/index.js"; -import { Converter } from "opencc-js"; -import { getAgentByUrl } from "@/misc/fetch.js"; -import { fetchMeta } from "@/misc/fetch-meta.js"; import { ApiError } from "@/server/api/error.js"; import { getNote } from "@/server/api/common/getters.js"; +import { translate } from "@/misc/translate.js"; +import type { PostLanguage } from "@/misc/langmap.js"; import define from "@/server/api/define.js"; export const meta = { @@ -38,13 +34,6 @@ export const paramDef = { required: ["noteId", "targetLang"], } as const; -function convertChinese(convert: boolean, src: string) { - if (!convert) return src; - - const converter = Converter({ from: "cn", to: "twp" }); - return converter(src); -} - export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch((err) => { if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") @@ -56,86 +45,9 @@ export default define(meta, paramDef, async (ps, user) => { return 204; } - const instance = await fetchMeta(); - - if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) { - return 204; // TODO: 良い感じのエラー返す - } - - let targetLang = ps.targetLang; - if (targetLang.includes("-")) targetLang = targetLang.split("-")[0]; - if (targetLang.includes("_")) targetLang = targetLang.split("_")[0]; - - if (instance.libreTranslateApiUrl != null) { - const jsonBody = { - q: note.text, - source: "auto", - target: targetLang, - format: "text", - api_key: instance.libreTranslateApiKey ?? "", - }; - - const url = new URL(instance.libreTranslateApiUrl); - if (url.pathname.endsWith("/")) { - url.pathname = url.pathname.slice(0, -1); - } - if (!url.pathname.endsWith("/translate")) { - url.pathname += "/translate"; - } - const res = await fetch(url.toString(), { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(jsonBody), - agent: getAgentByUrl, - }); - - const json = (await res.json()) as { - detectedLanguage?: { - confidence: number; - language: string; - }; - translatedText: string; - }; - - return { - sourceLang: json.detectedLanguage?.language, - text: convertChinese(ps.targetLang === "zh-TW", json.translatedText), - }; - } - - const params = new URLSearchParams(); - params.append("auth_key", instance.deeplAuthKey ?? ""); - params.append("text", note.text); - params.append("target_lang", targetLang); - - const endpoint = instance.deeplIsPro - ? "https://api.deepl.com/v2/translate" - : "https://api-free.deepl.com/v2/translate"; - - const res = await fetch(endpoint, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - "User-Agent": config.userAgent, - Accept: "application/json, */*", - }, - body: params, - // TODO - //timeout: 10000, - agent: getAgentByUrl, - }); - - const json = (await res.json()) as { - translations: { - detected_source_language: string; - text: string; - }[]; - }; - - return { - sourceLang: json.translations[0].detected_source_language, - text: convertChinese(ps.targetLang === "zh-TW", json.translations[0].text), - }; + return translate( + note.text, + note.lang as PostLanguage | null, + ps.targetLang as PostLanguage, + ); }); diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index ff3bfcd100..d3b6a08074 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -1,7 +1,6 @@ import * as os from "node:os"; import si from "systeminformation"; import define from "@/server/api/define.js"; -import meilisearch from "@/db/meilisearch.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; export const meta = { @@ -63,15 +62,3 @@ export default define(meta, paramDef, async () => { }, }; }); - -async function meilisearchStatus() { - if (meilisearch) { - return meilisearch.serverStats(); - } else { - return { - health: "unconfigured", - size: 0, - indexed_count: 0, - }; - } -} diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index f57983d4b9..68f605ecb2 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -90,6 +90,11 @@ export default define(meta, paramDef, async (ps, me) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); + // TODO: federate ffVisibility + if (profile.userHost != null) { + throw new ApiError(meta.errors.forbidden); + } + if (profile.ffVisibility === "private") { if (me == null || me.id !== user.id) { throw new ApiError(meta.errors.forbidden); diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 84eb7cccc5..c6e3e06f1d 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -89,6 +89,11 @@ export default define(meta, paramDef, async (ps, me) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); + // TODO: federate ffVisibility + if (profile.userHost != null) { + throw new ApiError(meta.errors.forbidden); + } + if (profile.ffVisibility === "private") { if (me == null || me.id !== user.id) { throw new ApiError(meta.errors.forbidden); diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index 483a78865f..1f9aec25a4 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -49,6 +49,11 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const profile = await UserProfiles.findOneByOrFail({ userId: ps.userId }); + // TODO: federate publicReactions + if (profile.userHost != null) { + throw new ApiError(meta.errors.reactionsNotPublic); + } + if (!profile.publicReactions && (me == null || me.id !== ps.userId)) { throw new ApiError(meta.errors.reactionsNotPublic); } diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index 3aef6dc901..a15a0feb4b 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -78,8 +78,8 @@ export default define(meta, paramDef, async (ps, me) => { const nameQuery = Users.createQueryBuilder("user") .where( new Brackets((qb) => { - qb.where("user.name ILIKE :query", { - query: `%${sqlLikeEscape(ps.query)}%`, + qb.where("user.name &@~ :query", { + query: `${sqlLikeEscape(ps.query)}`, }); // Also search username if it qualifies as username @@ -115,8 +115,8 @@ export default define(meta, paramDef, async (ps, me) => { if (users.length < ps.limit) { const profQuery = UserProfiles.createQueryBuilder("prof") .select("prof.userId") - .where("prof.description ILIKE :query", { - query: `%${sqlLikeEscape(ps.query)}%`, + .where("prof.description &@~ :query", { + query: `${sqlLikeEscape(ps.query)}`, }); if (ps.origin === "local") { diff --git a/packages/backend/src/server/api/mastodon/endpoints/meta.ts b/packages/backend/src/server/api/mastodon/endpoints/meta.ts index c458798d5f..fbad7d5ef4 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/meta.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/meta.ts @@ -1,13 +1,19 @@ import { Entity } from "megalodon"; import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; +import { Users, Notes } from "@/models/index.js"; +import { IsNull } from "typeorm"; import { MAX_NOTE_TEXT_LENGTH, FILE_TYPE_BROWSERSAFE } from "@/const.js"; export async function getInstance( response: Entity.Instance, contact: Entity.Account, ) { - const meta = await fetchMeta(true); + const [meta, totalUsers, totalStatuses] = await Promise.all([ + fetchMeta(), + Users.count({ where: { host: IsNull() } }), + Notes.count({ where: { userHost: IsNull() } }), + ]); return { uri: response.uri, @@ -21,8 +27,8 @@ export async function getInstance( version: `3.0.0 (compatible; Firefish ${config.version})`, urls: response.urls, stats: { - user_count: response.stats.user_count, - status_count: response.stats.status_count, + user_count: totalUsers, + status_count: totalStatuses, domain_count: response.stats.domain_count, }, thumbnail: response.thumbnail || "/static-assets/transparent.png", diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index 74345b9395..79d2fe90ec 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -23,6 +23,8 @@ export default class extends Channel { return; } + if (!meta.enableGuestTimeline && this.user == null) return; + this.withReplies = params != null ? !!params.withReplies : true; // Subscribe events @@ -69,7 +71,12 @@ export default class extends Channel { // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( this.userProfile && - (await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords)) + this.user?.id !== note.userId && + (await getWordHardMute( + note, + this.userProfile.mutedWords, + this.userProfile.mutedPatterns, + )) ) return; diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index f24218df92..8f23946259 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -68,7 +68,12 @@ export default class extends Channel { // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( this.userProfile && - (await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords)) + this.user?.id !== note.userId && + (await getWordHardMute( + note, + this.userProfile.mutedWords, + this.userProfile.mutedPatterns, + )) ) return; diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index f87d7ab6d2..7f5c662b8c 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -85,7 +85,12 @@ export default class extends Channel { // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( this.userProfile && - (await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords)) + this.user?.id !== note.userId && + (await getWordHardMute( + note, + this.userProfile.mutedWords, + this.userProfile.mutedPatterns, + )) ) return; diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 2cba992b9e..1df87dbfc8 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -22,6 +22,8 @@ export default class extends Channel { return; } + if (!meta.enableGuestTimeline && this.user == null) return; + this.withReplies = params != null ? !!params.withReplies : true; // Subscribe events @@ -61,7 +63,12 @@ export default class extends Channel { // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( this.userProfile && - (await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords)) + this.user?.id !== note.userId && + (await getWordHardMute( + note, + this.userProfile.mutedWords, + this.userProfile.mutedPatterns, + )) ) return; diff --git a/packages/backend/src/server/api/stream/channels/recommended-timeline.ts b/packages/backend/src/server/api/stream/channels/recommended-timeline.ts index 12df39fca2..a9da732f89 100644 --- a/packages/backend/src/server/api/stream/channels/recommended-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/recommended-timeline.ts @@ -83,7 +83,12 @@ export default class extends Channel { // そのためレコードが存在するかのチェックでは不十分なので、改めてgetWordHardMuteを呼んでいる if ( this.userProfile && - (await getWordHardMute(note, this.user?.id, this.userProfile.mutedWords)) + this.user?.id !== note.userId && + (await getWordHardMute( + note, + this.userProfile.mutedWords, + this.userProfile.mutedPatterns, + )) ) return; diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index f15eb8c6e2..1cb8eb1eaf 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -53,7 +53,7 @@ const nodeinfo2 = async () => { name: "firefish", version: config.version, repository: meta.repositoryUrl, - homepage: "https://joinfirefish.org/", + homepage: "https://firefish.dev/firefish/firefish", }, protocols: ["activitypub"], services: { @@ -74,7 +74,7 @@ const nodeinfo2 = async () => { email: meta.maintainerEmail, }, langs: meta.langs, - tosUrl: meta.ToSUrl, + tosUrl: meta.tosUrl, repositoryUrl: meta.repositoryUrl, feedbackUrl: meta.feedbackUrl, disableRegistration: meta.disableRegistration, @@ -82,7 +82,6 @@ const nodeinfo2 = async () => { disableRecommendedTimeline: meta.disableRecommendedTimeline, disableGlobalTimeline: meta.disableGlobalTimeline, emailRequiredForSignup: meta.emailRequiredForSignup, - searchFilters: config.meilisearch ? true : false, postEditing: true, postImports: meta.experimentalFeatures?.postImports || false, enableHcaptcha: meta.enableHcaptcha, diff --git a/packages/backend/src/services/chart/core.ts b/packages/backend/src/services/chart/core.ts index d11b78c671..75177e70d0 100644 --- a/packages/backend/src/services/chart/core.ts +++ b/packages/backend/src/services/chart/core.ts @@ -463,7 +463,7 @@ export default abstract class Chart { protected commit(diff: Commit, group: string | null = null): void { for (const [k, v] of Object.entries(diff)) { if (v == null || v === 0 || (Array.isArray(v) && v.length === 0)) - // rome-ignore lint/performance/noDelete: needs to be deleted not just set to undefined + // biome-ignore lint/performance/noDelete: needs to be deleted not just set to undefined delete diff[k]; } this.buffer.push({ diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 404583861c..194e4e90f0 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -100,7 +100,7 @@ async function save( const baseUrl = new URL( meta.objectStorageBaseUrl ?? `/${meta.objectStorageBucket}`, - `${meta.objectStorageUseSSL ? "https" : "http"}://${ + `${meta.objectStorageUseSsl ? "https" : "http"}://${ meta.objectStorageEndpoint }${meta.objectStoragePort ? `:${meta.objectStoragePort}` : ""}`, ); diff --git a/packages/backend/src/services/drive/s3.ts b/packages/backend/src/services/drive/s3.ts index 8886309222..a8b51ee3f8 100644 --- a/packages/backend/src/services/drive/s3.ts +++ b/packages/backend/src/services/drive/s3.ts @@ -7,10 +7,10 @@ import { inspect } from "node:util"; export function getS3(meta: Meta) { const u = meta.objectStorageEndpoint != null - ? `${meta.objectStorageUseSSL ? "https://" : "http://"}${ + ? `${meta.objectStorageUseSsl ? "https://" : "http://"}${ meta.objectStorageEndpoint }` - : `${meta.objectStorageUseSSL ? "https://" : "http://"}example.net`; + : `${meta.objectStorageUseSsl ? "https://" : "http://"}example.net`; try { return new S3({ @@ -18,7 +18,7 @@ export function getS3(meta: Meta) { accessKeyId: meta.objectStorageAccessKey!, secretAccessKey: meta.objectStorageSecretKey!, region: meta.objectStorageRegion || undefined, - sslEnabled: meta.objectStorageUseSSL, + sslEnabled: meta.objectStorageUseSsl, s3ForcePathStyle: !meta.objectStorageEndpoint // AWS with endPoint omitted ? false : meta.objectStorageS3ForcePathStyle, diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 59665e2219..fc9913e985 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -1,6 +1,4 @@ import * as mfm from "mfm-js"; -import es from "@/db/elasticsearch.js"; -import sonic from "@/db/sonic.js"; import { publishMainStream, publishNotesStream, @@ -33,6 +31,7 @@ import { Channels, ChannelFollowings, NoteThreadMutings, + NoteFiles, } from "@/models/index.js"; import type { DriveFile } from "@/models/entities/drive-file.js"; import type { App } from "@/models/entities/app.js"; @@ -59,7 +58,6 @@ import type { UserProfile } from "@/models/entities/user-profile.js"; import { db } from "@/db/postgre.js"; import { getActiveWebhooks } from "@/misc/webhook-cache.js"; import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; -import meilisearch from "@/db/meilisearch.js"; import { redisClient } from "@/db/redis.js"; import { Mutex } from "redis-semaphore"; import { langmap } from "@/misc/langmap.js"; @@ -68,9 +66,13 @@ import { inspect } from "node:util"; const logger = new Logger("create-note"); -const mutedWordsCache = new Cache< - { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] ->("mutedWords", 60 * 5); +const hardMutesCache = new Cache< + { + userId: UserProfile["userId"]; + mutedWords: UserProfile["mutedWords"]; + mutedPatterns: UserProfile["mutedPatterns"]; + }[] +>("hardMutes", 60 * 5); type NotificationType = "reply" | "renote" | "quote" | "mention"; @@ -166,7 +168,6 @@ export default async ( createdAt: User["createdAt"]; isBot: User["isBot"]; inbox?: User["inbox"]; - isIndexable?: User["isIndexable"]; }, data: Option, silent = false, @@ -343,6 +344,12 @@ export default async ( const note = await insertNote(user, data, tags, emojis, mentionedUsers); + await NoteFiles.insert( + note.fileIds.map((fileId) => ({ noteId: note.id, fileId })), + ).catch((e) => { + logger.error(inspect(e)); + }); + res(note); // Register host @@ -361,27 +368,30 @@ export default async ( incNotesCountOfUser(user); // Word mute - mutedWordsCache + hardMutesCache .fetch(null, () => UserProfiles.find({ where: { enableWordMute: true, }, - select: ["userId", "mutedWords"], + select: ["userId", "mutedWords", "mutedPatterns"], }), ) .then((us) => { for (const u of us) { - getWordHardMute(data, u.userId, u.mutedWords).then((shouldMute) => { - if (shouldMute) { - MutedNotes.insert({ - id: genId(), - userId: u.userId, - noteId: note.id, - reason: "word", - }); - } - }); + if (u.userId === user.id) return; + getWordHardMute(note, u.mutedWords, u.mutedPatterns).then( + (shouldMute: boolean) => { + if (shouldMute) { + MutedNotes.insert({ + id: genId(), + userId: u.userId, + noteId: note.id, + reason: "word", + }); + } + }, + ); } }); @@ -654,11 +664,6 @@ export default async ( } }); } - - // Register to search database - if (user.isIndexable) { - await index(note, false); - } }); async function renderNoteOrRenoteActivity(data: Option, note: Note) { @@ -814,40 +819,6 @@ async function insertNote( } } -export async function index(note: Note, reindexing: boolean): Promise { - if (!note.text || note.visibility !== "public") return; - - if (config.elasticsearch && es) { - es.index({ - index: config.elasticsearch.index || "misskey_note", - id: note.id.toString(), - body: { - text: normalizeForSearch(note.text), - userId: note.userId, - userHost: note.userHost, - }, - }); - } - - if (sonic) { - await sonic.ingest.push( - sonic.collection, - sonic.bucket, - JSON.stringify({ - id: note.id, - userId: note.userId, - userHost: note.userHost, - channelId: note.channelId, - }), - note.text, - ); - } - - if (meilisearch && !reindexing) { - await meilisearch.ingestNote(note); - } -} - async function notifyToWatchersOfRenotee( renote: Note, user: { id: User["id"] }, diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index f22fc35eba..b6f4e6815c 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -16,12 +16,24 @@ import { import { countSameRenotes } from "@/misc/count-same-renotes.js"; import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js"; import { deliverToRelays } from "@/services/relay.js"; -import meilisearch from "@/db/meilisearch.js"; +import type { IActivity } from "@/remote/activitypub/type.js"; + +async function recalculateNotesCountOfLocalUser(user: { + id: User["id"]; + host: User["host"]; +}) { + if (Users.isLocalUser(user)) { + await Notes.countBy({ userId: user.id }).then((newCount: number) => + Users.update(user.id, { updatedAt: new Date(), notesCount: newCount }), + ); + } +} /** * 投稿を削除します。 * @param user 投稿者 * @param note 投稿 + * @param deleteFromDb false if called by making private */ export default async function ( user: { id: User["id"]; uri: User["uri"]; host: User["host"] }, @@ -45,6 +57,16 @@ export default async function ( await Notes.decrement({ id: note.replyId }, "repliesCount", 1); } + const cascadingNotes = await findCascadingNotes(note); + const affectedLocalUsers: Record< + User["id"], + { id: User["id"]; uri: User["uri"]; host: null } + > = {}; + if (Users.isLocalUser(user)) { + affectedLocalUsers[user.id] = user; + } + const instanceNotesCountDecreasement: Record = {}; + if (!quiet) { // Only broadcast "deleted" to local if the note is deleted from db if (deleteFromDb) { @@ -88,12 +110,23 @@ export default async function ( } // also deliever delete activity to cascaded notes - const cascadingNotes = (await findCascadingNotes(note)).filter( - (note) => !note.localOnly, - ); // filter out local-only notes for (const cascadingNote of cascadingNotes) { + if (deleteFromDb) { + // For other notes, publishNoteStream is also required. + publishNoteStream(cascadingNote.id, "deleted", { + deletedAt: deletedAt, + }); + } + if (!cascadingNote.user) continue; - if (!Users.isLocalUser(cascadingNote.user)) continue; + if (!Users.isLocalUser(cascadingNote.user)) { + if (!Users.isRemoteUser(cascadingNote.user)) continue; + instanceNotesCountDecreasement[cascadingNote.user.host] ??= 0; + instanceNotesCountDecreasement[cascadingNote.user.host]++; + continue; // filter out remote users + } + affectedLocalUsers[cascadingNote.user.id] ??= cascadingNote.user; + if (cascadingNote.localOnly) continue; // filter out local-only notes const content = renderActivity( renderDelete( renderTombstone(`${config.url}/notes/${cascadingNote.id}`), @@ -105,8 +138,14 @@ export default async function ( //#endregion if (Users.isRemoteUser(user)) { - registerOrFetchInstanceDoc(user.host).then((i) => { - Instances.decrement({ id: i.id }, "notesCount", 1); + instanceNotesCountDecreasement[user.host] ??= 0; + instanceNotesCountDecreasement[user.host]++; + } + for (const [host, count] of Object.entries( + instanceNotesCountDecreasement, + )) { + registerOrFetchInstanceDoc(host).then((i) => { + Instances.decrement({ id: i.id }, "notesCount", count); }); } } @@ -116,17 +155,20 @@ export default async function ( id: note.id, userId: user.id, }); - } - if (meilisearch) { - await meilisearch.deleteNotes(note.id); + // Handle cascading deletion (it's not as simple as notesCount -= 1) + await Promise.all( + Object.values(affectedLocalUsers).map((user) => + recalculateNotesCountOfLocalUser(user), + ), + ); } } async function findCascadingNotes(note: Note) { const cascadingNotes: Note[] = []; - const recursive = async (noteId: string) => { + const findRepliesAndQuotes = async (noteId: string) => { const query = Notes.createQueryBuilder("note") .where("note.replyId = :noteId", { noteId }) .orWhere( @@ -137,15 +179,18 @@ async function findCascadingNotes(note: Note) { }), ) .leftJoinAndSelect("note.user", "user"); - const replies = await query.getMany(); - for (const reply of replies) { - cascadingNotes.push(reply); - await recursive(reply.id); - } - }; - await recursive(note.id); + const repliesAndQuotes = await query.getMany(); - return cascadingNotes.filter((note) => note.userHost === null); // filter out non-local users + await Promise.all( + repliesAndQuotes.map((n: Note) => { + cascadingNotes.push(n); + return findRepliesAndQuotes(n.id); + }), + ); + }; + await findRepliesAndQuotes(note.id); + + return cascadingNotes; } async function getMentionedRemoteUsers(note: Note) { @@ -176,7 +221,7 @@ async function getMentionedRemoteUsers(note: Note) { async function deliverToConcerned( user: { id: ILocalUser["id"]; host: null }, note: Note, - content: any, + content: IActivity | null, ) { deliverToFollowers(user, content); deliverToRelays(user, content); diff --git a/packages/backend/test/activitypub.ts b/packages/backend/test/activitypub.ts index 7b6f85f5a1..21d5a3b61b 100644 --- a/packages/backend/test/activitypub.ts +++ b/packages/backend/test/activitypub.ts @@ -1,6 +1,6 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; +import * as assert from "node:assert"; import rndstr from "rndstr"; import { initDb } from "../src/db/postgre.js"; import { initTestDb } from "./utils.js"; diff --git a/packages/backend/test/ap-request.ts b/packages/backend/test/ap-request.ts index 722977fe14..0f1e0c58bb 100644 --- a/packages/backend/test/ap-request.ts +++ b/packages/backend/test/ap-request.ts @@ -1,4 +1,4 @@ -import * as assert from "assert"; +import * as assert from "node:assert"; import httpSignature from "@peertube/http-signature"; import { genRsaKeyPair } from "../src/misc/gen-key-pair.js"; import { diff --git a/packages/backend/test/api-visibility.ts b/packages/backend/test/api-visibility.ts index 49b1b5a064..67ef6e2894 100644 --- a/packages/backend/test/api-visibility.ts +++ b/packages/backend/test/api-visibility.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, post, diff --git a/packages/backend/test/api.ts b/packages/backend/test/api.ts index 0fc2f424ec..86916b1b87 100644 --- a/packages/backend/test/api.ts +++ b/packages/backend/test/api.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, post, diff --git a/packages/backend/test/block.ts b/packages/backend/test/block.ts index 100a4ab7d5..e7bc8a74df 100644 --- a/packages/backend/test/block.ts +++ b/packages/backend/test/block.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, post, diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 30f36b4653..4495a4264f 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -1,6 +1,6 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; +import * as assert from "node:assert"; import { inspect } from "node:util"; import { signup, diff --git a/packages/backend/test/extract-mentions.ts b/packages/backend/test/extract-mentions.ts index f400e1e634..cf25a15f6e 100644 --- a/packages/backend/test/extract-mentions.ts +++ b/packages/backend/test/extract-mentions.ts @@ -1,4 +1,4 @@ -import * as assert from "assert"; +import * as assert from "node:assert"; import { parse } from "mfm-js"; import { extractMentions } from "../src/misc/extract-mentions.js"; diff --git a/packages/backend/test/fetch-resource.ts b/packages/backend/test/fetch-resource.ts index 00c0d736ef..688c3ffa81 100644 --- a/packages/backend/test/fetch-resource.ts +++ b/packages/backend/test/fetch-resource.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import * as openapi from "@redocly/openapi-core"; import { async, diff --git a/packages/backend/test/ff-visibility.ts b/packages/backend/test/ff-visibility.ts index efdbe7f0f6..2cd4d3c60e 100644 --- a/packages/backend/test/ff-visibility.ts +++ b/packages/backend/test/ff-visibility.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, connectStream, diff --git a/packages/backend/test/get-file-info.ts b/packages/backend/test/get-file-info.ts index b1092af278..cfe1fd445e 100644 --- a/packages/backend/test/get-file-info.ts +++ b/packages/backend/test/get-file-info.ts @@ -1,4 +1,4 @@ -import * as assert from "assert"; +import * as assert from "node:assert"; import { dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { getFileInfo } from "../src/misc/get-file-info.js"; diff --git a/packages/backend/test/mfm.ts b/packages/backend/test/mfm.ts index 81ed95848a..215da00dea 100644 --- a/packages/backend/test/mfm.ts +++ b/packages/backend/test/mfm.ts @@ -1,4 +1,4 @@ -import * as assert from "assert"; +import * as assert from "node:assert"; import * as mfm from "mfm-js"; import { fromHtml } from "../src/mfm/from-html.js"; @@ -55,33 +55,33 @@ describe("fromHtml", () => { it("link with different text", () => { assert.deepStrictEqual( - fromHtml('

a c d

'), - "a [c](https://joinfirefish.org/b) d", + fromHtml('

a c d

'), + "a [c](https://firefish.dev/firefish) d", ); }); it("link with different text, but not encoded", () => { assert.deepStrictEqual( - fromHtml('

a c d

'), - "a [c]() d", + fromHtml('

a c d

'), + "a [c]() d", ); }); it("link with same text", () => { assert.deepStrictEqual( fromHtml( - '

a https://joinfirefish.org/b d

', + '

a https://firefish.dev/firefish/firefish d

', ), - "a https://joinfirefish.org/b d", + "a https://firefish.dev/firefish/firefish d", ); }); it("link with same text, but not encoded", () => { assert.deepStrictEqual( fromHtml( - '

a https://joinfirefish.org/ä d

', + '

a https://firefish.dev/ä d

', ), - "a d", + "a d", ); }); @@ -98,8 +98,8 @@ describe("fromHtml", () => { it("link without text", () => { assert.deepStrictEqual( - fromHtml('

a d

'), - "a https://joinfirefish.org/b d", + fromHtml('

a d

'), + "a https://firefish.dev/b d", ); }); @@ -110,15 +110,15 @@ describe("fromHtml", () => { it("mention", () => { assert.deepStrictEqual( fromHtml( - '

a @user d

', + '

a @firefish d

', ), - "a @user@joinfirefish.org d", + "a @firefish@info.firefish.dev d", ); }); it("hashtag", () => { assert.deepStrictEqual( - fromHtml('

a #a d

', [ + fromHtml('

a #a d

', [ "#a", ]), "a #a d", diff --git a/packages/backend/test/mute.ts b/packages/backend/test/mute.ts index 831c2c1ee4..25556954ab 100644 --- a/packages/backend/test/mute.ts +++ b/packages/backend/test/mute.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, post, diff --git a/packages/backend/test/note.ts b/packages/backend/test/note.ts index b78138b1ed..a889b254b5 100644 --- a/packages/backend/test/note.ts +++ b/packages/backend/test/note.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { Note } from "../src/models/entities/note.js"; import { api, diff --git a/packages/backend/test/prelude/maybe.ts b/packages/backend/test/prelude/maybe.ts index df589981c3..b88431450a 100644 --- a/packages/backend/test/prelude/maybe.ts +++ b/packages/backend/test/prelude/maybe.ts @@ -1,4 +1,4 @@ -import * as assert from "assert"; +import * as assert from "node:assert"; import { just, nothing } from "../../src/prelude/maybe.js"; describe("just", () => { diff --git a/packages/backend/test/prelude/url.ts b/packages/backend/test/prelude/url.ts index 5d08ff8924..684776f52a 100644 --- a/packages/backend/test/prelude/url.ts +++ b/packages/backend/test/prelude/url.ts @@ -1,4 +1,4 @@ -import * as assert from "assert"; +import * as assert from "node:assert"; import { query } from "../../src/prelude/url.js"; describe("url", () => { diff --git a/packages/backend/test/streaming.ts b/packages/backend/test/streaming.ts index 37171f4184..6a026b6b72 100644 --- a/packages/backend/test/streaming.ts +++ b/packages/backend/test/streaming.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { Following } from "../src/models/entities/following.js"; import { api, diff --git a/packages/backend/test/thread-mute.ts b/packages/backend/test/thread-mute.ts index 88483b51c8..08a32eaf4a 100644 --- a/packages/backend/test/thread-mute.ts +++ b/packages/backend/test/thread-mute.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, connectStream, diff --git a/packages/backend/test/tsconfig.json b/packages/backend/test/tsconfig.json index bc7a9968b5..5fafa1005f 100644 --- a/packages/backend/test/tsconfig.json +++ b/packages/backend/test/tsconfig.json @@ -26,16 +26,9 @@ "paths": { "@/*": ["../src/*"] }, - "typeRoots": [ - "../node_modules/@types", - "../src/@types" - ], - "lib": [ - "esnext" - ] + "typeRoots": ["../node_modules/@types", "../src/@types"], + "lib": ["esnext"] }, "compileOnSave": false, - "include": [ - "./**/*.ts" - ] + "include": ["./**/*.ts"] } diff --git a/packages/backend/test/user-notes.ts b/packages/backend/test/user-notes.ts index cdf5e7dbbb..9b68561b4f 100644 --- a/packages/backend/test/user-notes.ts +++ b/packages/backend/test/user-notes.ts @@ -1,7 +1,7 @@ process.env.NODE_ENV = "test"; -import * as assert from "assert"; -import * as childProcess from "child_process"; +import * as assert from "node:assert"; +import type * as childProcess from "node:child_process"; import { async, post, diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index dfacd0738a..b67dc037d4 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -1,11 +1,11 @@ -import * as childProcess from "child_process"; import { SIGKILL } from "constants"; +import * as childProcess from "node:child_process"; import * as fs from "node:fs"; import * as http from "node:http"; import * as path from "node:path"; import { dirname } from "node:path"; import { fileURLToPath } from "node:url"; -import type { endpoints, Entities } from "firefish-js"; +import type { Entities, endpoints } from "firefish-js"; import FormData from "form-data"; import got from "got"; import fetch from "node-fetch"; diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json index a900763cc4..bee0077992 100644 --- a/packages/backend/tsconfig.json +++ b/packages/backend/tsconfig.json @@ -25,24 +25,13 @@ "rootDir": "./src", "baseUrl": "./", "paths": { - "@/*": [ - "./src/*" - ] + "@/*": ["./src/*"] }, "outDir": "./built", - "types": [ - "node" - ], - "typeRoots": [ - "./node_modules/@types", - "./src/@types" - ], - "lib": [ - "esnext" - ] + "types": ["node"], + "typeRoots": ["./node_modules/@types", "./src/@types"], + "lib": ["esnext"] }, "compileOnSave": false, - "include": [ - "./src/**/*.ts" - ] + "include": ["./src/**/*.ts"] } diff --git a/packages/client/@types/theme.d.ts b/packages/client/@types/theme.d.ts index 5f1b81603d..4cfefc55a4 100644 --- a/packages/client/@types/theme.d.ts +++ b/packages/client/@types/theme.d.ts @@ -1,5 +1,5 @@ declare module "@/themes/*.json5" { - import { Theme } from "@/scripts/theme"; + import type { Theme } from "@/scripts/theme"; const theme: Theme; diff --git a/packages/client/package.json b/packages/client/package.json index 93d1e68a50..b1e5f98b6d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -33,14 +33,13 @@ "@types/tinycolor2": "1.4.6", "@types/uuid": "9.0.8", "@vitejs/plugin-vue": "5.0.4", - "@vue/compiler-sfc": "3.4.21", "@vue/runtime-core": "3.4.21", "autobind-decorator": "2.4.0", "autosize": "6.0.1", "blurhash": "2.0.5", "broadcast-channel": "7.0.0", "browser-image-resizer": "github:misskey-dev/browser-image-resizer", - "chart.js": "4.4.1", + "chart.js": "4.4.2", "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-matrix": "^2.0.1", "chartjs-plugin-gradient": "0.6.1", @@ -48,7 +47,7 @@ "city-timezones": "^1.2.1", "compare-versions": "6.1.0", "cropperjs": "2.0.0-beta.4", - "date-fns": "3.3.1", + "date-fns": "3.6.0", "emojilib": "^3.0.11", "eslint-config-prettier": "9.1.0", "eslint-plugin-file-progress": "^1.3.0", @@ -65,26 +64,27 @@ "libopenmpt-wasm": "github:TheEssem/libopenmpt-packaging#build", "matter-js": "0.19.0", "mfm-js": "0.24.0", + "moment": "2.30.1", "photoswipe": "5.4.3", "prettier": "3.2.5", "prismjs": "1.29.0", "punycode": "2.3.1", - "rollup": "4.12.0", + "rollup": "4.13.0", "s-age": "1.1.2", - "sass": "1.71.1", + "sass": "1.72.0", "seedrandom": "3.0.5", "stringz": "2.1.0", "swiper": "11.0.7", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", - "three": "0.161.0", + "three": "0.162.0", "throttle-debounce": "5.0.0", "tinycolor2": "1.6.0", "tinyld": "^1.3.4", - "typescript": "5.3.3", - "unicode-emoji-json": "^0.4.0", + "typescript": "5.4.3", + "unicode-emoji-json": "^0.6.0", "uuid": "9.0.1", - "vite": "5.1.4", + "vite": "5.2.4", "vite-plugin-compression": "^0.5.1", "vue": "3.4.21", "vue-draggable-plus": "^0.3.5", diff --git a/packages/client/src/account.ts b/packages/client/src/account.ts index 756e94c971..140d865f01 100644 --- a/packages/client/src/account.ts +++ b/packages/client/src/account.ts @@ -2,9 +2,8 @@ import type { entities } from "firefish-js"; import { defineAsyncComponent } from "vue"; import { i18n } from "./i18n"; import { apiUrl } from "@/config"; +import { me } from "@/me"; import { alert, api, popup, popupMenu, waiting } from "@/os"; -import { $i } from "@/reactiveAccount"; -import icon from "@/scripts/icon"; import { del, get, set } from "@/scripts/idb-proxy"; import { reloadChannel, unisonReload } from "@/scripts/unison-reload"; @@ -12,11 +11,11 @@ import { reloadChannel, unisonReload } from "@/scripts/unison-reload"; export type Account = entities.MeDetailed; -export async function signout() { +export async function signOut() { waiting(); localStorage.removeItem("account"); - await removeAccount($i.id); + await removeAccount(me.id); const accounts = await getAccounts(); @@ -29,7 +28,7 @@ export async function signout() { await fetch(`${apiUrl}/sw/unregister`, { method: "POST", body: JSON.stringify({ - i: $i.token, + i: me.token, endpoint: push.endpoint, }), }); @@ -48,7 +47,7 @@ export async function signout() { document.cookie = "igi=; path=/"; - if (accounts.length > 0) login(accounts[0].token); + if (accounts.length > 0) signIn(accounts[0].token); else unisonReload("/"); } @@ -90,7 +89,7 @@ function fetchAccount(token: string): Promise { if (res.error) { if (res.error.id === "a8c724b3-6e9c-4b46-b1a8-bc3ed6258370") { showSuspendedDialog(); - signout(); + signOut(); } else { alert({ type: "error", @@ -117,22 +116,23 @@ function showSuspendedDialog() { export function updateAccount(accountData) { for (const [key, value] of Object.entries(accountData)) { - $i[key] = value; + me[key] = value; } - localStorage.setItem("account", JSON.stringify($i)); + localStorage.setItem("account", JSON.stringify(me)); } -export function refreshAccount() { - return fetchAccount($i.token).then(updateAccount); +export async function refreshAccount() { + const accountData = await fetchAccount(me.token); + return updateAccount(accountData); } -export async function login(token: Account["token"], redirect?: string) { +export async function signIn(token: Account["token"], redirect?: string) { waiting(); if (_DEV_) console.log("logging as token ", token); - const me = await fetchAccount(token); - localStorage.setItem("account", JSON.stringify(me)); + const newAccount = await fetchAccount(token); + localStorage.setItem("account", JSON.stringify(newAccount)); document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う - await addAccount(me.id, token); + await addAccount(newAccount.id, token); if (redirect) { // 他のタブは再読み込みするだけ @@ -190,11 +190,11 @@ export async function openAccountMenu( } function switchAccountWithToken(token: string) { - login(token); + signIn(token); } const storedAccounts = await getAccounts().then((accounts) => - accounts.filter((x) => x.id !== $i.id), + accounts.filter((x) => x.id !== me.id), ); const accountsPromise = api("users/show", { userIds: storedAccounts.map((x) => x.id), @@ -256,12 +256,12 @@ export async function openAccountMenu( { type: "link", text: i18n.ts.profile, - to: `/@${$i.username}`, - avatar: $i, + to: `/@${me.username}`, + avatar: me, }, null, ]), - ...(opts.includeCurrentAccount ? [createItem($i)] : []), + ...(opts.includeCurrentAccount ? [createItem(me)] : []), ...accountItemPromises, ...(isMobile ?? false ? [ @@ -269,8 +269,8 @@ export async function openAccountMenu( { type: "link", text: i18n.ts.profile, - to: `/@${$i.username}`, - avatar: $i, + to: `/@${me.username}`, + avatar: me, }, ] : [ @@ -304,7 +304,7 @@ export async function openAccountMenu( } else { popupMenu( [ - ...(opts.includeCurrentAccount ? [createItem($i)] : []), + ...(opts.includeCurrentAccount ? [createItem(me)] : []), ...accountItemPromises, ], ev.currentTarget ?? ev.target, diff --git a/packages/client/src/components/MkAutocomplete.vue b/packages/client/src/components/MkAutocomplete.vue index 88fa83d5c7..9a8582f19a 100644 --- a/packages/client/src/components/MkAutocomplete.vue +++ b/packages/client/src/components/MkAutocomplete.vue @@ -92,10 +92,10 @@ import { ref, watch, } from "vue"; +import { acct } from "firefish-js"; import contains from "@/scripts/contains"; import { char2filePath } from "@/scripts/twemoji-base"; import { getStaticImageUrl } from "@/scripts/get-static-image-url"; -import { acct } from "firefish-js"; import * as os from "@/os"; import { MFM_TAGS } from "@/scripts/mfm-tags"; import { defaultStore } from "@/store"; diff --git a/packages/client/src/components/MkChatPreview.vue b/packages/client/src/components/MkChatPreview.vue index b5075073f7..1b330b7b2d 100644 --- a/packages/client/src/components/MkChatPreview.vue +++ b/packages/client/src/components/MkChatPreview.vue @@ -4,7 +4,7 @@ :class="{ isMe: isMe(message), isRead: message.groupId - ? message.reads.includes($i?.id) + ? message.reads.includes(me?.id) : message.isRead, }" :to=" @@ -65,16 +65,16 @@ diff --git a/packages/client/src/components/MkCropperDialog.vue b/packages/client/src/components/MkCropperDialog.vue index 97418aa65d..1dfbd1e2d5 100644 --- a/packages/client/src/components/MkCropperDialog.vue +++ b/packages/client/src/components/MkCropperDialog.vue @@ -42,7 +42,7 @@ import Cropper from "cropperjs"; import tinycolor from "tinycolor2"; import XModalWindow from "@/components/MkModalWindow.vue"; import * as os from "@/os"; -import { $i } from "@/reactiveAccount"; +import { me } from "@/me"; import { defaultStore } from "@/store"; import { apiUrl, url } from "@/config"; import { query } from "@/scripts/url"; @@ -81,7 +81,7 @@ const ok = async () => { method: "POST", body: formData, headers: { - authorization: `Bearer ${$i.token}`, + authorization: `Bearer ${me.token}`, }, }) .then((response) => response.json()) diff --git a/packages/client/src/components/MkDialog.vue b/packages/client/src/components/MkDialog.vue index f93e164997..2dca900235 100644 --- a/packages/client/src/components/MkDialog.vue +++ b/packages/client/src/components/MkDialog.vue @@ -101,15 +101,6 @@ " /> - {{ - showCancelButton || input || select + okText ?? + (showCancelButton || input || select ? i18n.ts.ok - : i18n.ts.gotIt + : i18n.ts.gotIt) }} {{ i18n.ts.cancel }}{{ cancelText ?? i18n.ts.cancel }}
@@ -203,13 +195,11 @@ diff --git a/packages/client/src/components/MkSignin.vue b/packages/client/src/components/MkSignin.vue index 7fb2e6f16a..53a593fb13 100644 --- a/packages/client/src/components/MkSignin.vue +++ b/packages/client/src/components/MkSignin.vue @@ -142,7 +142,7 @@ import MkInfo from "@/components/MkInfo.vue"; import { host as configHost } from "@/config"; import { byteify, hexify } from "@/scripts/2fa"; import * as os from "@/os"; -import { login } from "@/account"; +import { signIn } from "@/account"; import { i18n } from "@/i18n"; import icon from "@/scripts/icon"; @@ -195,7 +195,7 @@ function onUsernameChange() { function onLogin(res) { if (props.autoSet) { - return login(res.i); + return signIn(res.i); } } diff --git a/packages/client/src/components/MkSignup.vue b/packages/client/src/components/MkSignup.vue index d855e09a13..6de17b2d48 100644 --- a/packages/client/src/components/MkSignup.vue +++ b/packages/client/src/components/MkSignup.vue @@ -1,11 +1,6 @@ + + + + diff --git a/packages/client/src/components/MkSubNoteContent.vue b/packages/client/src/components/MkSubNoteContent.vue index a7eb97bacb..3c1e2a418b 100644 --- a/packages/client/src/components/MkSubNoteContent.vue +++ b/packages/client/src/components/MkSubNoteContent.vue @@ -30,7 +30,8 @@ class="text" :text="note.cw" :author="note.user" - :i="$i" + :lang="note.lang" + :i="me" :custom-emojis="note.emojis" />

@@ -102,7 +103,8 @@ v-if="note.text" :text="note.text" :author="note.user" - :i="$i" + :i="me" + :lang="note.lang" :custom-emojis="note.emojis" /> import { computed, onUnmounted, provide, ref } from "vue"; +import type { Endpoints } from "firefish-js"; import MkPullToRefresh from "@/components/MkPullToRefresh.vue"; import XNotes from "@/components/MkNotes.vue"; import MkInfo from "@/components/MkInfo.vue"; import { useStream } from "@/stream"; import * as sound from "@/scripts/sound"; -import { $i, isSignedIn } from "@/reactiveAccount"; +import { isSignedIn, me } from "@/me"; import { i18n } from "@/i18n"; import { defaultStore } from "@/store"; import icon from "@/scripts/icon"; import type { Paging } from "@/components/MkPagination.vue"; -import type { Endpoints } from "firefish-js"; const props = defineProps<{ src: string; @@ -74,7 +74,23 @@ const tlComponent = ref>(); const pullToRefreshComponent = ref>(); let endpoint = ""; // keyof Endpoints -let query, connection, connection2; +let query: { + antennaId?: string | undefined; + withReplies?: boolean; + visibility?: string; + listId?: string | undefined; + channelId?: string | undefined; + fileId?: string | undefined; +}; +let connection: { + on: ( + arg0: string, + arg1: { (note: any): void; (note: any): void; (note: any): void }, + ) => void; + dispose: () => void; +}; +let connection2: { dispose: () => void } | null; + let tlHint: string; let tlHintClosed: boolean; let tlNotesCount = 0; @@ -87,7 +103,7 @@ const prepend = (note) => { emit("note"); if (props.sound) { - sound.play(isSignedIn && note.userId === $i.id ? "noteMy" : "note"); + sound.play(isSignedIn && note.userId === me.id ? "noteMy" : "note"); } }; diff --git a/packages/client/src/components/MkTutorialDialog.vue b/packages/client/src/components/MkTutorialDialog.vue index 9155d48e8a..9616c24802 100644 --- a/packages/client/src/components/MkTutorialDialog.vue +++ b/packages/client/src/components/MkTutorialDialog.vue @@ -211,7 +211,7 @@ import MkPushNotificationAllowButton from "@/components/MkPushNotificationAllowB import FormSwitch from "@/components/form/switch.vue"; import { defaultStore } from "@/store"; import { i18n } from "@/i18n"; -import { isModerator } from "@/reactiveAccount"; +import { isModerator } from "@/me"; import { instance } from "@/instance"; import icon from "@/scripts/icon"; diff --git a/packages/client/src/components/MkUserInfo.vue b/packages/client/src/components/MkUserInfo.vue index 9229993341..eb4940858a 100644 --- a/packages/client/src/components/MkUserInfo.vue +++ b/packages/client/src/components/MkUserInfo.vue @@ -8,7 +8,7 @@ :class="{ detailed }" > {{ i18n.ts.followsYou }} @@ -34,7 +34,7 @@ class="mfm" :text="user.description" :author="user" - :i="$i" + :i="me" :custom-emojis="user.emojis" /> {{ @@ -56,7 +56,7 @@ @@ -80,7 +80,7 @@
@@ -97,7 +97,7 @@ import XShowMoreButton from "@/components/MkShowMoreButton.vue"; import MkNumber from "@/components/MkNumber.vue"; import { userPage } from "@/filters/user"; import { i18n } from "@/i18n"; -import { $i, isSignedIn } from "@/reactiveAccount"; +import { isSignedIn, me } from "@/me"; const props = defineProps<{ user: entities.UserDetailed; diff --git a/packages/client/src/components/MkVisibility.vue b/packages/client/src/components/MkVisibility.vue index d82fd24e1b..160dba46f4 100644 --- a/packages/client/src/components/MkVisibility.vue +++ b/packages/client/src/components/MkVisibility.vue @@ -21,8 +21,8 @@ > diff --git a/packages/client/src/components/form/switch.vue b/packages/client/src/components/form/switch.vue index 2b7c7663c4..f71f607a88 100644 --- a/packages/client/src/components/form/switch.vue +++ b/packages/client/src/components/form/switch.vue @@ -97,6 +97,7 @@ function toggle(x) { display: block; transition: inherit; color: var(--fg); + text-align: initial; > span { display: block; diff --git a/packages/client/src/components/global/MkAvatar.vue b/packages/client/src/components/global/MkAvatar.vue index d9bb3c7c3e..54ce1693a7 100644 --- a/packages/client/src/components/global/MkAvatar.vue +++ b/packages/client/src/components/global/MkAvatar.vue @@ -22,6 +22,7 @@ @@ -70,13 +70,13 @@ diff --git a/packages/client/src/pages/about.vue b/packages/client/src/pages/about.vue index 815611cdd5..3f4ddb4d7e 100644 --- a/packages/client/src/pages/about.vue +++ b/packages/client/src/pages/about.vue @@ -28,7 +28,7 @@
@@ -41,7 +41,7 @@ @click="easterEgg" />
- {{ $instance.name || host }} + {{ instance.name || host }}
@@ -49,7 +49,7 @@ @@ -70,7 +70,7 @@ i18n.ts.administrator }} @@ -78,20 +78,20 @@ i18n.ts.contact }} {{ i18n.ts.tos }} {{ i18n.t("_aboutFirefish.donateHost", { - host: $instance.name || host, + host: instance.name || host, }) }} @@ -190,7 +190,7 @@ import number from "@/filters/number"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import { deviceKind } from "@/scripts/device-kind"; -import { isModerator } from "@/reactiveAccount"; +import { isModerator } from "@/me"; import { instance } from "@/instance"; import { defaultStore } from "@/store"; import icon from "@/scripts/icon"; diff --git a/packages/client/src/pages/admin-file.vue b/packages/client/src/pages/admin-file.vue index 91a4386e16..2ac0f66288 100644 --- a/packages/client/src/pages/admin-file.vue +++ b/packages/client/src/pages/admin-file.vue @@ -172,7 +172,7 @@ import * as os from "@/os"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import { deviceKind } from "@/scripts/device-kind"; -import { isAdmin, isModerator } from "@/reactiveAccount"; +import { isAdmin, isModerator } from "@/me"; import { defaultStore } from "@/store"; import icon from "@/scripts/icon"; import "swiper/scss"; diff --git a/packages/client/src/pages/admin/database.vue b/packages/client/src/pages/admin/database.vue index e2da648123..c746c7032e 100644 --- a/packages/client/src/pages/admin/database.vue +++ b/packages/client/src/pages/admin/database.vue @@ -7,9 +7,6 @@ :display-back-button="true" /> - {{ - i18n.ts.indexPosts - }} diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue index ee5bbabb33..701a63e6c2 100644 --- a/packages/client/src/pages/admin/index.vue +++ b/packages/client/src/pages/admin/index.vue @@ -5,7 +5,7 @@
- -
- -
-

MeiliSearch

-

- {{ i18n.ts._widgets.meiliStatus }}: {{ meiliAvailable }} -

-

- {{ i18n.ts._widgets.meiliSize }}: - {{ bytes(meiliTotalSize, 1) }} -

-

- {{ i18n.ts._widgets.meiliIndexCount }}: - {{ meiliIndexCount }} -

-
-
@@ -57,7 +39,6 @@ import XPie from "../../widgets/server-metric/pie.vue"; import bytes from "@/filters/bytes"; import { useStream } from "@/stream"; import * as os from "@/os"; -import { i18n } from "@/i18n"; import icon from "@/scripts/icon"; const stream = useStream(); @@ -72,11 +53,6 @@ const memTotal = ref(0); const memUsed = ref(0); const memFree = ref(0); -const meiliProgress = ref(0); -const meiliTotalSize = ref(0); -const meiliIndexCount = ref(0); -const meiliAvailable = ref("unavailable"); - const diskUsage = computed(() => meta.fs.used / meta.fs.total); const diskTotal = computed(() => meta.fs.total); const diskUsed = computed(() => meta.fs.used); @@ -89,11 +65,6 @@ function onStats(stats) { memTotal.value = stats.mem.total; memUsed.value = stats.mem.active; memFree.value = memTotal.value - memUsed.value; - - meiliTotalSize.value = stats.meilisearch.size; - meiliIndexCount.value = stats.meilisearch.indexed_count; - meiliAvailable.value = stats.meilisearch.health; - meiliProgress.value = meiliIndexCount.value / serverStats.notesCount; } const connection = stream.useChannel("serverStats"); diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index b54e5349b3..32a2dd9688 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -125,6 +125,9 @@ + {{ + i18n.ts.disablingTimelinesInfo + }} {{ i18n.ts.enableGlobalTimeline }} + + + {{ - i18n.ts.disablingTimelinesInfo + i18n.t("publishTimelinesDescription", { + url: `${instanceDomain}/timelime`, + }) }} + {{ i18n.ts.publishTimelines }} @@ -467,6 +480,7 @@ const defaultDarkTheme: any = ref(null); const enableLocalTimeline = ref(false); const enableGlobalTimeline = ref(false); const enableRecommendedTimeline = ref(false); +const enableGuestTimeline = ref(false); const pinnedUsers = ref(""); const customMOTD = ref(""); const recommendedInstances = ref(""); @@ -487,6 +501,7 @@ const defaultReaction = ref(""); const defaultReactionCustom = ref(""); const enableServerMachineStats = ref(false); const enableIdenticonGeneration = ref(false); +const instanceDomain = ref(""); function isValidHttpUrl(src: string) { let url: URL; @@ -522,6 +537,7 @@ function stringifyMoreUrls(src: { name: string; url: string }[]): string { async function init() { const meta = await os.api("admin/meta"); if (!meta) throw new Error("No meta"); + instanceDomain.value = meta.uri; name.value = meta.name; description.value = meta.description; tosUrl.value = meta.tosUrl; @@ -539,6 +555,7 @@ async function init() { enableLocalTimeline.value = !meta.disableLocalTimeline; enableGlobalTimeline.value = !meta.disableGlobalTimeline; enableRecommendedTimeline.value = !meta.disableRecommendedTimeline; + enableGuestTimeline.value = meta.enableGuestTimeline; pinnedUsers.value = meta.pinnedUsers.join("\n"); customMOTD.value = meta.customMOTD.join("\n"); customSplashIcons.value = meta.customSplashIcons.join("\n"); @@ -591,6 +608,7 @@ function save() { disableLocalTimeline: !enableLocalTimeline.value, disableGlobalTimeline: !enableGlobalTimeline.value, disableRecommendedTimeline: !enableRecommendedTimeline.value, + enableGuestTimeline: enableGuestTimeline.value, pinnedUsers: pinnedUsers.value.split("\n"), customMOTD: customMOTD.value.split("\n"), customSplashIcons: customSplashIcons.value.split("\n"), diff --git a/packages/client/src/pages/announcements.vue b/packages/client/src/pages/announcements.vue index befa3e72f7..df2a794ba4 100644 --- a/packages/client/src/pages/announcements.vue +++ b/packages/client/src/pages/announcements.vue @@ -59,7 +59,7 @@ import * as os from "@/os"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import icon from "@/scripts/icon"; -import { isSignedIn } from "@/reactiveAccount"; +import { isSignedIn } from "@/me"; const pagination = { endpoint: "announcements" as const, diff --git a/packages/client/src/pages/auth.vue b/packages/client/src/pages/auth.vue index 74b2a8cb53..8a600f7d72 100644 --- a/packages/client/src/pages/auth.vue +++ b/packages/client/src/pages/auth.vue @@ -51,8 +51,8 @@ import XForm from "./auth.form.vue"; import MkSignin from "@/components/MkSignin.vue"; import MkKeyValue from "@/components/MkKeyValue.vue"; import * as os from "@/os"; -import { login } from "@/account"; -import { isSignedIn } from "@/reactiveAccount"; +import { signIn } from "@/account"; +import { isSignedIn } from "@/me"; import { i18n } from "@/i18n"; const props = defineProps<{ @@ -132,6 +132,6 @@ const accepted = () => { }; const onLogin = (res) => { - login(res.i); + signIn(res.i); }; diff --git a/packages/client/src/pages/authorize_interaction.vue b/packages/client/src/pages/authorize_interaction.vue new file mode 100644 index 0000000000..22c6627aa0 --- /dev/null +++ b/packages/client/src/pages/authorize_interaction.vue @@ -0,0 +1,38 @@ + + + diff --git a/packages/client/src/pages/channel.vue b/packages/client/src/pages/channel.vue index 9bba5cf721..15e8b6e256 100644 --- a/packages/client/src/pages/channel.vue +++ b/packages/client/src/pages/channel.vue @@ -71,13 +71,13 @@ [ - ...(channel.value && channel.value?.userId === $i?.id + ...(channel.value && channel.value?.userId === me?.id ? [ { icon: `${icon("ph-gear-six")}`, - text: i18n.ts.edit, + text: i18n.ts.toEdit, handler: edit, }, ] diff --git a/packages/client/src/pages/clip.vue b/packages/client/src/pages/clip.vue index 61748b7368..155983ff22 100644 --- a/packages/client/src/pages/clip.vue +++ b/packages/client/src/pages/clip.vue @@ -8,7 +8,7 @@
@@ -31,7 +31,7 @@ import { computed, provide, ref, watch } from "vue"; import type { entities } from "firefish-js"; import XNotes from "@/components/MkNotes.vue"; -import { $i, isSignedIn } from "@/reactiveAccount"; +import { isSignedIn, me } from "@/me"; import { i18n } from "@/i18n"; import * as os from "@/os"; import { definePageMetadata } from "@/scripts/page-metadata"; @@ -51,7 +51,7 @@ const pagination = { }; const isOwned: boolean | null = computed( - () => isSignedIn && clip.value && $i.id === clip.value.userId, + () => isSignedIn && clip.value && me.id === clip.value.userId, ); watch( @@ -73,7 +73,7 @@ const headerActions = computed(() => ? [ { icon: `${icon("ph-pencil")}`, - text: i18n.ts.edit, + text: i18n.ts.toEdit, handler: async (): Promise => { const { canceled, result } = await os.form( clip.value.name, diff --git a/packages/client/src/pages/drive.vue b/packages/client/src/pages/drive.vue index eefe5b4e86..545e67474b 100644 --- a/packages/client/src/pages/drive.vue +++ b/packages/client/src/pages/drive.vue @@ -1,6 +1,10 @@ diff --git a/packages/client/src/pages/explore.users.vue b/packages/client/src/pages/explore.users.vue index 48215ac066..ac68bb8d2d 100644 --- a/packages/client/src/pages/explore.users.vue +++ b/packages/client/src/pages/explore.users.vue @@ -146,7 +146,7 @@ import MkFolder from "@/components/MkFolder.vue"; import MkTab from "@/components/MkTab.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; -import { isSignedIn } from "@/reactiveAccount"; +import { isSignedIn } from "@/me"; import icon from "@/scripts/icon"; const props = defineProps<{ diff --git a/packages/client/src/pages/follow-requests-sent.vue b/packages/client/src/pages/follow-requests-sent.vue index 997ed699c1..8ca769848b 100644 --- a/packages/client/src/pages/follow-requests-sent.vue +++ b/packages/client/src/pages/follow-requests-sent.vue @@ -47,7 +47,7 @@ :text="req.followee.description" :is-note="false" :author="req.followee" - :i="$i" + :i="me" :custom-emojis="req.followee.emojis" :plain="true" :nowrap="true" @@ -64,13 +64,13 @@ diff --git a/packages/client/src/pages/page-editor/page-editor.vue b/packages/client/src/pages/page-editor/page-editor.vue index 4d1608455b..64f5995f99 100644 --- a/packages/client/src/pages/page-editor/page-editor.vue +++ b/packages/client/src/pages/page-editor/page-editor.vue @@ -179,7 +179,7 @@ import { selectFile } from "@/scripts/select-file"; import { mainRouter } from "@/router"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; -import { $i } from "@/reactiveAccount"; +import { me } from "@/me"; import icon from "@/scripts/icon"; const props = defineProps<{ @@ -189,7 +189,7 @@ const props = defineProps<{ }>(); const tab = ref("settings"); -const author = ref($i); +const author = ref(me); const readonly = ref(false); const page = ref(null); const pageId = ref(null); diff --git a/packages/client/src/pages/page.vue b/packages/client/src/pages/page.vue index 2023595880..2133d56a3d 100644 --- a/packages/client/src/pages/page.vue +++ b/packages/client/src/pages/page.vue @@ -52,7 +52,7 @@ /> @@ -11,7 +11,7 @@ @@ -135,25 +135,25 @@ @@ -179,7 +179,7 @@ import MkKeyValue from "@/components/MkKeyValue.vue"; import * as os from "@/os"; import number from "@/filters/number"; import bytes from "@/filters/bytes"; -import { $i, isAdmin, isModerator } from "@/reactiveAccount"; +import { isAdmin, isModerator, me } from "@/me"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import icon from "@/scripts/icon"; @@ -188,7 +188,7 @@ const stats = ref({}); onMounted(() => { os.api("users/stats", { - userId: $i!.id, + userId: me!.id, }).then((response) => { stats.value = response; }); diff --git a/packages/client/src/pages/settings/accounts.vue b/packages/client/src/pages/settings/accounts.vue index 2e0230d7a2..00e8050ee3 100644 --- a/packages/client/src/pages/settings/accounts.vue +++ b/packages/client/src/pages/settings/accounts.vue @@ -37,9 +37,9 @@ import { removeAccount as _removeAccount, addAccount as addAccounts, getAccounts, - login, + signIn, } from "@/account"; -import { $i } from "@/reactiveAccount"; +import { me } from "@/me"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import icon from "@/scripts/icon"; @@ -50,7 +50,7 @@ const accounts = ref(null); const init = async () => { getAccounts() .then((accounts) => { - storedAccounts.value = accounts.filter((x) => x.id !== $i!.id); + storedAccounts.value = accounts.filter((x) => x.id !== me!.id); console.log(storedAccounts.value); @@ -142,7 +142,7 @@ async function switchAccount(account: any) { } function switchAccountWithToken(token: string) { - login(token); + signIn(token); } definePageMetadata({ diff --git a/packages/client/src/pages/settings/delete-account.vue b/packages/client/src/pages/settings/delete-account.vue index f1ad8ee1b4..9d697da024 100644 --- a/packages/client/src/pages/settings/delete-account.vue +++ b/packages/client/src/pages/settings/delete-account.vue @@ -7,7 +7,7 @@ i18n.ts._accountDelete.sendEmail }} (null); const capacity = ref(null); const uploadFolder = ref(null); -const alwaysMarkNsfw = ref(isSignedIn && $i.alwaysMarkNsfw); +const alwaysMarkNsfw = ref(isSignedIn && me.alwaysMarkNsfw); const meterStyle = computed(() => { return { diff --git a/packages/client/src/pages/settings/email.vue b/packages/client/src/pages/settings/email.vue index da8578ead7..c436a6eec3 100644 --- a/packages/client/src/pages/settings/email.vue +++ b/packages/client/src/pages/settings/email.vue @@ -6,11 +6,11 @@ -