Compare commits

...

318 Commits

Author SHA1 Message Date
naskya 9ced0d96ad
chore (client): don't make a new post as soon as you add descriptions 2024-04-22 07:20:07 +09:00
naskya 9a4988eaad
chore (client): fix type errors 2024-04-22 07:14:56 +09:00
naskya fbdc068115
locale: update en-US.yml 2024-04-22 07:09:54 +09:00
naskya 23ec206aee
Merge branch 'develop' into feat/alt_warning 2024-04-22 06:59:58 +09:00
naskya 455ecdf743 Merge branch 'docs/add_dependencies' into 'develop'
docs: add minimum dependencies

Co-authored-by: 老周部落 <laozhoubuluo@gmail.com>

See merge request firefish/firefish!10703
2024-04-21 21:40:34 +00:00
naskya d98c564ead
docs: move the dependencies section to the top 2024-04-22 06:39:20 +09:00
naskya 56aac15a6b
docs (minor): paraphrase a bit 2024-04-22 06:32:07 +09:00
naskya 280dddf464 Merge branch 'fix/download-url-agent' into 'develop'
fix: download-url should use proxy bypass hosts

Co-authored-by: 老周部落 <laozhoubuluo@gmail.com>

See merge request firefish/firefish!10739
2024-04-21 21:27:55 +00:00
naskya b3cc01c440 Merge branch 'feat/show-MkRemoteCaution-in-history' into 'develop'
feat: show MkRemoteCaution in note history page

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10743
2024-04-21 21:23:02 +00:00
naskya ebaefb9697
chore (minor, client): remove redundant attribute 2024-04-22 06:02:08 +09:00
naskya d9982a0b6a
Merge branch 'develop' into feat/show-MkRemoteCaution-in-history 2024-04-22 06:01:19 +09:00
naskya 0cb2e94d99 Merge branch 'fix/feed' into 'develop'
fix: notes in rss feed do not display HTML

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10744
2024-04-21 21:00:18 +00:00
naskya d1817d9a22 Merge branch 'feat/antenna_limit' into 'develop'
feat: antenna limit

Co-authored-by: 老周部落 <laozhoubuluo@gmail.com>

Closes #10894

See merge request firefish/firefish!10740
2024-04-21 20:58:09 +00:00
naskya c9de5f6095
docs: update api-changes.md 2024-04-22 05:56:46 +09:00
naskya c4658801aa
chore: regenerate entities 2024-04-22 05:54:32 +09:00
naskya a107d8c1ec
fix (backend): update import 2024-04-22 05:52:56 +09:00
naskya 4c91e8e37f
Merge branch 'develop' into feat/antenna_limit 2024-04-22 05:51:22 +09:00
naskya ce672f4edd
dev: add cargo test to pnpm scripts
mocha test has been unmaintained for a long time and is very broken :(
2024-04-21 22:36:05 +09:00
naskya 131b3686d4 Merge branch 'feat/drive-file-usage-hints' into 'develop'
feat: Add usageHint field to DriveFile

Co-authored-by: yumeko <yumeko@mainichi.social>

See merge request firefish/firefish!10750
2024-04-21 12:58:37 +00:00
naskya 6b008c651a
chore (backend): remove (technically) incorrect TypeORM decorator field 2024-04-21 11:09:18 +09:00
naskya d2dbfb37c7
chore (backend): reflect entity changes to the schema and repository 2024-04-21 10:59:02 +09:00
naskya 96481f1353
chore: update downgrade.sql 2024-04-21 10:48:31 +09:00
naskya c936102a4c
chore (backend-rs): regenerate entities and index.js/d.ts 2024-04-21 10:45:47 +09:00
naskya 43570a54aa
chore: format 2024-04-21 10:44:54 +09:00
naskya 4d34e14dd8
Merge branch 'develop' into feat/drive-file-usage-hints 2024-04-21 10:42:25 +09:00
naskya 28f7ac1acd
fix (backend): typo 2024-04-21 10:31:00 +09:00
naskya 9f3396af21
chore (backend): translate Japanese comments into English 2024-04-21 10:30:13 +09:00
naskya dac4043dd9
v20240421 2024-04-21 10:09:45 +09:00
naskya d1e898c0d0
docs: update changelog 2024-04-21 09:32:05 +09:00
mei23 dc02a07774
fix (backend): add Cache-Control to Bull Dashboard 2024-04-21 09:29:00 +09:00
naskya 2760e7feee
chore (minor): use ** in lieu of Math.pow 2024-04-21 06:40:53 +09:00
naskya 488323cc8e
chore: format 2024-04-21 05:57:05 +09:00
naskya a2699e6687
chore (backend): fix imports 2024-04-20 23:04:12 +09:00
naskya dd3ad89b64 Merge branch 'refactor/types' into 'develop'
revert unnecessary MaybeRef in components

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10751
2024-04-20 01:07:25 +00:00
naskya 4fb2cab617 Merge branch 'fix/emoji-picker' into 'develop'
fix: use settings from reactionPicker for non-reaction emoji picker

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

Closes #10905

See merge request firefish/firefish!10752
2024-04-20 01:06:53 +00:00
naskya 5c4a773ecf
chore (backend): qualify Node.js builtin modules 2024-04-20 03:09:18 +09:00
Lhcfl 207855b0e8 fix: use settings from reactionPicker for non-reaction emoji picker 2024-04-20 01:05:30 +08:00
Lhcfl 781c98dda7 revert unnecessary `.value` for MkLink 2024-04-20 00:18:36 +08:00
Lhcfl ab221c98a7 revert unnecessary MaybeRef in components 2024-04-20 00:05:37 +08:00
yumeko 6c46bb56fd
Switch DriveFile's usageHint field to an enum type 2024-04-19 18:24:48 +03:00
naskya 1be5373dfc
chore (backend-rs): make exported enum compatible w/ TypeScript's string enum 2024-04-19 21:59:35 +09:00
yumeko 968657d26e
Run format 2024-04-19 07:54:11 +03:00
yumeko 913de651db
When updating (remote) user avatar/banner, clear usageHint for the previous drivefile, if any 2024-04-19 07:25:42 +03:00
yumeko 4aeb0d95cc
Add DriveFile usageHint field to rust model as well 2024-04-19 07:03:09 +03:00
yumeko c0f93de94b
Set file usage hints on local avatar/banner uploads as well + export "valid" values as type 2024-04-19 06:29:28 +03:00
yumeko 4823abd3a9
Add usageHint field to DriveFile, and fill accordingly when operating on Persons 2024-04-19 03:41:36 +03:00
naskya c6e2776298
chore (backend): remove a horrible and unused function 2024-04-19 03:42:49 +09:00
naskya 4b7724ed1f Merge branch 'cw-text' into 'develop'
Increase CW character limit

Closes #10876

See merge request firefish/firefish!10746
2024-04-17 20:47:40 +00:00
naskya 9d87679800
chore: lint 2024-04-18 05:34:23 +09:00
naskya 78092cd4be
dev (client): update eslint rules 2024-04-18 05:32:42 +09:00
naskya ff08d044b5
chore: format 2024-04-18 05:22:54 +09:00
naskya bce88ec199 Merge branch 'refactor/types' into 'develop'
Refactor/types

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10737
2024-04-17 20:21:52 +00:00
naskya 1b076c96d7
Merge branch 'develop' into refactor/types 2024-04-18 05:10:20 +09:00
naskya c19c439ac1
fix (backend): add hasPoll to packed note 2024-04-18 05:08:14 +09:00
naskya cc452da6c5
Merge branch 'develop' into refactor/types 2024-04-18 05:03:32 +09:00
naskya 30969ad817
refactor (backend): port get-note-summary to backend-rs
I removed trim() as it wasn't strictly neccessary
2024-04-18 05:02:00 +09:00
naskya 8337863ed3
chore: format 2024-04-18 05:01:49 +09:00
naskya 6a94d1b65d Merge branch 'fix/server-stats-disable' into 'develop'
Fix check for whether stats are disabled in meta in server machine stats job

Co-authored-by: yumeko <yumeko@mainichi.social>

See merge request firefish/firefish!10748
2024-04-17 18:20:35 +00:00
naskya c471aa30ae Merge branch 'fix/pinned-user-null' into 'develop'
Fix internal error in api/pinned-users if one or more name fails to resolve

Co-authored-by: yumeko <yumeko@mainichi.social>

See merge request firefish/firefish!10747
2024-04-17 18:19:17 +00:00
yumeko a411f4e4d9 Fix internal error in api/pinned-users if one or more name fails to resolve 2024-04-17 18:19:17 +00:00
naskya 22f4278ab5
meta: update issue/merge request templates 2024-04-17 23:14:43 +09:00
naskya ec7578e78e
docs: specify max-old-space-size in example config files 2024-04-17 19:49:02 +09:00
naskya adaaae1583
Merge branch 'develop' into refactor/types 2024-04-17 19:07:43 +09:00
naskya 8489066130
fix (client): list layout on mobile 2024-04-17 19:06:29 +09:00
naskya 17fb05430e
fix (backend, Mastodon API): add 'meta.original' field to media attachments
addresses https://github.com/whitescent/Mastify/pull/102
2024-04-17 17:46:23 +09:00
yumeko bf3c0717b9 Fix check for whether stats are disabled in meta in server machine stats job 2024-04-16 15:29:18 +00:00
naskya 082948bfe0
Merge branch 'develop' into refactor/types 2024-04-16 22:29:04 +09:00
Hosted Weblate 86f2e32c66
Merge branch 'origin/develop' into Weblate 2024-04-16 05:02:06 +02:00
Gary O'Regan Kelly 7af2cca2d4
locale: update translations (French)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/fr/
2024-04-16 05:01:56 +02:00
naskya 07384a4f0f
feat (backend): increase CW character limit (close #10876) 2024-04-16 09:14:44 +09:00
naskya 77a2bcfc4b
chore: remove unused items from example config file 2024-04-16 09:01:12 +09:00
naskya fd333250c9
chore (backend): set proxyRemoteFiles to true by default (close #9426) 2024-04-16 08:56:05 +09:00
naskya 38192052c9
meta: update issue/merge request templates 2024-04-16 05:40:27 +09:00
naskya 80b80277e2
fix (pug): random MOTD not showing 2024-04-16 01:50:42 +09:00
naskya 71c158fbd3
refactor (backend): port env.ts to backend-rs 2024-04-15 17:28:20 +09:00
naskya 0f3126196f
refactor (backend): port reaction-lib to backend-rs 2024-04-15 10:02:44 +09:00
naskya 2731003bc9
refactor (backend): port emoji-regex to backend-rs 2024-04-15 05:37:09 +09:00
naskya 74875f174b
chore (minor, backend): use a template literal 2024-04-15 04:34:36 +09:00
naskya 884c69f377
chore (minor, backend): organize imports 2024-04-15 04:34:00 +09:00
naskya f412d7ace3
chore (backend): remove 'quiet' settings 2024-04-15 04:31:04 +09:00
naskya eb5dccacfe
chore (firefish-js): remove bun lockfile
Why is it there?
2024-04-15 04:18:44 +09:00
naskya 21225f7137
chore: update dependencies 2024-04-15 04:09:33 +09:00
naskya fca48b2a81
refactor (backend): port safe-for-sql, sql-like-escape to backend-rs 2024-04-14 20:29:44 +09:00
sup39 b71da18b03
refactor (backend): port fetch-meta to backend-rs
Co-authored-by: naskya <m@naskya.net>
2024-04-14 20:16:22 +09:00
Lhcfl 241c824ab5 fix: use better `]]>` replacer 2024-04-14 16:44:12 +08:00
Lhcfl 54d9916fec fix: rss feed no HTML 2024-04-14 16:34:33 +08:00
Lhcfl f0a50bc288 feat: show MkRemoteCaution in note history page 2024-04-14 13:59:27 +08:00
naskya ceca260c92
refactor (backend): port convert-milliseconds to backend-rs 2024-04-14 14:54:32 +09:00
sup39 70aa3704ef
refactor (backend): port password hashing/verification to backend-rs
Co-authored-by: naskya <m@naskya.net>
2024-04-14 14:41:01 +09:00
naskya baa57d7c17
dev: add rust-analyzer to recommended VSCode extensitons 2024-04-14 13:38:44 +09:00
naskya 19b45866c8
docs: update packages/README.md 2024-04-14 13:35:35 +09:00
Lhcfl 8a62bf90f5 fix: MkMenu.vue 2024-04-14 03:42:30 +08:00
Lhcfl cee3a13f51 fix types 2024-04-14 03:15:31 +08:00
naskya aea6659d0b
fix: workaround the issue that profile pages don't load if the version is older than 20240212
(v20240212 is vulnerable btw)
2024-04-14 02:35:25 +09:00
Lhcfl 1a6ba246f2 add other FormInput 2024-04-13 23:21:31 +08:00
Lhcfl 16880b1231 fix types 2024-04-13 23:08:58 +08:00
Lhcfl 3e43819ba1 rewrite MkFormDialog 2024-04-13 23:08:46 +08:00
naskya 5ba88f3d6f
v20240413 2024-04-13 21:34:20 +09:00
naskya 008d8d8f5c
docs: update changelog 2024-04-13 21:30:38 +09:00
Lhcfl bb9a58ce34 Merge branch 'develop' of https://firefish.dev/firefish/firefish into refactor/types 2024-04-13 20:08:41 +08:00
naskya ad58ae8f30
refactor: remove /api/patrons endpoint 2024-04-13 20:03:02 +09:00
naskya 799ad1f3f8
dev (minor, backend-rs): format Makefile 2024-04-13 19:49:36 +09:00
naskya d57c9dc289
fix (client): set displayMode to true for block math expressions 2024-04-13 19:48:35 +09:00
naskya d0de0d14b2
docs: fix indent 2024-04-13 19:42:03 +09:00
Lhcfl baba86a203 Downgrade vue-tsc
new versions of vue-tsc have perfomance issues:
see https://github.com/vuejs/language-tools/issues/4223
2024-04-13 17:55:40 +08:00
Lhcfl f95e2d1c51 Merge branch 'develop' of https://firefish.dev/firefish/firefish into refactor/types 2024-04-13 15:39:44 +08:00
Lhcfl 2b88ef18a5 fix type errors of components 2024-04-13 15:37:23 +08:00
Hosted Weblate a86be6a9cb
Merge branch 'origin/develop' into Weblate 2024-04-13 09:02:03 +02:00
jolupa 68be7d6be9
locale: update translations (Catalan)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-13 09:01:54 +02:00
老周部落 5eff4da27b
feat: antenna limit 2024-04-13 10:02:32 +08:00
老周部落 f44a2937d4
fix: download-url should use proxy bypass hosts 2024-04-13 09:00:08 +08:00
naskya 64581d2088
chore (backend-rs): add serde attribute
This is redundant though
2024-04-13 00:02:07 +09:00
naskya 0517a83dc5
container: fix cargo fetch 2024-04-12 23:03:40 +09:00
Lhcfl 393ab2590d fix type errors of components 2024-04-12 22:02:03 +08:00
sup39 99b8a40566
fix (backend-rs): selected texts may be None in check_word_mute
Co-authored-by: naskya <m@naskya.net>
2024-04-12 22:32:42 +09:00
naskya 603ec70b97
refactor (backend-rs): rewrite Mastodon ID conversion
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 21:48:55 +09:00
Lhcfl f422842aef use Number.parseInt 2024-04-12 16:55:34 +08:00
Lhcfl 695cb452bc chore: Temporarily disable organizeImports 2024-04-12 16:50:07 +08:00
Lhcfl e4927c9b9b fix types of components 2024-04-12 16:37:32 +08:00
naskya 35ca75bfe5
chore (backend-rs): use pretty_assertions in unit tests 2024-04-12 17:18:39 +09:00
naskya 148c3736ce
refactor (backend): port convert-host to backend-rs
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 17:13:57 +09:00
naskya 3d6031dca3
chore: get rid of re2 from dependencies 2024-04-12 15:47:04 +09:00
naskya 83c15b1026
refactor (backend): port checkWordMute to backend-rs
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 15:43:17 +09:00
Lhcfl ea6ef881c2 fix types of components 2024-04-12 14:08:20 +08:00
sup39 0cfa85197d
refactor (backend-rs): rewrite the function to get db connection
Co-authored-by: naskya <m@naskya.net>
2024-04-12 14:38:44 +09:00
naskya e2cd25ea4f
refactor (backend): port config loader to backend-rs
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 14:25:27 +09:00
Lhcfl 2bf51abc12 fix type of MkModalPageWindow 2024-04-12 11:31:11 +08:00
sup39 3e32fc7b04
feat (macro-rs): add macro_rs::export macro
Co-authored-by: naskya <m@naskya.net>
2024-04-12 12:28:27 +09:00
naskya 08bea415c9
chore (backend-rs): track index.d.ts
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 12:28:21 +09:00
Lhcfl 5da03666b2 fix types of component 2024-04-12 11:16:26 +08:00
sup39 9592b88e52
feat (macro-rs): set `use_nullable = true` for `object` and `constructor` by default 2024-04-12 11:54:21 +09:00
naskya 8926d86ab8
chore (backend-rs): remove impl_into_napi_error macro
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 11:54:20 +09:00
naskya 6b812fb30b
chore: lint 2024-04-12 11:54:20 +09:00
naskya 0335a353e8
dev: update format/lint scripts 2024-04-12 11:54:14 +09:00
naskya 50b2d1c22b
fix: old target directory must be removed 2024-04-12 11:10:53 +09:00
naskya ad30d16f23
chore (backend): remove unused file 2024-04-12 11:10:52 +09:00
naskya 452e0b921c
refactor (backend): port acct to backend-rs 2024-04-12 11:10:52 +09:00
naskya beb16ab9cf
refactor (backend): port nyaify to backend-rs 2024-04-12 11:10:42 +09:00
Lhcfl f3b189a70c refactor: rewrite MkMediaCaption 2024-04-12 09:46:04 +08:00
Lhcfl 95b91c6396 chore: remove unused type imports 2024-04-12 09:40:34 +08:00
Lhcfl 9c75dd0b26 refactor: define more cleared type of os.ts 2024-04-12 09:33:27 +08:00
naskya 0b90a7daaf
refactor (backend-rs): use macro_rs::napi
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 05:20:55 +09:00
naskya f60ff2eaf4
refactor (backend-rs): rewrite id generator
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 05:20:45 +09:00
sup39 186919aac3
feat (macro-rs): handle macro attr 2024-04-12 05:20:41 +09:00
sup39 2ba60a3b40
feat (macro-rs): convert `&[T]` to `Vec<T>` 2024-04-12 05:20:02 +09:00
sup39 b6b07d562c
feat (macro-rs): handle async fn 2024-04-12 05:19:39 +09:00
sup39 c231bf43cb
feat (macro-rs): convert Result<T, E> return type to napi::Result<T> 2024-04-12 05:19:26 +09:00
sup39 5d2238a266
fix (macro-rs): use `cfg` instead of `cfg_attr` 2024-04-12 05:18:14 +09:00
sup39 8b6e300d4e
feat (macro-rs): create macro_rs::napi macro 2024-04-12 05:17:02 +09:00
naskya 0491e11a9e
refactor: create virtual rust workspace in the repository root
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-12 03:24:13 +09:00
naskya 3fe8ace571
chore: update dependencies 2024-04-12 02:55:27 +09:00
naskya afc57d834c
fix (backend): add missing Relation wrapper
should have done in aedf873248
2024-04-12 02:42:17 +09:00
Lhcfl 38668c4c11 fix type errors 2024-04-12 01:32:04 +08:00
naskya 24f79d4796
fix (backend): prevent chat messages from being deleted when attached file is deleted 2024-04-12 02:26:00 +09:00
Lhcfl e6b7eca775 fix type errors of components 2024-04-12 01:12:18 +08:00
naskya 6eee5c651c
meta (minor): update issue templates 2024-04-12 01:59:20 +09:00
Lhcfl 8e28f0e97c Merge branch 'develop' of https://firefish.dev/firefish/firefish into refactor/types 2024-04-12 00:23:21 +08:00
Lhcfl d8b4eb6f5e fix: gallery posts not show & fix types 2024-04-12 00:22:49 +08:00
Lhcfl ef94ba1474 refactor: fix type errrors of some components 2024-04-12 00:20:51 +08:00
naskya 88aaa47220
meta: update issue/merge request templates (close #10896) 2024-04-12 00:42:40 +09:00
naskya 69b93554e8 Merge branch 'use-sync-visibility-picker' into 'develop'
chore: don't import MkVisibilityPicker dynamically

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10736
2024-04-11 13:20:09 +00:00
naskya 5f2697f304
fix (client): import path 2024-04-11 22:17:49 +09:00
naskya 9bbdb1638f
docs: update COPYING 2024-04-11 22:09:07 +09:00
naskya aedf873248
refactor (backend): distinguish between database columns and relations, set correct nullability 2024-04-11 21:58:06 +09:00
Lhcfl c4a093209f fix type of MkEmojiPicker 2024-04-11 18:00:37 +08:00
Lhcfl db37eb4ad1 refactor: rewrite MkFolder 2024-04-11 17:29:07 +08:00
Lhcfl 3716e7f74c fix: expose toggleContent for it was a method 2024-04-11 17:11:48 +08:00
Lhcfl 7a4e6334f1 fix type error 2024-04-11 17:01:37 +08:00
Lhcfl 783f5481bb remove unnecessary assertion 2024-04-11 16:58:58 +08:00
Lhcfl da6f07952b rename client-types.ts -> note.ts; fix type importing 2024-04-11 16:55:39 +08:00
Lhcfl 3ddd68097a fix type errors 2024-04-11 00:48:35 +08:00
Lhcfl f275fc9cdf refactor: fix type errors of MkCropperDialog 2024-04-11 00:14:36 +08:00
Lhcfl 18ba024cbb chore: format 2024-04-11 00:00:54 +08:00
Lhcfl 43aeec32ce fix types error of MkContextMenu 2024-04-10 23:36:42 +08:00
Lhcfl 909125e519 refactor: rewrite MkContainer using composition api 2024-04-10 23:35:14 +08:00
Lhcfl 124b2244d6 fix type errors of MkCode & MkModalWindow 2024-04-10 22:50:30 +08:00
Lhcfl 0b7ab1b90d fix type errors of MkChatPreview 2024-04-10 22:45:01 +08:00
Lhcfl 6982843716 fix: channel editor cannot remove channel banner 2024-04-10 22:25:45 +08:00
Lhcfl 17a945b8b1 fix type errors of channel 2024-04-10 22:25:11 +08:00
Lhcfl f7f7959ba6 refactor: fix waring for MkCaptcha 2024-04-10 22:24:16 +08:00
Lhcfl c1155f169a fix type warnings of MkCaptcha 2024-04-10 20:42:48 +08:00
Lhcfl b59186f093 fix type errors of MkButton 2024-04-10 20:41:31 +08:00
Lhcfl 1a1d817772 fix type errors of MkAvatars 2024-04-10 20:37:34 +08:00
Lhcfl 73537ec6fa fix type errors of MkAutoComplete 2024-04-10 20:36:20 +08:00
Lhcfl 6ac6a4cfa9 refactor: fix type errors of MkAnnouncements 2024-04-10 20:10:43 +08:00
Lhcfl b6baded2e3 refactor: fix MkAcct type 2024-04-10 17:58:02 +08:00
Lhcfl 23145c61af refactor: fix type of MkAbuseReport 2024-04-10 17:55:52 +08:00
Lhcfl 268b7aeb3f refactor: Fix type errors of mfm.ts 2024-04-10 17:16:25 +08:00
Hosted Weblate 8287874cd6
Merge branch 'origin/develop' into Weblate 2024-04-10 10:01:59 +02:00
老周部落 4f50156931
locale: update translations (Chinese (Simplified))
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/zh_Hans/
2024-04-10 10:01:53 +02:00
Linerly 80f8afbb26
locale: update translations (Indonesian)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/id/
2024-04-10 10:01:51 +02:00
jolupa cbaa577e58
locale: update translations (Catalan)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-10 10:01:49 +02:00
naskya 12f04a19b4
docs (minor): update notice-for-admins.md 2024-04-10 14:45:25 +09:00
Lhcfl 75899aeb51 move consts.ts from @/types to @/script 2024-04-10 01:22:48 +08:00
Lhcfl 6ee1049731 use client-only noteVisibilities type 2024-04-10 01:18:08 +08:00
naskya 3bde79e6a9
docs: update notice-for-admins.md 2024-04-10 00:50:25 +09:00
naskya 8dd0a8b752
docs: update notice-for-admins.md
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-09 22:59:02 +09:00
Lhcfl e486715e9a chore: use sync MkVisibiliityPicker 2024-04-09 19:29:27 +08:00
Hosted Weblate bd62b5e964
Merge branch 'origin/develop' into Weblate 2024-04-09 09:24:05 +02:00
jolupa 0ed207d81b
locale: update translations (Catalan)
Currently translated at 100.0% (1921 of 1921 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-09 09:23:58 +02:00
naskya 0b231e6d24
docs: update changelog 2024-04-08 21:40:36 +09:00
naskya 8b14e57ba6
style: remove MkLoading from MkPullToRefresh 2024-04-08 21:19:20 +09:00
naskya c707221dfb
chore (minor): use type import 2024-04-08 21:15:18 +09:00
naskya e1345e4e29
fix (backend): make sure that instance info fit in the database (close #10891)
I guess there is a better way to do this...
2024-04-08 20:52:14 +09:00
naskya 3f918f9dcc
fix (client): MkLoading doesn't show up at some places 2024-04-08 18:24:08 +09:00
naskya 273f1a8568
chore (minor, client): accept linter suggestions in MkModal 2024-04-08 17:42:29 +09:00
naskya 2beeeddca2
chore (client): replace pageXOffset (pageYOffset) with scrollX (scrollY)
b4b47d85cf

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
2024-04-08 17:31:33 +09:00
naskya 7adef666d1
chore (client): rename iconClass to iconify 2024-04-08 17:27:06 +09:00
naskya fcfbee4c1d
chore (client): searchByGoogle -> search 2024-04-08 17:17:08 +09:00
naskya 30619301d3
chore: replace `new Date().getTime()` with `Date.now()`
959cc8ff37

Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com>
2024-04-08 17:00:41 +09:00
naskya fce0e5a218
feat (backend): federate math expressions using MathML
Co-authored-by: Johann150 <johann.galle@protonmail.com>
2024-04-08 12:15:54 +09:00
Hosted Weblate 2ca4d17697
Merge branch 'origin/develop' into Weblate 2024-04-08 00:02:17 +02:00
naskya 086253ebb1
locale: update translations (Japanese)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ja/
2024-04-08 00:01:56 +02:00
Gary O'Regan Kelly a75c0c5fd7
locale: update translations (French)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/fr/
2024-04-08 00:01:55 +02:00
naskya 3edeb7a270
fix: custom emojis on user overview not being rendered 2024-04-07 19:19:19 +09:00
naskya 9df08ea16a
refactor (minor): replace substr with substring 2024-04-07 19:10:26 +09:00
naskya 15ddde2431
fix: downgrade gulp for now 2024-04-07 18:55:29 +09:00
naskya 65e7d9d157
fix (client): Unicode emoji rendering 2024-04-07 18:54:14 +09:00
naskya 26c3b25a40
chore: update dependencies 2024-04-07 16:42:25 +09:00
tmorio ea357b71a0
feat (client): add "Media" tab to user page
https://maniakey.com/notes/9rsfrmqm1a
66a2d2fa5c

Co-authored-by: naskya <m@naskya.net>
2024-04-07 16:29:51 +09:00
naskya d0901d77ab
fix (client): antenna layout on mobile 2024-04-07 13:41:03 +09:00
naskya a64e42208e
fix (client): EndpointsOf import 2024-04-07 13:03:10 +09:00
naskya cb7e9ab449 Merge branch 'refactor/lists' into 'develop'
refactor: Fix types of components

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10730
2024-04-07 03:57:10 +00:00
naskya 110e092262
chore (backend): use type import for MigrationInterface and QueryRunner 2024-04-07 12:38:52 +09:00
naskya 9ea5fcd1bf Merge branch 'refactor/sea-orm-entities' into 'develop'
Make it possible to manipulate the database in backend-rs


See merge request firefish/firefish!10735
2024-04-07 03:34:41 +00:00
naskya 5e2376a6dc Merge branch 'feat/spin-when-posting' into 'develop'
feat: show a MkLoading when posting

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10734
2024-04-07 03:33:25 +00:00
naskya fb3cc4b4f1
dev: make update-index-js -> make index-js 2024-04-07 12:28:09 +09:00
naskya 6a7d8c0b13
dev: specify the source of backend-rs/index.js in Makefile 2024-04-07 12:25:33 +09:00
naskya e4c9a91a16
dev: format the code on entity regeneration 2024-04-07 12:20:46 +09:00
naskya 18f4114f18
chore: format 2024-04-07 12:17:02 +09:00
naskya 5c0d771dff
chore: await migration queries 2024-04-07 12:16:53 +09:00
naskya 6efcddd0ee
dev: make sure to update backend-rs/index.js before merging develop into main 2024-04-07 05:07:00 +09:00
naskya d6a88419a4
chore: update backend-rs/index.js 2024-04-07 05:07:00 +09:00
naskya e9030a6b82
chore: regenerate entities 2024-04-07 05:06:59 +09:00
naskya aa11eeb1c8
refactor (backend-rs): expose SeaORM entities to Node API
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-07 05:06:44 +09:00
naskya c52973234c
docs: update notice-for-admins.md 2024-04-07 05:06:42 +09:00
naskya 383b2b874d
chore: format 2024-04-07 05:06:42 +09:00
naskya 91ccce4307
refactor (backend): drop timezone data (which is not used at all)
Co-authored-by: sup39 <dev@sup39.dev>
2024-04-07 05:06:27 +09:00
naskya 3c469ccf43
chore: regenerate entities 2024-04-07 04:43:09 +09:00
Hosted Weblate ba140134bf
Merge branch 'origin/develop' into Weblate 2024-04-06 21:01:59 +02:00
jolupa ac69480f28
locale: update translations (Catalan)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-06 21:01:54 +02:00
naskya 6dcf8c65b4 Merge branch 'fix/noteWithFiles' into 'develop'
fix: "Show posts with this file" page shows nothing

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10731
2024-04-05 22:48:22 +00:00
naskya 54c5192a06
chore (backend): add some more comments on the translate function 2024-04-06 07:42:32 +09:00
Lhcfl ced13ff12b chore: add explainations for biome-lint, clear unused export 2024-04-05 13:34:06 +08:00
Lhcfl 12aa04447b feat: show a MkLoading when posting 2024-04-05 11:40:58 +08:00
naskya 0a080159d4 Merge branch 'fix/mfm-cheatsheet' into 'develop'
fix: remove blur from MFM cheatsheet to reduce performance issues

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10732
2024-04-04 22:06:53 +00:00
Linca 98fc5af2a8 fix: remove blur from MFM cheatsheet to reduce performance issues
Co-authored-by: Lhcfl <Lhcfl@outlook.com>
2024-04-04 22:06:53 +00:00
naskya 8a74892df4
v20240405 2024-04-05 06:44:16 +09:00
naskya a401239cfd
docs: update changelog 2024-04-05 05:38:27 +09:00
naskya 0c74ac471e Merge branch 'docs/pgroonga' into 'develop'
docs: optimize pgroonga installation

Co-authored-by: 老周部落 <laozhoubuluo@gmail.com>

See merge request firefish/firefish!10728
2024-04-04 20:20:00 +00:00
naskya 01158d7dd5
docs: update notice-for-admins.md 2024-04-05 05:19:20 +09:00
Lhcfl 3251a07ae0 chore: add types check for client 2024-04-04 20:23:50 +08:00
Lhcfl bfffd94ae5 fix type errors of components/form 2024-04-04 18:48:23 +08:00
Lhcfl 3abe6a0dfe fix type errors of MkStickyContainer 2024-04-04 17:01:33 +08:00
Lhcfl 3586d0cde7 chore: disable noNonNullAssertion for vue 2024-04-04 16:58:11 +08:00
Lhcfl 995d679afd fix type errors of MkPageHeader 2024-04-04 16:53:02 +08:00
Lhcfl 3902b82470 fix type errors of MkMisskeyFlavoredMarkdown.vue 2024-04-04 16:13:56 +08:00
Lhcfl 85e42f7c27 fix type errors of MkLoading 2024-04-04 16:03:22 +08:00
Hosted Weblate 94a1b01564
Merge branch 'origin/develop' into Weblate 2024-04-04 10:02:15 +02:00
Eana Hufwe 13d607c58d
locale: update translations (Chinese (Simplified))
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/zh_Hans/
2024-04-04 10:02:11 +02:00
Linerly 5560b6d481
locale: update translations (Indonesian)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/id/
2024-04-04 10:02:09 +02:00
jolupa 99b928c833
locale: update translations (Catalan)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-04 10:02:07 +02:00
Lhcfl 9bfa8dc417 fix type errors in MkEmoji 2024-04-04 15:51:43 +08:00
Lhcfl 75cf048876 fix type errors of MkAvatar 2024-04-04 15:47:04 +08:00
Lhcfl 5d3cfcff36 fix type error for MkAd 2024-04-04 15:28:41 +08:00
Lhcfl ee3ce22b74 fix type error of i18n.ts 2024-04-04 15:20:15 +08:00
Lhcfl 2505b58f99 fix: MFM component props type 2024-04-04 15:07:36 +08:00
Lhcfl ae071d66b7 chore: warn "useShorthandFunctionType" in biome for vue 2024-04-04 15:04:31 +08:00
Lhcfl 3f8bd14f0d chore: format 2024-04-04 14:57:47 +08:00
Lhcfl 66dec9c54e chore: Chang `useImportType` to warn for vue files
vue is only partically supported by biome (see https://biomejs.dev/internals/language-support/)
Some components may be incorrectly recognized as type imports
2024-04-04 14:51:31 +08:00
Lhcfl 6b89d666af fix: fix all type errors of MkPagination 2024-04-04 14:38:21 +08:00
Lhcfl 435260e197 chore: change for better type inference 2024-04-04 00:11:58 +08:00
Lhcfl 93e80353eb chore: add type for connection 2024-04-04 00:07:44 +08:00
Lhcfl 3d39daff8c refactor: Add more type support to MkPagination 2024-04-03 23:10:49 +08:00
Lhcfl 914fff5658 refactor: Rewrite MkDateSeperatedList for better type supports 2024-04-03 23:10:08 +08:00
Lhcfl d0989c692d chore: diable noUselessElse 2024-04-03 21:42:40 +08:00
Lhcfl add6081f18 fix: error of notes with file 2024-04-03 21:26:58 +08:00
老周部落 ff6e722f0c
docs: optimize pgroonga installation 2024-04-03 18:59:04 +08:00
naskya 7c712df731
fix (firefish-js): update LiteInstanceMetadata 2024-04-03 13:39:37 +09:00
naskya 6dc4f3d8a1
refactor (client, minor): replace i18n.t with i18n.ts 2024-04-03 13:36:09 +09:00
naskya 46baec14d2
fix (client): use icon script 2024-04-03 13:14:36 +09:00
naskya acf64acb11
locale: update translations (Japanese)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ja/
2024-04-03 06:02:03 +02:00
jolupa 45a217adaf
locale: update translations (Catalan)
Currently translated at 100.0% (1920 of 1920 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-03 06:02:01 +02:00
naskya 82dff9beb1 Merge branch 'feat/note-edit-history' into 'develop'
feat: Add post edit history

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10714
2024-04-01 17:44:18 +00:00
naskya 97e6dc1bb4
chore (client, minor): slightly more readable condition 2024-04-02 02:40:55 +09:00
naskya 6f1c29cf05 Merge branch 'fix/replyLanguage' into 'develop'
fix: Don't set language to null when reply/renote lang is null/undefined

Co-authored-by: Lhcfl <Lhcfl@outlook.com>

See merge request firefish/firefish!10727
2024-04-01 17:02:25 +00:00
naskya 84eb75e03e Merge branch 'scrollTouchscreen' into 'develop'
fix(client): pull to refresh activates when scrolling down mid-way in the page

Co-authored-by: eana <coder@apps.1a23.com>

Closes #10869

See merge request firefish/firefish!10725
2024-04-01 17:01:21 +00:00
eana a5cd3c8b70 Address comments 2024-04-01 15:08:01 +00:00
naskya 81b9fdf397
refactor (client): stop importing things directly from firefish-js/src 2024-04-01 13:58:54 +09:00
naskya f70c9efe6b
chore (client): use i18n.ts instead of i18n.t 2024-04-01 13:55:20 +09:00
naskya 0001ffa356
chore: update SeaORM entity 2024-04-01 13:28:12 +09:00
naskya 76097b25c9
chore: update downgrade.sql 2024-04-01 13:26:01 +09:00
Lhcfl 70dd49740e chore: format 2024-04-01 11:34:57 +08:00
Lhcfl e8f178458f Merge branch 'develop' of https://firefish.dev/firefish/firefish into feat/note-edit-history 2024-04-01 11:32:14 +08:00
Lhcfl c735156ef2 fix: Don't set language to null when reply/renote lang is null/undefined 2024-04-01 11:16:58 +08:00
Lhcfl f2075e361a update docs/api-change 2024-04-01 11:06:59 +08:00
Lhcfl 0b226f7013 store emojis for note_edit 2024-04-01 11:01:59 +08:00
naskya 7e0f20c24f Merge branch 'replyLanguage' into 'develop'
feat(client): inherit reply/quote language

Co-authored-by: eana <coder@apps.1a23.com>

Closes #10885

See merge request firefish/firefish!10726
2024-04-01 02:09:32 +00:00
Eana Hufwe 12abccc9a3 feat(client): inherit reply/quote language
Co-authored-by: eana <coder@apps.1a23.com>
2024-04-01 02:09:32 +00:00
Hosted Weblate cc83abac7e
Merge branch 'origin/develop' into Weblate 2024-04-01 01:27:57 +02:00
Salif Mehmed 059f9e1be1
locale: update translations (Bulgarian)
Currently translated at 44.1% (848 of 1919 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/bg/
2024-04-01 01:27:53 +02:00
jolupa 02aef92d8b
locale: update translations (Catalan)
Currently translated at 100.0% (1919 of 1919 strings)

Translation: Firefish/locales
Translate-URL: https://hosted.weblate.org/projects/firefish/locales/ca/
2024-04-01 01:27:52 +02:00
eana 0666a78dcf fix(client): pull to refresh activates when scrolling down mid-way in the page
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2024-03-31 20:13:00 +00:00
Lhcfl a562d9bb39 chore: format 2024-04-01 03:24:30 +08:00
Lhcfl 9a0136514b fix: incorrect note id 2024-04-01 03:21:55 +08:00
naskya 54dfe1c222
v20240401 2024-04-01 04:16:15 +09:00
Laura Hausmann 88ca0e1621
fix (backend): set X-Content-Type-Options to nosniff on the drive files endpoint 2024-04-01 03:22:06 +09:00
naskya 9086ef11ff Merge branch 'pageDetailsButtonAlign' into 'develop'
fix(client): page details button icon alignment

Co-authored-by: eana <coder@apps.1a23.com>

See merge request firefish/firefish!10722
2024-03-31 18:19:53 +00:00
Eana Hufwe 0d990e07cb fix(client): page details button icon alignment
Co-authored-by: eana <coder@apps.1a23.com>
2024-03-31 18:19:53 +00:00
naskya 3ba7137eaa Merge branch 'emojiListLoad' into 'develop'
fix(client): emoji data format change

Co-authored-by: eana <coder@apps.1a23.com>

See merge request firefish/firefish!10721
2024-03-31 18:09:06 +00:00
Lhcfl cbe88c56ef feat: show files of noteEdit 2024-04-01 01:53:21 +08:00
Lhcfl 6d4cb5b4aa fix: note.updatedAt might be null 2024-04-01 00:40:58 +08:00
naskya 9b354790c3
dev: keep db/redis data on db.down 2024-03-31 12:14:13 +09:00
eana 4370bd1012 fix(client): emoji data format change 2024-03-30 16:49:22 +00:00
naskya 293afc7fe4
Merge branch 'develop' into feat/note-edit-history 2024-03-28 14:27:29 +09:00
Lhcfl bab704992f feat: add post history page 2024-03-26 16:59:42 +08:00
Lhcfl d64d133d7f backend: added /note/history endpoint 2024-03-26 10:07:00 +08:00
老周部落 de4da3c1fd
docs: add minimum dependencies 2024-03-19 22:51:05 +08:00
910 changed files with 11736 additions and 6597 deletions

View File

@ -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

View File

@ -10,7 +10,7 @@ node_modules
report.*.json
# Rust
packages/backend-rs/target
/target
# Coverage
coverage

3
.gitignore vendored
View File

@ -14,6 +14,9 @@ packages/backend/.idea/vcs.xml
node_modules
report.*.json
# Cargo
/target
# Cypress
cypress/screenshots
cypress/videos

View File

@ -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.

View File

@ -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.

View File

@ -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> -->

View File

@ -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) -->

View File

@ -12,6 +12,7 @@
"esbenp.prettier-vscode",
"redhat.vscode-yaml",
"yoavbls.pretty-ts-errors",
"biomejs.biome"
"biomejs.biome",
"rust-lang.rust-analyzer"
]
}

View File

@ -1,5 +0,0 @@
{
"rust-analyzer.linkedProjects": [
"packages/backend-rs/Cargo.toml"
]
}

View File

@ -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.

View File

@ -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
View 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

View File

@ -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

View File

@ -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:

View File

@ -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"
}
}
}
}
]
}

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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: "اعرض الوسائط ذات المحتوى الحساس"

View File

@ -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: Автоматично откриване на езика и показване на бутон за превеждане
за публикации на чужди езици

View File

@ -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: "স্পর্শকাতর মিডিয়া লুকাবেন না"

View File

@ -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

View File

@ -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"

View File

@ -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:

View File

@ -295,7 +295,6 @@ searchResult: "Αποτελέσματα αναζήτησης"
learnMore: "Μάθετε περισσότερα"
controlPanel: "Πίνακας ελέγχου"
manageAccounts: "Διαχείριση Λογαριασμών"
searchByGoogle: "Αναζήτηση"
file: "Αρχεία"
recommended: "Προτεινόμενα"
cannotUploadBecauseNoFreeSpace: "Το ανέβασμα απέτυχε λόγω ανεπαρκούς Αποθηκευτικού

View File

@ -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."
@ -1226,8 +1227,8 @@ publishTimelinesDescription: "If enabled, the Local and Global timelines will be
on {url} even when signed out."
noAltTextWarning: "Some attached file(s) have no description. Did you forget to write?"
showNoAltTextWarning: "Show a warning if you attempt to post files without a description"
showAddFileDescriptionAtFirstPost: "Show add description page automatically when
first try to post a post attachment without a description"
showAddFileDescriptionAtFirstPost: "Automatically open a form to write a description when you
attempt to post files without a description"
_emojiModPerm:
unauthorized: "None"
@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)"

View File

@ -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: 編集履歴

View File

@ -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チートシート"

View File

@ -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:

View File

@ -59,7 +59,6 @@ remove: "ಅಳಿಸು"
smtpUser: "ಬಳಕೆಹೆಸರು"
smtpPass: "ಗುಪ್ತಪದ"
user: "ಬಳಕೆದಾರ"
searchByGoogle: "ಹುಡುಕು"
file: "ಕಡತಗಳು"
_email:
_follow:

View File

@ -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} 에게 기부하기'

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -497,7 +497,6 @@ smtpPass: "Senha"
clearCache: "Limpar memória transitória"
info: "Informações"
user: "Usuários"
searchByGoogle: "Buscar"
file: "Ficheiros"
_email:
_follow:

View File

@ -692,7 +692,6 @@ user: "Utilizatori"
administration: "Gestionare"
middle: "Mediu"
sent: "Trimite"
searchByGoogle: "Caută"
file: "Fișiere"
_email:
_follow:

View File

@ -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}, чтобы

View File

@ -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á"

View File

@ -268,7 +268,6 @@ smtpUser: "Användarnamn"
smtpPass: "Lösenord"
clearCache: "Rensa cache"
user: "Användare"
searchByGoogle: "Sök"
file: "Filer"
_email:
_follow:

View File

@ -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"

View File

@ -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

View File

@ -1,6 +1,5 @@
---
_lang_: "ياپونچە"
search: "ئىزدەش"
searchByGoogle: "ئىزدەش"
_mfm:
search: "ئىزدەش"

View File

@ -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 медіа"

View File

@ -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"

View File

@ -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: 媒体

View File

@ -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},以支援龐大的運營成本。

View File

@ -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"
}
}

View File

@ -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

View File

@ -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 }

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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"

View 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(),
}
}

View File

@ -0,0 +1,2 @@
pub mod environment;
pub mod server;

View 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);

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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;

View File

@ -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())
}
}
};
}

View File

@ -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))
}

View 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);
}
}

View 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,
))
}
}

View 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"
);
}
}

View 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:"));
}
}

View 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%"));
}
}

View 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)"
);
}
}

View 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) 📊");
}
}

View 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);
}
}

View 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,
}
}

View 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;

View 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), "일어냐다냥");
}
}

View 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());
}
}

View 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);
}
}

View File

@ -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")]

View File

@ -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>,

View File

@ -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,

View File

@ -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")]

View File

@ -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)]

View File

@ -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,

View File

@ -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,

View File

@ -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,
}

View File

@ -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>,

View File

@ -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")]

View File

@ -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,

View File

@ -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")]

View File

@ -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")]

View File

@ -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,

View File

@ -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