Merge branch 'develop' into 'main'
release: v20240818 Co-authored-by: Hosted Weblate <hosted@weblate.org> Co-authored-by: GitLab CI <project_7_bot_1bfaee5701aed20091a86249a967a6c1@noreply.firefish.dev> Co-authored-by: mester yui <oscarodriguez56@gmail.com> Co-authored-by: jolupa <jolupameister@gmail.com> Co-authored-by: Lacey Anaya <yecakeh263@anawalls.com> Co-authored-by: FLY_MC <me@flymc.cc> See merge request firefish/firefish!11293
This commit is contained in:
commit
aa1d23e6cd
65 changed files with 837 additions and 735 deletions
102
Cargo.lock
generated
102
Cargo.lock
generated
|
@ -98,7 +98,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -149,7 +149,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -160,7 +160,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -213,6 +213,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"cuid2",
|
||||
"emojis",
|
||||
"error-doc",
|
||||
"futures-util",
|
||||
"identicon-rs",
|
||||
"idna 1.0.2",
|
||||
|
@ -660,7 +661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -798,7 +799,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -858,7 +859,7 @@ dependencies = [
|
|||
"enum-ordinalize",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -926,7 +927,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -945,6 +946,17 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-doc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ffaad84523e0144697672bce3a0d8e300fd43404a630d420f238e2ef2e85b84"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "etcetera"
|
||||
version = "0.8.0"
|
||||
|
@ -1478,7 +1490,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1571,7 +1583,7 @@ checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1600,7 +1612,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1856,7 +1868,7 @@ dependencies = [
|
|||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -1867,7 +1879,7 @@ dependencies = [
|
|||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1964,7 +1976,7 @@ dependencies = [
|
|||
"napi-derive-backend",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1979,7 +1991,7 @@ dependencies = [
|
|||
"quote",
|
||||
"regex",
|
||||
"semver",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2109,7 +2121,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2200,7 +2212,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2261,7 +2273,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2419,7 +2431,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2595,7 +2607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2994,7 +3006,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3033,7 +3045,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"sea-bae",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
|
@ -3095,29 +3107,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.205"
|
||||
version = "1.0.208"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150"
|
||||
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.205"
|
||||
version = "1.0.208"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1"
|
||||
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.122"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
|
||||
checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
|
@ -3584,9 +3596,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.72"
|
||||
version = "2.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||
checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3613,7 +3625,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3687,7 +3699,7 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3698,7 +3710,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3782,9 +3794,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.39.2"
|
||||
version = "1.39.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
|
||||
checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -3805,7 +3817,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3899,7 +3911,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4135,7 +4147,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -4157,7 +4169,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -4273,7 +4285,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4284,7 +4296,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4482,7 +4494,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
"synstructure 0.13.1",
|
||||
]
|
||||
|
||||
|
@ -4504,7 +4516,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4524,7 +4536,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
"synstructure 0.13.1",
|
||||
]
|
||||
|
||||
|
@ -4553,7 +4565,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"syn 2.0.75",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -23,6 +23,7 @@ chrono = { version = "0.4.38", default-features = false }
|
|||
convert_case = { version = "0.6.0", default-features = false }
|
||||
cuid2 = { version = "0.1.2", default-features = false }
|
||||
emojis = { version = "0.6.3", default-features = false }
|
||||
error-doc = { version = "0.1.0" }
|
||||
futures-util = { version = "0.3.30", default-features = false }
|
||||
identicon-rs = "5.0.1"
|
||||
idna = { version = "1.0.2", default-features = false }
|
||||
|
@ -38,13 +39,13 @@ redis = { version = "0.26.1", default-features = false }
|
|||
regex = { version = "1.10.6", default-features = false }
|
||||
rmp-serde = { version = "1.3.0", default-features = false }
|
||||
sea-orm = { version = "1.0.0", default-features = false }
|
||||
serde = { version = "1.0.205", default-features = false }
|
||||
serde_json = { version = "1.0.122", default-features = false }
|
||||
serde = { version = "1.0.208", default-features = false }
|
||||
serde_json = { version = "1.0.125", default-features = false }
|
||||
serde_yaml = { version = "0.9.34", default-features = false }
|
||||
syn = { version = "2.0.72", default-features = false }
|
||||
syn = { version = "2.0.75", default-features = false }
|
||||
sysinfo = { version = "0.31.2", default-features = false }
|
||||
thiserror = { version = "1.0.63", default-features = false }
|
||||
tokio = { version = "1.39.2", default-features = false }
|
||||
tokio = { version = "1.39.3", default-features = false }
|
||||
tokio-test = { version = "0.4.4", default-features = false }
|
||||
tracing = { version = "0.1.40", default-features = false }
|
||||
tracing-subscriber = { version = "0.3.18", default-features = false }
|
||||
|
|
|
@ -7,6 +7,10 @@ This changelog is not an exhaustive list. Code refactorings, minor bug fixes, do
|
|||
- Server administrators must check [notice-for-admins.md](https://firefish.dev/firefish/firefish/-/blob/main/docs/notice-for-admins.md) as well.
|
||||
- Third-party client/bot developers may want to check [api-change.md](https://firefish.dev/firefish/firefish/-/blob/main/docs/api-change.md) as well.
|
||||
|
||||
## [v20240818](https://firefish.dev/firefish/firefish/-/merge_requests/11293/commits)
|
||||
|
||||
- Fix bugs
|
||||
|
||||
## [v20240809](https://firefish.dev/firefish/firefish/-/merge_requests/11262/commits)
|
||||
|
||||
- Add writing mode (right-to-left, vertical) support (!11222)
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
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](https://firefish.dev/firefish/firefish/-/blob/main/docs/upgrade.md).
|
||||
|
||||
## Upcoming breaking change (unreleased)
|
||||
|
||||
Please take a look at #10947.
|
||||
|
||||
## v20240809
|
||||
|
||||
### For systemd/pm2 users
|
||||
|
|
|
@ -1250,8 +1250,8 @@ disablePlayer: Tancar el reproductor de vídeo
|
|||
fileIdOrUrl: ID o adreça URL del fitxer
|
||||
behavior: Comportament
|
||||
regenerateLoginTokenDescription: Regenera la clau que es fa servir de manera interna
|
||||
durant l'inici de sessió. Normalment això no és necessari. Si la clau és torna a
|
||||
generar, es tancarà la sessió a tots els dispositius.
|
||||
durant l'inici de sessió. Usualment aquesta acció no és necessària. Si la clau és
|
||||
torna a generar, es tancarà la sessió a tots els dispositius.
|
||||
setMultipleBySeparatingWithSpace: Separa diferents entrades amb espais.
|
||||
reportAbuseOf: Informa d'un abús de {name}
|
||||
sample: Exemple
|
||||
|
|
|
@ -128,7 +128,7 @@ pinnedNote: "Pinned post"
|
|||
pinned: "Pin to profile"
|
||||
you: "You"
|
||||
clickToShow: "Click to show"
|
||||
sensitive: "NSFW"
|
||||
sensitive: "Sensitive"
|
||||
add: "Add"
|
||||
reaction: "Reaction"
|
||||
reactions: "Reactions"
|
||||
|
@ -139,8 +139,8 @@ reactionSetting: "Reactions to show in the reaction picker"
|
|||
reactionSettingDescription2: "Drag to reorder, click to delete, press \"+\" to add."
|
||||
rememberNoteVisibility: "Remember post visibility settings"
|
||||
attachCancel: "Remove attachment"
|
||||
markAsSensitive: "Mark as NSFW"
|
||||
unmarkAsSensitive: "Unmark as NSFW"
|
||||
markAsSensitive: "Mark as sensitive"
|
||||
unmarkAsSensitive: "Unmark as sensitive"
|
||||
clickToShowPatterns: "Click to show module patterns"
|
||||
enterFileName: "Enter filename"
|
||||
mute: "Mute"
|
||||
|
@ -176,7 +176,7 @@ cacheRemoteFilesDescription: "When this setting is disabled, remote files are lo
|
|||
increase traffic, as thumbnails will not be generated."
|
||||
markLocalFilesNsfwByDefault: "Mark all new local file as sensitive by default"
|
||||
markLocalFilesNsfwByDefaultDescription: "Regardless of this setting, users can remove
|
||||
the NSFW flag themselves. Existing files are unaffected."
|
||||
the sensitive flag themselves. Existing files are unaffected."
|
||||
flagAsBot: "Mark this account as automated"
|
||||
flagAsBotDescription: "Enable this option if this account is controlled by a program.
|
||||
If enabled, it will act as a flag for other developers to prevent endless interaction
|
||||
|
@ -362,7 +362,7 @@ copyUrl: "Copy URL"
|
|||
rename: "Rename"
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
nsfw: "NSFW"
|
||||
nsfw: "Sensitive"
|
||||
whenServerDisconnected: "When losing connection to the server"
|
||||
disconnectedFromServer: "Connection to server has been lost"
|
||||
reload: "Refresh"
|
||||
|
@ -727,7 +727,7 @@ useGlobalSettingDesc: "If turned on, your account's notification settings will b
|
|||
other: "Other"
|
||||
regenerateLoginToken: "Regenerate sign in token"
|
||||
regenerateLoginTokenDescription: "Regenerates the token used internally during sign
|
||||
in. Normally this action is not necessary. If regenerated, all devices will be logged
|
||||
in. Usually this action is not necessary. If regenerated, all devices will be logged
|
||||
out."
|
||||
setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces."
|
||||
fileIdOrUrl: "File ID or URL"
|
||||
|
@ -792,7 +792,7 @@ noCrawle: "Reject crawler indexing"
|
|||
noCrawleDescription: "Ask external search engines to not index your content."
|
||||
lockedAccountInfo: "Unless you set your post visiblity to \"Followers only\", your
|
||||
posts will be visible to anyone, even if you require followers to be manually approved."
|
||||
alwaysMarkSensitive: "Mark as NSFW by default"
|
||||
alwaysMarkSensitive: "Mark as sensitive by default"
|
||||
loadRawImages: "Load original images instead of showing thumbnails"
|
||||
disableShowingAnimatedImages: "Don't play animated images"
|
||||
verificationEmailSent: "A verification email has been sent. Please follow the included
|
||||
|
@ -1035,20 +1035,16 @@ type: "Type"
|
|||
speed: "Speed"
|
||||
slow: "Slow"
|
||||
fast: "Fast"
|
||||
sensitiveMediaDetection: "Detection of NSFW media"
|
||||
localOnly: "Local only"
|
||||
remoteOnly: "Remote only"
|
||||
failedToUpload: "Upload failed"
|
||||
cannotUploadBecauseInappropriate: "This file could not be uploaded because parts of
|
||||
it have been detected as potentially NSFW."
|
||||
it have been detected as potentially sensitive."
|
||||
cannotUploadBecauseNoFreeSpace: "Upload failed due to lack of Drive capacity."
|
||||
cannotUploadBecauseExceedsFileSizeLimit: "This file could not be uploaded because
|
||||
it exceeds the maximum allowed size."
|
||||
beta: "Beta"
|
||||
enableAutoSensitive: "Automatic NSFW-Marking"
|
||||
enableAutoSensitiveDescription: "Allows automatic detection and marking of NSFW media
|
||||
through Machine Learning where possible. Even if this option is disabled, it may
|
||||
be enabled server-wide."
|
||||
enableAutoSensitive: "Mark as sensitive automatically"
|
||||
activeEmailValidationDescription: "Enables stricter validation of email addresses,
|
||||
which includes checking for disposable addresses and by whether it can actually
|
||||
be communicated with. When unchecked, only the format of the email is validated."
|
||||
|
@ -1249,19 +1245,6 @@ _emojiModPerm:
|
|||
add: "Add"
|
||||
mod: "Add and Edit"
|
||||
full: "Allow All"
|
||||
_sensitiveMediaDetection:
|
||||
description: "Reduces the effort of server moderation through automatically recognizing
|
||||
NSFW media via Machine Learning. This will slightly increase the load on the server."
|
||||
sensitivity: "Detection sensitivity"
|
||||
sensitivityDescription: "Reducing the sensitivity will lead to fewer misdetections
|
||||
(false positives) whereas increasing it will lead to fewer missed detections (false
|
||||
negatives)."
|
||||
setSensitiveFlagAutomatically: "Mark as NSFW"
|
||||
setSensitiveFlagAutomaticallyDescription: "The results of the internal detection
|
||||
will be retained even if this option is turned off."
|
||||
analyzeVideos: "Enable analysis of videos"
|
||||
analyzeVideosDescription: "Analyzes videos in addition to images. This will slightly
|
||||
increase the load on the server."
|
||||
_emailUnavailable:
|
||||
used: "This email address is already being used"
|
||||
format: "The format of this email address is invalid"
|
||||
|
@ -1354,8 +1337,8 @@ _aboutFirefish:
|
|||
to help support its operation costs."
|
||||
donateHost: "Donate to {host}"
|
||||
_nsfw:
|
||||
respect: "Hide NSFW media"
|
||||
ignore: "Don't hide NSFW media"
|
||||
respect: "Hide sensitive media"
|
||||
ignore: "Don't hide sensitive media"
|
||||
force: "Hide all media"
|
||||
writingMode: "Writing mode"
|
||||
_writingMode:
|
||||
|
|
|
@ -30,3 +30,11 @@ loggingIn: Ensalutante
|
|||
logout: Elsaluti
|
||||
timeline: Templinio
|
||||
signup: Registru
|
||||
favorites: Paĝosignoj
|
||||
unfavorite: Forigi el paĝosignoj
|
||||
uploading: Alŝutante...
|
||||
save: Konservi
|
||||
users: Uzantoj
|
||||
addUser: Aldoni uzanton
|
||||
addInstance: Aldoni servilon
|
||||
favorite: Aldoni al paĝosigno
|
||||
|
|
|
@ -939,7 +939,7 @@ cannotUploadBecauseInappropriate: "不適切な内容を含む可能性がある
|
|||
cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いためアップロードできません。"
|
||||
cannotUploadBecauseExceedsFileSizeLimit: "ファイルサイズの制限を超えているためアップロードできません。"
|
||||
beta: "ベータ"
|
||||
enableAutoSensitive: "自動NSFW判定"
|
||||
enableAutoSensitive: "自動で閲覧注意にする"
|
||||
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、サーバーによっては自動で設定されることがあります。"
|
||||
activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。"
|
||||
showAds: "コミュニティバナーを表示する"
|
||||
|
@ -1017,7 +1017,7 @@ searchWordsDescription: "投稿を検索するには、ここに検索語句を
|
|||
(@user@example.com) や投稿のURLを入力し「照会」を押してください。「検索」を押すとそのIDやURLが文字通り含まれる投稿を検索します。"
|
||||
searchUsers: "投稿元(省略可)"
|
||||
searchUsersDescription: "投稿検索で投稿者を絞りたい場合、@user@example.com(ローカルユーザーなら @user)の形式で投稿者のIDを入力してください。ユーザーIDではなくドメイン名
|
||||
(example.com) を指定すると、そのサーバーの投稿を検索します。\n\nme とだけ入力すると、自分の投稿を検索します。この検索結果には未収載・フォロワー限定・ダイレクト・秘密を含む全ての投稿が含まれます。\n
|
||||
(example.com) を指定すると、そのサーバーの投稿を検索します。\n\nme とだけ入力すると、自分の投稿を検索します。この検索結果には控えめな公開・フォロワー限定・ダイレクト・秘密を含む全ての投稿が含まれます。\n
|
||||
\nlocal とだけ入力すると、ローカルサーバーの投稿を検索します。"
|
||||
searchRange: "投稿期間(省略可)"
|
||||
searchRangeDescription: "投稿検索で投稿期間を絞りたい場合、20220615-20231031 のような形式で投稿期間を入力してください。今年の日付を指定する場合には年の指定を省略できます(0105-0106
|
||||
|
@ -1516,7 +1516,7 @@ _poll:
|
|||
_visibility:
|
||||
public: "公開"
|
||||
publicDescription: "全ての公開タイムラインに配信されます"
|
||||
home: "未収載"
|
||||
home: "控えめな公開"
|
||||
homeDescription: "ホームタイムラインのみに公開"
|
||||
followers: "フォロワー"
|
||||
followersDescription: "フォロワーと会話相手のみに公開"
|
||||
|
@ -2070,7 +2070,7 @@ driveCapacityOverride: ドライブ容量の変更
|
|||
autocorrectNoteLanguage: 設定した投稿言語が自動検出されたものと異なる場合に警告する
|
||||
incorrectLanguageWarning: "この投稿は{detected}で書かれていると判定されました。\n投稿言語を{current}ではなく{detected}にしますか?"
|
||||
markLocalFilesNsfwByDefault: このサーバーの全てのファイルをデフォルトでNSFWに設定する
|
||||
markLocalFilesNsfwByDefaultDescription: この設定が有効でも、ユーザーは自分でNSFWのフラグを外すことができます。また、この設定は既存のファイルには影響しません。
|
||||
markLocalFilesNsfwByDefaultDescription: この設定が有効でも、ユーザーは自分で閲覧注意のフラグを外すことができます。また、この設定は既存のファイルには影響しません。
|
||||
noteEditHistory: 編集履歴
|
||||
showAddFileDescriptionAtFirstPost: 説明の無い添付ファイルを投稿しようとした際に説明を書く画面を自動で開く
|
||||
antennaLimit: 各ユーザーが作れるアンテナの最大数
|
||||
|
|
|
@ -1392,7 +1392,7 @@ _poll:
|
|||
_visibility:
|
||||
public: "公開"
|
||||
publicDescription: "發佈至公開時間軸"
|
||||
home: "不在主頁顯示"
|
||||
home: "悄悄公開"
|
||||
homeDescription: "僅發送至首頁的時間軸"
|
||||
followers: "追隨者"
|
||||
followersDescription: "僅發佈至關注者"
|
||||
|
|
10
package.json
10
package.json
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "firefish",
|
||||
"version": "20240809",
|
||||
"version": "20240818",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://firefish.dev/firefish/firefish.git"
|
||||
},
|
||||
"packageManager": "pnpm@9.7.0",
|
||||
"packageManager": "pnpm@9.7.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"rebuild": "pnpm run clean && pnpm run build",
|
||||
|
@ -47,8 +47,8 @@
|
|||
"@biomejs/cli-darwin-x64": "1.8.3",
|
||||
"@biomejs/cli-linux-arm64": "1.8.3",
|
||||
"@biomejs/cli-linux-x64": "1.8.3",
|
||||
"@types/node": "20.14.14",
|
||||
"execa": "9.3.0",
|
||||
"pnpm": "9.7.0"
|
||||
"@types/node": "20.15.0",
|
||||
"execa": "9.3.1",
|
||||
"pnpm": "9.7.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ bcrypt = { workspace = true, features = ["std"] }
|
|||
chrono = { workspace = true }
|
||||
cuid2 = { workspace = true }
|
||||
emojis = { workspace = true }
|
||||
error-doc = { workspace = true }
|
||||
futures-util = { workspace = true, features = ["io"] }
|
||||
identicon-rs = { workspace = true }
|
||||
idna = { workspace = true, features = ["std", "compiled_data"] }
|
||||
|
|
80
packages/backend-rs/index.d.ts
vendored
80
packages/backend-rs/index.d.ts
vendored
|
@ -48,6 +48,20 @@ export interface Acct {
|
|||
|
||||
export declare function acctToString(acct: Acct): string
|
||||
|
||||
export type Activity = 'Accept'|
|
||||
'Add'|
|
||||
'Emoji'|
|
||||
'Flag'|
|
||||
'Follow'|
|
||||
'Hashtag'|
|
||||
'Like'|
|
||||
'Mention'|
|
||||
'Image'|
|
||||
'Read'|
|
||||
'Reject'|
|
||||
'Remove'|
|
||||
'Tombstone';
|
||||
|
||||
export interface Ad {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
@ -106,21 +120,28 @@ export type AntennaSrc = 'all'|
|
|||
|
||||
export interface ApAccept {
|
||||
id: string
|
||||
type: ApObject
|
||||
type: Activity
|
||||
actor: string
|
||||
object: ApFollow
|
||||
}
|
||||
|
||||
export interface ApAdd {
|
||||
type: Activity
|
||||
actor: string
|
||||
target: string
|
||||
object: string
|
||||
}
|
||||
|
||||
export interface ApEmoji {
|
||||
id: string
|
||||
type: ApObject
|
||||
type: Activity
|
||||
name: string
|
||||
updated: string
|
||||
icon: Icon
|
||||
}
|
||||
|
||||
export interface ApFlag {
|
||||
type: ApObject
|
||||
type: Activity
|
||||
actor: string
|
||||
content: string
|
||||
object: string
|
||||
|
@ -128,33 +149,32 @@ export interface ApFlag {
|
|||
|
||||
export interface ApFollow {
|
||||
id: string
|
||||
type: ApObject
|
||||
type: Activity
|
||||
actor: string
|
||||
object: string
|
||||
}
|
||||
|
||||
export interface ApHashtag {
|
||||
id: string
|
||||
type: ApObject
|
||||
type: Activity
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface ApLike {
|
||||
id: string
|
||||
type: Activity
|
||||
actor: string
|
||||
object: string
|
||||
content: string
|
||||
tag?: Array<ApEmoji>
|
||||
}
|
||||
|
||||
export interface ApMention {
|
||||
type: ApObject
|
||||
type: Activity
|
||||
href: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export type ApObject = 'Accept'|
|
||||
'Emoji'|
|
||||
'Flag'|
|
||||
'Follow'|
|
||||
'Hashtag'|
|
||||
'Mention'|
|
||||
'Image'|
|
||||
'Read'|
|
||||
'Tombstone';
|
||||
|
||||
export interface App {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
@ -167,14 +187,28 @@ export interface App {
|
|||
}
|
||||
|
||||
export interface ApRead {
|
||||
type: ApObject
|
||||
type: Activity
|
||||
actor: string
|
||||
object: string
|
||||
}
|
||||
|
||||
export interface ApReject {
|
||||
id: string
|
||||
type: Activity
|
||||
actor: string
|
||||
object: ApFollow
|
||||
}
|
||||
|
||||
export interface ApRemove {
|
||||
type: Activity
|
||||
actor: string
|
||||
target: string
|
||||
object: string
|
||||
}
|
||||
|
||||
export interface ApTombstone {
|
||||
id: string
|
||||
type: ApObject
|
||||
type: Activity
|
||||
}
|
||||
|
||||
export interface AttestationChallenge {
|
||||
|
@ -578,7 +612,7 @@ export interface Hashtag {
|
|||
}
|
||||
|
||||
export interface Icon {
|
||||
type: ApObject
|
||||
type: Activity
|
||||
mediaType: string
|
||||
url: string
|
||||
}
|
||||
|
@ -1328,6 +1362,8 @@ export declare function removeOldAttestationChallenges(): Promise<void>
|
|||
|
||||
export declare function renderAccept(userId: string, followObject: ApFollow): ApAccept
|
||||
|
||||
export declare function renderAdd(userId: string, noteId: string): ApAdd
|
||||
|
||||
export declare function renderEmoji(emoji: Emoji): ApEmoji
|
||||
|
||||
export declare function renderFlag(targetUserUri: string, comment: string): Promise<ApFlag>
|
||||
|
@ -1338,10 +1374,16 @@ export declare function renderFollowRelay(relayId: string): Promise<ApFollow>
|
|||
|
||||
export declare function renderHashtag(tagName: string): ApHashtag
|
||||
|
||||
export declare function renderLike(reaction: Model): Promise<ApLike>
|
||||
|
||||
export declare function renderMention(user: UserLike): ApMention
|
||||
|
||||
export declare function renderRead(userId: string, messageUri: string): ApRead
|
||||
|
||||
export declare function renderReject(userId: string, followObject: ApFollow): ApReject
|
||||
|
||||
export declare function renderRemove(userId: string, noteId: string): ApRemove
|
||||
|
||||
export declare function renderTombstone(noteId: string): ApTombstone
|
||||
|
||||
export interface RenoteMuting {
|
||||
|
|
|
@ -362,8 +362,8 @@ if (!nativeBinding) {
|
|||
}
|
||||
|
||||
module.exports.acctToString = nativeBinding.acctToString
|
||||
module.exports.Activity = nativeBinding.Activity
|
||||
module.exports.AntennaSrc = nativeBinding.AntennaSrc
|
||||
module.exports.ApObject = nativeBinding.ApObject
|
||||
module.exports.ChatEvent = nativeBinding.ChatEvent
|
||||
module.exports.ChatIndexEvent = nativeBinding.ChatIndexEvent
|
||||
module.exports.checkWordMute = nativeBinding.checkWordMute
|
||||
|
@ -439,13 +439,17 @@ module.exports.PushSubscriptionType = nativeBinding.PushSubscriptionType
|
|||
module.exports.RelayStatus = nativeBinding.RelayStatus
|
||||
module.exports.removeOldAttestationChallenges = nativeBinding.removeOldAttestationChallenges
|
||||
module.exports.renderAccept = nativeBinding.renderAccept
|
||||
module.exports.renderAdd = nativeBinding.renderAdd
|
||||
module.exports.renderEmoji = nativeBinding.renderEmoji
|
||||
module.exports.renderFlag = nativeBinding.renderFlag
|
||||
module.exports.renderFollow = nativeBinding.renderFollow
|
||||
module.exports.renderFollowRelay = nativeBinding.renderFollowRelay
|
||||
module.exports.renderHashtag = nativeBinding.renderHashtag
|
||||
module.exports.renderLike = nativeBinding.renderLike
|
||||
module.exports.renderMention = nativeBinding.renderMention
|
||||
module.exports.renderRead = nativeBinding.renderRead
|
||||
module.exports.renderReject = nativeBinding.renderReject
|
||||
module.exports.renderRemove = nativeBinding.renderRemove
|
||||
module.exports.renderTombstone = nativeBinding.renderTombstone
|
||||
module.exports.safeForSql = nativeBinding.safeForSql
|
||||
module.exports.sendPushNotification = nativeBinding.sendPushNotification
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
use super::*;
|
||||
use crate::{config::CONFIG, misc::user};
|
||||
use uuid::Uuid;
|
||||
use crate::misc::user;
|
||||
|
||||
#[macros::export(object)]
|
||||
pub struct ApAccept {
|
||||
pub id: String,
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub object: follow::ApFollow,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApAccept {}
|
||||
impl ApObject for ApAccept {}
|
||||
|
||||
impl ApAccept {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(user_id: String, follow_object: follow::ApFollow) -> Self {
|
||||
Self {
|
||||
id: format!("{}/{}", CONFIG.url, Uuid::new_v4()),
|
||||
r#type: ApObject::Accept,
|
||||
id: random_local_uri(),
|
||||
r#type: Activity::Accept,
|
||||
actor: user::local_uri(user_id),
|
||||
object: follow_object,
|
||||
}
|
||||
|
|
34
packages/backend-rs/src/federation/activitypub/object/add.rs
Normal file
34
packages/backend-rs/src/federation/activitypub/object/add.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
//! Add note to featured collection (pinned posts)
|
||||
|
||||
use super::*;
|
||||
use crate::misc::{note, user};
|
||||
|
||||
#[macros::export(object)]
|
||||
pub struct ApAdd {
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub target: String,
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
impl ApObject for ApAdd {}
|
||||
|
||||
impl ApAdd {
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(user_id: String, note_id: String) -> Self {
|
||||
let actor_uri = user::local_uri(user_id);
|
||||
let collection_uri = format!("{}/collections/featured", actor_uri);
|
||||
|
||||
Self {
|
||||
r#type: Activity::Add,
|
||||
actor: actor_uri,
|
||||
target: collection_uri,
|
||||
object: note::local_uri(note_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macros::ts_export]
|
||||
pub fn render_add(user_id: String, note_id: String) -> ApAdd {
|
||||
ApAdd::new(user_id, note_id)
|
||||
}
|
|
@ -5,7 +5,7 @@ use chrono::Utc;
|
|||
#[macros::export(object)]
|
||||
pub struct ApEmoji {
|
||||
pub id: String,
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub name: String,
|
||||
pub updated: String,
|
||||
pub icon: Icon,
|
||||
|
@ -13,26 +13,25 @@ pub struct ApEmoji {
|
|||
|
||||
#[macros::export(object)]
|
||||
pub struct Icon {
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub media_type: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApEmoji {}
|
||||
impl ApObject for ApEmoji {}
|
||||
|
||||
impl ApEmoji {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
fn new(emoji: emoji::Model) -> Self {
|
||||
pub fn new(emoji: emoji::Model) -> Self {
|
||||
Self {
|
||||
id: misc::emoji::local_uri(&emoji.name),
|
||||
r#type: ApObject::Emoji,
|
||||
r#type: Activity::Emoji,
|
||||
name: format!(":{}:", emoji.name),
|
||||
updated: emoji
|
||||
.updated_at
|
||||
.unwrap_or_else(|| Utc::now().into())
|
||||
.to_rfc3339(),
|
||||
icon: Icon {
|
||||
r#type: ApObject::Image,
|
||||
r#type: Activity::Image,
|
||||
media_type: emoji.r#type.unwrap_or_else(|| "image/png".to_owned()),
|
||||
url: emoji.public_url,
|
||||
},
|
||||
|
|
|
@ -3,23 +3,23 @@ use crate::{federation::internal_actor, misc::user};
|
|||
|
||||
#[macros::export(object)]
|
||||
pub struct ApFlag {
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub content: String,
|
||||
// TODO: object can be an array of uri's
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApFlag {}
|
||||
impl ApObject for ApFlag {}
|
||||
|
||||
impl ApFlag {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
async fn new(
|
||||
target_user_uri: String,
|
||||
comment: String,
|
||||
) -> Result<Self, internal_actor::instance::Error> {
|
||||
Ok(Self {
|
||||
r#type: ApObject::Flag,
|
||||
r#type: Activity::Flag,
|
||||
actor: user::local_uri(&internal_actor::instance::get().await?.id),
|
||||
content: comment,
|
||||
object: target_user_uri,
|
||||
|
|
|
@ -4,12 +4,12 @@ use crate::{config::CONFIG, federation::internal_actor, misc::user};
|
|||
#[macros::export(object)]
|
||||
pub struct ApFollow {
|
||||
pub id: String,
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApFollow {}
|
||||
impl ApObject for ApFollow {}
|
||||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
|
@ -20,7 +20,7 @@ pub enum Error {
|
|||
}
|
||||
|
||||
impl ApFollow {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(
|
||||
follower: UserLike,
|
||||
followee: UserLike,
|
||||
|
@ -30,7 +30,7 @@ impl ApFollow {
|
|||
id: request_id.unwrap_or_else(|| {
|
||||
format!("{}/follows/{}/{}", CONFIG.url, follower.id, followee.id)
|
||||
}),
|
||||
r#type: ApObject::Follow,
|
||||
r#type: Activity::Follow,
|
||||
actor: match user::is_local!(follower) {
|
||||
true => user::local_uri(follower.id),
|
||||
false => follower.uri.ok_or(Error::MissingFollowerUri)?,
|
||||
|
@ -42,11 +42,11 @@ impl ApFollow {
|
|||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
async fn new_relay(relay_id: String) -> Result<Self, internal_actor::relay::Error> {
|
||||
Ok(Self {
|
||||
id: format!("{}/activities/follow-relay/{}", CONFIG.url, relay_id),
|
||||
r#type: ApObject::Follow,
|
||||
r#type: Activity::Follow,
|
||||
actor: user::local_uri(internal_actor::relay::get_id().await?),
|
||||
object: AS_PUBLIC_URL.to_owned(),
|
||||
})
|
||||
|
|
|
@ -4,18 +4,18 @@ use crate::config::CONFIG;
|
|||
#[macros::export(object)]
|
||||
pub struct ApHashtag {
|
||||
pub id: String,
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApHashtag {}
|
||||
impl ApObject for ApHashtag {}
|
||||
|
||||
impl ApHashtag {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(tag_name: &str) -> Self {
|
||||
Self {
|
||||
id: format!("{}/tags/{}", CONFIG.url, urlencoding::encode(tag_name)),
|
||||
r#type: ApObject::Hashtag,
|
||||
r#type: Activity::Hashtag,
|
||||
name: format!("#{}", tag_name),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
use super::{emoji::ApEmoji, *};
|
||||
use crate::{
|
||||
config::CONFIG,
|
||||
database::db_conn,
|
||||
misc::{self, user},
|
||||
model::entity::{emoji, note, note_reaction},
|
||||
};
|
||||
use sea_orm::{ColumnTrait, DbErr, EntityTrait, QueryFilter, QuerySelect};
|
||||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "Nonexistent note"]
|
||||
#[error("note {0} not found")]
|
||||
NoteNotFound(String),
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] DbErr),
|
||||
}
|
||||
|
||||
#[macros::export(object, use_nullable = false)]
|
||||
pub struct ApLike {
|
||||
pub id: String,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub object: String,
|
||||
pub content: String,
|
||||
pub tag: Option<Vec<ApEmoji>>,
|
||||
}
|
||||
|
||||
impl ApObject for ApLike {}
|
||||
|
||||
impl ApLike {
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
async fn new(reaction: note_reaction::Model) -> Result<Self, Error> {
|
||||
let db = db_conn().await?;
|
||||
|
||||
let note_uri = {
|
||||
let note_uri = note::Entity::find()
|
||||
.select_only()
|
||||
.column(note::Column::Uri)
|
||||
.filter(note::Column::Id.eq(&reaction.note_id))
|
||||
.into_tuple::<Option<String>>()
|
||||
.one(db)
|
||||
.await?;
|
||||
|
||||
match note_uri {
|
||||
Some(Some(uri)) => uri,
|
||||
Some(None) => misc::note::local_uri(reaction.note_id),
|
||||
None => return Err(Error::NoteNotFound(reaction.note_id)),
|
||||
}
|
||||
};
|
||||
|
||||
let tag = emoji::Entity::find()
|
||||
.filter(emoji::Column::Name.eq(reaction.reaction.replace(':', "")))
|
||||
.filter(emoji::Column::Host.is_null())
|
||||
.one(db)
|
||||
.await?
|
||||
.map(|emoji| vec![ApEmoji::new(emoji)]);
|
||||
|
||||
Ok(Self {
|
||||
id: format!("{}/likes/{}", CONFIG.url, reaction.id),
|
||||
r#type: Activity::Like,
|
||||
actor: user::local_uri(reaction.user_id),
|
||||
object: note_uri,
|
||||
content: reaction.reaction,
|
||||
tag,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[macros::ts_export]
|
||||
pub async fn render_like(reaction: note_reaction::Model) -> Result<ApLike, Error> {
|
||||
ApLike::new(reaction).await
|
||||
}
|
|
@ -7,18 +7,18 @@ pub struct MissingRemoteUserUri;
|
|||
|
||||
#[macros::export(object)]
|
||||
pub struct ApMention {
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub href: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApMention {}
|
||||
impl ApObject for ApMention {}
|
||||
|
||||
impl ApMention {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(user: UserLike) -> Result<Self, MissingRemoteUserUri> {
|
||||
Ok(Self {
|
||||
r#type: ApObject::Mention,
|
||||
r#type: Activity::Mention,
|
||||
href: match user::is_local!(user) {
|
||||
true => user::local_uri(user.id),
|
||||
false => user.uri.ok_or(MissingRemoteUserUri)?,
|
||||
|
|
|
@ -1,29 +1,44 @@
|
|||
pub mod accept;
|
||||
pub mod add;
|
||||
pub mod emoji;
|
||||
pub mod flag;
|
||||
pub mod follow;
|
||||
pub mod hashtag;
|
||||
pub mod like;
|
||||
pub mod mention;
|
||||
pub mod read;
|
||||
pub mod reject;
|
||||
pub mod remove;
|
||||
pub mod tombstone;
|
||||
|
||||
pub trait ActivityPubObject {}
|
||||
pub trait ApObject {}
|
||||
|
||||
#[macros::export(string_enum)]
|
||||
pub enum ApObject {
|
||||
pub enum Activity {
|
||||
Accept,
|
||||
Add,
|
||||
Emoji,
|
||||
Flag,
|
||||
Follow,
|
||||
Hashtag,
|
||||
Like,
|
||||
Mention,
|
||||
Image,
|
||||
Read,
|
||||
Reject,
|
||||
Remove,
|
||||
Tombstone,
|
||||
}
|
||||
|
||||
const AS_PUBLIC_URL: &str = "https://www.w3.org/ns/activitystreams#Public";
|
||||
|
||||
use crate::config::CONFIG;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn random_local_uri() -> String {
|
||||
format!("{}/{}", CONFIG.url, Uuid::new_v4())
|
||||
}
|
||||
|
||||
#[macros::export(object)]
|
||||
pub struct UserLike {
|
||||
pub id: String,
|
||||
|
|
|
@ -3,18 +3,18 @@ use crate::misc::user;
|
|||
|
||||
#[macros::export(object)]
|
||||
pub struct ApRead {
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApRead {}
|
||||
impl ApObject for ApRead {}
|
||||
|
||||
impl ApRead {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(user_id: String, message_uri: String) -> Self {
|
||||
Self {
|
||||
r#type: ApObject::Read,
|
||||
r#type: Activity::Read,
|
||||
actor: user::local_uri(user_id),
|
||||
object: message_uri,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
use super::*;
|
||||
use crate::misc::user;
|
||||
|
||||
#[macros::export(object)]
|
||||
pub struct ApReject {
|
||||
pub id: String,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub object: follow::ApFollow,
|
||||
}
|
||||
|
||||
impl ApObject for ApReject {}
|
||||
|
||||
impl ApReject {
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(user_id: String, follow_object: follow::ApFollow) -> Self {
|
||||
Self {
|
||||
id: random_local_uri(),
|
||||
r#type: Activity::Accept,
|
||||
actor: user::local_uri(user_id),
|
||||
object: follow_object,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macros::ts_export]
|
||||
pub fn render_reject(user_id: String, follow_object: follow::ApFollow) -> ApReject {
|
||||
ApReject::new(user_id, follow_object)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//! Remove note from featured collection (pinned posts)
|
||||
|
||||
use super::*;
|
||||
use crate::misc::{note, user};
|
||||
|
||||
#[macros::export(object)]
|
||||
pub struct ApRemove {
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub target: String,
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
impl ApObject for ApRemove {}
|
||||
|
||||
impl ApRemove {
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(user_id: String, note_id: String) -> Self {
|
||||
let actor_uri = user::local_uri(user_id);
|
||||
let collection_uri = format!("{}/collections/featured", actor_uri);
|
||||
|
||||
Self {
|
||||
r#type: Activity::Remove,
|
||||
actor: actor_uri,
|
||||
target: collection_uri,
|
||||
object: note::local_uri(note_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macros::ts_export]
|
||||
pub fn render_remove(user_id: String, note_id: String) -> ApRemove {
|
||||
ApRemove::new(user_id, note_id)
|
||||
}
|
|
@ -4,17 +4,17 @@ use crate::misc::note;
|
|||
#[macros::export(object)]
|
||||
pub struct ApTombstone {
|
||||
pub id: String,
|
||||
pub r#type: ApObject,
|
||||
pub r#type: Activity,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for ApTombstone {}
|
||||
impl ApObject for ApTombstone {}
|
||||
|
||||
impl ApTombstone {
|
||||
#[allow(dead_code)] // TODO: remove this line
|
||||
#[allow(dead_code)] // TODO: remove this line by actually using it
|
||||
fn new(note_id: String) -> Self {
|
||||
Self {
|
||||
id: note::local_uri(note_id),
|
||||
r#type: ApObject::Tombstone,
|
||||
r#type: Activity::Tombstone,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ pub enum Error {
|
|||
#[error("@instance.actor not found")]
|
||||
InstanceActorNotFound,
|
||||
#[error(transparent)]
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
Db(#[from] DbErr),
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! In-memory relay actor id cache
|
||||
|
||||
use crate::{database::db_conn, model::entity::user};
|
||||
use sea_orm::{prelude::*, QuerySelect, SelectColumns};
|
||||
use sea_orm::{prelude::*, QuerySelect};
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
pub const USERNAME: &str = "relay.actor";
|
||||
|
@ -12,7 +12,7 @@ pub enum Error {
|
|||
#[error("@relay.actor not found")]
|
||||
RelayActorNotFound,
|
||||
#[error(transparent)]
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
Db(#[from] DbErr),
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ async fn set_id_cache() -> Result<&'static str, Error> {
|
|||
tracing::debug!("caching @relay.actor");
|
||||
let found_id = user::Entity::find()
|
||||
.select_only()
|
||||
.select_column(user::Column::Id)
|
||||
.column(user::Column::Id)
|
||||
.filter(user::Column::Username.eq(USERNAME))
|
||||
.filter(user::Column::Host.is_null())
|
||||
.into_tuple::<String>()
|
||||
|
|
|
@ -14,7 +14,7 @@ pub enum Error {
|
|||
HttpClient(#[from] http_client::Error),
|
||||
#[error("HTTP request failed")]
|
||||
Http(#[from] isahc::Error),
|
||||
#[doc = "bad HTTP status"]
|
||||
#[doc = "Bad HTTP status"]
|
||||
#[error("bad HTTP status ({0})")]
|
||||
BadStatus(String),
|
||||
#[error("failed to parse HTTP response body as text")]
|
||||
|
|
|
@ -145,7 +145,7 @@ pub async fn nodeinfo_2_0() -> Result<Nodeinfo20, DbErr> {
|
|||
#[macros::for_ts]
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] DbErr),
|
||||
#[error("failed to serialize nodeinfo into JSON")]
|
||||
|
|
|
@ -15,7 +15,7 @@ pub enum Error {
|
|||
HttpClient(#[from] http_client::Error),
|
||||
#[error("HTTP request failed")]
|
||||
Isahc(#[from] isahc::Error),
|
||||
#[doc = "bad HTTP status"]
|
||||
#[doc = "Bad HTTP status"]
|
||||
#[error("bad HTTP status ({0})")]
|
||||
BadStatus(String),
|
||||
#[error("failed to decode an image")]
|
||||
|
@ -24,10 +24,10 @@ pub enum Error {
|
|||
Io(#[from] std::io::Error),
|
||||
#[error("failed to extract the exif data")]
|
||||
Exif(#[from] nom_exif::Error),
|
||||
#[doc = "too many fetch attempts"]
|
||||
#[doc = "Too many fetch attempts"]
|
||||
#[error("too many fetch attempts for {0}")]
|
||||
TooManyAttempts(String),
|
||||
#[doc = "unsupported image type"]
|
||||
#[doc = "Unsupported image type"]
|
||||
#[error("unsupported image type ({0})")]
|
||||
UnsupportedImage(String),
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use identicon_rs::{error::IdenticonError, Identicon};
|
|||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "failed to generate identicon"]
|
||||
#[doc = "Failed to generate identicon"]
|
||||
#[error(transparent)]
|
||||
Identicon(#[from] IdenticonError),
|
||||
#[error("Redis cache operation has failed")]
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
use crate::{cache, database::db_conn, model::entity::user};
|
||||
use chrono::Duration;
|
||||
use sea_orm::{DbErr, EntityTrait, QuerySelect, SelectColumns};
|
||||
use sea_orm::{DbErr, EntityTrait, QuerySelect};
|
||||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] DbErr),
|
||||
#[doc = "cache error"]
|
||||
#[doc = "Cache error"]
|
||||
#[error(transparent)]
|
||||
Cache(#[from] cache::redis::Error),
|
||||
#[doc = "user not found"]
|
||||
#[doc = "User not found"]
|
||||
#[error("user {0} not found")]
|
||||
NotFound(String),
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ pub async fn should_nyaify(reader_user_id: &str) -> Result<bool, Error> {
|
|||
|
||||
let fetched_value = user::Entity::find_by_id(reader_user_id)
|
||||
.select_only()
|
||||
.select_column(user::Column::ReadCatLanguage)
|
||||
.column(user::Column::ReadCatLanguage)
|
||||
.into_tuple::<bool>()
|
||||
.one(db_conn().await?)
|
||||
.await?
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] sea_orm::DbErr),
|
||||
#[error("failed to acquire an HTTP client")]
|
||||
|
|
|
@ -10,7 +10,7 @@ use sea_orm::{prelude::*, QuerySelect};
|
|||
|
||||
#[macros::errors]
|
||||
pub enum AntennaCheckError {
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] DbErr),
|
||||
#[error("Redis cache operation has failed")]
|
||||
|
|
|
@ -16,7 +16,7 @@ use sea_orm::prelude::*;
|
|||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] DbErr),
|
||||
#[error("Redis cache operation has failed")]
|
||||
|
@ -25,7 +25,7 @@ pub enum Error {
|
|||
Redis(#[from] RedisError),
|
||||
#[error("bad Redis connection")]
|
||||
RedisConn(#[from] RedisConnError),
|
||||
#[doc = "provided string is not a valid Firefish ID"]
|
||||
#[doc = "Provided string is not a valid Firefish ID"]
|
||||
#[error(transparent)]
|
||||
InvalidId(#[from] InvalidIdError),
|
||||
#[error("Redis stream operation has failed")]
|
||||
|
|
|
@ -15,17 +15,17 @@ use web_push::*;
|
|||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[doc = "database error"]
|
||||
#[doc = "Database error"]
|
||||
#[error(transparent)]
|
||||
Db(#[from] DbErr),
|
||||
#[error("web push has failed")]
|
||||
WebPush(#[from] WebPushError),
|
||||
#[error("failed to (de)serialize an object")]
|
||||
Serialize(#[from] serde_json::Error),
|
||||
#[doc = "provided content is invalid"]
|
||||
#[doc = "Provided content is invalid"]
|
||||
#[error("invalid content ({0})")]
|
||||
InvalidContent(String),
|
||||
#[doc = "found Mastodon subscription is invalid"]
|
||||
#[doc = "Found Mastodon subscription is invalid"]
|
||||
#[error("invalid subscription ({0})")]
|
||||
InvalidSubscription(String),
|
||||
#[error("invalid notification ID")]
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
"format": "pnpm biome format --write src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bull-board/api": "5.21.3",
|
||||
"@bull-board/koa": "5.21.3",
|
||||
"@bull-board/ui": "5.21.3",
|
||||
"@discordapp/twemoji": "15.0.3",
|
||||
"@bull-board/api": "5.21.4",
|
||||
"@bull-board/koa": "5.21.4",
|
||||
"@bull-board/ui": "5.21.4",
|
||||
"@discordapp/twemoji": "15.1.0",
|
||||
"@koa/cors": "5.0.0",
|
||||
"@koa/multer": "3.0.2",
|
||||
"@koa/router": "12.0.1",
|
||||
"@koa/router": "13.0.0",
|
||||
"@ladjs/koa-views": "9.0.0",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@redocly/openapi-core": "1.19.0",
|
||||
|
@ -33,8 +33,8 @@
|
|||
"archiver": "7.0.1",
|
||||
"async-lock": "1.4.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"aws-sdk": "2.1671.0",
|
||||
"axios": "1.7.3",
|
||||
"aws-sdk": "2.1677.0",
|
||||
"axios": "1.7.4",
|
||||
"backend-rs": "workspace:*",
|
||||
"blurhash": "2.0.5",
|
||||
"bull": "4.16.0",
|
||||
|
@ -49,7 +49,7 @@
|
|||
"deep-email-validator": "0.1.21",
|
||||
"escape-regexp": "0.0.1",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "19.4.0",
|
||||
"file-type": "19.4.1",
|
||||
"firefish-js": "workspace:*",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.0",
|
||||
|
@ -97,7 +97,7 @@
|
|||
"rss-parser": "3.13.0",
|
||||
"sanitize-html": "2.13.0",
|
||||
"semver": "7.6.3",
|
||||
"sharp": "0.33.4",
|
||||
"sharp": "0.33.5",
|
||||
"stringz": "2.1.0",
|
||||
"summaly": "2.7.0",
|
||||
"syslog-pro": "1.0.0",
|
||||
|
@ -133,7 +133,7 @@
|
|||
"@types/koa__cors": "5.0.0",
|
||||
"@types/koa__multer": "2.0.7",
|
||||
"@types/koa__router": "12.0.4",
|
||||
"@types/node": "20.14.14",
|
||||
"@types/node": "20.15.0",
|
||||
"@types/node-fetch": "2.6.11",
|
||||
"@types/nodemailer": "6.4.15",
|
||||
"@types/oauth": "0.9.5",
|
||||
|
@ -163,7 +163,7 @@
|
|||
"ts-node": "10.9.2",
|
||||
"tsc-alias": "1.8.10",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"type-fest": "4.24.0",
|
||||
"type-fest": "4.25.0",
|
||||
"typescript": "5.5.4",
|
||||
"webpack": "5.93.0",
|
||||
"ws": "8.18.0"
|
||||
|
|
|
@ -12,11 +12,7 @@ export default async (actor: CacheableRemoteUser, activity: ILike) => {
|
|||
|
||||
await extractEmojis(activity.tag || [], actor.host).catch(() => null);
|
||||
|
||||
return await create(
|
||||
actor,
|
||||
note,
|
||||
activity._misskey_reaction || activity.content || activity.name,
|
||||
)
|
||||
return await create(actor, note, activity.content || activity.name)
|
||||
.catch((e) => {
|
||||
if (e.id === "51c42bb4-931a-456b-bff7-e5a8a70dd298") {
|
||||
return "skip: already reacted";
|
||||
|
|
|
@ -550,7 +550,6 @@ export const WellKnownContext = {
|
|||
// Misskey
|
||||
misskey: "https://misskey-hub.net/ns#",
|
||||
_misskey_talk: "misskey:_misskey_talk",
|
||||
_misskey_reaction: "misskey:_misskey_reaction",
|
||||
_misskey_votes: "misskey:_misskey_votes",
|
||||
_misskey_summary: "misskey:_misskey_summary",
|
||||
isCat: "misskey:isCat",
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import { config } from "@/config.js";
|
||||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
|
||||
export default (user: ILocalUser, target: any, object: any) => ({
|
||||
type: "Add",
|
||||
actor: `${config.url}/users/${user.id}`,
|
||||
target,
|
||||
object,
|
||||
});
|
|
@ -1,31 +0,0 @@
|
|||
import { IsNull } from "typeorm";
|
||||
import { config } from "@/config.js";
|
||||
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import { Emojis } from "@/models/index.js";
|
||||
import { renderEmoji } from "backend-rs";
|
||||
|
||||
export const renderLike = async (noteReaction: NoteReaction, note: Note) => {
|
||||
const reaction = noteReaction.reaction;
|
||||
|
||||
const object = {
|
||||
type: "Like",
|
||||
id: `${config.url}/likes/${noteReaction.id}`,
|
||||
actor: `${config.url}/users/${noteReaction.userId}`,
|
||||
object: note.uri ? note.uri : `${config.url}/notes/${noteReaction.noteId}`,
|
||||
content: reaction,
|
||||
_misskey_reaction: reaction,
|
||||
} as any;
|
||||
|
||||
if (reaction.startsWith(":")) {
|
||||
const name = reaction.replace(/:/g, "");
|
||||
const emoji = await Emojis.findOneBy({
|
||||
name,
|
||||
host: IsNull(),
|
||||
});
|
||||
|
||||
if (emoji) object.tag = [renderEmoji(emoji)];
|
||||
}
|
||||
|
||||
return object;
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
import { config } from "@/config.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
|
||||
export default (object: any, user: { id: User["id"] }) => ({
|
||||
type: "Reject",
|
||||
actor: `${config.url}/users/${user.id}`,
|
||||
object,
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
import { config } from "@/config.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
|
||||
export default (user: { id: User["id"] }, target: any, object: any) => ({
|
||||
type: "Remove",
|
||||
actor: `${config.url}/users/${user.id}`,
|
||||
target,
|
||||
object,
|
||||
});
|
|
@ -7,6 +7,7 @@ import {
|
|||
isBlockedServer,
|
||||
isSelfHost,
|
||||
renderFollow,
|
||||
renderLike,
|
||||
} from "backend-rs";
|
||||
import { apGet } from "./request.js";
|
||||
import type { IObject, ICollection, IOrderedCollection } from "./type.js";
|
||||
|
@ -20,7 +21,6 @@ import {
|
|||
} from "@/models/index.js";
|
||||
import { parseUri } from "./db-resolver.js";
|
||||
import renderNote from "@/remote/activitypub/renderer/note.js";
|
||||
import { renderLike } from "@/remote/activitypub/renderer/like.js";
|
||||
import { renderPerson } from "@/remote/activitypub/renderer/person.js";
|
||||
import renderQuestion from "@/remote/activitypub/renderer/question.js";
|
||||
import renderCreate from "@/remote/activitypub/renderer/create.js";
|
||||
|
@ -181,7 +181,7 @@ export default class Resolver {
|
|||
}
|
||||
case "likes": {
|
||||
const reaction = await NoteReactions.findOneByOrFail({ id: parsed.id });
|
||||
return renderActivity(renderLike(reaction, { uri: null }));
|
||||
return renderActivity(await renderLike(reaction));
|
||||
}
|
||||
case "follows": {
|
||||
// if rest is a <followee id>
|
||||
|
|
|
@ -303,7 +303,7 @@ export interface IRemove extends IActivity {
|
|||
|
||||
export interface ILike extends IActivity {
|
||||
type: "Like" | "EmojiReaction" | "EmojiReact";
|
||||
_misskey_reaction?: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
export interface IAnnounce extends IActivity {
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
isSelfHost,
|
||||
renderEmoji,
|
||||
renderFollow,
|
||||
renderLike,
|
||||
} from "backend-rs";
|
||||
import {
|
||||
Notes,
|
||||
|
@ -23,7 +24,6 @@ import {
|
|||
FollowRequests,
|
||||
} from "@/models/index.js";
|
||||
import type { ILocalUser, User } from "@/models/entities/user.js";
|
||||
import { renderLike } from "@/remote/activitypub/renderer/like.js";
|
||||
import { getUserKeypair } from "@/misc/keypair-store.js";
|
||||
import {
|
||||
checkFetch,
|
||||
|
@ -466,7 +466,7 @@ router.get("/likes/:like", async (ctx) => {
|
|||
return;
|
||||
}
|
||||
|
||||
ctx.body = renderActivity(await renderLike(reaction, note));
|
||||
ctx.body = renderActivity(await renderLike(reaction));
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
|
|
|
@ -2,7 +2,6 @@ import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
|||
import { renderUndo } from "@/remote/activitypub/renderer/undo.js";
|
||||
import { renderBlock } from "@/remote/activitypub/renderer/block.js";
|
||||
import { deliver } from "@/queue/index.js";
|
||||
import renderReject from "@/remote/activitypub/renderer/reject.js";
|
||||
import type { Blocking } from "@/models/entities/blocking.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import {
|
||||
|
@ -20,6 +19,7 @@ import {
|
|||
publishToUserStream,
|
||||
UserEvent,
|
||||
renderFollow,
|
||||
renderReject,
|
||||
} from "backend-rs";
|
||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||
import { webhookDeliver } from "@/queue/index.js";
|
||||
|
@ -103,8 +103,8 @@ async function cancelRequest(follower: User, followee: User) {
|
|||
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
|
||||
const content = renderActivity(
|
||||
renderReject(
|
||||
followee.id,
|
||||
renderFollow(follower, followee, request.requestId!),
|
||||
followee,
|
||||
),
|
||||
);
|
||||
deliver(followee.id, content, follower.inbox);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import renderReject from "@/remote/activitypub/renderer/reject.js";
|
||||
import { deliver } from "@/queue/index.js";
|
||||
import createFollowRequest from "./requests/create.js";
|
||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||
|
@ -23,6 +22,7 @@ import {
|
|||
UserEvent,
|
||||
renderAccept,
|
||||
renderFollow,
|
||||
renderReject,
|
||||
} from "backend-rs";
|
||||
import { createNotification } from "@/services/create-notification.js";
|
||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||
|
@ -196,7 +196,7 @@ export default async function (
|
|||
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee) && blocked) {
|
||||
// リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。
|
||||
const content = renderActivity(
|
||||
renderReject(renderFollow(follower, followee, requestId), followee),
|
||||
renderReject(followee.id, renderFollow(follower, followee, requestId)),
|
||||
);
|
||||
deliver(followee.id, content, follower.inbox);
|
||||
return;
|
||||
|
|
|
@ -4,10 +4,10 @@ import {
|
|||
publishToUserStream,
|
||||
UserEvent,
|
||||
renderFollow,
|
||||
renderReject,
|
||||
} from "backend-rs";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import { renderUndo } from "@/remote/activitypub/renderer/undo.js";
|
||||
import renderReject from "@/remote/activitypub/renderer/reject.js";
|
||||
import { deliver, webhookDeliver } from "@/queue/index.js";
|
||||
import Logger from "../logger.js";
|
||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||
|
@ -22,6 +22,7 @@ export default async function (
|
|||
id: User["id"];
|
||||
host: User["host"];
|
||||
uri: User["host"];
|
||||
username: User["username"];
|
||||
inbox: User["inbox"];
|
||||
sharedInbox: User["sharedInbox"];
|
||||
},
|
||||
|
@ -29,6 +30,7 @@ export default async function (
|
|||
id: User["id"];
|
||||
host: User["host"];
|
||||
uri: User["host"];
|
||||
username: User["username"];
|
||||
inbox: User["inbox"];
|
||||
sharedInbox: User["sharedInbox"];
|
||||
},
|
||||
|
@ -79,7 +81,7 @@ export default async function (
|
|||
if (Users.isLocalUser(followee) && Users.isRemoteUser(follower)) {
|
||||
// local user has null host
|
||||
const content = renderActivity(
|
||||
renderReject(renderFollow(follower, followee), followee),
|
||||
renderReject(followee.id, renderFollow(follower, followee)),
|
||||
);
|
||||
deliver(followee.id, content, follower.inbox);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import renderReject from "@/remote/activitypub/renderer/reject.js";
|
||||
import { deliver, webhookDeliver } from "@/queue/index.js";
|
||||
import {
|
||||
Event,
|
||||
|
@ -7,6 +6,7 @@ import {
|
|||
publishToUserStream,
|
||||
UserEvent,
|
||||
renderFollow,
|
||||
renderReject,
|
||||
} from "backend-rs";
|
||||
import type { ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
||||
import { Users, FollowRequests, Followings } from "@/models/index.js";
|
||||
|
@ -19,6 +19,7 @@ type Local =
|
|||
id: ILocalUser["id"];
|
||||
host: ILocalUser["host"];
|
||||
uri: ILocalUser["uri"];
|
||||
username: ILocalUser["username"];
|
||||
};
|
||||
type Remote =
|
||||
| IRemoteUser
|
||||
|
@ -26,6 +27,7 @@ type Remote =
|
|||
id: IRemoteUser["id"];
|
||||
host: IRemoteUser["host"];
|
||||
uri: IRemoteUser["uri"];
|
||||
username: IRemoteUser["username"];
|
||||
inbox: IRemoteUser["inbox"];
|
||||
};
|
||||
type Both = Local | Remote;
|
||||
|
@ -109,8 +111,8 @@ async function deliverReject(followee: Local, follower: Remote) {
|
|||
|
||||
const content = renderActivity(
|
||||
renderReject(
|
||||
followee.id,
|
||||
renderFollow(follower, followee, request?.requestId || undefined),
|
||||
followee,
|
||||
),
|
||||
);
|
||||
deliver(followee.id, content, follower.inbox);
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import { config } from "@/config.js";
|
||||
import renderAdd from "@/remote/activitypub/renderer/add.js";
|
||||
import renderRemove from "@/remote/activitypub/renderer/remove.js";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import { Notes, UserNotePinings, Users } from "@/models/index.js";
|
||||
import type { UserNotePining } from "@/models/entities/user-note-pining.js";
|
||||
import { genIdAt } from "backend-rs";
|
||||
import { genIdAt, renderAdd, renderRemove } from "backend-rs";
|
||||
import { deliverToFollowers } from "@/remote/activitypub/deliver-manager.js";
|
||||
import { deliverToRelays } from "@/services/relay.js";
|
||||
|
||||
|
@ -115,12 +112,8 @@ export async function deliverPinnedChange(
|
|||
|
||||
if (!Users.isLocalUser(user)) return;
|
||||
|
||||
const target = `${config.url}/users/${user.id}/collections/featured`;
|
||||
const item = `${config.url}/notes/${noteId}`;
|
||||
const content = renderActivity(
|
||||
isAddition
|
||||
? renderAdd(user, target, item)
|
||||
: renderRemove(user, target, item),
|
||||
isAddition ? renderAdd(user.id, noteId) : renderRemove(user.id, noteId),
|
||||
);
|
||||
|
||||
deliverToFollowers(user, content);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { renderLike } from "@/remote/activitypub/renderer/like.js";
|
||||
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import type { User, IRemoteUser } from "@/models/entities/user.js";
|
||||
|
@ -17,6 +16,7 @@ import {
|
|||
genIdAt,
|
||||
NoteEvent,
|
||||
publishToNoteStream,
|
||||
renderLike,
|
||||
toDbReaction,
|
||||
} from "backend-rs";
|
||||
import { createNotification } from "@/services/create-notification.js";
|
||||
|
@ -152,7 +152,7 @@ export default async (
|
|||
!note.localOnly &&
|
||||
note.visibility !== "hidden"
|
||||
) {
|
||||
const content = renderActivity(await renderLike(record, note));
|
||||
const content = renderActivity(await renderLike(record));
|
||||
const dm = new DeliverManager(user, content);
|
||||
if (note.userHost != null) {
|
||||
const reactee = await Users.findOneBy({ id: note.userId });
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { renderLike } from "@/remote/activitypub/renderer/like.js";
|
||||
import { renderUndo } from "@/remote/activitypub/renderer/undo.js";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
||||
|
@ -6,7 +5,12 @@ import { IdentifiableError } from "@/misc/identifiable-error.js";
|
|||
import type { User, IRemoteUser } from "@/models/entities/user.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import { NoteReactions, Users, Notes } from "@/models/index.js";
|
||||
import { decodeReaction, NoteEvent, publishToNoteStream } from "backend-rs";
|
||||
import {
|
||||
decodeReaction,
|
||||
NoteEvent,
|
||||
publishToNoteStream,
|
||||
renderLike,
|
||||
} from "backend-rs";
|
||||
|
||||
export default async (
|
||||
user: { id: User["id"]; host: User["host"] },
|
||||
|
@ -55,7 +59,7 @@ export default async (
|
|||
//#region 配信
|
||||
if (Users.isLocalUser(user) && !note.localOnly) {
|
||||
const content = renderActivity(
|
||||
renderUndo(await renderLike(reaction, note), user.id),
|
||||
renderUndo(await renderLike(reaction), user.id),
|
||||
);
|
||||
const dm = new DeliverManager(user, content);
|
||||
if (note.userHost != null) {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/uuid": "10.0.0",
|
||||
"@vitejs/plugin-vue": "5.1.2",
|
||||
"@vue/runtime-core": "3.4.37",
|
||||
"@vue/runtime-core": "3.4.38",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "6.0.1",
|
||||
"broadcast-channel": "7.0.0",
|
||||
|
@ -82,9 +82,9 @@
|
|||
"typescript": "5.5.4",
|
||||
"unicode-emoji-json": "0.6.0",
|
||||
"uuid": "10.0.0",
|
||||
"vite": "5.4.0",
|
||||
"vite": "5.4.1",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vue": "3.4.37",
|
||||
"vue": "3.4.38",
|
||||
"vue-draggable-plus": "0.5.3",
|
||||
"vue-plyr": "7.0.0",
|
||||
"vue-prism-editor": "2.0.0-alpha.2",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MkModal ref="modal" @click="done(true)" @closed="emit('closed')">
|
||||
<MkModal ref="modal">
|
||||
<div class="container">
|
||||
<div class="fullwidth top-caption">
|
||||
<div class="mk-dialog">
|
||||
|
@ -50,7 +50,6 @@
|
|||
:src="image.url"
|
||||
:alt="image.comment || undefined"
|
||||
:title="image.comment || undefined"
|
||||
@click="modal!.close()"
|
||||
/>
|
||||
<footer>
|
||||
<span>{{ image.type }}</span>
|
||||
|
@ -89,13 +88,11 @@ const props = withDefaults(
|
|||
showOkButton?: boolean;
|
||||
showCaptionButton?: boolean;
|
||||
showCancelButton?: boolean;
|
||||
cancelableByBgClick?: boolean;
|
||||
}>(),
|
||||
{
|
||||
showOkButton: true,
|
||||
showCaptionButton: true,
|
||||
showCancelButton: true,
|
||||
cancelableByBgClick: true,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -130,12 +127,6 @@ function cancel() {
|
|||
done(true);
|
||||
}
|
||||
|
||||
// function onBgClick() {
|
||||
// if (props.cancelableByBgClick) {
|
||||
// cancel();
|
||||
// }
|
||||
// }
|
||||
|
||||
function onKeydown(evt) {
|
||||
if (evt.which === 27) {
|
||||
// ESC
|
||||
|
@ -184,7 +175,8 @@ onBeforeUnmount(() => {
|
|||
inset-inline-start: 0;
|
||||
inset-block-start: 0;
|
||||
}
|
||||
@media (max-inline-size: 850px) {
|
||||
// TODO: use logical property (max-inline-size doesn't work)
|
||||
@media (max-width: 850px) {
|
||||
.container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
</div>
|
||||
<div class="right">
|
||||
<span
|
||||
v-if="maxTextLength - textLength < 500"
|
||||
class="text-count"
|
||||
:class="{ over: textLength > maxTextLength }"
|
||||
>{{ maxTextLength - textLength }}</span
|
||||
|
|
|
@ -239,7 +239,8 @@ function showMenu(ev) {
|
|||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
|
||||
@media (max-inline-size: 1200px) {
|
||||
// TODO: use logical property (max-inline-size doesn't work)
|
||||
@media (max-width: 1200px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +271,8 @@ function showMenu(ev) {
|
|||
inset-inline-start: 42px;
|
||||
inline-size: 140px;
|
||||
|
||||
@media (max-inline-size: 450px) {
|
||||
// TODO: use logical property (max-inline-size doesn't work)
|
||||
@media (max-width: 450px) {
|
||||
inline-size: 130px;
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +287,8 @@ function showMenu(ev) {
|
|||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
@media (max-inline-size: 1200px) {
|
||||
// TODO: use logical property (max-inline-size doesn't work)
|
||||
@media (max-width: 1200px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -301,7 +304,8 @@ function showMenu(ev) {
|
|||
border-radius: var(--radius);
|
||||
box-shadow: 0 12px 32px rgb(0 0 0 / 25%);
|
||||
|
||||
@media (max-inline-size: 1200px) {
|
||||
// TODO: use logical property (max-inline-size doesn't work)
|
||||
@media (max-width: 1200px) {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
|
@ -374,7 +378,8 @@ function showMenu(ev) {
|
|||
padding-block: 8px;
|
||||
padding-inline: 0;
|
||||
|
||||
@media (max-inline-size: 900px) {
|
||||
// TODO: use logical property (max-inline-size doesn't work)
|
||||
@media (max-width: 900px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,6 +250,9 @@ a {
|
|||
&:hover {
|
||||
text-decoration-color: currentColor;
|
||||
}
|
||||
&[target="_blank"] {
|
||||
-webkit-touch-callout: default;
|
||||
}
|
||||
}
|
||||
|
||||
// i {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.14.14",
|
||||
"@types/node": "20.15.0",
|
||||
"jest": "29.7.0",
|
||||
"jest-fetch-mock": "3.0.3",
|
||||
"jest-websocket-mock": "2.5.0",
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
//! Automatically generate doc comments for error variants from the error messages
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
/// Generates doc comments for error enums.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use macros_impl::error::error_variants as errors;
|
||||
/// # macros_impl::macro_doctest!({
|
||||
/// #[macros::errors]
|
||||
/// pub enum Error {
|
||||
/// #[error("config file name is not set")]
|
||||
/// NoConfigFileName,
|
||||
/// #[error("failed to read the config file")]
|
||||
/// ReadConfigFile(#[from] io::Error),
|
||||
/// #[error("invalid file content ({0})")]
|
||||
/// #[doc = "invalid file content"]
|
||||
/// InvalidContent(String),
|
||||
/// #[error(transparent)]
|
||||
/// #[doc = "database error"]
|
||||
/// Db(#[from] sea_orm::DbErr)
|
||||
/// }
|
||||
///
|
||||
/// # }, {
|
||||
/// /******* the code above expands to *******/
|
||||
///
|
||||
/// pub enum Error {
|
||||
/// #[error("config file name is not set")]
|
||||
/// #[doc = "config file name is not set"]
|
||||
/// NoConfigFileName,
|
||||
/// #[error("failed to read the config file")]
|
||||
/// #[doc = "failed to read the config file"]
|
||||
/// ReadConfigFile(#[from] io::Error),
|
||||
/// #[error("invalid file content ({0})")]
|
||||
/// #[doc = "invalid file content"]
|
||||
/// InvalidContent(String),
|
||||
/// #[error(transparent)]
|
||||
/// #[doc = "database error"]
|
||||
/// Db(#[from] sea_orm::DbErr)
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn error_variants(_attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||
let mut item: syn::ItemEnum = syn::parse2(item)?;
|
||||
|
||||
item.variants = item
|
||||
.variants
|
||||
.into_iter()
|
||||
.map(|mut variant| {
|
||||
// check if doc attribute is alredy there
|
||||
if variant.attrs.iter().any(|attr| attr.path().is_ident("doc")) {
|
||||
return variant;
|
||||
}
|
||||
|
||||
let msg = variant.attrs.iter().find_map(|attr| {
|
||||
if !attr.path().is_ident("error") {
|
||||
return None;
|
||||
}
|
||||
let lit: syn::LitStr = attr.parse_args().ok()?;
|
||||
Some(lit.value())
|
||||
});
|
||||
|
||||
// add #[doc] attribute
|
||||
if let Some(msg) = msg {
|
||||
variant.attrs.push(syn::parse_quote! { #[doc = #msg] });
|
||||
}
|
||||
|
||||
variant
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(quote! { #item })
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#![allow(clippy::items_after_test_module)]
|
||||
|
||||
pub mod error;
|
||||
pub mod napi;
|
||||
mod util;
|
||||
|
|
|
@ -84,11 +84,9 @@ define_wrapper_proc_macro_attributes! {
|
|||
/// When applied to enums, this macro implements [`std::error::Error`] trait
|
||||
/// and generates a document based on error messages unless there is already a doc comment
|
||||
///
|
||||
/// See [`macros_impl::error::error_variants`] for more details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore
|
||||
/// # use std::io;
|
||||
/// #[macros::errors]
|
||||
/// pub enum Error {
|
||||
|
@ -97,13 +95,13 @@ define_wrapper_proc_macro_attributes! {
|
|||
/// #[error("failed to read the config file")]
|
||||
/// ReadConfigFile(#[from] io::Error),
|
||||
/// #[error("invalid file content ({0})")]
|
||||
/// #[doc = "invalid file content"]
|
||||
/// #[doc = "Invalid file content"]
|
||||
/// InvalidContent(String),
|
||||
/// }
|
||||
/// ```
|
||||
errors(attr, item) {
|
||||
errors(_attr, item) {
|
||||
#[derive(::thiserror::Error, ::std::fmt::Debug)]
|
||||
#[macros::error_variants(#attr, #item)]
|
||||
#[error_doc::error_doc]
|
||||
#item
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +110,4 @@ reexport_proc_macro_attributes! {
|
|||
/// Creates an extra wrapper function for [napi_derive](https://docs.rs/napi-derive/latest/napi_derive/).
|
||||
/// See [macros_impl::napi::napi] for details.
|
||||
macros_impl::napi::napi as napi
|
||||
|
||||
/// Generates doc comments for error variants from the error messages
|
||||
macros_impl::error::error_variants as error_variants
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"devDependencies": {
|
||||
"firefish-js": "workspace:*",
|
||||
"idb-keyval": "6.2.1",
|
||||
"vite": "5.4.0",
|
||||
"vite": "5.4.1",
|
||||
"vite-plugin-compression": "0.5.1"
|
||||
}
|
||||
}
|
||||
|
|
710
pnpm-lock.yaml
710
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue