mirror of
https://git.joinfirefish.org/firefish/firefish.git
synced 2024-05-06 07:11:11 +02:00
Merge branch 'develop' into feat/alt_warning
This commit is contained in:
commit
23ec206aee
|
@ -178,19 +178,13 @@ logLevel: [
|
|||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: false)
|
||||
# Proxy remote files (default: true)
|
||||
#proxyRemoteFiles: true
|
||||
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
# TWA
|
||||
#twa:
|
||||
# nameSpace: android_app
|
||||
# packageName: tld.domain.twa
|
||||
# sha256CertFingerprints: ['AB:CD:EF']
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ node_modules
|
|||
report.*.json
|
||||
|
||||
# Rust
|
||||
packages/backend-rs/target
|
||||
/target
|
||||
|
||||
# Coverage
|
||||
coverage
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -14,6 +14,9 @@ packages/backend/.idea/vcs.xml
|
|||
node_modules
|
||||
report.*.json
|
||||
|
||||
# Cargo
|
||||
/target
|
||||
|
||||
# Cypress
|
||||
cypress/screenshots
|
||||
cypress/videos
|
||||
|
|
|
@ -3,27 +3,47 @@
|
|||
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://firefish.dev/firefish/firefish/-/blob/develop/SECURITY.md)
|
||||
🤝 By submitting this issue, you agree to follow our [Contribution Guidelines.](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md) -->
|
||||
|
||||
**What happened?** _(Please give us a brief description of what happened.)_
|
||||
## What happened? <!-- Please give us a brief description of what happened. -->
|
||||
|
||||
**What did you expect to happen?** _(Please give us a brief description of what you expected to happen.)_
|
||||
|
||||
**Version** _(What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information.)_
|
||||
## What did you expect to happen? <!-- Please give us a brief description of what you expected to happen. -->
|
||||
|
||||
**Instance** _(What instance of firefish are you using?)_
|
||||
|
||||
**What type of issue is this?** _(If this happens on your device and has to do with the user interface, it's client-side. If this happens on either with the API or the backend, or you got a server-side error in the client, it's server-side.)_
|
||||
## Version <!-- What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information. -->
|
||||
|
||||
**What browser are you using? (Client-side issues only)**
|
||||
|
||||
**What operating system are you using? (Client-side issues only)**
|
||||
## What type of issue is this? <!-- If this happens on your device and has to do with the user interface, it's client-side. If this happens on either with the API or the backend, or you got a server-side error in the client, it's server-side. -->
|
||||
|
||||
**How do you deploy Firefish on your server? (Server-side issues only)**
|
||||
- [ ] server-side
|
||||
- [ ] client-side
|
||||
- [ ] not sure
|
||||
|
||||
**What operating system are you using? (Server-side issues only)**
|
||||
<details>
|
||||
|
||||
**Relevant log output** _(Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. This will be automatically formatted into code, so no need for backticks.)_
|
||||
### Instance <!-- What instance of firefish are you using? -->
|
||||
|
||||
**Contribution Guidelines**
|
||||
|
||||
### What browser are you using? (client-side issues only)
|
||||
|
||||
|
||||
### What operating system are you using? (client-side issues only)
|
||||
|
||||
|
||||
### How do you deploy Firefish on your server? (server-side issues only)
|
||||
|
||||
|
||||
### What operating system are you using? (Server-side issues only)
|
||||
|
||||
|
||||
### Relevant log output <!-- Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. -->
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
## Contribution Guidelines
|
||||
By submitting this issue, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
||||
- [ ] I agree to follow this project's Contribution Guidelines
|
||||
- [ ] I have searched the issue tracker for similar issues, and this is not a duplicate.
|
||||
|
||||
## Are you willing to fix this bug? (optional)
|
||||
- [ ] Yes. I will fix this bug and open a merge request if the change is agreed upon.
|
||||
|
|
|
@ -3,15 +3,22 @@
|
|||
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://firefish.dev/firefish/firefish/-/blob/develop/SECURITY.md)
|
||||
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md) -->
|
||||
|
||||
**What feature would you like implemented?** _(Please give us a brief description of what you'd like.)_
|
||||
## What feature would you like implemented? <!-- Please give us a brief description of what you'd like. -->
|
||||
|
||||
**Why should we add this feature?** _(Please give us a brief description of why your feature is important.)_
|
||||
|
||||
**Version** _(What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information.)_
|
||||
## Why should we add this feature? <!-- Please give us a brief description of why your feature is important. -->
|
||||
|
||||
**Instance** _(What instance of firefish are you using?)_
|
||||
|
||||
**Contribution Guidelines**
|
||||
## Version <!-- What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information. -->
|
||||
|
||||
|
||||
## Instance <!-- What instance of firefish are you using? -->
|
||||
|
||||
|
||||
## Contribution Guidelines
|
||||
By submitting this issue, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
||||
- [ ] I agree to follow this project's Contribution Guidelines
|
||||
- [ ] I have searched the issue tracker for similar requests, and this is not a duplicate.
|
||||
|
||||
## Are you willing to implement this feature? (optional)
|
||||
- [ ] Yes. I will implement this feature and open a merge request if the change is agreed upon.
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<!-- Thanks for taking the time to make Firefish better! It's not required, but please consider using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) when making your commits. If you use VSCode, please use the [Conventional Commits extension](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits). -->
|
||||
|
||||
**What does this PR do?** _(Please give us a brief description of what this PR does.)_
|
||||
## What does this PR do? <!-- Please give us a brief description of what this PR does. -->
|
||||
|
||||
**Contribution Guidelines**
|
||||
|
||||
## Contribution Guidelines
|
||||
By submitting this merge request, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
||||
- [ ] This change is reviewed in an issue / This is a minor bug fix
|
||||
- [ ] I agree to follow this project's Contribution Guidelines
|
||||
- [ ] I have made sure to test this pull request
|
||||
- [ ] I have made sure to run `pnpm run format` before submitting this pull request
|
||||
|
@ -12,4 +14,4 @@ If this merge request makes changes to the Firefish API, please update `docs/api
|
|||
- [ ] I updated the document / This merge request doesn't include API changes
|
||||
|
||||
<!-- Uncomment if your merge request has multiple authors -->
|
||||
<!-- Co-authored-by: Name <email@email.com> -->
|
||||
<!-- Co-authored-by: Name <email@example.com> -->
|
||||
|
|
|
@ -10,6 +10,7 @@ I have updated...
|
|||
- [ ] `docs/changelog.md`
|
||||
- [ ] `docs/notice-for-admins.md`
|
||||
- [ ] `docs/api-change.md`
|
||||
- [ ] `packages/backend-rs/index.js`
|
||||
- [ ] OCI container image
|
||||
|
||||
<!-- TODO: Add automated tests (task runners are currently down) -->
|
||||
|
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
|
@ -12,6 +12,7 @@
|
|||
"esbenp.prettier-vscode",
|
||||
"redhat.vscode-yaml",
|
||||
"yoavbls.pretty-ts-errors",
|
||||
"biomejs.biome"
|
||||
"biomejs.biome",
|
||||
"rust-lang.rust-analyzer"
|
||||
]
|
||||
}
|
||||
|
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"packages/backend-rs/Cargo.toml"
|
||||
]
|
||||
}
|
2
COPYING
2
COPYING
|
@ -1,6 +1,7 @@
|
|||
Unless specified otherwise, the entirety of this repository is subject to the following:
|
||||
Copyright © 2014-2023 syuilo and contributors
|
||||
Copyright © 2022-2023 Kainoa Kanter and contributors
|
||||
Copyright © 2024 Firefish contributors
|
||||
|
||||
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.
|
||||
|
||||
|
@ -13,6 +14,7 @@ These specific configuration directories:
|
|||
|
||||
and their contents are
|
||||
Copyright © 2022-2023 Kainoa Kanter and contributors
|
||||
Copyright © 2024 Firefish contributors
|
||||
|
||||
And are distributed under The Apache License, Version 2.0, you should have received a copy of the license file as LICENSE in each specified directory.
|
||||
|
||||
|
|
428
packages/backend-rs/Cargo.lock → Cargo.lock
generated
428
packages/backend-rs/Cargo.lock → Cargo.lock
generated
|
@ -59,9 +59,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
|
|||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.16"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
|
@ -128,9 +128,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
|
||||
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"cpufeatures",
|
||||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
|
@ -157,18 +169,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.79"
|
||||
version = "0.1.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
|
||||
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -190,12 +202,17 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
|||
name = "backend-rs"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"async-trait",
|
||||
"basen",
|
||||
"bcrypt",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"cuid2",
|
||||
"emojis",
|
||||
"idna",
|
||||
"jsonschema",
|
||||
"macro_rs",
|
||||
"napi",
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
|
@ -203,12 +220,16 @@ dependencies = [
|
|||
"parse-display",
|
||||
"pretty_assertions",
|
||||
"rand",
|
||||
"regex",
|
||||
"schemars",
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -232,6 +253,12 @@ version = "0.21.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
|
@ -244,6 +271,19 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dbe4bb73fd931c4d1aaf53b35d1286c8a948ad00ec92c8e3c856f15fd027f43"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7"
|
||||
dependencies = [
|
||||
"base64 0.22.0",
|
||||
"blowfish",
|
||||
"getrandom",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bigdecimal"
|
||||
version = "0.3.1"
|
||||
|
@ -297,6 +337,15 @@ dependencies = [
|
|||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
|
@ -307,10 +356,20 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "1.3.1"
|
||||
name = "blowfish"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667"
|
||||
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0901fc8eb0aca4c83be0106d6f2db17d86a08dfc2c25f0e84464bf381158add6"
|
||||
dependencies = [
|
||||
"borsh-derive",
|
||||
"cfg_aliases",
|
||||
|
@ -318,23 +377,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "borsh-derive"
|
||||
version = "1.3.1"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd"
|
||||
checksum = "51670c3aa053938b0ee3bd67c3817e471e626151131b934038e83c5bf8de48f5"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
"syn_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.15.4"
|
||||
version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck"
|
||||
|
@ -378,9 +437,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.90"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
|
||||
checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -396,9 +455,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.35"
|
||||
version = "0.4.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
|
||||
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
@ -406,7 +465,17 @@ dependencies = [
|
|||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -440,7 +509,7 @@ dependencies = [
|
|||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -497,9 +566,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.0.1"
|
||||
version = "3.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
|
||||
checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
|
||||
dependencies = [
|
||||
"crc-catalog",
|
||||
]
|
||||
|
@ -542,7 +611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -565,9 +634,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.8"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
|
||||
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"pem-rfc7468",
|
||||
|
@ -627,18 +696,27 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.33"
|
||||
name = "emojis"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
|
||||
checksum = "4ee61eb945bff65ee7d19d157d39c67c33290ff0742907413fd5eefd29edc979"
|
||||
dependencies = [
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
@ -839,9 +917,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.12"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
|
||||
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
|
@ -858,9 +936,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
|||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.25"
|
||||
version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb"
|
||||
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -1066,7 +1144,16 @@ checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1116,7 +1203,7 @@ checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978"
|
|||
dependencies = [
|
||||
"ahash 0.8.11",
|
||||
"anyhow",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytecount",
|
||||
"clap",
|
||||
"fancy-regex",
|
||||
|
@ -1169,7 +1256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1211,6 +1298,18 @@ version = "0.4.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "macro_rs"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"napi",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.6"
|
||||
|
@ -1223,9 +1322,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
|
@ -1261,43 +1360,46 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "napi"
|
||||
version = "2.16.1"
|
||||
version = "2.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4ca998356d8ff9fba7a070dae4508a2298439c98c9f3bc9c07669538b999e8f"
|
||||
checksum = "70d04890ef4ec001fad791be785b8b920e2a3f5a6b1188e7a81dfa6197c0dee4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"chrono",
|
||||
"ctor",
|
||||
"napi-derive",
|
||||
"napi-sys",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-build"
|
||||
version = "2.1.2"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f9130fccc5f763cf2069b34a089a18f0d0883c66aceb81f2fad541a3d823c43"
|
||||
checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a"
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive"
|
||||
version = "2.16.1"
|
||||
version = "2.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b138cecf1141ae0ff5d62f4aa0e2f269aec339f66070f346ba6fb4279f1fc178"
|
||||
checksum = "aff4a63f26a7aa9fa25df6ea36675890115972b207ae516e86bd0c47e31eba39"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"convert_case",
|
||||
"napi-derive-backend",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive-backend"
|
||||
version = "1.0.63"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce5126b64f6ad9e28e30e6d15213dd378626b38f556454afebc42f7f02a90902"
|
||||
checksum = "e5e76afe642e2424ebe465406e328e4316d82af1f79256231d4b0f184c67550a"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"once_cell",
|
||||
|
@ -1305,14 +1407,14 @@ dependencies = [
|
|||
"quote",
|
||||
"regex",
|
||||
"semver",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-sys"
|
||||
version = "2.3.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b"
|
||||
checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
@ -1329,9 +1431,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
|
@ -1487,7 +1589,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1515,28 +1617,38 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parse-display"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6509d08722b53e8dafe97f2027b22ccbe3a5db83cb352931e9716b0aa44bc5c"
|
||||
checksum = "06af5f9333eb47bd9ba8462d612e37a8328a5cb80b13f0af4de4c3b89f52dee5"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"parse-display-derive",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-display-derive"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68517892c8daf78da08c0db777fcc17e07f2f63ef70041718f8a7630ad84f341"
|
||||
checksum = "dc9252f259500ee570c75adcc4e317fa6f57a1e47747d622e0bf838002a7b790"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"regex-syntax 0.7.5",
|
||||
"regex-syntax",
|
||||
"structmeta",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1561,10 +1673,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.13"
|
||||
name = "phf"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -1685,9 +1815,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -1746,7 +1876,7 @@ dependencies = [
|
|||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.2",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1757,20 +1887,14 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
|||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.2",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.5"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "rend"
|
||||
|
@ -1787,7 +1911,7 @@ version = "0.11.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
|
@ -1883,9 +2007,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.34.3"
|
||||
version = "1.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39449a79f45e8da28c57c341891b69a183044b29518bb8f86dbac9df60bb7df"
|
||||
checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"borsh",
|
||||
|
@ -1933,7 +2057,7 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2003,7 +2127,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2044,7 +2168,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"sea-bae",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
|
@ -2110,7 +2234,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2147,6 +2271,19 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
|
@ -2204,6 +2341,12 @@ version = "0.1.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -2371,7 +2514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bigdecimal",
|
||||
"bitflags 2.5.0",
|
||||
"byteorder",
|
||||
|
@ -2418,7 +2561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bigdecimal",
|
||||
"bitflags 2.5.0",
|
||||
"byteorder",
|
||||
|
@ -2500,31 +2643,31 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "structmeta"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d"
|
||||
checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"structmeta-derive",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structmeta-derive"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00"
|
||||
checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2552,9 +2695,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.55"
|
||||
version = "2.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
|
||||
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2570,7 +2713,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2635,14 +2778,14 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.34"
|
||||
version = "0.3.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
|
@ -2661,9 +2804,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
|||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.17"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
|
||||
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
|
@ -2686,9 +2829,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.36.0"
|
||||
version = "1.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
|
||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -2711,7 +2854,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2782,7 +2925,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2839,6 +2982,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
|
@ -2931,7 +3080,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -2965,7 +3114,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -3008,7 +3157,7 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3026,7 +3175,7 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3046,17 +3195,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"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",
|
||||
"windows_aarch64_gnullvm 0.52.5",
|
||||
"windows_aarch64_msvc 0.52.5",
|
||||
"windows_i686_gnu 0.52.5",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.5",
|
||||
"windows_x86_64_gnu 0.52.5",
|
||||
"windows_x86_64_gnullvm 0.52.5",
|
||||
"windows_x86_64_msvc 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3067,9 +3217,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
@ -3079,9 +3229,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -3091,9 +3241,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
@ -3103,9 +3259,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
@ -3115,9 +3271,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
@ -3127,9 +3283,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -3139,9 +3295,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
|
@ -3194,7 +3350,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[package]]
|
42
Cargo.toml
Normal file
42
Cargo.toml
Normal file
|
@ -0,0 +1,42 @@
|
|||
[workspace]
|
||||
members = ["packages/backend-rs", "packages/macro-rs"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.dependencies]
|
||||
macro_rs = { path = "packages/macro-rs" }
|
||||
|
||||
napi = { version = "2.16.2", default-features = false }
|
||||
napi-derive = "2.16.2"
|
||||
napi-build = "2.1.3"
|
||||
|
||||
argon2 = "0.5.3"
|
||||
async-trait = "0.1.80"
|
||||
basen = "0.1.0"
|
||||
bcrypt = "0.15.1"
|
||||
cfg-if = "1.0.0"
|
||||
chrono = "0.4.37"
|
||||
convert_case = "0.6.0"
|
||||
cuid2 = "0.1.2"
|
||||
emojis = "0.6.1"
|
||||
idna = "0.5.0"
|
||||
jsonschema = "0.17.1"
|
||||
once_cell = "1.19.0"
|
||||
parse-display = "0.9.0"
|
||||
pretty_assertions = "1.4.0"
|
||||
proc-macro2 = "1.0.79"
|
||||
quote = "1.0.36"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.4"
|
||||
schemars = "0.8.16"
|
||||
sea-orm = "0.12.15"
|
||||
serde = "1.0.197"
|
||||
serde_json = "1.0.115"
|
||||
serde_yaml = "0.9.34"
|
||||
syn = "2.0.58"
|
||||
thiserror = "1.0.58"
|
||||
tokio = "1.37.0"
|
||||
url = "2.5.0"
|
||||
urlencoding = "2.1.3"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
|
@ -8,9 +8,12 @@ RUN curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rust
|
|||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
|
||||
# Copy only the cargo dependency-related files first, to cache efficiently
|
||||
COPY Cargo.toml Cargo.toml
|
||||
COPY Cargo.lock Cargo.lock
|
||||
COPY packages/backend-rs/Cargo.toml packages/backend-rs/Cargo.toml
|
||||
COPY packages/backend-rs/Cargo.lock packages/backend-rs/Cargo.lock
|
||||
COPY packages/backend-rs/src/lib.rs packages/backend-rs/src/
|
||||
COPY packages/macro-rs/Cargo.toml packages/macro-rs/Cargo.toml
|
||||
COPY packages/macro-rs/src/lib.rs packages/macro-rs/src/
|
||||
|
||||
# Install cargo dependencies
|
||||
RUN cargo fetch --locked --manifest-path /firefish/packages/backend-rs/Cargo.toml
|
||||
|
|
14
Makefile
14
Makefile
|
@ -3,7 +3,7 @@ export
|
|||
|
||||
|
||||
.PHONY: pre-commit
|
||||
pre-commit: format entities update-index-js
|
||||
pre-commit: format entities napi-index
|
||||
|
||||
.PHONY: format
|
||||
format:
|
||||
|
@ -14,9 +14,9 @@ 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: napi-index
|
||||
napi-index:
|
||||
$(MAKE) -C ./packages/backend-rs update-index
|
||||
|
||||
|
||||
.PHONY: build
|
||||
|
@ -27,13 +27,13 @@ build:
|
|||
pnpm run migrate
|
||||
|
||||
|
||||
.PHONY: db.init db.up db.down
|
||||
db.init:
|
||||
$(MAKE) -C ./dev/db-container init
|
||||
.PHONY: db.up db.down db.init
|
||||
db.up:
|
||||
$(MAKE) -C ./dev/db-container up
|
||||
db.down:
|
||||
$(MAKE) -C ./dev/db-container down
|
||||
db.init:
|
||||
$(MAKE) -C ./dev/db-container init
|
||||
|
||||
.PHONY: psql redis-cli
|
||||
psql:
|
||||
|
|
27
biome.json
27
biome.json
|
@ -1,12 +1,31 @@
|
|||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.0.0/schema.json",
|
||||
"$schema": "https://biomejs.dev/schemas/1.6.4/schema.json",
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
"enabled": false
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
"recommended": true,
|
||||
"style": {
|
||||
"noUselessElse": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"include": ["*.vue"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"style": {
|
||||
"useImportType": "warn",
|
||||
"useShorthandFunctionType": "warn",
|
||||
"useTemplate": "warn",
|
||||
"noNonNullAssertion": "off",
|
||||
"useNodejsImportProtocol": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
.PHONY: init up down
|
||||
init: down up
|
||||
.PHONY: up down init
|
||||
up:
|
||||
$(COMPOSE) up --detach
|
||||
down:
|
||||
$(COMPOSE) down
|
||||
init:
|
||||
$(COMPOSE) down --volumes
|
||||
$(COMPOSE) up --detach
|
||||
|
||||
.PHONY: psql redis-cli
|
||||
psql:
|
||||
|
|
|
@ -5,6 +5,8 @@ services:
|
|||
image: docker.io/redis:7-alpine
|
||||
ports:
|
||||
- "26379:6379"
|
||||
volumes:
|
||||
- "redis-data:/data"
|
||||
db:
|
||||
image: docker.io/groonga/pgroonga:3.1.8-alpine-12
|
||||
env_file:
|
||||
|
@ -13,3 +15,10 @@ services:
|
|||
- "25432:5432"
|
||||
volumes:
|
||||
- "./install.sql:/docker-entrypoint-initdb.d/install.sql:ro"
|
||||
- "postgres-data:/var/lib/postgresql/data"
|
||||
|
||||
volumes:
|
||||
redis-data:
|
||||
name: redis-data
|
||||
postgres-data:
|
||||
name: postgres-data
|
||||
|
|
|
@ -42,6 +42,8 @@ cargo --version
|
|||
|
||||
### PostgreSQL and PGroonga
|
||||
|
||||
Firefish requires PostgreSQL v12 or later. We recommend that you install v12.x for the same reason as Node.js.
|
||||
|
||||
PostgreSQL install instructions can be found at [this page](https://www.postgresql.org/download/).
|
||||
|
||||
```sh
|
||||
|
|
|
@ -17,6 +17,7 @@ services:
|
|||
# - web
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
NODE_OPTIONS: --max-old-space-size=3072
|
||||
volumes:
|
||||
- ./custom:/firefish/custom:ro
|
||||
- ./files:/firefish/files
|
||||
|
|
|
@ -2,6 +2,18 @@
|
|||
|
||||
Breaking changes are indicated by the :warning: icon.
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Added `antennaLimit` field to the response of `meta` and `admin/meta`, and the request of `admin/update-meta` (optional).
|
||||
|
||||
## v20240413
|
||||
|
||||
- :warning: Removed `patrons` endpoint.
|
||||
|
||||
## v20240405
|
||||
|
||||
- Added `notes/history` endpoint.
|
||||
|
||||
## v20240319
|
||||
|
||||
- :warning: `followingCount` and `followersCount` in `users/show` will be `null` (instead of 0) if these values are unavailable.
|
||||
|
|
|
@ -5,6 +5,27 @@ Critical security updates are indicated by the :warning: icon.
|
|||
- 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.
|
||||
|
||||
## [v20240421](https://firefish.dev/firefish/firefish/-/merge_requests/10756/commits)
|
||||
|
||||
- Fix bugs
|
||||
|
||||
## [v20240413](https://firefish.dev/firefish/firefish/-/merge_requests/10741/commits)
|
||||
|
||||
- Add "Media" tab to user page
|
||||
- Improve federation and rendering of mathematical expressions
|
||||
- Remove donor information from the web client
|
||||
- See also: https://info.firefish.dev/notes/9s1n283sb10rh869
|
||||
- Fix bugs
|
||||
|
||||
## [v20240405](https://firefish.dev/firefish/firefish/-/merge_requests/10733/commits)
|
||||
|
||||
- Add ability to view the history of post edits (!10714)
|
||||
- Fix bugs
|
||||
|
||||
## [v20240401](https://firefish.dev/firefish/firefish/-/merge_requests/10724/commits)
|
||||
|
||||
- Fix bugs
|
||||
|
||||
## :warning: [v20240330](https://firefish.dev/firefish/firefish/-/merge_requests/10719/commits)
|
||||
|
||||
- Fix bugs (including a critical security issue)
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
BEGIN;
|
||||
|
||||
DELETE FROM "migrations" WHERE name IN (
|
||||
'AddDriveFileUsage1713451569342',
|
||||
'ConvertCwVarcharToText1713225866247',
|
||||
'FixChatFileConstraint1712855579316',
|
||||
'DropTimeZone1712425488543',
|
||||
'ExpandNoteEdit1711936358554',
|
||||
'markLocalFilesNsfwByDefault1709305200000',
|
||||
'FixMutingIndices1710690239308',
|
||||
'NoteFile1710304584214',
|
||||
|
@ -19,6 +24,99 @@ DELETE FROM "migrations" WHERE name IN (
|
|||
'RemoveNativeUtilsMigration1705877093218'
|
||||
);
|
||||
|
||||
-- AddDriveFileUsage
|
||||
ALTER TABLE "drive_file" DROP COLUMN "usageHint";
|
||||
DROP TYPE "drive_file_usage_hint_enum";
|
||||
|
||||
-- convert-cw-varchar-to-text
|
||||
DROP INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f";
|
||||
ALTER TABLE "note" ALTER COLUMN "cw" TYPE character varying(512);
|
||||
CREATE INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f" ON "note" USING "pgroonga" ("cw" pgroonga_varchar_full_text_search_ops_v2);
|
||||
|
||||
-- fix-chat-file-constraint
|
||||
ALTER TABLE "messaging_message" DROP CONSTRAINT "FK_535def119223ac05ad3fa9ef64b";
|
||||
ALTER TABLE "messaging_message" ADD CONSTRAINT "FK_535def119223ac05ad3fa9ef64b" FOREIGN KEY ("fileId") REFERENCES "drive_file"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
|
||||
|
||||
-- drop-time-zone
|
||||
ALTER TABLE "abuse_user_report" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "access_token" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "access_token" ALTER "lastUsedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "ad" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "ad" ALTER "expiresAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "announcement" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "announcement" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "announcement_read" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "antenna" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "app" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "attestation_challenge" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "auth_session" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "blocking" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "channel" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "channel" ALTER "lastNotedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "channel_following" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "channel_note_pining" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "clip" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "drive_file" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "drive_folder" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "emoji" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "following" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "follow_request" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "gallery_like" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "gallery_post" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "gallery_post" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "instance" ALTER "caughtAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "instance" ALTER "infoUpdatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "instance" ALTER "lastCommunicatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "instance" ALTER "latestRequestReceivedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "instance" ALTER "latestRequestSentAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "messaging_message" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "moderation_log" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "muting" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "muting" ALTER "expiresAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note_edit" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note_favorite" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note_reaction" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note_thread_muting" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "note_watching" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "notification" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "page" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "page" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "page_like" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "password_reset_request" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "poll" ALTER "expiresAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "poll_vote" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "promo_note" ALTER "expiresAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "promo_read" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "registration_ticket" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "registry_item" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "registry_item" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "renote_muting" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "reply_muting" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "signin" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "sw_subscription" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "used_username" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user" ALTER "lastActiveDate" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user" ALTER "lastFetchedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user" ALTER "updatedAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_group" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_group_invitation" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_group_invite" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_group_joining" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_ip" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_list" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_list_joining" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_note_pining" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_pending" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "user_security_key" ALTER "lastUsed" TYPE timestamp with time zone;
|
||||
ALTER TABLE "webhook" ALTER "createdAt" TYPE timestamp with time zone;
|
||||
ALTER TABLE "webhook" ALTER "latestSentAt" TYPE timestamp with time zone;
|
||||
|
||||
-- expand-note-edit
|
||||
ALTER TABLE "note_edit" DROP COLUMN "emojis";
|
||||
|
||||
-- markLocalFilesNsfwByDefault
|
||||
ALTER TABLE "meta" DROP COLUMN "markLocalFilesNsfwByDefault";
|
||||
|
||||
|
|
|
@ -1,9 +1,36 @@
|
|||
# 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.
|
||||
Firefish depends on the following software.
|
||||
|
||||
## Runtime dependencies
|
||||
|
||||
- At least [NodeJS](https://nodejs.org/en/) v18.17.0 (v20/v21 recommended)
|
||||
- At least [PostgreSQL](https://www.postgresql.org/) v12 (v16 recommended) with [PGroonga](https://pgroonga.github.io/) extension
|
||||
- At least [Redis](https://redis.io/) v7
|
||||
- Web Proxy (one of the following)
|
||||
- Caddy (recommended)
|
||||
- Nginx (recommended)
|
||||
- Apache
|
||||
- [FFmpeg](https://ffmpeg.org/) for video transcoding (**optional**)
|
||||
- Caching server (**optional**, one of the following)
|
||||
- [DragonflyDB](https://www.dragonflydb.io/)
|
||||
- [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/)
|
||||
|
||||
This document shows an example procedure for installing these dependencies and 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).
|
||||
|
||||
If you do not prepare your environment as document, be sure to meet the minimum dependencies given at the bottom of the page.
|
||||
|
||||
Make sure that you can use the `sudo` command before proceeding.
|
||||
|
||||
## 1. Install dependencies
|
||||
|
@ -154,7 +181,7 @@ sudo apt install ffmpeg
|
|||
1. Build
|
||||
```sh
|
||||
pnpm install --frozen-lockfile
|
||||
NODE_ENV=production pnpm run build
|
||||
NODE_ENV=production NODE_OPTIONS='--max-old-space-size=3072' pnpm run build
|
||||
```
|
||||
1. Execute database migrations
|
||||
```sh
|
||||
|
@ -242,6 +269,7 @@ In this instruction, we use [Caddy](https://caddyserver.com/) to make the Firefi
|
|||
WorkingDirectory=/home/firefish/firefish
|
||||
Environment="NODE_ENV=production"
|
||||
Environment="npm_config_cache=/tmp"
|
||||
Environment="NODE_OPTIONS=--max-old-space-size=3072"
|
||||
# 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
|
||||
|
|
|
@ -2,6 +2,33 @@
|
|||
|
||||
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).
|
||||
|
||||
## v20240413
|
||||
|
||||
### For all users
|
||||
|
||||
Upgrading may take a long time due to the large changes in the database. Please make sure to perform the operations when you have time.
|
||||
|
||||
The time required to upgrade varies greatly depending on the database size and the environment. For reference, we have checked that the database migration takes
|
||||
|
||||
- 70 seconds if the database stores 600,000 posts
|
||||
- 28 minutes if the database stores 12,000,000 posts
|
||||
|
||||
(i.e., it takes roughly (𝑛 / 470,000) minutes where 𝑛 is the number of posts) on a server with 2 GB of RAM. You may want to tweak your database configuration (`postgres.conf`) if the process is significantly slower than our experimental result.
|
||||
|
||||
The number of posts stored on your database can be found at `https://yourserver.example.com/admin/database` (or `notesCount` of `stats` API response).
|
||||
|
||||
### For systemd/pm2 users
|
||||
|
||||
- Please remove `packages/backend-rs/target` before building Firefish.
|
||||
```sh
|
||||
rm --recursive --force packages/backend-rs/target
|
||||
```
|
||||
- Please do not terminate `pnpm run migrate` even if it appears to be frozen.
|
||||
|
||||
### For Docker/Podman users
|
||||
|
||||
You may not be able to access your server for a while after starting the container.
|
||||
|
||||
## v20240326
|
||||
|
||||
### For Docker/Podman users
|
||||
|
@ -31,11 +58,11 @@ psql (PostgreSQL) 16.1
|
|||
|
||||
In this case, your PostgreSQL major version is `16`.
|
||||
|
||||
There are official installation instructions for many operating systems on <https://pgroonga.github.io/install>, 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.
|
||||
There are official installation instructions for many operating systems on <https://pgroonga.github.io/install>, so please follow the instructions on this page. However, since many users are using Ubuntu LTS or Debian, and there are no instructions for Arch Linux and Fedora, we explicitly list the instructions for Ubuntu LTS, Debian, Arch Linux and Fedora here. Please keep in mind that this is not official information and the procedures may change.
|
||||
|
||||
##### Ubuntu
|
||||
##### Ubuntu LTS
|
||||
|
||||
1. Install subdependencies and add apt repository
|
||||
1. Install subdependencies
|
||||
```sh
|
||||
sudo apt install -y software-properties-common
|
||||
sudo add-apt-repository -y universe
|
||||
|
@ -43,14 +70,35 @@ There are official installation instructions for many operating systems on <http
|
|||
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
|
||||
2. Install PGroonga (replace `16` with your PostgreSQL version)
|
||||
```sh
|
||||
# Please replace "16" with your PostgreSQL major version
|
||||
sudo apt install postgresql-16-pgdg-pgroonga
|
||||
|
||||
# Depending on your PostgreSQL installation method,
|
||||
# the above command may fail and you need to run
|
||||
# the following instead:
|
||||
# sudo apt install postgresql-16-pgroonga
|
||||
```
|
||||
|
||||
##### Debian
|
||||
|
||||
1. Install subdependencies
|
||||
```sh
|
||||
sudo apt install -y -V ca-certificates lsb-release wget
|
||||
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 -y -V ./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 -y -V ./groonga-apt-source-latest-$(lsb_release --codename --short).deb
|
||||
```
|
||||
2. Install PGroonga (replace `16` with your PostgreSQL version)
|
||||
```sh
|
||||
sudo apt install postgresql-16-pgdg-pgroonga
|
||||
|
||||
# Depending on your PostgreSQL installation method,
|
||||
# the above command may fail and you need to run
|
||||
# the following instead:
|
||||
# sudo apt install postgresql-16-pgroonga
|
||||
```
|
||||
|
||||
##### Arch Linux
|
||||
|
|
|
@ -822,7 +822,6 @@ auto: "تلقائي"
|
|||
themeColor: "لون السمة"
|
||||
size: "الحجم"
|
||||
numberOfColumn: "عدد الأعمدة"
|
||||
searchByGoogle: "غوغل"
|
||||
mutePeriod: "مدة الكتم"
|
||||
indefinitely: "أبدًا"
|
||||
tenMinutes: "10 دقائق"
|
||||
|
@ -894,9 +893,6 @@ _aboutFirefish:
|
|||
source: "الشفرة المصدرية"
|
||||
translation: "ترجم ميسكي"
|
||||
donate: "تبرع لميسكي"
|
||||
morePatrons: "نحن نقدر الدعم الذي قدمه العديد من الأشخاص الذين لم نذكرهم. شكرًا
|
||||
لكم 🥰"
|
||||
patrons: "الداعمون"
|
||||
_nsfw:
|
||||
respect: "اخف الوسائط ذات المحتوى الحساس"
|
||||
ignore: "اعرض الوسائط ذات المحتوى الحساس"
|
||||
|
|
|
@ -21,8 +21,8 @@ searchUser: Търсене на потребител
|
|||
reply: Отговор
|
||||
showMore: Покажи още
|
||||
loadMore: Зареди още
|
||||
followRequestAccepted: Заявка за последване приета
|
||||
importAndExport: Импорт/Експорт на Данни
|
||||
followRequestAccepted: Заявката за последване е приета
|
||||
importAndExport: Импорт/експорт на данни
|
||||
import: Импортиране
|
||||
download: Изтегляне
|
||||
export: Експортиране
|
||||
|
@ -34,7 +34,6 @@ searchWith: 'Търсене: {q}'
|
|||
smtpUser: Потребителско име
|
||||
notificationType: Тип известие
|
||||
searchResult: Резултати от търсенето
|
||||
searchByGoogle: Търсене
|
||||
markAsReadAllNotifications: Маркиране на всички известия като прочетени
|
||||
settingGuide: Препоръчителни настройки
|
||||
smtpPass: Парола
|
||||
|
@ -47,7 +46,7 @@ groups: Групи
|
|||
incorrectPassword: Грешна парола.
|
||||
leaveGroup: Напускане на групата
|
||||
numberOfColumn: Брой колони
|
||||
passwordLessLogin: Вход без парола
|
||||
passwordLessLogin: Влизане без парола
|
||||
newPasswordRetype: Повтори новата парола
|
||||
saveAs: Запазване като...
|
||||
resetPassword: Нулиране на паролата
|
||||
|
@ -101,6 +100,8 @@ _profile:
|
|||
metadataLabel: Етикет
|
||||
metadataEdit: Редактиране на допълнителната информация
|
||||
changeAvatar: Промяна на профилната снимка
|
||||
youCanIncludeHashtags: Можеш също да включиш хаштагове в биографията си.
|
||||
changeBanner: Промяна на банера
|
||||
addAccount: Добавяне на акаунт
|
||||
followRequestPending: Заявка за последване в изчакване
|
||||
signinHistory: История на вписванията
|
||||
|
@ -237,6 +238,7 @@ _theme:
|
|||
installedThemes: Инсталирани теми
|
||||
constant: Константа
|
||||
addConstant: Добавяне на константа
|
||||
make: Направа на тема
|
||||
_pages:
|
||||
script:
|
||||
blocks:
|
||||
|
@ -369,8 +371,8 @@ enterUsername: Въведи потребителско име
|
|||
renotedBy: Подсилено от {user}
|
||||
noNotifications: Няма известия
|
||||
instance: Сървър
|
||||
basicSettings: Основни Настройки
|
||||
otherSettings: Други Настройки
|
||||
basicSettings: Основни настройки
|
||||
otherSettings: Други настройки
|
||||
openInWindow: Отваряне в прозорец
|
||||
profile: Профил
|
||||
timeline: Инфопоток
|
||||
|
@ -638,7 +640,7 @@ _preferencesBackups:
|
|||
updatedAt: 'Обновено на: {date} {time}'
|
||||
editWidgetsExit: Готово
|
||||
done: Готово
|
||||
emailRequiredForSignup: Изискване на адрес на ел. поща за регистриране
|
||||
emailRequiredForSignup: Изискване на адрес за ел. поща за регистриране
|
||||
preview: Преглед
|
||||
privacy: Поверителност
|
||||
about: Относно
|
||||
|
@ -785,6 +787,9 @@ _menuDisplay:
|
|||
hide: Скриване
|
||||
_exportOrImport:
|
||||
allNotes: Всички публикации
|
||||
followingList: Следвани потребители
|
||||
blockingList: Блокирани потребители
|
||||
muteList: Заглушени потребители
|
||||
exploreFediverse: Разглеждане на Федивселената
|
||||
recentlyUpdatedUsers: Последно активни потребители
|
||||
uiLanguage: Език на потребителския интерфейс
|
||||
|
@ -793,7 +798,7 @@ tags: Тагове
|
|||
youHaveNoGroups: Нямаш групи
|
||||
accessibility: Достъпност
|
||||
email: Ел. поща
|
||||
emailAddress: Адрес на ел. поща
|
||||
emailAddress: Адрес за ел. поща
|
||||
addItem: Добавяне на елемент
|
||||
visibility: Видимост
|
||||
description: Описание
|
||||
|
@ -890,3 +895,40 @@ updatedAt: Обновено на
|
|||
privateDescription: Видима само за теб
|
||||
enableTimelineStreaming: Автоматично обновяване на инфопотоците
|
||||
toEdit: Редактиране
|
||||
showEmojisInReactionNotifications: Показване на емоджита в известията за реакции
|
||||
rememberNoteVisibility: Запомняне на настройките за видимост на публикациите
|
||||
drive: Диск
|
||||
banner: Банер
|
||||
public: Общодостъпна
|
||||
makeExplorable: Акаунтът да е видим в "Разглеждане"
|
||||
hideOnlineStatus: Скриване на онлайн състоянието
|
||||
customCss: Персонализиран CSS
|
||||
keepCw: Запазване на предупрежденията за съдържание
|
||||
makeReactionsPublic: Историята на реакциите да е общодостъпна
|
||||
noEmailServerWarning: Сървърът за ел. поща не е конфигуриран.
|
||||
languageForTranslation: Език за превеждане на публикации
|
||||
private: Частна
|
||||
replies: Отговори
|
||||
wordMute: Заглушаване на думи и езици
|
||||
instanceMute: Заглушаване на сървъри
|
||||
notificationSettingDesc: Избиране на какви известия да се показват.
|
||||
preventAiLearning: Предотвратяване на ИИ scraping
|
||||
indexable: Индексируем
|
||||
showPreviewByDefault: Показване на преглед при публикуване по подразбиране
|
||||
showNoAltTextWarning: Показване на предупреждение при опит за публикуване на файлове
|
||||
без описание
|
||||
makeFollowManuallyApprove: Заявките за последване да изискват одобряване
|
||||
enableEmojiReactions: Включване на реакциите с емоджи
|
||||
autoAcceptFollowed: Автоматично одобряване на заявките за последване от последвани
|
||||
потребители
|
||||
expandOnNoteClick: Отваряне на публикацията при кликване
|
||||
enableInfiniteScroll: Автоматично зареждане на повече
|
||||
noCrawle: Предотвратяване на индексирането от търсачки
|
||||
misskeyUpdated: Firefish бе обновен!
|
||||
emailNotConfiguredWarning: Адресът за ел. поща не е зададен.
|
||||
notificationSetting: Настройки за известията
|
||||
emailNotification: Известия по ел. поща
|
||||
clientSettings: Настройки за устройството
|
||||
behavior: Поведение
|
||||
detectPostLanguage: Автоматично откриване на езика и показване на бутон за превеждане
|
||||
за публикации на чужди езици
|
||||
|
|
|
@ -894,7 +894,6 @@ auto: "স্বয়ংক্রিয়"
|
|||
themeColor: "থিমের রং"
|
||||
size: "আকার"
|
||||
numberOfColumn: "কলামের সংখ্যা"
|
||||
searchByGoogle: "গুগল"
|
||||
instanceDefaultLightTheme: "ইন্সট্যান্সের ডিফল্ট লাইট থিম"
|
||||
instanceDefaultDarkTheme: "ইন্সট্যান্সের ডিফল্ট ডার্ক থিম"
|
||||
instanceDefaultThemeDescription: "অবজেক্ট ফরম্যাটে থিম কোড লিখুন"
|
||||
|
@ -976,8 +975,6 @@ _aboutFirefish:
|
|||
source: "সোর্স কোড"
|
||||
translation: "Firefish অনুবাদ করুন"
|
||||
donate: "Firefish তে দান করুন"
|
||||
morePatrons: "আরও অনেকে আমাদের সাহায্য করছেন। তাদের সবাইকে ধন্যবাদ 🥰"
|
||||
patrons: "সমর্থনকারী"
|
||||
_nsfw:
|
||||
respect: "স্পর্শকাতর মিডিয়া লুকান"
|
||||
ignore: "স্পর্শকাতর মিডিয়া লুকাবেন না"
|
||||
|
|
|
@ -135,7 +135,6 @@ userList: "Llistes"
|
|||
smtpUser: "Nom d'usuari"
|
||||
smtpPass: "Contrasenya"
|
||||
user: "Usuari"
|
||||
searchByGoogle: "Cerca"
|
||||
file: "Fitxer"
|
||||
_email:
|
||||
_follow:
|
||||
|
@ -856,7 +855,7 @@ more: Més!
|
|||
featured: Destacat
|
||||
usernameOrUserId: Nom o ID d'usuari
|
||||
noSuchUser: No s'ha trobat l'usuari
|
||||
lookup: Cerca
|
||||
lookup: Ves a
|
||||
attachFile: Afegeix fitxers
|
||||
currentPassword: Contrasenya actual
|
||||
newPassword: Nova contrasenya
|
||||
|
@ -877,7 +876,7 @@ fromDrive: Des del Disc
|
|||
uploadFromUrl: Puja des d'una adreça URL
|
||||
uploadFromUrlDescription: Adreça URL del fitxer que vols pujar
|
||||
uploadFromUrlRequested: Pujada demanada
|
||||
noMoreHistory: No hi ha res més a l'historial
|
||||
noMoreHistory: No hi ha més historial
|
||||
tos: Condicions d'ús
|
||||
start: Comença
|
||||
startMessaging: Comença una conversa
|
||||
|
@ -1577,7 +1576,7 @@ cannotUploadBecauseInappropriate: Aquest fitxer no s'ha pogut carregar perquè s
|
|||
cannotUploadBecauseNoFreeSpace: La pujada ha fallat a causa de la manca d'espai al
|
||||
Disc.
|
||||
enableAutoSensitive: Marcatge automàtic NSFW
|
||||
moveTo: Mou el compte actual al compte nou
|
||||
moveTo: Mou aquest compte a un compte nou
|
||||
customKaTeXMacro: Macros KaTeX personalitzats
|
||||
_aboutFirefish:
|
||||
contributors: Col·laboradors principals
|
||||
|
@ -1587,18 +1586,12 @@ _aboutFirefish:
|
|||
translation: Tradueix Firefish
|
||||
about: Firefish és una bifurcació de Misskey feta per ThatOneCalculator, que està
|
||||
en desenvolupament des del 2022.
|
||||
morePatrons: També agraïm el suport de molts altres ajudants que no figuren aquí.
|
||||
Gràcies! 🥰
|
||||
patrons: Mecenes de Firefish
|
||||
patronsList: Llistats cronològicament, no per la quantitat donada. Fes una donació
|
||||
amb l'enllaç de dalt per veure el teu nom aquí!
|
||||
donateTitle: T'agrada Firefish?
|
||||
pleaseDonateToFirefish: Penseu en fer una donació a Firefish per donar suport al
|
||||
seu desenvolupament.
|
||||
pleaseDonateToHost: Penseu també en fer una donació a la vostre instància, {host},
|
||||
per ajudar-lo a suportar els costos de funcionament.
|
||||
donateHost: Fes una donació a {host}
|
||||
sponsors: Patrocinadors de Calckey
|
||||
misskeyContributors: Col·laboradors de Misskey
|
||||
unknown: Desconegut
|
||||
pageLikesCount: Nombre de pàgines amb M'agrada
|
||||
|
@ -1724,7 +1717,7 @@ deleteConfirm: De veritat ho vols esborrar?
|
|||
receiveAnnouncementFromInstance: Rep notificacions d'aquest servidor
|
||||
emailNotification: Notificacions per correu electrònic
|
||||
publish: Publicar
|
||||
inChannelSearch: Buscar al canal
|
||||
inChannelSearch: Cerca al canal
|
||||
useReactionPickerForContextMenu: Obrir el selector de reaccions al fer click esquerra
|
||||
typingUsers: L'{users} està escrivint
|
||||
oneDay: Un dia
|
||||
|
@ -1762,7 +1755,7 @@ customSplashIconsDescription: Les URLS de les icones personalitzades a la pantal
|
|||
de benvinguda separades per salts de línia. Es mostraran aleatòriament cada vegada
|
||||
que un usuari carrega/recarrega la pàgina. Si us plau, assegureu-vos que les imatges
|
||||
estiguin en una URL estàtica, preferiblement amb imatges amb la de 192 x 192.
|
||||
moveFrom: Mou a aquest compte des d'un compte anterior
|
||||
moveFrom: Mou-te a aquest compte des d'un compte anterior
|
||||
moveFromLabel: 'Compte des del qual us moveu:'
|
||||
migrationConfirm: "Esteu absolutament segur que voleu migrar el vostre compte a {account}?
|
||||
Un cop ho feu, no podreu revertir-ho i no podreu tornar a utilitzar el vostre compte
|
||||
|
@ -2085,9 +2078,9 @@ _experiments:
|
|||
release: Publicà
|
||||
title: Experiments
|
||||
enablePostImports: Activar l'importació de publicacions
|
||||
postImportsCaption: Permet els usuaris importar publicacions desde comptes a Firefish,
|
||||
postImportsCaption: Permet als usuaris importar publicacions des de comptes de Firefish,
|
||||
Misskey, Mastodon, Akkoma i Pleroma. Pot fer que el servidor vagi més lent durant
|
||||
la càrrega si tens un coll d'ampolla a la cua.
|
||||
la importació si la teva cua de feina és saturada.
|
||||
noGraze: Si us plau, desactiva l'extensió del navegador "Graze for Mastodon", ja que
|
||||
interfereix amb Firefish.
|
||||
accessibility: Accessibilitat
|
||||
|
@ -2210,8 +2203,8 @@ squareCatAvatars: Mostrar avatars quadrats per a comptes de gats
|
|||
replaceChatButtonWithAccountButton: Canviar el botó de xats amb el botó de canvi de
|
||||
compte
|
||||
replaceWidgetsButtonWithReloadButton: Canviar el botó de ginys amb el botó de recarregar
|
||||
searchEngine: Motor de cerca fet servir anla barra MFM
|
||||
postSearch: Posar els resultats en aquest servidor
|
||||
searchEngine: Motor de cerca fet servir a la barra MFM
|
||||
postSearch: Publicar els resultats en aquest servidor
|
||||
showBigPostButton: Mostrar un botó gegant al formulari de publicació
|
||||
_emojiModPerm:
|
||||
unauthorized: Res
|
||||
|
@ -2238,7 +2231,7 @@ 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
|
||||
searchWords: Paraules / ID o adreça URL que vols cercar
|
||||
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
|
||||
|
@ -2251,12 +2244,12 @@ searchWordsDescription: "Per cercar publicacions, escriu el terme a buscar. Sepa
|
|||
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à
|
||||
URL o la ID en aquest camp i fes clic al botó 'Ves a'. Fent clic a 'Cerca' 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)
|
||||
searchRange: Publicat entre les dates (opcional)
|
||||
publishTimelines: Publica línies de temps per visitants
|
||||
toPost: Publicar
|
||||
publishTimelinesDescription: Si està activat, les línies de temps Global i Local es
|
||||
|
@ -2294,3 +2287,5 @@ markLocalFilesNsfwByDefaultDescription: Independentment d'aquest ajust, els usua
|
|||
afectats.
|
||||
autocorrectNoteLanguage: Mostra un avís si l'idioma de la publicació no coincideix
|
||||
amb el resultat de l'idioma detectat automàticament
|
||||
noteEditHistory: Historial d'edicions
|
||||
media: Multimèdia
|
||||
|
|
|
@ -600,7 +600,6 @@ tablet: "Tablet"
|
|||
auto: "Auto"
|
||||
size: "Velikost"
|
||||
numberOfColumn: "Počet sloupců"
|
||||
searchByGoogle: "Vyhledávání"
|
||||
indefinitely: "Navždy"
|
||||
tenMinutes: "10 minut"
|
||||
oneHour: "1 hodina"
|
||||
|
|
|
@ -923,7 +923,6 @@ auto: "Automatisch"
|
|||
themeColor: "Farbe der Ticker-Laufschrift"
|
||||
size: "Größe"
|
||||
numberOfColumn: "Spaltenanzahl"
|
||||
searchByGoogle: "Suchen"
|
||||
instanceDefaultLightTheme: "Standard-Farbkombination auf diesem Server: \"Hell\""
|
||||
instanceDefaultDarkTheme: "Standard-Farbkombination auf diesem Server: \"Dunkel\""
|
||||
instanceDefaultThemeDescription: "Gib den Farbschemencode im Objektformat ein."
|
||||
|
@ -1093,17 +1092,11 @@ _aboutFirefish:
|
|||
source: "Quellcode"
|
||||
translation: "Firefish übersetzen"
|
||||
donate: "An Firefish spenden"
|
||||
morePatrons: "Wir schätzen ebenso die Unterstützung vieler anderer hier nicht gelisteter
|
||||
Personen sehr. Danke! 🥰"
|
||||
patrons: "UnterstützerInnen"
|
||||
patronsList: Auflistung chonologisch, nicht nach Spenden-Größe. Spende über den
|
||||
Link oben, um hier aufgeführt zu werden!
|
||||
donateTitle: Gefällt dir Firefish?
|
||||
pleaseDonateToFirefish: Bitte erwäge eine Spende an Firefish, um dessen Entwicklung
|
||||
zu unterstützen.
|
||||
pleaseDonateToHost: Bitte erwäge auch, an deinen Heimatserver {host} zu spenden,
|
||||
um bei der Deckung der Betriebskosten zu helfen.
|
||||
sponsors: Firefish-Sponsoren
|
||||
donateHost: Spende an {host}
|
||||
misskeyContributors: Misskey-Mitwirkende
|
||||
_nsfw:
|
||||
|
|
|
@ -295,7 +295,6 @@ searchResult: "Αποτελέσματα αναζήτησης"
|
|||
learnMore: "Μάθετε περισσότερα"
|
||||
controlPanel: "Πίνακας ελέγχου"
|
||||
manageAccounts: "Διαχείριση Λογαριασμών"
|
||||
searchByGoogle: "Αναζήτηση"
|
||||
file: "Αρχεία"
|
||||
recommended: "Προτεινόμενα"
|
||||
cannotUploadBecauseNoFreeSpace: "Το ανέβασμα απέτυχε λόγω ανεπαρκούς Αποθηκευτικού
|
||||
|
|
|
@ -394,6 +394,7 @@ enableRegistration: "Enable new user registration"
|
|||
invite: "Invite"
|
||||
driveCapacityPerLocalAccount: "Drive capacity per local user"
|
||||
driveCapacityPerRemoteAccount: "Drive capacity per remote user"
|
||||
antennaLimit: "The maximum number of antennas that each user can create"
|
||||
inMb: "In megabytes"
|
||||
iconUrl: "Icon URL"
|
||||
bannerUrl: "Banner image URL"
|
||||
|
@ -708,6 +709,7 @@ display: "Display"
|
|||
copy: "Copy"
|
||||
metrics: "Metrics"
|
||||
overview: "Overview"
|
||||
media: "Media"
|
||||
logs: "Logs"
|
||||
delayed: "Delayed"
|
||||
database: "Database"
|
||||
|
@ -977,7 +979,6 @@ auto: "Auto"
|
|||
themeColor: "Server Ticker Color"
|
||||
size: "Size"
|
||||
numberOfColumn: "Number of columns"
|
||||
searchByGoogle: "Search"
|
||||
instanceDefaultLightTheme: "Server-wide default light theme"
|
||||
instanceDefaultDarkTheme: "Server-wide default dark theme"
|
||||
instanceDefaultThemeDescription: "Enter the theme code in object format."
|
||||
|
@ -1338,12 +1339,6 @@ _aboutFirefish:
|
|||
pleaseDonateToHost: "Please also consider donating to your home server, {host},
|
||||
to help support its operation costs."
|
||||
donateHost: "Donate to {host}"
|
||||
morePatrons: "We also appreciate the support of many other helpers not listed here.
|
||||
Thank you! 🥰"
|
||||
sponsors: "Firefish sponsors"
|
||||
patrons: "Firefish patrons"
|
||||
patronsList: "Listed chronologically, not by donation size. Donate with the link
|
||||
above to get your name on here!"
|
||||
_nsfw:
|
||||
respect: "Hide NSFW media"
|
||||
ignore: "Don't hide NSFW media"
|
||||
|
@ -2236,3 +2231,4 @@ autocorrectNoteLanguage: "Show a warning if the post language does not match the
|
|||
result"
|
||||
incorrectLanguageWarning: "It looks like your post is in {detected}, but you selected
|
||||
{current}.\nWould you like to set the language to {detected} instead?"
|
||||
noteEditHistory: "Post edit history"
|
||||
|
|
|
@ -907,7 +907,6 @@ auto: "Automático"
|
|||
themeColor: "Color de la marquesina del servidor"
|
||||
size: "Tamaño"
|
||||
numberOfColumn: "Cantidad de columnas"
|
||||
searchByGoogle: "Buscar"
|
||||
instanceDefaultLightTheme: "Tema claro por defecto del servidor"
|
||||
instanceDefaultDarkTheme: "Tema oscuro por defecto del servidor"
|
||||
instanceDefaultThemeDescription: "Ingrese el código del tema en formato objeto"
|
||||
|
@ -1074,17 +1073,11 @@ _aboutFirefish:
|
|||
source: "Código fuente"
|
||||
translation: "Traducir Firefish"
|
||||
donate: "Donar a Firefish"
|
||||
morePatrons: "También apreciamos el apoyo de muchos más que no están enlistados
|
||||
aquí. ¡Gracias! 🥰"
|
||||
patrons: "Mecenas de Firefish"
|
||||
pleaseDonateToFirefish: Por favor considera donar a Firefish para apollar su desarrollo.
|
||||
donateHost: Dona a {host}
|
||||
patronsList: Listados cronológicamente no por monto de la donación. ¡Dona con el
|
||||
vínculo de arriba para que tu nombre aparezca aquí!
|
||||
donateTitle: ¿Te gusta Firefish?
|
||||
pleaseDonateToHost: También considera donar a tu propio servidor , {host}, para
|
||||
ayudar con los costos de operación.
|
||||
sponsors: Patrocinadores de Firefish
|
||||
misskeyContributors: Contribuidores de Misskey
|
||||
_nsfw:
|
||||
respect: "Ocultar medios NSFW"
|
||||
|
|
|
@ -948,7 +948,6 @@ clickToFinishEmailVerification: Klikkaa [{ok}] viimeistelläksesi sähköpostiva
|
|||
overridedDeviceKind: Laitetyyppi
|
||||
tablet: Tabletti
|
||||
numberOfColumn: Sarakkeiden määrä
|
||||
searchByGoogle: Etsi
|
||||
mutePeriod: Vaiennuksen kesto
|
||||
indefinitely: Pysyvästi
|
||||
tenMinutes: 10 minuuttia
|
||||
|
|
|
@ -910,7 +910,6 @@ auto: "Automatique"
|
|||
themeColor: "Couleur du bandeau d'information du serveur"
|
||||
size: "Taille"
|
||||
numberOfColumn: "Nombre de colonnes"
|
||||
searchByGoogle: "Google"
|
||||
instanceDefaultLightTheme: "Thème clair par défaut sur tout le serveur"
|
||||
instanceDefaultDarkTheme: "Thème sombre par défaut sur tout le serveur"
|
||||
instanceDefaultThemeDescription: "Saisissez le code du thème en format objet."
|
||||
|
@ -997,18 +996,12 @@ _aboutFirefish:
|
|||
source: "Code source"
|
||||
translation: "Traduire Firefish"
|
||||
donate: "Soutenir Firefish"
|
||||
morePatrons: "Nous apprécions vraiment le soutien de nombreuses autres personnes
|
||||
non mentionnées ici. Merci à toutes et à tous ! 🥰"
|
||||
patrons: "Contributeurs"
|
||||
pleaseDonateToFirefish: Merci de considérer de faire un don pour soutenir le développement
|
||||
de Firefish.
|
||||
sponsors: Sponsors Firefish
|
||||
donateTitle: Firefish vous plaît ?
|
||||
pleaseDonateToHost: Également, veuillez envisager de faire un don à votre serveur
|
||||
d'accueil, {host}, pour contribuer à couvrir ses frais de fonctionnement.
|
||||
donateHost: Faire un don à {host}
|
||||
patronsList: Listé chronologiquement, pas par taille de donation. Faite un don avec
|
||||
le lien ci-dessus pour avoir votre nom affiché ici !
|
||||
misskeyContributors: Contributeurs Misskey
|
||||
_nsfw:
|
||||
respect: "Cacher les médias marqués comme contenu sensible (NSFW)"
|
||||
|
@ -2324,3 +2317,5 @@ markLocalFilesNsfwByDefault: Marquer tous les nouveaux fichiers locaux comme sen
|
|||
markLocalFilesNsfwByDefaultDescription: Indépendamment de ce réglage, les utilisateurs
|
||||
peuvent supprimer le drapeau « sensible » (NSFW) eux-mêmes. Les fichiers existants
|
||||
ne sont pas affectés.
|
||||
noteEditHistory: Historique des publications
|
||||
media: Multimédia
|
||||
|
|
|
@ -901,7 +901,6 @@ auto: "Otomatis"
|
|||
themeColor: "Warna Jam Server"
|
||||
size: "Ukuran"
|
||||
numberOfColumn: "Jumlah per kolom"
|
||||
searchByGoogle: "Penelusuran"
|
||||
instanceDefaultLightTheme: "Tema terang bawaan ranah server"
|
||||
instanceDefaultDarkTheme: "Tema gelap bawaan ranah server"
|
||||
instanceDefaultThemeDescription: "Masukkan kode tema di format obyek."
|
||||
|
@ -986,12 +985,6 @@ _aboutFirefish:
|
|||
source: "Sumber kode"
|
||||
translation: "Terjemahkan Firefish"
|
||||
donate: "Donasi ke Firefish"
|
||||
morePatrons: "Kami sangat mengapresiasi dukungan dari banyak penolong lain yang
|
||||
tidak tercantum disini. Terima kasih! 🥰"
|
||||
patrons: "Pendukung"
|
||||
patronsList: Diurutkan secara kronologis, bukan berdasarkan jumlah donasi. Berdonasilah
|
||||
dengan tautan di atas supaya nama kamu ada di sini!
|
||||
sponsors: Sponsor Firefish
|
||||
donateTitle: Suka Firefish?
|
||||
pleaseDonateToFirefish: Silakan pertimbangkan berdonasi ke Firefish untuk mendukung
|
||||
pengembangannya.
|
||||
|
@ -2272,3 +2265,5 @@ autocorrectNoteLanguage: Tampilkan peringatan jika bahasa kiriman tidak cocok de
|
|||
markLocalFilesNsfwByDefault: Tandai semua berkas lokal baru sensitif secara bawaan
|
||||
markLocalFilesNsfwByDefaultDescription: Terlepas dari pengaturan ini, pengguna dapat
|
||||
menghapus sendiri tanda NSFW. Berkas yang ada tidak berpengaruh.
|
||||
noteEditHistory: Riwayat penyuntingan kiriman
|
||||
media: Media
|
||||
|
|
|
@ -859,7 +859,6 @@ useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile"
|
|||
welcomeBackWithName: "Ciao {name}"
|
||||
clickToFinishEmailVerification: "Fai click su [{ok}] per completare la verifica dell'indirizzo
|
||||
email."
|
||||
searchByGoogle: "Cerca"
|
||||
indefinitely: "Senza scadenza"
|
||||
tenMinutes: "10 minuti"
|
||||
oneHour: "1 ora"
|
||||
|
@ -935,18 +934,12 @@ _aboutFirefish:
|
|||
source: "Codice sorgente"
|
||||
translation: "Traduzione di Firefish"
|
||||
donate: "Sostieni Firefish"
|
||||
morePatrons: "Apprezziamo sinceramente l'aiuto di tante altre persone non elencate
|
||||
qui. Grazie mille! 🥰"
|
||||
patrons: "Sostenitori"
|
||||
sponsors: Gli sponsor di Firefish
|
||||
misskeyContributors: Contributori di Misskey
|
||||
donateTitle: Ti piace Firefish?
|
||||
pleaseDonateToFirefish: Con una donazione puoi supportare lo sviluppo di Firefish.
|
||||
pleaseDonateToHost: Considera anche una donazione al server che ti ospita, {host},
|
||||
per contribuire ai costi che sostiene.
|
||||
donateHost: Dona a {host}
|
||||
patronsList: Elencati in ordine cronologico, non per importo. Dona con il link sopra
|
||||
per apparire in questa lista!
|
||||
_nsfw:
|
||||
respect: "Nascondi i media sensibli (NSFW)"
|
||||
ignore: "Mostra i media sensibili (NSFW)"
|
||||
|
|
|
@ -638,6 +638,7 @@ display: "表示"
|
|||
copy: "コピー"
|
||||
metrics: "メトリクス"
|
||||
overview: "概要"
|
||||
media: "メディア"
|
||||
logs: "ログ"
|
||||
delayed: "遅延"
|
||||
database: "データベース"
|
||||
|
@ -885,7 +886,6 @@ socialTimeline: "ソーシャルタイムライン"
|
|||
themeColor: "テーマカラー"
|
||||
size: "サイズ"
|
||||
numberOfColumn: "列の数"
|
||||
searchByGoogle: "検索"
|
||||
instanceDefaultLightTheme: "サーバーの標準ライトテーマ"
|
||||
instanceDefaultDarkTheme: "サーバーの標準ダークテーマ"
|
||||
instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。"
|
||||
|
@ -1011,11 +1011,11 @@ searchWordsDescription: "投稿を検索するには、ここに検索語句を
|
|||
「(朝 OR 夜) 眠い」のように、AND検索とOR検索を同時に行うこともできます。\n空白を含む文字列をAND検索ではなくそのまま検索したい場合、\"明日 買うもの\"\
|
||||
\ のように二重引用符 (\") で囲む必要があります。\n\n特定のユーザーや投稿のページに飛びたい場合には、この欄にID (@user@example.com)
|
||||
や投稿のURLを入力し「照会」を押してください。「検索」を押すとそのIDやURLが文字通り含まれる投稿を検索します。"
|
||||
searchUsers: "投稿元(オプション)"
|
||||
searchUsers: "投稿元(省略可)"
|
||||
searchUsersDescription: "投稿検索で投稿者を絞りたい場合、@user@example.com(ローカルユーザーなら @user)の形式で投稿者のIDを入力してください。ユーザーIDではなくドメイン名
|
||||
(example.com) を指定すると、そのサーバーの投稿を検索します。\n\nme とだけ入力すると、自分の投稿を検索します。この検索結果には未収載・フォロワー限定・ダイレクト・秘密を含む全ての投稿が含まれます。\n
|
||||
\nlocal とだけ入力すると、ローカルサーバーの投稿を検索します。"
|
||||
searchRange: "投稿期間(オプション)"
|
||||
searchRange: "投稿期間(省略可)"
|
||||
searchRangeDescription: "投稿検索で投稿期間を絞りたい場合、20220615-20231031 のような形式で投稿期間を入力してください。今年の日付を指定する場合には年の指定を省略できます(0105-0106
|
||||
や 20231105-0110 のように)。\n\n開始日と終了日のどちらか一方は省略可能です。例えば -0102 とすると今年1月2日までの投稿のみを、20231026-
|
||||
とすると2023年10月26日以降の投稿のみを検索します。"
|
||||
|
@ -1109,14 +1109,10 @@ _aboutFirefish:
|
|||
source: "ソースコード"
|
||||
translation: "Firefishを翻訳"
|
||||
donate: "Firefishに寄付"
|
||||
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます! 🥰"
|
||||
patrons: "支援者"
|
||||
patronsList: 寄付額ではなく時系列順に並んでいます。上記のリンクから寄付を行ってここにあなたのIDを載せましょう!
|
||||
pleaseDonateToFirefish: Firefish開発への寄付をご検討ください。
|
||||
pleaseDonateToHost: また、このサーバー {host} の運営者への寄付もご検討ください。
|
||||
donateHost: '{host} に寄付する'
|
||||
donateTitle: Firefishを気に入りましたか?
|
||||
sponsors: Firefish の支援者
|
||||
_nsfw:
|
||||
respect: "閲覧注意のメディアは隠す"
|
||||
ignore: "閲覧注意のメディアを隠さない"
|
||||
|
@ -2060,3 +2056,4 @@ autocorrectNoteLanguage: 設定した投稿言語が自動検出されたもの
|
|||
incorrectLanguageWarning: "この投稿は{detected}で書かれていると判定されました。\n投稿言語を{current}ではなく{detected}にしますか?"
|
||||
markLocalFilesNsfwByDefault: このサーバーの全てのファイルをデフォルトでNSFWに設定する
|
||||
markLocalFilesNsfwByDefaultDescription: この設定が有効でも、ユーザーは自分でNSFWのフラグを外すことができます。また、この設定は既存のファイルには影響しません。
|
||||
noteEditHistory: 編集履歴
|
||||
|
|
|
@ -803,7 +803,6 @@ unresolved: "まだ解決してないで"
|
|||
breakFollow: "フォロワーを解除するで"
|
||||
itsOn: "オンになっとるよ"
|
||||
hide: "隠す"
|
||||
searchByGoogle: "探す"
|
||||
indefinitely: "無期限"
|
||||
file: "ファイル"
|
||||
requireAdminForView: "これを見るには管理者アカウントでログインしとらなあかんで。"
|
||||
|
@ -875,8 +874,6 @@ _aboutFirefish:
|
|||
source: "ソースコード"
|
||||
translation: "Firefishを翻訳"
|
||||
donate: "Firefishに寄付"
|
||||
morePatrons: "他にもぎょうさんの人からサポートしてもろてんねん。ほんまおおきに🥰"
|
||||
patrons: "支援者"
|
||||
misskeyContributors: フォーク元のMisskeyを作らはった人ら
|
||||
_mfm:
|
||||
cheatSheet: "MFMチートシート"
|
||||
|
|
|
@ -54,7 +54,6 @@ accountInfo: "Talɣut n umiḍan"
|
|||
emailNotification: "Ilɣa imayl"
|
||||
selectAccount: "Fren amiḍan"
|
||||
accounts: "Imiḍan"
|
||||
searchByGoogle: "Nadi"
|
||||
file: "Ifuyla"
|
||||
account: "Imiḍan"
|
||||
_email:
|
||||
|
|
|
@ -59,7 +59,6 @@ remove: "ಅಳಿಸು"
|
|||
smtpUser: "ಬಳಕೆಹೆಸರು"
|
||||
smtpPass: "ಗುಪ್ತಪದ"
|
||||
user: "ಬಳಕೆದಾರ"
|
||||
searchByGoogle: "ಹುಡುಕು"
|
||||
file: "ಕಡತಗಳು"
|
||||
_email:
|
||||
_follow:
|
||||
|
|
|
@ -851,7 +851,6 @@ auto: "자동"
|
|||
themeColor: "테마 컬러"
|
||||
size: "크기"
|
||||
numberOfColumn: "한 줄에 보일 리액션의 수"
|
||||
searchByGoogle: "검색"
|
||||
instanceDefaultLightTheme: "서버 기본 라이트 테마"
|
||||
instanceDefaultDarkTheme: "서버 기본 다크 테마"
|
||||
instanceDefaultThemeDescription: "객체 형식의 테마 코드를 입력해 주세요."
|
||||
|
@ -993,10 +992,6 @@ _aboutFirefish:
|
|||
source: "소스 코드"
|
||||
translation: "Firefish를 번역하기"
|
||||
donate: "Firefish에 기부하기"
|
||||
morePatrons: "이 외에도 다른 많은 분들이 도움을 주시고 계십니다. 감사합니다🥰"
|
||||
patrons: "후원자"
|
||||
patronsList: 기부 금액이 아닌 시간 순서로 정렬합니다. 위 링크를 통해 후원하여 당신의 이름을 새겨 보세요!
|
||||
sponsors: Firefish 스폰서
|
||||
pleaseDonateToHost: 또한, 이 서버 {host} 의 운영자에게 기부하는 것도 검토하여 주십시오.
|
||||
pleaseDonateToFirefish: Firefish의 개발에 후원하는 것을 검토하여 주십시오.
|
||||
donateHost: '{host} 에게 기부하기'
|
||||
|
|
|
@ -326,7 +326,6 @@ user: "Gebruikers"
|
|||
muteThread: "Discussies dempen "
|
||||
unmuteThread: "Dempen van discussie ongedaan maken"
|
||||
hide: "Verbergen"
|
||||
searchByGoogle: "Zoeken"
|
||||
cropImage: "Afbeelding bijsnijden"
|
||||
cropImageAsk: "Bijsnijdengevraagd"
|
||||
file: "Bestanden"
|
||||
|
|
|
@ -902,7 +902,6 @@ swipeOnDesktop: Tillat mobil-lignende sveiping på skrivebords-PC
|
|||
migration: Migrering
|
||||
useDrawerReactionPickerForMobile: Vis reaksjosnvelger som en skuff på mobil
|
||||
numberOfColumn: Antall kolonner
|
||||
searchByGoogle: Søk
|
||||
oneWeek: En uke
|
||||
file: Fil
|
||||
recentNHours: Siste {n} timer
|
||||
|
@ -988,8 +987,6 @@ _aboutFirefish:
|
|||
pleaseDonateToFirefish: Du kan vurdere å donere en slant til Firefish for å støtte
|
||||
videre utvikling og feilretting.
|
||||
donateHost: Donér til {host}
|
||||
morePatrons: Vi er også takknemlige for bidragene fra mange andre som ikke er listet
|
||||
her. Takk til dere alle! 🥰
|
||||
contributors: Hovedutviklere
|
||||
source: Kildekode
|
||||
allContributors: Alle bidragsytere
|
||||
|
@ -997,10 +994,6 @@ _aboutFirefish:
|
|||
pleaseDonateToHost: Du kan også vurdere å donere til hjemme-tjeneren din, {host},
|
||||
for å hjelpe dem med driftskostnadene for tjenesten.
|
||||
about: Firefish ble opprettet av ThatOneCalculator i 2022, basert på Misskey.
|
||||
sponsors: Firefishs sponsorer
|
||||
patrons: Firefishs patroner
|
||||
patronsList: Listen er kronologisk, ikke etter donert beløp. Doner med lenken over
|
||||
for å få navnet ditt her!
|
||||
isBot: Denne kontoen er en bot
|
||||
_nsfw:
|
||||
respect: Skjul NSFW-merket media
|
||||
|
|
|
@ -867,7 +867,6 @@ tablet: "Tablet"
|
|||
auto: "Automatycznie"
|
||||
size: "Rozmiar"
|
||||
numberOfColumn: "Liczba kolumn"
|
||||
searchByGoogle: "Szukaj"
|
||||
indefinitely: "Dożywotnio"
|
||||
file: "Pliki"
|
||||
logoutConfirm: "Czy na pewno chcesz się wylogować?"
|
||||
|
@ -991,9 +990,6 @@ _aboutFirefish:
|
|||
source: "Kod źródłowy"
|
||||
translation: "Tłumacz Firefish"
|
||||
donate: "Przekaż darowiznę na Firefish"
|
||||
morePatrons: "Naprawdę doceniam wsparcie ze strony wielu niewymienionych tu osób.
|
||||
Dziękuję! 🥰"
|
||||
patrons: "Wspierający"
|
||||
_nsfw:
|
||||
respect: "Ukrywaj media NSFW"
|
||||
ignore: "Nie ukrywaj mediów NSFW"
|
||||
|
|
|
@ -497,7 +497,6 @@ smtpPass: "Senha"
|
|||
clearCache: "Limpar memória transitória"
|
||||
info: "Informações"
|
||||
user: "Usuários"
|
||||
searchByGoogle: "Buscar"
|
||||
file: "Ficheiros"
|
||||
_email:
|
||||
_follow:
|
||||
|
|
|
@ -692,7 +692,6 @@ user: "Utilizatori"
|
|||
administration: "Gestionare"
|
||||
middle: "Mediu"
|
||||
sent: "Trimite"
|
||||
searchByGoogle: "Caută"
|
||||
file: "Fișiere"
|
||||
_email:
|
||||
_follow:
|
||||
|
|
|
@ -894,7 +894,6 @@ auto: "Автоматически"
|
|||
themeColor: "Цвет темы сервера"
|
||||
size: "Размер"
|
||||
numberOfColumn: "Количество столбцов"
|
||||
searchByGoogle: "Поиск"
|
||||
instanceDefaultLightTheme: "Светлая тема по умолчанию для всего сервера"
|
||||
instanceDefaultDarkTheme: "Темная тема по умолчанию для всего сервера"
|
||||
indefinitely: "вечно"
|
||||
|
@ -987,12 +986,6 @@ _aboutFirefish:
|
|||
source: "Исходный код"
|
||||
translation: "Перевод Firefish"
|
||||
donate: "Пожертвование на Firefish"
|
||||
morePatrons: "Большое спасибо и многим другим, кто принял участие в этом проекте!
|
||||
🥰"
|
||||
patrons: "Материальная поддержка"
|
||||
patronsList: Перечислены в хронологическом порядке, а не по размеру пожертвования.
|
||||
Сделайте взнос по ссылке выше, чтобы ваше имя было здесь!
|
||||
sponsors: Спонсоры Firefish
|
||||
donateTitle: Понравился Firefish?
|
||||
pleaseDonateToFirefish: Пожалуйста, поддержите разработку Firefish.
|
||||
pleaseDonateToHost: Также не забудьте поддержать ваш домашний сервер {host}, чтобы
|
||||
|
|
|
@ -886,7 +886,6 @@ auto: "Automaticky"
|
|||
themeColor: "Farba témy"
|
||||
size: "Veľkosť"
|
||||
numberOfColumn: "Počet stĺpcov"
|
||||
searchByGoogle: "Hľadať cez Google"
|
||||
instanceDefaultLightTheme: "Predvolená svetlá téma"
|
||||
instanceDefaultDarkTheme: "Predvolená tmavá téma"
|
||||
instanceDefaultThemeDescription: "Vložte kód témy v objektovom formáte"
|
||||
|
@ -1037,9 +1036,6 @@ _aboutFirefish:
|
|||
source: "Zdrojový kód"
|
||||
translation: "Preložiť Firefish"
|
||||
donate: "Podporiť Firefish"
|
||||
morePatrons: "Takisto oceňujeme podporu mnoých ďalších, ktorí tu nie sú uvedení.
|
||||
Ďakujeme! 🥰"
|
||||
patrons: "Prispievatelia"
|
||||
_nsfw:
|
||||
respect: "Skryť NSFW médiá"
|
||||
ignore: "Neskrývať NSFW médiá"
|
||||
|
|
|
@ -268,7 +268,6 @@ smtpUser: "Användarnamn"
|
|||
smtpPass: "Lösenord"
|
||||
clearCache: "Rensa cache"
|
||||
user: "Användare"
|
||||
searchByGoogle: "Sök"
|
||||
file: "Filer"
|
||||
_email:
|
||||
_follow:
|
||||
|
|
|
@ -873,7 +873,6 @@ auto: "อัตโนมัติ"
|
|||
themeColor: "สีข้อความเลื่อนของเซิร์ฟเวอร์"
|
||||
size: "ขนาด"
|
||||
numberOfColumn: "จำนวนคอลัมน์"
|
||||
searchByGoogle: "ค้นหา"
|
||||
instanceDefaultLightTheme: "ธีมสว่างค่าเริ่มต้นของเซิร์ฟเวอร์"
|
||||
instanceDefaultDarkTheme: "ธีมมืดค่าเริ่มต้นของเซิร์ฟเวอร์"
|
||||
instanceDefaultThemeDescription: "ป้อนรหัสธีมในรูปแบบออบเจ็กต์"
|
||||
|
@ -1023,9 +1022,6 @@ _aboutFirefish:
|
|||
source: "ซอร์สโค้ด"
|
||||
translation: "รับแปลภาษา Firefish"
|
||||
donate: "บริจาคให้กับ Firefish"
|
||||
morePatrons: "เราขอขอบคุณสำหรับความช่วยเหลือจากผู้ช่วยอื่นๆ ที่ไม่ได้ระบุไว้ที่นี่นะ
|
||||
ขอขอบคุณ! 🥰"
|
||||
patrons: "สมาชิกพันธมิตร"
|
||||
_nsfw:
|
||||
respect: "ซ่อนสื่อ NSFW"
|
||||
ignore: "อย่าซ่อนสื่อ NSFW"
|
||||
|
|
|
@ -48,7 +48,6 @@ remove: "Sil"
|
|||
smtpUser: "Kullanıcı Adı"
|
||||
smtpPass: "Şifre"
|
||||
user: "Kullanıcı"
|
||||
searchByGoogle: "Arama"
|
||||
_mfm:
|
||||
search: "Arama"
|
||||
play: MFM'i çal
|
||||
|
@ -1911,14 +1910,9 @@ _preferencesBackups:
|
|||
updatedAt: 'Güncelleme tarihi: {date} {time}'
|
||||
cannotLoad: Yüklenemedi
|
||||
_aboutFirefish:
|
||||
patronsList: Bağış büyüklüğüne göre değil, kronolojik olarak listelenmiştir. Adınızı
|
||||
buraya almak için yukarıdaki bağlantıyla bağış yapın!
|
||||
about: Firefish, 2022'den beri geliştirilmekte olan ThatOneCalculator tarafından
|
||||
yapılan bir Misskey çatalıdır.
|
||||
allContributors: Tüm katkıda bulunanlar
|
||||
patrons: Firefish patronları
|
||||
morePatrons: Burada listelenmeyen diğer birçok yardımcının desteğini de takdir ediyoruz.
|
||||
Teşekkür ederim! 🥰
|
||||
donate: Firefish'e bağışta bulunun
|
||||
contributors: Ana katkıda bulunanlar
|
||||
source: Kaynak Kodu
|
||||
|
@ -1929,7 +1923,6 @@ _aboutFirefish:
|
|||
pleaseDonateToHost: İşletme maliyetlerini desteklemek için lütfen ev sunucunuz {host}'a
|
||||
bağış yapmayı da düşünün.
|
||||
donateHost: '{ev sahibi} için bağış yapın'
|
||||
sponsors: Firefish sponsorları
|
||||
misskeyContributors: Misskey'e katkıda bulunanlar
|
||||
_weekday:
|
||||
saturday: Cumartesi
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
_lang_: "ياپونچە"
|
||||
search: "ئىزدەش"
|
||||
searchByGoogle: "ئىزدەش"
|
||||
_mfm:
|
||||
search: "ئىزدەش"
|
||||
|
|
|
@ -788,7 +788,6 @@ global: "Глобальна"
|
|||
sent: "Відправлене"
|
||||
hashtags: "Хештеґ"
|
||||
hide: "Сховати"
|
||||
searchByGoogle: "Пошук"
|
||||
indefinitely: "Ніколи"
|
||||
file: "Файли"
|
||||
reverse: "Переворот"
|
||||
|
@ -826,17 +825,11 @@ _aboutFirefish:
|
|||
source: "Вихідний код"
|
||||
translation: "Перекладати Firefish"
|
||||
donate: "Пожертвувати Firefish"
|
||||
morePatrons: "Ми дуже цінуємо підтримку багатьох інших помічників, не перелічених
|
||||
тут. Дякуємо! 🥰"
|
||||
patrons: "Підтримали"
|
||||
patronsList: Перераховані в хронологічному порядку, а не за розміром пожертви. Зробіть
|
||||
внесок за посиланням вище, щоб ваше ім'я було тут!
|
||||
donateTitle: Сподобався Firefish?
|
||||
pleaseDonateToFirefish: Будь ласка, підтримайте розробку Firefish.
|
||||
pleaseDonateToHost: Також не забудьте підтримати ваш домашній сервер {host}, щоб
|
||||
допомогти з його операційними витратами.
|
||||
donateHost: Зробити внесок на рахунок {host}
|
||||
sponsors: Спонсори Firefish
|
||||
misskeyContributors: Контрибутори Misskey
|
||||
_nsfw:
|
||||
respect: "Приховувати NSFW медіа"
|
||||
|
|
|
@ -892,7 +892,6 @@ auto: "Tự động"
|
|||
themeColor: "Màu theme"
|
||||
size: "Kích thước"
|
||||
numberOfColumn: "Số lượng cột"
|
||||
searchByGoogle: "Google"
|
||||
instanceDefaultLightTheme: "Theme máy chủ Sáng-Rộng"
|
||||
instanceDefaultDarkTheme: "Theme máy chủ Tối-Rộng"
|
||||
instanceDefaultThemeDescription: "Nhập mã theme trong định dạng đối tượng."
|
||||
|
@ -1051,15 +1050,10 @@ _aboutFirefish:
|
|||
source: "Mã nguồn"
|
||||
translation: "Dịch Firefish"
|
||||
donate: "Ủng hộ Firefish"
|
||||
morePatrons: "Chúng tôi cũng trân trọng sự hỗ trợ của nhiều người đóng góp khác
|
||||
không được liệt kê ở đây. Cảm ơn! 🥰"
|
||||
patrons: "Người ủng hộ"
|
||||
patronsList: Liệt kê theo thứ tự, không theo số tiền ủng hộ. Hãy để tên bạn ở đây!
|
||||
donateTitle: Thích Firefish?
|
||||
pleaseDonateToFirefish: Hãy cân nhắc ủng hộ Firefish phát triển.
|
||||
donateHost: Ủng hộ {host}
|
||||
pleaseDonateToHost: Cũng như ủng hộ chi phí vận hành máy chủ {host} của bạn.
|
||||
sponsors: Nhà tài trợ Firefish
|
||||
misskeyContributors: Người đóng góp Misskey
|
||||
_nsfw:
|
||||
respect: "Ẩn nội dung NSFW"
|
||||
|
|
|
@ -269,7 +269,7 @@ agreeTo: "我同意 {0}"
|
|||
tos: "服务条款"
|
||||
start: "开始"
|
||||
home: "首页"
|
||||
remoteUserCaution: "由于此用户来自其它服务器,显示的信息不完整。"
|
||||
remoteUserCaution: "此用户来自其它服务器,显示信息会不完整。"
|
||||
activity: "活动"
|
||||
images: "图片"
|
||||
birthday: "生日"
|
||||
|
@ -340,6 +340,7 @@ invite: "邀请"
|
|||
driveCapacityPerLocalAccount: "每个本地用户的网盘容量"
|
||||
driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
|
||||
inMb: "以兆字节 (MegaByte) 为单位"
|
||||
antennaLimit: "每个用户最多可以创建的天线数量"
|
||||
iconUrl: "图标 URL"
|
||||
bannerUrl: "横幅图 URL"
|
||||
backgroundImageUrl: "背景图 URL"
|
||||
|
@ -851,7 +852,6 @@ auto: "自动"
|
|||
themeColor: "服务器滚动条颜色"
|
||||
size: "大小"
|
||||
numberOfColumn: "列数"
|
||||
searchByGoogle: "搜索"
|
||||
instanceDefaultLightTheme: "服务器默认浅色主题"
|
||||
instanceDefaultDarkTheme: "服务器默认深色主题"
|
||||
instanceDefaultThemeDescription: "以对象格式键入主题代码。"
|
||||
|
@ -996,10 +996,6 @@ _aboutFirefish:
|
|||
source: "源代码"
|
||||
translation: "翻译 Firefish"
|
||||
donate: "赞助 Firefish"
|
||||
morePatrons: "还有很多其它的人也在支持我们,非常感谢🥰"
|
||||
patrons: "Firefish 赞助者"
|
||||
patronsList: 按时间顺序而不是捐赠金额排列。通过上面的链接捐款,让您的名字出现在这里!
|
||||
sponsors: Firefish 赞助者们
|
||||
donateTitle: 喜欢 Firefish 吗?
|
||||
pleaseDonateToFirefish: 请考虑赞助 Firefish 以支持其开发。
|
||||
pleaseDonateToHost: 也请考虑赞助您的主服务器 {host},以帮助支持其运营成本。
|
||||
|
@ -2061,3 +2057,5 @@ showNoAltTextWarning: 当您尝试发布没有描述的帖子附件时显示警
|
|||
showAddFileDescriptionAtFirstPost: 当您首次尝试发布没有描述的帖子附件时自动弹出添加描述页面
|
||||
autocorrectNoteLanguage: 当帖子语言不符合自动检测的结果的时候显示警告
|
||||
incorrectLanguageWarning: "看上去您帖子使用的语言是{detected},但您选择的语言是{current}。\n要改为以{detected}发帖吗?"
|
||||
noteEditHistory: "帖子编辑历史"
|
||||
media: 媒体
|
||||
|
|
|
@ -847,7 +847,6 @@ auto: "自動"
|
|||
themeColor: "主題顏色"
|
||||
size: "大小"
|
||||
numberOfColumn: "列數"
|
||||
searchByGoogle: "搜尋"
|
||||
instanceDefaultLightTheme: "伺服器預設的淺色主題"
|
||||
instanceDefaultDarkTheme: "伺服器預設的深色主題"
|
||||
instanceDefaultThemeDescription: "輸入物件形式的主題代碼。"
|
||||
|
@ -992,10 +991,6 @@ _aboutFirefish:
|
|||
source: "原始碼"
|
||||
translation: "翻譯Firefish"
|
||||
donate: "贊助Firefish"
|
||||
morePatrons: "還有許許多多幫助我們的其他人,非常感謝你們。 🥰"
|
||||
patrons: "贊助者"
|
||||
patronsList: 按時間順序列出,而不是按贊助規模列出。使用上面的連結贊助,在這裡獲得顯示您名字的機會!
|
||||
sponsors: Firefish 贊助者們
|
||||
donateTitle: 覺得 Firefish 棒嗎?
|
||||
pleaseDonateToFirefish: 請考慮向 Firefish 贊助以支持其發展。
|
||||
pleaseDonateToHost: 還請考慮捐贈給您在使用的伺服器 {host},以支援龐大的運營成本。
|
||||
|
|
38
package.json
38
package.json
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "firefish",
|
||||
"version": "20240330",
|
||||
"version": "20240421",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://firefish.dev/firefish/firefish.git"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.5",
|
||||
"packageManager": "pnpm@8.15.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"rebuild": "pnpm run clean && pnpm run build",
|
||||
|
@ -20,33 +20,39 @@
|
|||
"watch": "pnpm run dev",
|
||||
"dev": "pnpm node ./scripts/dev.mjs",
|
||||
"dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start",
|
||||
"lint": "pnpm --filter !megalodon --filter !firefish-js -r --parallel run lint",
|
||||
"lint": "pnpm run lint:ts; pnpm run lint:rs",
|
||||
"lint:ts": "pnpm --filter !firefish-js -r --parallel run lint",
|
||||
"lint:rs": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt --all --",
|
||||
"debug": "pnpm run build:debug && pnpm run start",
|
||||
"build:debug": "pnpm run clean && pnpm node ./scripts/dev-build.mjs && pnpm run gulp",
|
||||
"mocha": "pnpm --filter backend run mocha",
|
||||
"test": "pnpm run mocha",
|
||||
"format": "pnpm -r --parallel run format",
|
||||
"test": "pnpm run test:ts && pnpm run test:rs",
|
||||
"test:ts": "pnpm run mocha",
|
||||
"test:rs": "cargo test",
|
||||
"format": "pnpm run format:ts; pnpm run format:rs",
|
||||
"format:ts": "pnpm -r --parallel run format",
|
||||
"format:rs": "cargo fmt --all --",
|
||||
"clean": "pnpm node ./scripts/clean-built.mjs",
|
||||
"clean-npm": "pnpm node ./scripts/clean-npm.mjs",
|
||||
"clean-cargo": "pnpm node ./scripts/clean-cargo.mjs",
|
||||
"clean-cargo": "cargo clean",
|
||||
"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-replace": "1.1.4",
|
||||
"gulp-terser": "2.1.0"
|
||||
"gulp-terser": "2.1.0",
|
||||
"js-yaml": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.6.3",
|
||||
"@biomejs/cli-darwin-arm64": "^1.6.3",
|
||||
"@biomejs/cli-darwin-x64": "^1.6.3",
|
||||
"@biomejs/cli-linux-arm64": "^1.6.3",
|
||||
"@biomejs/cli-linux-x64": "^1.6.3",
|
||||
"@types/node": "20.11.30",
|
||||
"@biomejs/biome": "1.6.4",
|
||||
"@biomejs/cli-darwin-arm64": "^1.6.4",
|
||||
"@biomejs/cli-darwin-x64": "^1.6.4",
|
||||
"@biomejs/cli-linux-arm64": "^1.6.4",
|
||||
"@biomejs/cli-linux-x64": "^1.6.4",
|
||||
"@types/node": "20.12.7",
|
||||
"execa": "8.0.1",
|
||||
"pnpm": "8.15.5",
|
||||
"typescript": "5.4.3"
|
||||
"pnpm": "8.15.7",
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ This directory contains all of the packages Firefish uses.
|
|||
|
||||
- `backend`: Main backend code written in TypeScript for NodeJS
|
||||
- `backend-rs`: Backend code written in Rust, bound to NodeJS by [NAPI-RS](https://napi.rs/)
|
||||
- `macro-rs`: Procedural macros for backend-rs
|
||||
- `client`: Web interface written in Vue3 and TypeScript
|
||||
- `sw`: Web [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) written in TypeScript
|
||||
- `firefish-js`: TypeScript SDK for both backend and client
|
||||
|
|
|
@ -12,31 +12,37 @@ napi = ["dep:napi", "dep:napi-derive"]
|
|||
crate-type = ["cdylib", "lib"]
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.79"
|
||||
cfg-if = "1.0.0"
|
||||
chrono = "0.4.35"
|
||||
cuid2 = "0.1.2"
|
||||
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.15", features = ["sqlx-postgres", "runtime-tokio-rustls"] }
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_json = "1.0.115"
|
||||
thiserror = "1.0.58"
|
||||
tokio = { version = "1.36.0", features = ["full"] }
|
||||
macro_rs = { workspace = true }
|
||||
|
||||
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
||||
napi = { version = "2.16.1", default-features = false, features = ["napi9", "tokio_rt"], optional = true }
|
||||
napi-derive = { version = "2.16.1", optional = true }
|
||||
basen = "0.1.0"
|
||||
napi = { workspace = true, optional = true, default-features = false, features = ["napi9", "tokio_rt", "chrono_date", "serde-json"] }
|
||||
napi-derive = { workspace = true, optional = true }
|
||||
|
||||
argon2 = { workspace = true, features = ["std"] }
|
||||
async-trait = { workspace = true }
|
||||
basen = { workspace = true }
|
||||
bcrypt = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
cuid2 = { workspace = true }
|
||||
emojis = { workspace = true }
|
||||
idna = { workspace = true }
|
||||
jsonschema = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
parse-display = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
schemars = { workspace = true, features = ["chrono"] }
|
||||
sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
url = { workspace = true }
|
||||
urlencoding = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.4.0"
|
||||
pretty_assertions = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = "2.1.2"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
napi-build = { workspace = true }
|
||||
|
|
|
@ -1,11 +1,33 @@
|
|||
recursive_wildcard = $(foreach d, $(wildcard $(1:=/*)), $(call recursive_wildcard, $d, $2) $(filter $(subst *, %, $2), $d))
|
||||
|
||||
SRC := Cargo.toml
|
||||
SRC += $(call recursive_wildcard, src, *)
|
||||
|
||||
|
||||
.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)'
|
||||
--output-dir='src/model/entity' \
|
||||
--database-url='postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@localhost:25432/$(POSTGRES_DB)' \
|
||||
--date-time-crate='chrono' \
|
||||
--model-extra-attributes='NAPI_EXTRA_ATTR_PLACEHOLDER' && \
|
||||
for file in src/model/entity/*; do \
|
||||
base=$$(basename -- "$${file}"); \
|
||||
jsname=$$(printf '%s\n' "$${base%.*}" | perl -pe 's/(^|_)./uc($$&)/ge;s/_//g'); \
|
||||
attribute=$$(printf 'cfg_attr(feature = "napi", napi_derive::napi(object, js_name = "%s", use_nullable = true))' "$${jsname}"); \
|
||||
sed -i "s/NAPI_EXTRA_ATTR_PLACEHOLDER/$${attribute}/" "$${file}"; \
|
||||
done
|
||||
sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \
|
||||
src/model/entity/sea_orm_active_enums.rs
|
||||
cargo fmt --all --
|
||||
|
||||
index.js:
|
||||
.PHONY: update-index
|
||||
update-index: index.js index.d.ts
|
||||
|
||||
index.js index.d.ts: $(SRC)
|
||||
NODE_OPTIONS='--max_old_space_size=3072' pnpm run build:debug
|
||||
[ -f built/index.js ]
|
||||
rm --force index.js
|
||||
[ -f built/index.js ] && [ -f built/index.d.ts ]
|
||||
rm --force index.js index.d.ts
|
||||
cp built/index.js index.js
|
||||
cp built/index.d.ts index.d.ts
|
||||
sed -i 's/^ \*r"/ */g' index.d.ts
|
||||
|
|
1054
packages/backend-rs/index.d.ts
vendored
Normal file
1054
packages/backend-rs/index.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -224,17 +224,32 @@ switch (platform) {
|
|||
}
|
||||
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')
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'backend-rs.linux-arm-musleabihf.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./backend-rs.linux-arm-musleabihf.node')
|
||||
} else {
|
||||
nativeBinding = require('backend-rs-linux-arm-musleabihf')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
} else {
|
||||
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
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'riscv64':
|
||||
|
@ -295,11 +310,46 @@ if (!nativeBinding) {
|
|||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { nativeRandomStr, IdConvertType, convertId, nativeGetTimestamp, nativeCreateId, nativeInitIdGenerator } = nativeBinding
|
||||
const { readEnvironmentConfig, readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = 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
|
||||
module.exports.readEnvironmentConfig = readEnvironmentConfig
|
||||
module.exports.readServerConfig = readServerConfig
|
||||
module.exports.stringToAcct = stringToAcct
|
||||
module.exports.acctToString = acctToString
|
||||
module.exports.checkWordMute = checkWordMute
|
||||
module.exports.getFullApAccount = getFullApAccount
|
||||
module.exports.isSelfHost = isSelfHost
|
||||
module.exports.isSameOrigin = isSameOrigin
|
||||
module.exports.extractHost = extractHost
|
||||
module.exports.toPuny = toPuny
|
||||
module.exports.isUnicodeEmoji = isUnicodeEmoji
|
||||
module.exports.sqlLikeEscape = sqlLikeEscape
|
||||
module.exports.safeForSql = safeForSql
|
||||
module.exports.formatMilliseconds = formatMilliseconds
|
||||
module.exports.getNoteSummary = getNoteSummary
|
||||
module.exports.toMastodonId = toMastodonId
|
||||
module.exports.fromMastodonId = fromMastodonId
|
||||
module.exports.fetchMeta = fetchMeta
|
||||
module.exports.metaToPugArgs = metaToPugArgs
|
||||
module.exports.nyaify = nyaify
|
||||
module.exports.hashPassword = hashPassword
|
||||
module.exports.verifyPassword = verifyPassword
|
||||
module.exports.isOldPasswordAlgorithm = isOldPasswordAlgorithm
|
||||
module.exports.decodeReaction = decodeReaction
|
||||
module.exports.countReactions = countReactions
|
||||
module.exports.toDbReaction = toDbReaction
|
||||
module.exports.AntennaSrcEnum = AntennaSrcEnum
|
||||
module.exports.DriveFileUsageHintEnum = DriveFileUsageHintEnum
|
||||
module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum
|
||||
module.exports.NoteVisibilityEnum = NoteVisibilityEnum
|
||||
module.exports.NotificationTypeEnum = NotificationTypeEnum
|
||||
module.exports.PageVisibilityEnum = PageVisibilityEnum
|
||||
module.exports.PollNotevisibilityEnum = PollNotevisibilityEnum
|
||||
module.exports.RelayStatusEnum = RelayStatusEnum
|
||||
module.exports.UserEmojimodpermEnum = UserEmojimodpermEnum
|
||||
module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum
|
||||
module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum
|
||||
module.exports.initIdGenerator = initIdGenerator
|
||||
module.exports.getTimestamp = getTimestamp
|
||||
module.exports.genId = genId
|
||||
module.exports.secureRndstr = secureRndstr
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@napi-rs/cli": "2.18.0",
|
||||
"@napi-rs/cli": "2.18.1",
|
||||
"ava": "6.1.2"
|
||||
},
|
||||
"ava": {
|
||||
|
@ -33,14 +33,12 @@
|
|||
},
|
||||
"scripts": {
|
||||
"artifacts": "napi artifacts",
|
||||
"build": "napi build --features napi --platform --release ./built/",
|
||||
"build:debug": "napi build --features napi --platform ./built/",
|
||||
"build": "napi build --features napi --no-const-enum --platform --release ./built/",
|
||||
"build:debug": "napi build --features napi --no-const-enum --platform ./built/",
|
||||
"prepublishOnly": "napi prepublish -t npm",
|
||||
"test": "pnpm run cargo:test && pnpm run build:debug && ava",
|
||||
"universal": "napi universal",
|
||||
"version": "napi version",
|
||||
"format": "cargo fmt --all --",
|
||||
"lint": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt --all --",
|
||||
"cargo:test": "pnpm run cargo:unit && pnpm run cargo:integration",
|
||||
"cargo:unit": "cargo test unit_test && cargo test -F napi unit_test",
|
||||
"cargo:integration": "cargo test int_test"
|
||||
|
|
27
packages/backend-rs/src/config/environment.rs
Normal file
27
packages/backend-rs/src/config/environment.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// FIXME: Are these options used?
|
||||
#[crate::export(object)]
|
||||
pub struct EnvConfig {
|
||||
pub only_queue: bool,
|
||||
pub only_server: bool,
|
||||
pub no_daemons: bool,
|
||||
pub disable_clustering: bool,
|
||||
pub verbose: bool,
|
||||
pub with_log_time: bool,
|
||||
pub slow: bool,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn read_environment_config() -> EnvConfig {
|
||||
let node_env = std::env::var("NODE_ENV").unwrap_or_default().to_lowercase();
|
||||
let is_testing = node_env == "test";
|
||||
|
||||
EnvConfig {
|
||||
only_queue: std::env::var("MK_ONLY_QUEUE").is_ok(),
|
||||
only_server: std::env::var("MK_ONLY_SERVER").is_ok(),
|
||||
no_daemons: is_testing || std::env::var("MK_NO_DAEMONS").is_ok(),
|
||||
disable_clustering: is_testing || std::env::var("MK_DISABLE_CLUSTERING").is_ok(),
|
||||
verbose: std::env::var("MK_VERBOSE").is_ok(),
|
||||
with_log_time: std::env::var("MK_WITH_LOG_TIME").is_ok(),
|
||||
slow: std::env::var("MK_SLOW").is_ok(),
|
||||
}
|
||||
}
|
2
packages/backend-rs/src/config/mod.rs
Normal file
2
packages/backend-rs/src/config/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod environment;
|
||||
pub mod server;
|
183
packages/backend-rs/src/config/server.rs
Normal file
183
packages/backend-rs/src/config/server.rs
Normal file
|
@ -0,0 +1,183 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct ServerConfig {
|
||||
pub url: String,
|
||||
pub port: u16,
|
||||
/// host to listen on
|
||||
pub bind: Option<String>,
|
||||
pub disable_hsts: Option<bool>,
|
||||
|
||||
pub db: DbConfig,
|
||||
pub redis: RedisConfig,
|
||||
pub cache_server: Option<RedisConfig>,
|
||||
|
||||
pub proxy: Option<String>,
|
||||
pub proxy_smtp: Option<String>,
|
||||
pub proxy_bypass_hosts: Option<Vec<String>>,
|
||||
|
||||
pub allowed_private_networks: Option<Vec<String>>,
|
||||
/// `NapiValue` is not implemented for `u64`
|
||||
pub max_file_size: Option<i64>,
|
||||
pub access_log: Option<String>,
|
||||
pub cluster_limits: Option<WorkerConfig>,
|
||||
pub cuid: Option<IdConfig>,
|
||||
pub outgoing_address: Option<String>,
|
||||
|
||||
pub deliver_job_concurrency: Option<u32>,
|
||||
pub inbox_job_concurrency: Option<u32>,
|
||||
pub deliver_job_per_sec: Option<u32>,
|
||||
pub inbox_job_per_sec: Option<u32>,
|
||||
pub deliver_job_max_attempts: Option<u32>,
|
||||
pub inbox_job_max_attempts: Option<u32>,
|
||||
|
||||
pub log_level: Option<Vec<String>>,
|
||||
|
||||
pub syslog: Option<SysLogConfig>,
|
||||
|
||||
pub proxy_remote_files: Option<bool>,
|
||||
pub media_proxy: Option<String>,
|
||||
pub summaly_proxy_url: Option<String>,
|
||||
|
||||
pub reserved_usernames: Option<Vec<String>>,
|
||||
|
||||
pub max_user_signups: Option<u32>,
|
||||
pub is_managed_hosting: Option<bool>,
|
||||
pub max_note_length: Option<u32>,
|
||||
pub max_caption_length: Option<u32>,
|
||||
|
||||
pub deepl: Option<DeepLConfig>,
|
||||
pub libre_translate: Option<LibreTranslateConfig>,
|
||||
pub email: Option<EmailConfig>,
|
||||
pub object_storage: Option<ObjectStorageConfig>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct DbConfig {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
pub db: String,
|
||||
pub user: String,
|
||||
pub pass: String,
|
||||
pub disable_cache: Option<bool>,
|
||||
pub extra: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct RedisConfig {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
pub family: Option<u8>,
|
||||
pub user: Option<String>,
|
||||
pub pass: Option<String>,
|
||||
pub tls: Option<TlsConfig>,
|
||||
#[serde(default)]
|
||||
pub db: u32,
|
||||
#[serde(default)]
|
||||
pub prefix: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct TlsConfig {
|
||||
pub host: String,
|
||||
pub reject_unauthorized: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct WorkerConfig {
|
||||
pub web: Option<u32>,
|
||||
pub queue: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct IdConfig {
|
||||
pub length: Option<u8>,
|
||||
pub fingerprint: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct SysLogConfig {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct DeepLConfig {
|
||||
pub managed: Option<bool>,
|
||||
pub auth_key: Option<String>,
|
||||
pub is_pro: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct LibreTranslateConfig {
|
||||
pub managed: Option<bool>,
|
||||
pub api_url: Option<String>,
|
||||
pub api_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct EmailConfig {
|
||||
pub managed: Option<bool>,
|
||||
pub address: Option<String>,
|
||||
pub host: Option<String>,
|
||||
pub port: Option<u16>,
|
||||
pub user: Option<String>,
|
||||
pub pass: Option<String>,
|
||||
pub use_implicit_ssl_tls: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[crate::export(object, use_nullable = false)]
|
||||
pub struct ObjectStorageConfig {
|
||||
pub managed: Option<bool>,
|
||||
pub base_url: Option<String>,
|
||||
pub bucket: Option<String>,
|
||||
pub prefix: Option<String>,
|
||||
pub endpoint: Option<String>,
|
||||
pub region: Option<String>,
|
||||
pub access_key: Option<String>,
|
||||
pub secret_key: Option<String>,
|
||||
pub use_ssl: Option<bool>,
|
||||
pub connnect_over_proxy: Option<bool>,
|
||||
pub set_public_read_on_upload: Option<bool>,
|
||||
pub s3_force_path_style: Option<bool>,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn read_server_config() -> ServerConfig {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let yml = fs::File::open(cwd.join("../../.config/default.yml"))
|
||||
.expect("Failed to open '.config/default.yml'");
|
||||
let mut data: ServerConfig = serde_yaml::from_reader(yml).expect("Failed to parse yaml");
|
||||
data.url = url::Url::parse(&data.url)
|
||||
.expect("Config url is invalid")
|
||||
.origin()
|
||||
.ascii_serialization();
|
||||
data
|
||||
}
|
||||
|
||||
pub static SERVER_CONFIG: Lazy<ServerConfig> = Lazy::new(read_server_config);
|
|
@ -1,13 +0,0 @@
|
|||
use sea_orm::error::DbErr;
|
||||
|
||||
use crate::impl_into_napi_error;
|
||||
|
||||
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
#[error("The database connections have not been initialized yet")]
|
||||
Uninitialized,
|
||||
#[error("ORM error: {0}")]
|
||||
OrmError(#[from] DbErr),
|
||||
}
|
||||
|
||||
impl_into_napi_error!(Error);
|
|
@ -1,26 +1,34 @@
|
|||
pub mod error;
|
||||
|
||||
use error::Error;
|
||||
use sea_orm::{Database, DbConn};
|
||||
use crate::config::server::SERVER_CONFIG;
|
||||
use sea_orm::{Database, DbConn, DbErr};
|
||||
|
||||
static DB_CONN: once_cell::sync::OnceCell<DbConn> = once_cell::sync::OnceCell::new();
|
||||
|
||||
pub async fn init_database(conn_uri: impl Into<String>) -> Result<(), Error> {
|
||||
let conn = Database::connect(conn_uri.into()).await?;
|
||||
DB_CONN.get_or_init(move || conn);
|
||||
Ok(())
|
||||
async fn init_database() -> Result<&'static DbConn, DbErr> {
|
||||
let database_uri = format!(
|
||||
"postgres://{}:{}@{}:{}/{}",
|
||||
SERVER_CONFIG.db.user,
|
||||
urlencoding::encode(&SERVER_CONFIG.db.pass),
|
||||
SERVER_CONFIG.db.host,
|
||||
SERVER_CONFIG.db.port,
|
||||
SERVER_CONFIG.db.db,
|
||||
);
|
||||
let conn = Database::connect(database_uri).await?;
|
||||
Ok(DB_CONN.get_or_init(move || conn))
|
||||
}
|
||||
|
||||
pub fn get_database() -> Result<&'static DbConn, Error> {
|
||||
DB_CONN.get().ok_or(Error::Uninitialized)
|
||||
pub async fn db_conn() -> Result<&'static DbConn, DbErr> {
|
||||
match DB_CONN.get() {
|
||||
Some(conn) => Ok(conn),
|
||||
None => init_database().await,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{error::Error, get_database};
|
||||
use super::db_conn;
|
||||
|
||||
#[test]
|
||||
fn error_uninitialized() {
|
||||
assert_eq!(get_database().unwrap_err(), Error::Uninitialized);
|
||||
#[tokio::test]
|
||||
async fn connect_test() {
|
||||
assert!(db_conn().await.is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
pub use macro_rs::export;
|
||||
|
||||
pub mod config;
|
||||
pub mod database;
|
||||
pub mod macros;
|
||||
pub mod misc;
|
||||
pub mod model;
|
||||
pub mod util;
|
||||
|
||||
#[cfg(feature = "napi")]
|
||||
pub mod mastodon_api;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#[macro_export]
|
||||
macro_rules! impl_into_napi_error {
|
||||
($a:ty) => {
|
||||
#[cfg(feature = "napi")]
|
||||
impl Into<napi::Error> for $a {
|
||||
fn into(self) -> napi::Error {
|
||||
napi::Error::from_reason(self.to_string())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
use napi::{Error, Status};
|
||||
use napi_derive::napi;
|
||||
|
||||
static CHAR_COLLECTION: &str = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
// -- NAPI exports --
|
||||
|
||||
#[napi]
|
||||
pub enum IdConvertType {
|
||||
MastodonId,
|
||||
FirefishId,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn convert_id(in_id: String, id_convert_type: IdConvertType) -> napi::Result<String> {
|
||||
use IdConvertType::*;
|
||||
match id_convert_type {
|
||||
MastodonId => {
|
||||
let mut out: i128 = 0;
|
||||
for (i, c) in in_id.to_lowercase().chars().rev().enumerate() {
|
||||
out += num_from_char(c)? as i128 * 36_i128.pow(i as u32);
|
||||
}
|
||||
|
||||
Ok(out.to_string())
|
||||
}
|
||||
FirefishId => {
|
||||
let mut input: i128 = match in_id.parse() {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Unable to parse ID as MastodonId",
|
||||
))
|
||||
}
|
||||
};
|
||||
let mut out = String::new();
|
||||
|
||||
while input != 0 {
|
||||
out.insert(0, char_from_num((input % 36) as u8)?);
|
||||
input /= 36;
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- end --
|
||||
|
||||
#[inline(always)]
|
||||
fn num_from_char(character: char) -> napi::Result<u8> {
|
||||
for (i, c) in CHAR_COLLECTION.chars().enumerate() {
|
||||
if c == character {
|
||||
return Ok(i as u8);
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Invalid character in parsed base36 id",
|
||||
))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn char_from_num(number: u8) -> napi::Result<char> {
|
||||
CHAR_COLLECTION
|
||||
.chars()
|
||||
.nth(number as usize)
|
||||
.ok_or(Error::from_status(Status::Unknown))
|
||||
}
|
74
packages/backend-rs/src/misc/acct.rs
Normal file
74
packages/backend-rs/src/misc/acct.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
#[derive(Debug, PartialEq)]
|
||||
#[crate::export(object)]
|
||||
pub struct Acct {
|
||||
pub username: String,
|
||||
pub host: Option<String>,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn string_to_acct(acct: &str) -> Acct {
|
||||
let split: Vec<&str> = if let Some(stripped) = acct.strip_prefix('@') {
|
||||
stripped
|
||||
} else {
|
||||
acct
|
||||
}
|
||||
.split('@')
|
||||
.collect();
|
||||
|
||||
Acct {
|
||||
username: split[0].to_string(),
|
||||
host: if split.len() == 1 {
|
||||
None
|
||||
} else {
|
||||
Some(split[1].to_string())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn acct_to_string(acct: &Acct) -> String {
|
||||
match &acct.host {
|
||||
Some(host) => format!("{}@{}", acct.username, host),
|
||||
None => acct.username.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{acct_to_string, string_to_acct, Acct};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_acct_to_string() {
|
||||
let remote_acct = Acct {
|
||||
username: "firefish".to_string(),
|
||||
host: Some("example.com".to_string()),
|
||||
};
|
||||
let local_acct = Acct {
|
||||
username: "MisakaMikoto".to_string(),
|
||||
host: None,
|
||||
};
|
||||
|
||||
assert_eq!(acct_to_string(&remote_acct), "firefish@example.com");
|
||||
assert_ne!(acct_to_string(&remote_acct), "mastodon@example.com");
|
||||
assert_eq!(acct_to_string(&local_acct), "MisakaMikoto");
|
||||
assert_ne!(acct_to_string(&local_acct), "ShiraiKuroko");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_to_acct() {
|
||||
let remote_acct = Acct {
|
||||
username: "firefish".to_string(),
|
||||
host: Some("example.com".to_string()),
|
||||
};
|
||||
let local_acct = Acct {
|
||||
username: "MisakaMikoto".to_string(),
|
||||
host: None,
|
||||
};
|
||||
|
||||
assert_eq!(string_to_acct("@firefish@example.com"), remote_acct);
|
||||
assert_eq!(string_to_acct("firefish@example.com"), remote_acct);
|
||||
assert_eq!(string_to_acct("@MisakaMikoto"), local_acct);
|
||||
assert_eq!(string_to_acct("MisakaMikoto"), local_acct);
|
||||
}
|
||||
}
|
118
packages/backend-rs/src/misc/check_word_mute.rs
Normal file
118
packages/backend-rs/src/misc/check_word_mute.rs
Normal file
|
@ -0,0 +1,118 @@
|
|||
use crate::database::db_conn;
|
||||
use crate::model::entity::{drive_file, note};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use sea_orm::{prelude::*, QuerySelect};
|
||||
|
||||
/// TODO: handle name collisions better
|
||||
#[crate::export(object, js_name = "NoteLikeForCheckWordMute")]
|
||||
pub struct NoteLike {
|
||||
pub file_ids: Vec<String>,
|
||||
pub user_id: Option<String>,
|
||||
pub text: Option<String>,
|
||||
pub cw: Option<String>,
|
||||
pub renote_id: Option<String>,
|
||||
pub reply_id: Option<String>,
|
||||
}
|
||||
|
||||
async fn all_texts(note: NoteLike) -> Result<Vec<String>, DbErr> {
|
||||
let db = db_conn().await?;
|
||||
|
||||
let mut texts: Vec<String> = vec![];
|
||||
|
||||
if let Some(text) = note.text {
|
||||
texts.push(text);
|
||||
}
|
||||
if let Some(cw) = note.cw {
|
||||
texts.push(cw);
|
||||
}
|
||||
|
||||
texts.extend(
|
||||
drive_file::Entity::find()
|
||||
.select_only()
|
||||
.column(drive_file::Column::Comment)
|
||||
.filter(drive_file::Column::Id.is_in(note.file_ids))
|
||||
.into_tuple::<Option<String>>()
|
||||
.all(db)
|
||||
.await?
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
);
|
||||
|
||||
if let Some(renote_id) = note.renote_id {
|
||||
if let Some((text, cw)) = note::Entity::find_by_id(renote_id)
|
||||
.select_only()
|
||||
.columns([note::Column::Text, note::Column::Cw])
|
||||
.into_tuple::<(Option<String>, Option<String>)>()
|
||||
.one(db)
|
||||
.await?
|
||||
{
|
||||
if let Some(t) = text {
|
||||
texts.push(t);
|
||||
}
|
||||
if let Some(c) = cw {
|
||||
texts.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(reply_id) = note.reply_id {
|
||||
if let Some((text, cw)) = note::Entity::find_by_id(reply_id)
|
||||
.select_only()
|
||||
.columns([note::Column::Text, note::Column::Cw])
|
||||
.into_tuple::<(Option<String>, Option<String>)>()
|
||||
.one(db)
|
||||
.await?
|
||||
{
|
||||
if let Some(t) = text {
|
||||
texts.push(t);
|
||||
}
|
||||
if let Some(c) = cw {
|
||||
texts.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(texts)
|
||||
}
|
||||
|
||||
fn convert_regex(js_regex: &str) -> String {
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"^/(.+)/(.*)$").unwrap());
|
||||
RE.replace(js_regex, "(?$2)$1").to_string()
|
||||
}
|
||||
|
||||
fn check_word_mute_impl(
|
||||
texts: &[String],
|
||||
muted_word_lists: &[Vec<String>],
|
||||
muted_patterns: &[String],
|
||||
) -> bool {
|
||||
muted_word_lists.iter().any(|muted_word_list| {
|
||||
texts.iter().any(|text| {
|
||||
let text_lower = text.to_lowercase();
|
||||
muted_word_list
|
||||
.iter()
|
||||
.all(|muted_word| text_lower.contains(&muted_word.to_lowercase()))
|
||||
})
|
||||
}) || muted_patterns.iter().any(|muted_pattern| {
|
||||
Regex::new(convert_regex(muted_pattern).as_str())
|
||||
.map(|re| texts.iter().any(|text| re.is_match(text)))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub async fn check_word_mute(
|
||||
note: NoteLike,
|
||||
muted_word_lists: Vec<Vec<String>>,
|
||||
muted_patterns: Vec<String>,
|
||||
) -> Result<bool, DbErr> {
|
||||
if muted_word_lists.is_empty() && muted_patterns.is_empty() {
|
||||
Ok(false)
|
||||
} else {
|
||||
Ok(check_word_mute_impl(
|
||||
&all_texts(note).await?,
|
||||
&muted_word_lists,
|
||||
&muted_patterns,
|
||||
))
|
||||
}
|
||||
}
|
67
packages/backend-rs/src/misc/convert_host.rs
Normal file
67
packages/backend-rs/src/misc/convert_host.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
use crate::config::server::SERVER_CONFIG;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Idna error: {0}")]
|
||||
IdnaError(#[from] idna::Errors),
|
||||
#[error("Url parse error: {0}")]
|
||||
UrlParseError(#[from] url::ParseError),
|
||||
#[error("Hostname is missing")]
|
||||
NoHostname,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn get_full_ap_account(username: &str, host: Option<&str>) -> Result<String, Error> {
|
||||
Ok(match host {
|
||||
Some(host) => format!("{}@{}", username, to_puny(host)?),
|
||||
None => format!("{}@{}", username, extract_host(&SERVER_CONFIG.url)?),
|
||||
})
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn is_self_host(host: Option<&str>) -> Result<bool, Error> {
|
||||
Ok(match host {
|
||||
Some(host) => extract_host(&SERVER_CONFIG.url)? == to_puny(host)?,
|
||||
None => true,
|
||||
})
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn is_same_origin(uri: &str) -> Result<bool, Error> {
|
||||
Ok(url::Url::parse(uri)?.origin().ascii_serialization() == SERVER_CONFIG.url)
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn extract_host(uri: &str) -> Result<String, Error> {
|
||||
url::Url::parse(uri)?
|
||||
.host_str()
|
||||
.ok_or(Error::NoHostname)
|
||||
.and_then(|v| Ok(to_puny(v)?))
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn to_puny(host: &str) -> Result<String, idna::Errors> {
|
||||
idna::domain_to_ascii(host)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{extract_host, to_puny};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn extract_host_test() {
|
||||
assert_eq!(
|
||||
extract_host("https://firefish.dev/firefish/firefish.git").unwrap(),
|
||||
"firefish.dev"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_puny_test() {
|
||||
assert_eq!(
|
||||
to_puny("何もかも.owari.shop").unwrap(),
|
||||
"xn--u8jyfb5762a.owari.shop"
|
||||
);
|
||||
}
|
||||
}
|
31
packages/backend-rs/src/misc/emoji.rs
Normal file
31
packages/backend-rs/src/misc/emoji.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
#[inline]
|
||||
#[crate::export]
|
||||
pub fn is_unicode_emoji(s: &str) -> bool {
|
||||
emojis::get(s).is_some()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::is_unicode_emoji;
|
||||
|
||||
#[test]
|
||||
fn test_unicode_emoji_check() {
|
||||
assert!(is_unicode_emoji("⭐"));
|
||||
assert!(is_unicode_emoji("👍"));
|
||||
assert!(is_unicode_emoji("❤"));
|
||||
assert!(is_unicode_emoji("♥️"));
|
||||
assert!(is_unicode_emoji("❤️"));
|
||||
assert!(is_unicode_emoji("💙"));
|
||||
assert!(is_unicode_emoji("🩷"));
|
||||
assert!(is_unicode_emoji("🖖🏿"));
|
||||
assert!(is_unicode_emoji("🏃➡️"));
|
||||
assert!(is_unicode_emoji("👩❤️👨"));
|
||||
assert!(is_unicode_emoji("👩👦👦"));
|
||||
assert!(is_unicode_emoji("🏳️🌈"));
|
||||
|
||||
assert!(!is_unicode_emoji("⭐⭐"));
|
||||
assert!(!is_unicode_emoji("x"));
|
||||
assert!(!is_unicode_emoji("\t"));
|
||||
assert!(!is_unicode_emoji(":meow_aww:"));
|
||||
}
|
||||
}
|
36
packages/backend-rs/src/misc/escape_sql.rs
Normal file
36
packages/backend-rs/src/misc/escape_sql.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
#[crate::export]
|
||||
pub fn sql_like_escape(src: &str) -> String {
|
||||
src.replace('%', r"\%").replace('_', r"\_")
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn safe_for_sql(src: &str) -> bool {
|
||||
!src.contains([
|
||||
'\0', '\x08', '\x09', '\x1a', '\n', '\r', '"', '\'', '\\', '%',
|
||||
])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{safe_for_sql, sql_like_escape};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn sql_like_escape_test() {
|
||||
assert_eq!(sql_like_escape(""), "");
|
||||
assert_eq!(sql_like_escape("abc"), "abc");
|
||||
assert_eq!(sql_like_escape("a%bc"), r"a\%bc");
|
||||
assert_eq!(sql_like_escape("a呼%吸bc"), r"a呼\%吸bc");
|
||||
assert_eq!(sql_like_escape("a呼%吸b%_c"), r"a呼\%吸b\%\_c");
|
||||
assert_eq!(sql_like_escape("_اللغة العربية"), r"\_اللغة العربية");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_for_sql_test() {
|
||||
assert!(safe_for_sql("123"));
|
||||
assert!(safe_for_sql("人間"));
|
||||
assert!(!safe_for_sql("人間\x09"));
|
||||
assert!(!safe_for_sql("abc\ndef"));
|
||||
assert!(!safe_for_sql("%something%"));
|
||||
}
|
||||
}
|
46
packages/backend-rs/src/misc/format_milliseconds.rs
Normal file
46
packages/backend-rs/src/misc/format_milliseconds.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
/// Convert milliseconds to a human readable string
|
||||
#[crate::export]
|
||||
pub fn format_milliseconds(milliseconds: u32) -> String {
|
||||
let mut seconds = milliseconds / 1000;
|
||||
let mut minutes = seconds / 60;
|
||||
let mut hours = minutes / 60;
|
||||
let days = hours / 24;
|
||||
|
||||
seconds %= 60;
|
||||
minutes %= 60;
|
||||
hours %= 24;
|
||||
|
||||
let mut buf: Vec<String> = vec![];
|
||||
|
||||
if days > 0 {
|
||||
buf.push(format!("{} day(s)", days));
|
||||
}
|
||||
if hours > 0 {
|
||||
buf.push(format!("{} hour(s)", hours));
|
||||
}
|
||||
if minutes > 0 {
|
||||
buf.push(format!("{} minute(s)", minutes));
|
||||
}
|
||||
if seconds > 0 {
|
||||
buf.push(format!("{} second(s)", seconds));
|
||||
}
|
||||
|
||||
buf.join(", ")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::format_milliseconds;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn format_milliseconds_test() {
|
||||
assert_eq!(format_milliseconds(1000), "1 second(s)");
|
||||
assert_eq!(format_milliseconds(1387938), "23 minute(s), 7 second(s)");
|
||||
assert_eq!(format_milliseconds(34200457), "9 hour(s), 30 minute(s)");
|
||||
assert_eq!(
|
||||
format_milliseconds(998244353),
|
||||
"11 day(s), 13 hour(s), 17 minute(s), 24 second(s)"
|
||||
);
|
||||
}
|
||||
}
|
90
packages/backend-rs/src/misc/get_note_summary.rs
Normal file
90
packages/backend-rs/src/misc/get_note_summary.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
/// TODO: handle name collisions better
|
||||
#[crate::export(object, js_name = "NoteLikeForGetNoteSummary")]
|
||||
pub struct NoteLike {
|
||||
pub file_ids: Vec<String>,
|
||||
pub text: Option<String>,
|
||||
pub cw: Option<String>,
|
||||
pub has_poll: bool,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn get_note_summary(note: NoteLike) -> String {
|
||||
let mut buf: Vec<String> = vec![];
|
||||
|
||||
if let Some(cw) = note.cw {
|
||||
buf.push(cw)
|
||||
} else if let Some(text) = note.text {
|
||||
buf.push(text)
|
||||
}
|
||||
|
||||
match note.file_ids.len() {
|
||||
0 => (),
|
||||
1 => buf.push("📎".to_string()),
|
||||
n => buf.push(format!("📎 ({})", n)),
|
||||
};
|
||||
|
||||
if note.has_poll {
|
||||
buf.push("📊".to_string())
|
||||
}
|
||||
|
||||
buf.join(" ")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{get_note_summary, NoteLike};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_note_summary() {
|
||||
let note = NoteLike {
|
||||
file_ids: vec![],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: None,
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note), "Hello world!");
|
||||
|
||||
let note_with_cw = NoteLike {
|
||||
file_ids: vec![],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: Some("Content warning".to_string()),
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_with_cw), "Content warning");
|
||||
|
||||
let note_with_file_and_cw = NoteLike {
|
||||
file_ids: vec!["9s7fmcqogiq4igin".to_string()],
|
||||
text: None,
|
||||
cw: Some("Selfie, no ec".to_string()),
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_with_file_and_cw), "Selfie, no ec 📎");
|
||||
|
||||
let note_with_files_only = NoteLike {
|
||||
file_ids: vec![
|
||||
"9s7fmcqogiq4igin".to_string(),
|
||||
"9s7qrld5u14cey98".to_string(),
|
||||
"9s7gebs5zgts4kca".to_string(),
|
||||
"9s5z3e4vefqd29ee".to_string(),
|
||||
],
|
||||
text: None,
|
||||
cw: None,
|
||||
has_poll: false,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_with_files_only), "📎 (4)");
|
||||
|
||||
let note_all = NoteLike {
|
||||
file_ids: vec![
|
||||
"9s7fmcqogiq4igin".to_string(),
|
||||
"9s7qrld5u14cey98".to_string(),
|
||||
"9s7gebs5zgts4kca".to_string(),
|
||||
"9s5z3e4vefqd29ee".to_string(),
|
||||
],
|
||||
text: Some("Hello world!".to_string()),
|
||||
cw: Some("Content warning".to_string()),
|
||||
has_poll: true,
|
||||
};
|
||||
assert_eq!(get_note_summary(note_all), "Content warning 📎 (4) 📊");
|
||||
}
|
||||
}
|
35
packages/backend-rs/src/misc/mastodon_id.rs
Normal file
35
packages/backend-rs/src/misc/mastodon_id.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
#[crate::export]
|
||||
pub fn to_mastodon_id(firefish_id: &str) -> Option<String> {
|
||||
let decoded: [u8; 16] = basen::BASE36.decode_var_len(&firefish_id.to_ascii_lowercase())?;
|
||||
Some(basen::BASE10.encode_var_len(&decoded))
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn from_mastodon_id(mastodon_id: &str) -> Option<String> {
|
||||
let decoded: [u8; 16] = basen::BASE10.decode_var_len(mastodon_id)?;
|
||||
Some(basen::BASE36.encode_var_len(&decoded))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{from_mastodon_id, to_mastodon_id};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn to_mastodon_id_test() {
|
||||
assert_eq!(
|
||||
to_mastodon_id("9pdqi3rjl4lxirq3").unwrap(),
|
||||
"2145531976185871567229403"
|
||||
);
|
||||
assert_eq!(to_mastodon_id("9pdqi3r*irq3"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_mastodon_id_test() {
|
||||
assert_eq!(
|
||||
from_mastodon_id("2145531976185871567229403").unwrap(),
|
||||
"9pdqi3rjl4lxirq3"
|
||||
);
|
||||
assert_eq!(from_mastodon_id("9pdqi3rjl4lxirq3"), None);
|
||||
}
|
||||
}
|
83
packages/backend-rs/src/misc/meta.rs
Normal file
83
packages/backend-rs/src/misc/meta.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use crate::database::db_conn;
|
||||
use crate::model::entity::meta;
|
||||
use rand::prelude::*;
|
||||
use sea_orm::{prelude::*, ActiveValue};
|
||||
use std::sync::Mutex;
|
||||
|
||||
type Meta = meta::Model;
|
||||
|
||||
static CACHE: Mutex<Option<Meta>> = Mutex::new(None);
|
||||
fn update_cache(meta: &Meta) {
|
||||
let _ = CACHE.lock().map(|mut cache| *cache = Some(meta.clone()));
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub async fn fetch_meta(use_cache: bool) -> Result<Meta, DbErr> {
|
||||
// try using cache
|
||||
if use_cache {
|
||||
if let Some(cache) = CACHE.lock().ok().and_then(|cache| cache.clone()) {
|
||||
return Ok(cache);
|
||||
}
|
||||
}
|
||||
|
||||
// try fetching from db
|
||||
let db = db_conn().await?;
|
||||
let meta = meta::Entity::find().one(db).await?;
|
||||
if let Some(meta) = meta {
|
||||
update_cache(&meta);
|
||||
return Ok(meta);
|
||||
}
|
||||
|
||||
// create a new meta object and insert into db
|
||||
let meta = meta::Entity::insert(meta::ActiveModel {
|
||||
id: ActiveValue::Set("x".to_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
.exec_with_returning(db)
|
||||
.await?;
|
||||
update_cache(&meta);
|
||||
Ok(meta)
|
||||
}
|
||||
|
||||
#[crate::export(object)]
|
||||
pub struct PugArgs {
|
||||
pub img: Option<String>,
|
||||
pub title: String,
|
||||
pub instance_name: String,
|
||||
pub desc: Option<String>,
|
||||
pub icon: Option<String>,
|
||||
pub splash_icon: Option<String>,
|
||||
pub theme_color: Option<String>,
|
||||
pub random_motd: String,
|
||||
pub private_mode: Option<bool>,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn meta_to_pug_args(meta: Meta) -> PugArgs {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let splash_icon = meta
|
||||
.custom_splash_icons
|
||||
.choose(&mut rng)
|
||||
.map(|s| s.to_owned())
|
||||
.or_else(|| meta.icon_url.to_owned());
|
||||
|
||||
let random_motd = meta
|
||||
.custom_motd
|
||||
.choose(&mut rng)
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| "Loading...".to_owned());
|
||||
|
||||
let name = meta.name.unwrap_or_else(|| "Firefish".to_owned());
|
||||
PugArgs {
|
||||
img: meta.banner_url,
|
||||
title: name.clone(),
|
||||
instance_name: name.clone(),
|
||||
desc: meta.description,
|
||||
icon: meta.icon_url,
|
||||
splash_icon,
|
||||
theme_color: meta.theme_color,
|
||||
random_motd,
|
||||
private_mode: meta.private_mode,
|
||||
}
|
||||
}
|
12
packages/backend-rs/src/misc/mod.rs
Normal file
12
packages/backend-rs/src/misc/mod.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
pub mod acct;
|
||||
pub mod check_word_mute;
|
||||
pub mod convert_host;
|
||||
pub mod emoji;
|
||||
pub mod escape_sql;
|
||||
pub mod format_milliseconds;
|
||||
pub mod get_note_summary;
|
||||
pub mod mastodon_id;
|
||||
pub mod meta;
|
||||
pub mod nyaify;
|
||||
pub mod password;
|
||||
pub mod reaction;
|
97
packages/backend-rs/src/misc/nyaify.rs
Normal file
97
packages/backend-rs/src/misc/nyaify.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use regex::{Captures, Regex};
|
||||
|
||||
#[crate::export]
|
||||
pub fn nyaify(text: &str, lang: Option<&str>) -> String {
|
||||
let mut to_return = text.to_owned();
|
||||
|
||||
{
|
||||
static RE: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"(?i-u)(non)([bcdfghjklmnpqrstvwxyz])").unwrap());
|
||||
to_return = RE
|
||||
.replace_all(&to_return, |caps: &Captures<'_>| {
|
||||
format!(
|
||||
"{}{}",
|
||||
match &caps[1] {
|
||||
"non" => "nyan",
|
||||
"Non" => "Nyan",
|
||||
"NON" => "NYAN",
|
||||
_ => &caps[1],
|
||||
},
|
||||
&caps[2]
|
||||
)
|
||||
})
|
||||
.to_string();
|
||||
}
|
||||
|
||||
{
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"다([..。…??!!\s]|$)").unwrap());
|
||||
to_return = RE.replace_all(&to_return, r"다냥$1").to_string();
|
||||
}
|
||||
|
||||
{
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"야([??\s]|$)").unwrap());
|
||||
to_return = RE.replace_all(&to_return, r"냥$1").to_string();
|
||||
}
|
||||
|
||||
{
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"([나-낳])").unwrap());
|
||||
to_return = RE
|
||||
.replace_all(&to_return, |caps: &Captures<'_>| {
|
||||
format!(
|
||||
"{}",
|
||||
char::from_u32(
|
||||
caps[0].chars().next().unwrap() as u32 + 56 /* = '냐' - '나' */
|
||||
)
|
||||
.unwrap()
|
||||
)
|
||||
})
|
||||
.to_string();
|
||||
}
|
||||
|
||||
if lang.is_some() && lang.unwrap().starts_with("zh") {
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[妙庙描渺瞄秒苗藐廟]").unwrap());
|
||||
to_return = RE.replace_all(&to_return, "喵").to_string();
|
||||
}
|
||||
|
||||
let simple_rules = [
|
||||
("な", "にゃ"),
|
||||
("ナ", "ニャ"),
|
||||
("ナ", "ニャ"),
|
||||
("na", "nya"),
|
||||
("NA", "NYA"),
|
||||
("Na", "Nya"),
|
||||
("morning", "mornyan"),
|
||||
("Morning", "Mornyan"),
|
||||
("MORNING", "MORNYAN"),
|
||||
("everyone", "everynyan"),
|
||||
("Everyone", "Everynyan"),
|
||||
("EVERYONE", "EVERYNYAN"),
|
||||
("να", "νια"),
|
||||
("ΝΑ", "ΝΙΑ"),
|
||||
("Να", "Νια"),
|
||||
];
|
||||
|
||||
simple_rules.into_iter().for_each(|(from, to)| {
|
||||
to_return = to_return.replace(from, to);
|
||||
});
|
||||
|
||||
to_return
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::nyaify;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn can_nyaify() {
|
||||
assert_eq!(nyaify("Hello everyone!", Some("en")), "Hello everynyan!");
|
||||
assert_eq!(nyaify("Nonbinary people", None), "Nyanbinyary people");
|
||||
assert_eq!(nyaify("1分鐘是60秒", Some("zh-TW")), "1分鐘是60喵");
|
||||
assert_eq!(nyaify("1分間は60秒です", Some("ja-JP")), "1分間は60秒です");
|
||||
assert_eq!(nyaify("あなたは誰ですか", None), "あにゃたは誰ですか");
|
||||
assert_eq!(nyaify("Ναυτικός", Some("el-GR")), "Νιαυτικός");
|
||||
assert_eq!(nyaify("일어나다", None), "일어냐다냥");
|
||||
}
|
||||
}
|
69
packages/backend-rs/src/misc/password.rs
Normal file
69
packages/backend-rs/src/misc/password.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use argon2::{
|
||||
password_hash,
|
||||
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
||||
Argon2,
|
||||
};
|
||||
|
||||
#[crate::export]
|
||||
pub fn hash_password(password: &str) -> Result<String, password_hash::errors::Error> {
|
||||
let salt = SaltString::generate(&mut OsRng);
|
||||
Ok(Argon2::default()
|
||||
.hash_password(password.as_bytes(), &salt)?
|
||||
.to_string())
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum VerifyError {
|
||||
#[error("An error occured while bcrypt verification: {0}")]
|
||||
BcryptError(#[from] bcrypt::BcryptError),
|
||||
#[error("Invalid argon2 password hash: {0}")]
|
||||
InvalidArgon2Hash(#[from] password_hash::Error),
|
||||
#[error("An error occured while argon2 verification: {0}")]
|
||||
Argon2Error(#[from] argon2::Error),
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn verify_password(password: &str, hash: &str) -> Result<bool, VerifyError> {
|
||||
if is_old_password_algorithm(hash) {
|
||||
Ok(bcrypt::verify(password, hash)?)
|
||||
} else {
|
||||
let parsed_hash = PasswordHash::new(hash)?;
|
||||
Ok(Argon2::default()
|
||||
.verify_password(password.as_bytes(), &parsed_hash)
|
||||
.is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[crate::export]
|
||||
pub fn is_old_password_algorithm(hash: &str) -> bool {
|
||||
// bcrypt hashes start with $2[ab]$
|
||||
hash.starts_with("$2")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{hash_password, is_old_password_algorithm, verify_password};
|
||||
|
||||
#[test]
|
||||
fn verify_password_test() {
|
||||
let password = "omWc*%sD^fn7o2cXmc9e2QasBdrbRuhNB*gx!J5";
|
||||
|
||||
let hash = hash_password(password).unwrap();
|
||||
assert!(verify_password(password, hash.as_str()).unwrap());
|
||||
|
||||
let argon2_hash = "$argon2id$v=19$m=19456,t=2,p=1$jty3puDFd4ENv/lgHn3ROQ$kRHDdEoVv2rruvnF731E74NxnYlvj5FMgePdGIIq3Jk";
|
||||
let argon2_invalid_hash = "$argon2id$v=19$m=19456,t=2,p=1$jty3puDFd4ENv/lgHn3ROQ$kRHDdEoVv2rruvnF731E74NxnYlvj4FMgePdGIIq3Jk";
|
||||
let bcrypt_hash = "$2a$12$WzUc.20jgbHmQjUMqTr8vOhKqYbS1BUvubapv/GLjCK1IN.h4e4la";
|
||||
let bcrypt_invalid_hash = "$2a$12$WzUc.20jgbHmQjUMqTr7vOhKqYbS1BUvubapv/GLjCK1IN.h4e4la";
|
||||
|
||||
assert!(!is_old_password_algorithm(argon2_hash));
|
||||
assert!(is_old_password_algorithm(bcrypt_hash));
|
||||
|
||||
assert!(verify_password(password, argon2_hash).unwrap());
|
||||
assert!(verify_password(password, bcrypt_hash).unwrap());
|
||||
|
||||
assert!(!verify_password(password, argon2_invalid_hash).unwrap());
|
||||
assert!(!verify_password(password, bcrypt_invalid_hash).unwrap());
|
||||
}
|
||||
}
|
191
packages/backend-rs/src/misc/reaction.rs
Normal file
191
packages/backend-rs/src/misc/reaction.rs
Normal file
|
@ -0,0 +1,191 @@
|
|||
use crate::database::db_conn;
|
||||
use crate::misc::{convert_host::to_puny, emoji::is_unicode_emoji, meta::fetch_meta};
|
||||
use crate::model::entity::emoji;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use sea_orm::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[crate::export(object)]
|
||||
pub struct DecodedReaction {
|
||||
pub reaction: String,
|
||||
pub name: Option<String>,
|
||||
pub host: Option<String>,
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn decode_reaction(reaction: &str) -> DecodedReaction {
|
||||
// Misskey allows you to include "+" and "-" in emoji shortcodes
|
||||
// MFM spec: https://github.com/misskey-dev/mfm.js/blob/6aaf68089023c6adebe44123eebbc4dcd75955e0/docs/syntax.md?plain=1#L583
|
||||
// Misskey's implementation: https://github.com/misskey-dev/misskey/blob/bba3097765317cbf95d09627961b5b5dce16a972/packages/backend/src/core/ReactionService.ts#L68
|
||||
static RE: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"^:([0-9A-Za-z_+-]+)(?:@([0-9A-Za-z_.-]+))?:$").unwrap());
|
||||
|
||||
if let Some(captures) = RE.captures(reaction) {
|
||||
let name = &captures[1];
|
||||
let host = captures.get(2).map(|s| s.as_str());
|
||||
|
||||
DecodedReaction {
|
||||
reaction: format!(":{}@{}:", name, host.unwrap_or(".")),
|
||||
name: Some(name.to_owned()),
|
||||
host: host.map(|s| s.to_owned()),
|
||||
}
|
||||
} else {
|
||||
DecodedReaction {
|
||||
reaction: reaction.to_owned(),
|
||||
name: None,
|
||||
host: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn count_reactions(reactions: &HashMap<String, u32>) -> HashMap<String, u32> {
|
||||
let mut res = HashMap::<String, u32>::new();
|
||||
|
||||
for (reaction, count) in reactions.iter() {
|
||||
if count > &0 {
|
||||
let decoded = decode_reaction(reaction).reaction;
|
||||
let total = res.entry(decoded).or_insert(0);
|
||||
*total += count;
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Idna error: {0}")]
|
||||
IdnaError(#[from] idna::Errors),
|
||||
#[error("Database error: {0}")]
|
||||
DbError(#[from] DbErr),
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub async fn to_db_reaction(reaction: Option<&str>, host: Option<&str>) -> Result<String, Error> {
|
||||
if let Some(reaction) = reaction {
|
||||
// FIXME: Is it okay to do this only here?
|
||||
// This was introduced in https://firefish.dev/firefish/firefish/-/commit/af730e75b6fc1a57ca680ce83459d7e433b130cf
|
||||
if reaction.contains('❤') || reaction.contains("♥️") {
|
||||
return Ok("❤️".to_owned());
|
||||
}
|
||||
|
||||
if is_unicode_emoji(reaction) {
|
||||
return Ok(reaction.to_owned());
|
||||
}
|
||||
|
||||
static RE: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"^:([0-9A-Za-z_+-]+)(?:@\.)?:$").unwrap());
|
||||
|
||||
if let Some(captures) = RE.captures(reaction) {
|
||||
let name = &captures[1];
|
||||
let db = db_conn().await?;
|
||||
|
||||
if let Some(host) = host {
|
||||
// remote emoji
|
||||
let ascii_host = to_puny(host)?;
|
||||
|
||||
// TODO: Does SeaORM have the `exists` method?
|
||||
if emoji::Entity::find()
|
||||
.filter(emoji::Column::Name.eq(name))
|
||||
.filter(emoji::Column::Host.eq(&ascii_host))
|
||||
.one(db)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
return Ok(format!(":{name}@{ascii_host}:"));
|
||||
}
|
||||
} else {
|
||||
// local emoji
|
||||
// TODO: Does SeaORM have the `exists` method?
|
||||
if emoji::Entity::find()
|
||||
.filter(emoji::Column::Name.eq(name))
|
||||
.filter(emoji::Column::Host.is_null())
|
||||
.one(db)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
return Ok(format!(":{name}:"));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Ok(fetch_meta(true).await?.default_reaction)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{decode_reaction, DecodedReaction};
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
|
||||
#[test]
|
||||
fn test_decode_reaction() {
|
||||
let unicode_emoji_1 = DecodedReaction {
|
||||
reaction: "⭐".to_string(),
|
||||
name: None,
|
||||
host: None,
|
||||
};
|
||||
let unicode_emoji_2 = DecodedReaction {
|
||||
reaction: "🩷".to_string(),
|
||||
name: None,
|
||||
host: None,
|
||||
};
|
||||
|
||||
assert_eq!(decode_reaction("⭐"), unicode_emoji_1);
|
||||
assert_eq!(decode_reaction("🩷"), unicode_emoji_2);
|
||||
|
||||
assert_ne!(decode_reaction("⭐"), unicode_emoji_2);
|
||||
assert_ne!(decode_reaction("🩷"), unicode_emoji_1);
|
||||
|
||||
let unicode_emoji_3 = DecodedReaction {
|
||||
reaction: "🖖🏿".to_string(),
|
||||
name: None,
|
||||
host: None,
|
||||
};
|
||||
assert_eq!(decode_reaction("🖖🏿"), unicode_emoji_3);
|
||||
|
||||
let local_emoji = DecodedReaction {
|
||||
reaction: ":meow_melt_tears@.:".to_string(),
|
||||
name: Some("meow_melt_tears".to_string()),
|
||||
host: None,
|
||||
};
|
||||
assert_eq!(decode_reaction(":meow_melt_tears:"), local_emoji);
|
||||
|
||||
let remote_emoji_1 = DecodedReaction {
|
||||
reaction: ":meow_uwu@some-domain.example.org:".to_string(),
|
||||
name: Some("meow_uwu".to_string()),
|
||||
host: Some("some-domain.example.org".to_string()),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_reaction(":meow_uwu@some-domain.example.org:"),
|
||||
remote_emoji_1
|
||||
);
|
||||
|
||||
let remote_emoji_2 = DecodedReaction {
|
||||
reaction: ":C++23@xn--eckwd4c7c.example.org:".to_string(),
|
||||
name: Some("C++23".to_string()),
|
||||
host: Some("xn--eckwd4c7c.example.org".to_string()),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_reaction(":C++23@xn--eckwd4c7c.example.org:"),
|
||||
remote_emoji_2
|
||||
);
|
||||
|
||||
let invalid_reaction_1 = DecodedReaction {
|
||||
reaction: ":foo".to_string(),
|
||||
name: None,
|
||||
host: None,
|
||||
};
|
||||
assert_eq!(decode_reaction(":foo"), invalid_reaction_1);
|
||||
|
||||
let invalid_reaction_2 = DecodedReaction {
|
||||
reaction: ":foo&@example.com:".to_string(),
|
||||
name: None,
|
||||
host: None,
|
||||
};
|
||||
assert_eq!(decode_reaction(":foo&@example.com:"), invalid_reaction_2);
|
||||
}
|
||||
}
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "abuse_user_report")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "AbuseUserReport", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "targetUserId")]
|
||||
pub target_user_id: String,
|
||||
#[sea_orm(column_name = "reporterId")]
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "access_token")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "AccessToken", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
pub token: String,
|
||||
pub hash: String,
|
||||
#[sea_orm(column_name = "userId")]
|
||||
|
@ -16,7 +20,7 @@ pub struct Model {
|
|||
#[sea_orm(column_name = "appId")]
|
||||
pub app_id: Option<String>,
|
||||
#[sea_orm(column_name = "lastUsedAt")]
|
||||
pub last_used_at: Option<DateTimeWithTimeZone>,
|
||||
pub last_used_at: Option<DateTime>,
|
||||
pub session: Option<String>,
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
|
|
|
@ -4,13 +4,17 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "ad")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "Ad", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "expiresAt")]
|
||||
pub expires_at: DateTimeWithTimeZone,
|
||||
pub expires_at: DateTime,
|
||||
pub place: String,
|
||||
pub priority: String,
|
||||
pub url: String,
|
||||
|
|
|
@ -4,17 +4,21 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "announcement")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "Announcement", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
pub text: String,
|
||||
pub title: String,
|
||||
#[sea_orm(column_name = "imageUrl")]
|
||||
pub image_url: Option<String>,
|
||||
#[sea_orm(column_name = "updatedAt")]
|
||||
pub updated_at: Option<DateTimeWithTimeZone>,
|
||||
pub updated_at: Option<DateTime>,
|
||||
#[sea_orm(column_name = "showPopup")]
|
||||
pub show_popup: bool,
|
||||
#[sea_orm(column_name = "isGoodNews")]
|
||||
|
|
|
@ -4,6 +4,10 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "announcement_read")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "AnnouncementRead", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
|
@ -12,7 +16,7 @@ pub struct Model {
|
|||
#[sea_orm(column_name = "announcementId")]
|
||||
pub announcement_id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
|
|
|
@ -5,11 +5,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "antenna")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "Antenna", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "userId")]
|
||||
pub user_id: String,
|
||||
pub name: String,
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "app")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "App", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "userId")]
|
||||
pub user_id: Option<String>,
|
||||
pub secret: String,
|
||||
|
|
|
@ -4,6 +4,10 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "attestation_challenge")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "AttestationChallenge", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
|
@ -11,7 +15,7 @@ pub struct Model {
|
|||
pub user_id: String,
|
||||
pub challenge: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "registrationChallenge")]
|
||||
pub registration_challenge: bool,
|
||||
}
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "auth_session")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "AuthSession", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
pub token: String,
|
||||
#[sea_orm(column_name = "userId")]
|
||||
pub user_id: Option<String>,
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "blocking")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "Blocking", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "blockeeId")]
|
||||
pub blockee_id: String,
|
||||
#[sea_orm(column_name = "blockerId")]
|
||||
|
|
|
@ -4,13 +4,17 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "channel")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "Channel", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "lastNotedAt")]
|
||||
pub last_noted_at: Option<DateTimeWithTimeZone>,
|
||||
pub last_noted_at: Option<DateTime>,
|
||||
#[sea_orm(column_name = "userId")]
|
||||
pub user_id: Option<String>,
|
||||
pub name: String,
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "channel_following")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "ChannelFollowing", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "followeeId")]
|
||||
pub followee_id: String,
|
||||
#[sea_orm(column_name = "followerId")]
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "channel_note_pining")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "ChannelNotePining", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "channelId")]
|
||||
pub channel_id: String,
|
||||
#[sea_orm(column_name = "noteId")]
|
||||
|
|
|
@ -4,11 +4,15 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "clip")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "Clip", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
#[sea_orm(column_name = "createdAt")]
|
||||
pub created_at: DateTimeWithTimeZone,
|
||||
pub created_at: DateTime,
|
||||
#[sea_orm(column_name = "userId")]
|
||||
pub user_id: String,
|
||||
pub name: String,
|
||||
|
|
|
@ -4,6 +4,10 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "clip_note")]
|
||||
#[cfg_attr(
|
||||
feature = "napi",
|
||||
napi_derive::napi(object, js_name = "ClipNote", use_nullable = true)
|
||||
)]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: String,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue