From 1548250360d32ee8d66ec1d3f320a1847cf2b65a Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 11:50:34 -0700 Subject: [PATCH 01/37] feat: :zap: cache server --- .config/example.yml | 14 ++++++++++++++ README.md | 9 ++++++++- packages/backend/src/config/types.ts | 10 ++++++++++ packages/backend/src/db/redis.ts | 20 ++++++++++++-------- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/.config/example.yml b/.config/example.yml index 51d380e7e7..ba74df8a59 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -67,6 +67,20 @@ redis: #db: 1 #user: default +# ┌─────────────────────────────┐ +#───┘ Cache server configuration └───────────────────────────────────── + +# A Redis-compatible server (DragonflyDB, Keydb, Redis) for caching +# If left blank, it will use the Redis server from above + +#cacheServer: + #host: localhost + #port: 6379 + #family: 0 # 0=Both, 4=IPv4, 6=IPv6 + #pass: example-pass + #prefix: example-prefix + #db: 1 + # Please configure either MeiliSearch *or* Sonic. # If both MeiliSearch and Sonic configurations are present, MeiliSearch will take precedence. diff --git a/README.md b/README.md index f66d14a324..0ad935667e 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,10 @@ If you have access to a server that supports one of the sources below, I recomme - 🦔 [Sonic](https://crates.io/crates/sonic-server) - [MeiliSearch](https://www.meilisearch.com/) - [ElasticSearch](https://www.elastic.co/elasticsearch/) - +- Caching server + - 🐲 At least [Dragonfly](https://www.dragonflydb.io/) v1.4.0 (recommended) + - 👻 [KeyDB](https://keydb.dev/) (untested) + - 🍱 Another [Redis](https://redis.io/) server, at least v6 ### 🏗️ Build dependencies - 🦀 At least [Rust](https://www.rust-lang.org/) v1.68.0 @@ -161,6 +164,10 @@ psql postgres -c "create database calckey with encoding = 'UTF8';" In Calckey's directory, fill out the `db` section of `.config/default.yml` with the correct information, where the `db` key is `calckey`. +## 💰 Caching server + +If you experience a lot of traffic, it's a good idea to set up another Redis-compatible caching server. If you don't set one one up, it'll falll back to the mandatory Redis server. + ## 🔎 Set up search ### 🦔 Sonic diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 84808413c0..43168662c4 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -26,6 +26,16 @@ export type Source = { user?: string; tls?: { [y: string]: string }; }; + cacheServer: { + host: string; + port: number; + family?: number; + pass?: string; + db?: number; + prefix?: string; + user?: string; + tls?: { [z: string]: string }; + }; elasticsearch: { host: string; port: number; diff --git a/packages/backend/src/db/redis.ts b/packages/backend/src/db/redis.ts index a1f3279f35..215effd8ea 100644 --- a/packages/backend/src/db/redis.ts +++ b/packages/backend/src/db/redis.ts @@ -2,15 +2,19 @@ import Redis from "ioredis"; import config from "@/config/index.js"; export function createConnection() { + let source = config.redis; + if (config.cacheServer) { + source = config.cacheServer; + } return new Redis({ - port: config.redis.port, - host: config.redis.host, - family: config.redis.family ?? 0, - password: config.redis.pass, - username: config.redis.user ?? "default", - keyPrefix: `${config.redis.prefix}:`, - db: config.redis.db || 0, - tls: config.redis.tls, + port: source.port, + host: source.host, + family: source.family ?? 0, + password: source.pass, + username: source.user ?? "default", + keyPrefix: `${source.prefix}:`, + db: source.db || 0, + tls: source.tls, }); } From 5aef784ecdb0b05379f1b3ae89977724c2b1c6ed Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 11:52:48 -0700 Subject: [PATCH 02/37] docs: :memo: dragonfly flag --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0ad935667e..d66560d0ea 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,8 @@ If you have access to a server that supports one of the sources below, I recomme - [ElasticSearch](https://www.elastic.co/elasticsearch/) - Caching server - 🐲 At least [Dragonfly](https://www.dragonflydb.io/) v1.4.0 (recommended) - - 👻 [KeyDB](https://keydb.dev/) (untested) - 🍱 Another [Redis](https://redis.io/) server, at least v6 + - 👻 [KeyDB](https://keydb.dev/) (untested) ### 🏗️ Build dependencies - 🦀 At least [Rust](https://www.rust-lang.org/) v1.68.0 @@ -166,7 +166,9 @@ In Calckey's directory, fill out the `db` section of `.config/default.yml` with ## 💰 Caching server -If you experience a lot of traffic, it's a good idea to set up another Redis-compatible caching server. If you don't set one one up, it'll falll back to the mandatory Redis server. +If you experience a lot of traffic, it's a good idea to set up another Redis-compatible caching server. If you don't set one one up, it'll fall back to the mandatory Redis server. + +For DragonflyDB, launch with the flag `--default_lua_flags='allow-undeclared-keys'`. ## 🔎 Set up search From 5fb2d9559814b9d4bee38c754164e15b271a7138 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 11:55:02 -0700 Subject: [PATCH 03/37] docs: :pencil2: dragonflydb typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d66560d0ea..9701bc86ef 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ If you have access to a server that supports one of the sources below, I recomme - [MeiliSearch](https://www.meilisearch.com/) - [ElasticSearch](https://www.elastic.co/elasticsearch/) - Caching server - - 🐲 At least [Dragonfly](https://www.dragonflydb.io/) v1.4.0 (recommended) + - 🐲 At least [DragonflyDB](https://www.dragonflydb.io/) v1.4.0 (recommended) - 🍱 Another [Redis](https://redis.io/) server, at least v6 - 👻 [KeyDB](https://keydb.dev/) (untested) ### 🏗️ Build dependencies From aa1482224c1ac04c912b519a8c03877ae74a7adb Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 12:25:54 -0700 Subject: [PATCH 04/37] fix: use unique key for my page query --- packages/client/src/pages/pages.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/pages/pages.vue b/packages/client/src/pages/pages.vue index 75a32ff295..a3a08be7cf 100644 --- a/packages/client/src/pages/pages.vue +++ b/packages/client/src/pages/pages.vue @@ -66,10 +66,10 @@ :pagination="myPagesPagination" > From e61b229229987329c69e91b5ed9722c82277d6cf Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 12:26:37 -0700 Subject: [PATCH 05/37] fix: use unique key for my galleries --- packages/client/src/pages/gallery/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/pages/gallery/index.vue b/packages/client/src/pages/gallery/index.vue index 66dc28d174..a4a09325c9 100644 --- a/packages/client/src/pages/gallery/index.vue +++ b/packages/client/src/pages/gallery/index.vue @@ -92,9 +92,9 @@ >
From 815917c3d16c5cac4c872444f4ad16edf1bea619 Mon Sep 17 00:00:00 2001 From: Kainoa Kanter Date: Thu, 6 Jul 2023 21:04:39 +0000 Subject: [PATCH 06/37] revert 6355bb604290a09a4a3b7c68b791234a0c1771ea revert build: :zap: build megalodon with swc --- packages/README.md | 1 - packages/megalodon/.swcrc | 19 ------------------- packages/megalodon/package.json | 9 ++------- pnpm-lock.yaml | 16 +++------------- 4 files changed, 5 insertions(+), 40 deletions(-) delete mode 100644 packages/megalodon/.swcrc diff --git a/packages/README.md b/packages/README.md index eeb5803f18..7d7c03e0b5 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,4 +7,3 @@ This directory contains all of the packages Calckey uses. - `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 - `calckey-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/calckey-js) for public use -- `megalodon`: TypeScript library used for Mastodon compatibility diff --git a/packages/megalodon/.swcrc b/packages/megalodon/.swcrc deleted file mode 100644 index c590064ecd..0000000000 --- a/packages/megalodon/.swcrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/swcrc", - "jsc": { - "parser": { - "syntax": "typescript", - "dynamicImport": true, - "decorators": true - }, - "transform": { - "decoratorMetadata": true - }, - "target": "es2022" - }, - "minify": false, - "module": { - "type": "commonjs", - "strict": true - } -} diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json index 6de3076aad..43479b2e73 100644 --- a/packages/megalodon/package.json +++ b/packages/megalodon/package.json @@ -4,7 +4,7 @@ "main": "./lib/src/index.js", "typings": "./lib/src/index.d.ts", "scripts": { - "build": "pnpm swc src -d built -D", + "build": "tsc -p ./", "lint": "eslint --ext .js,.ts src", "doc": "typedoc --out ../docs ./src", "test": "NODE_ENV=test jest -u --maxWorkers=3" @@ -49,8 +49,6 @@ "async-lock": "1.4.0" }, "devDependencies": { - "@swc/cli": "^0.1.62", - "@swc/core": "^1.3.62", "@types/core-js": "^2.5.0", "@types/form-data": "^2.5.0", "@types/jest": "^29.4.0", @@ -79,8 +77,5 @@ "directories": { "lib": "lib", "test": "test" - }, - "optionalDependencies": { - "@swc/core-android-arm64": "1.3.11" - } + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fc168cf1d..c5e7f1fada 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -789,7 +789,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b + version: github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -970,17 +970,7 @@ importers: ws: specifier: 8.12.0 version: 8.12.0 - optionalDependencies: - '@swc/core-android-arm64': - specifier: 1.3.11 - version: 1.3.11 devDependencies: - '@swc/cli': - specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62)(chokidar@3.3.1) - '@swc/core': - specifier: ^1.3.62 - version: 1.3.62 '@types/async-lock': specifier: 1.4.0 version: 1.4.0 @@ -17444,8 +17434,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/15fd9504f943763a057ff803ee2009ec0524c96b} + github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/9d16541664dc8fef3201ae9b647477070676a52e} name: emojilib version: 3.0.10 dev: true From c51e5074cf5449151554a60898b965096ec6c6e3 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Thu, 6 Jul 2023 17:06:31 -0400 Subject: [PATCH 07/37] fix: use host as prefix of cacheServer if undefined --- packages/backend/src/config/load.ts | 2 ++ packages/backend/src/config/types.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index 9b8ee5edbb..fa98789554 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -55,6 +55,8 @@ export default function load() { mixin.clientEntry = clientManifest["src/init.ts"]; if (!config.redis.prefix) config.redis.prefix = mixin.host; + if (config.cacheServer && !config.cacheServer.prefix) + config.cacheServer.prefix = mixin.host; return Object.assign(config, mixin); } diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 43168662c4..7789c26e07 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -26,7 +26,7 @@ export type Source = { user?: string; tls?: { [y: string]: string }; }; - cacheServer: { + cacheServer?: { host: string; port: number; family?: number; From f5edaaf130eebe4322358f4c334a8e262c4328c6 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Thu, 6 Jul 2023 17:22:15 -0400 Subject: [PATCH 08/37] perf: use msgpackr to encode and decode --- packages/backend/package.json | 4 ++-- packages/backend/src/misc/cache.ts | 2 +- pnpm-lock.yaml | 11 +++-------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index 0600644899..ec6451f61c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -28,13 +28,11 @@ "@bull-board/api": "5.2.0", "@bull-board/koa": "5.2.0", "@bull-board/ui": "5.2.0", - "megalodon": "workspace:*", "@discordapp/twemoji": "14.1.2", "@elastic/elasticsearch": "7.17.0", "@koa/cors": "3.4.3", "@koa/multer": "3.0.2", "@koa/router": "9.0.1", - "@msgpack/msgpack": "3.0.0-beta2", "@peertube/http-signature": "1.7.0", "@redocly/openapi-core": "1.0.0-beta.120", "@sinonjs/fake-timers": "9.1.2", @@ -87,9 +85,11 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "koa-views": "7.0.2", + "megalodon": "workspace:*", "meilisearch": "0.33.0", "mfm-js": "0.23.3", "mime-types": "2.1.35", + "msgpackr": "1.9.5", "multer": "1.4.4-lts.1", "native-utils": "link:native-utils", "nested-property": "4.0.0", diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index fe68908e57..913258f05a 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -1,5 +1,5 @@ import { redisClient } from "@/db/redis.js"; -import { encode, decode } from "@msgpack/msgpack"; +import { encode, decode } from "msgpackr"; import { ChainableCommander } from "ioredis"; export class Cache { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fc168cf1d..b9522c4346 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,9 +105,6 @@ importers: '@koa/router': specifier: 9.0.1 version: 9.0.1 - '@msgpack/msgpack': - specifier: 3.0.0-beta2 - version: 3.0.0-beta2 '@peertube/http-signature': specifier: 1.7.0 version: 1.7.0 @@ -276,6 +273,9 @@ importers: mime-types: specifier: 2.1.35 version: 2.1.35 + msgpackr: + specifier: 1.9.5 + version: 1.9.5 multer: specifier: 1.4.4-lts.1 version: 1.4.4-lts.1 @@ -2607,11 +2607,6 @@ packages: os-filter-obj: 2.0.0 dev: true - /@msgpack/msgpack@3.0.0-beta2: - resolution: {integrity: sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw==} - engines: {node: '>= 14'} - dev: false - /@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.2: resolution: {integrity: sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==} cpu: [arm64] From 3705a1ecb17982068f6fdc8cefe37db09490bd56 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Thu, 6 Jul 2023 17:49:41 -0400 Subject: [PATCH 09/37] refactor: cache relays for a longer time --- packages/backend/src/services/relay.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/services/relay.ts b/packages/backend/src/services/relay.ts index 6f7829c218..e969d783a0 100644 --- a/packages/backend/src/services/relay.ts +++ b/packages/backend/src/services/relay.ts @@ -15,7 +15,7 @@ import { createSystemUser } from "./create-system-user.js"; const ACTOR_USERNAME = "relay.actor" as const; -const relaysCache = new Cache("relay", 60 * 10); +const relaysCache = new Cache("relay", 60 * 60); export async function getRelayActor(): Promise { const user = await Users.findOneBy({ From 1ad0eec00d48a3b50ed8e068aa86688ac2419e26 Mon Sep 17 00:00:00 2001 From: Kainoa Kanter Date: Thu, 6 Jul 2023 21:53:44 +0000 Subject: [PATCH 10/37] revert 49fd4034744f7642210bb66a3558d544d67e13b8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit revert fix: 🐛 fix quotes with CW-only quotes --- .../backend/src/server/activitypub/outbox.ts | 2 +- packages/backend/src/services/note/create.ts | 28 ++++++++++++++----- packages/client/src/components/MkNote.vue | 1 - 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts index 469bd62eca..e0a380ffb6 100644 --- a/packages/backend/src/server/activitypub/outbox.ts +++ b/packages/backend/src/server/activitypub/outbox.ts @@ -138,7 +138,7 @@ export async function packActivity(note: Note): Promise { ) { const renote = await Notes.findOneByOrFail({ id: note.renoteId }); return renderAnnounce( - renote.uri ?? `${config.url}/notes/${renote.id}`, + renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`, note, ); } diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 12c5015330..095c75f427 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -67,7 +67,6 @@ import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; import meilisearch from "../../db/meilisearch.js"; import { redisClient } from "@/db/redis.js"; import { Mutex } from "redis-semaphore"; -import { packActivity } from "@/server/activitypub/outbox.js"; const mutedWordsCache = new Cache< { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] @@ -597,13 +596,9 @@ export default async ( }); //#region AP deliver - if ( - Users.isLocalUser(user) && - !data.localOnly && - !dontFederateInitially - ) { + if (Users.isLocalUser(user) && !dontFederateInitially) { (async () => { - const noteActivity = renderActivity(await packActivity(note)); + const noteActivity = await renderNoteOrRenoteActivity(data, note); const dm = new DeliverManager(user, noteActivity); // メンションされたリモートユーザーに配送 @@ -660,6 +655,25 @@ export default async ( await index(note, false); }); +async function renderNoteOrRenoteActivity(data: Option, note: Note) { + if (data.localOnly) return null; + + const content = + data.renote && + data.text == null && + data.poll == null && + (data.files == null || data.files.length === 0) + ? renderAnnounce( + data.renote.uri + ? data.renote.uri + : `${config.url}/notes/${data.renote.id}`, + note, + ) + : renderCreate(await renderNote(note, false), note); + + return renderActivity(content); +} + function incRenoteCount(renote: Note) { Notes.createQueryBuilder() .update() diff --git a/packages/client/src/components/MkNote.vue b/packages/client/src/components/MkNote.vue index a7ed284800..a1a519f79f 100644 --- a/packages/client/src/components/MkNote.vue +++ b/packages/client/src/components/MkNote.vue @@ -328,7 +328,6 @@ if (noteViewInterruptors.length > 0) { const isRenote = note.renote != null && note.text == null && - note.cw == null && note.fileIds.length === 0 && note.poll == null; From b28a1c97cbd4c0afb51da94407d180d4cee86a2c Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 17:29:29 -0700 Subject: [PATCH 12/37] =?UTF-8?q?docs:=20=F0=9F=93=9D=20KeyDB,=20megalodon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++---- packages/README.md | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9701bc86ef..4a58a27095 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,8 @@ If you have access to a server that supports one of the sources below, I recomme - [ElasticSearch](https://www.elastic.co/elasticsearch/) - Caching server - 🐲 At least [DragonflyDB](https://www.dragonflydb.io/) v1.4.0 (recommended) + - 👻 At least [KeyDB](https://keydb.dev/) v6.3.3 - 🍱 Another [Redis](https://redis.io/) server, at least v6 - - 👻 [KeyDB](https://keydb.dev/) (untested) ### 🏗️ Build dependencies - 🦀 At least [Rust](https://www.rust-lang.org/) v1.68.0 @@ -166,9 +166,7 @@ In Calckey's directory, fill out the `db` section of `.config/default.yml` with ## 💰 Caching server -If you experience a lot of traffic, it's a good idea to set up another Redis-compatible caching server. If you don't set one one up, it'll fall back to the mandatory Redis server. - -For DragonflyDB, launch with the flag `--default_lua_flags='allow-undeclared-keys'`. +If you experience a lot of traffic, it's a good idea to set up another Redis-compatible caching server. If you don't set one one up, it'll fall back to the mandatory Redis server. DragonflyDB is the recommended option due to its unrivaled performance and ease of use. ## 🔎 Set up search diff --git a/packages/README.md b/packages/README.md index 7d7c03e0b5..0ed7c64039 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,3 +7,4 @@ This directory contains all of the packages Calckey uses. - `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 - `calckey-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/calckey-js) for public use +- `megalodon`: TypeScript library used for partial Mastodon API compatibility From 7e77819c692b7d8309204b00247d6daa6adea682 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Thu, 6 Jul 2023 17:44:32 -0700 Subject: [PATCH 13/37] fix: :children_crossing: switch account when adding existing account --- packages/client/src/account.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/account.ts b/packages/client/src/account.ts index 6d858292a5..ea17387fab 100644 --- a/packages/client/src/account.ts +++ b/packages/client/src/account.ts @@ -162,7 +162,7 @@ export async function openAccountMenu( { done: (res) => { addAccount(res.id, res.i); - success(); + switchAccountWithToken(res.i); }, }, "closed", From 86d595387053e8503653fe307c1486caba364191 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Thu, 6 Jul 2023 22:54:53 -0400 Subject: [PATCH 14/37] fix: add megalodon to docker image --- .dockerignore | 14 ++++---------- Dockerfile | 7 +++---- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/.dockerignore b/.dockerignore index 90d15ddd90..ad6ad169ae 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,12 +1,8 @@ # Visual Studio Code -/.vscode -!/.vscode/extensions.json +.vscode # Intelij-IDEA -/.idea -packages/backend/.idea/backend.iml -packages/backend/.idea/modules.xml -packages/backend/.idea/vcs.xml +.idea # Node.js node_modules @@ -14,7 +10,7 @@ node_modules report.*.json # Rust -packages/backend/native-utils/target/* +packages/backend/native-utils/target # Cypress cypress/screenshots @@ -24,9 +20,7 @@ cypress/videos coverage # config -/.config/* -!/.config/example.yml -!/.config/docker_example.env +/.config # misskey built diff --git a/Dockerfile b/Dockerfile index e11cb2bf44..823f78caa0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,7 @@ COPY packages/backend/package.json packages/backend/package.json COPY packages/client/package.json packages/client/package.json COPY packages/sw/package.json packages/sw/package.json COPY packages/calckey-js/package.json packages/calckey-js/package.json +COPY packages/megalodon/package.json packages/megalodon/package.json COPY packages/backend/native-utils/package.json packages/backend/native-utils/package.json COPY packages/backend/native-utils/npm/linux-x64-musl/package.json packages/backend/native-utils/npm/linux-x64-musl/package.json COPY packages/backend/native-utils/npm/linux-arm64-musl/package.json packages/backend/native-utils/npm/linux-arm64-musl/package.json @@ -29,10 +30,7 @@ COPY packages/backend/native-utils/npm/linux-arm64-musl/package.json packages/ba RUN corepack enable && corepack prepare pnpm@latest --activate && pnpm i --frozen-lockfile # Copy in the rest of the native-utils rust files -COPY packages/backend/native-utils/.cargo packages/backend/native-utils/.cargo -COPY packages/backend/native-utils/build.rs packages/backend/native-utils/ -COPY packages/backend/native-utils/src packages/backend/native-utils/src/ -COPY packages/backend/native-utils/migration/src packages/backend/native-utils/migration/src/ +COPY packages/backend/native-utils packages/backend/native-utils/ # Compile native-utils RUN pnpm run --filter native-utils build @@ -59,6 +57,7 @@ COPY --from=build /calckey/packages/backend/node_modules /calckey/packages/backe COPY --from=build /calckey/packages/sw/node_modules /calckey/packages/sw/node_modules COPY --from=build /calckey/packages/client/node_modules /calckey/packages/client/node_modules COPY --from=build /calckey/packages/calckey-js/node_modules /calckey/packages/calckey-js/node_modules +COPY --from=build /calckey/packages/megalodon/node_modules /calckey/packages/megalodon/node_modules # Copy the finished compiled files COPY --from=build /calckey/built /calckey/built From bcb8ceadc73ad26a8ffdbf0fd6c3a9e6f2180dbc Mon Sep 17 00:00:00 2001 From: Kainoa Kanter Date: Fri, 7 Jul 2023 05:44:22 +0000 Subject: [PATCH 15/37] =?UTF-8?q?docs:=20=F0=9F=93=9D=20simplify=20depende?= =?UTF-8?q?ncies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4a58a27095..2e6907e306 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,6 @@ If you have access to a server that supports one of the sources below, I recomme ## 🧑‍💻 Dependencies - 🐢 At least [NodeJS](https://nodejs.org/en/) v18.16.0 (v20 recommended) - - Install with [nvm](https://github.com/nvm-sh/nvm) - 🐘 At least [PostgreSQL](https://www.postgresql.org/) v12 (v14 recommended) - 🍱 At least [Redis](https://redis.io/) v6 (v7 recommended) - Web Proxy (one of the following) @@ -104,10 +103,11 @@ If you have access to a server that supports one of the sources below, I recomme - 🦔 [Sonic](https://crates.io/crates/sonic-server) - [MeiliSearch](https://www.meilisearch.com/) - [ElasticSearch](https://www.elastic.co/elasticsearch/) -- Caching server - - 🐲 At least [DragonflyDB](https://www.dragonflydb.io/) v1.4.0 (recommended) - - 👻 At least [KeyDB](https://keydb.dev/) v6.3.3 - - 🍱 Another [Redis](https://redis.io/) server, at least v6 +- Caching server (one of the following) + - 🐲 [DragonflyDB](https://www.dragonflydb.io/) (recommended) + - 👻 [KeyDB](https://keydb.dev/) + - 🍱 Another [Redis](https://redis.io/) server + ### 🏗️ Build dependencies - 🦀 At least [Rust](https://www.rust-lang.org/) v1.68.0 From 430390e93008e9b0cfb2ebdbbe7fdbfcb1487d03 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Fri, 7 Jul 2023 02:46:50 -0400 Subject: [PATCH 16/37] fix: copy megalodon before node_modules, fix #10424 --- Dockerfile | 3 ++- scripts/clean-all.js | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 823f78caa0..744dba2115 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,13 +51,14 @@ RUN apk add --no-cache --no-progress tini ffmpeg vips-dev zip unzip nodejs-curre COPY . ./ +COPY --from=build /calckey/packages/megalodon /calckey/packages/megalodon + # Copy node modules COPY --from=build /calckey/node_modules /calckey/node_modules COPY --from=build /calckey/packages/backend/node_modules /calckey/packages/backend/node_modules COPY --from=build /calckey/packages/sw/node_modules /calckey/packages/sw/node_modules COPY --from=build /calckey/packages/client/node_modules /calckey/packages/client/node_modules COPY --from=build /calckey/packages/calckey-js/node_modules /calckey/packages/calckey-js/node_modules -COPY --from=build /calckey/packages/megalodon/node_modules /calckey/packages/megalodon/node_modules # Copy the finished compiled files COPY --from=build /calckey/built /calckey/built diff --git a/scripts/clean-all.js b/scripts/clean-all.js index c5fc658499..47aaec25c0 100644 --- a/scripts/clean-all.js +++ b/scripts/clean-all.js @@ -46,6 +46,14 @@ const { join } = require("node:path"); recursive: true, force: true, }); + fs.rmSync(join(__dirname, "/../packages/megalodon/built"), { + recursive: true, + force: true, + }); + fs.rmSync(join(__dirname, "/../packages/megalodon/node_modules"), { + recursive: true, + force: true, + }); fs.rmSync(join(__dirname, "/../built"), { recursive: true, force: true }); fs.rmSync(join(__dirname, "/../node_modules"), { From b75c935eb8814abdaba8780a1c3fbb23f8404223 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Fri, 7 Jul 2023 02:53:10 -0400 Subject: [PATCH 17/37] chore: add megalodon to cleaning scripts --- scripts/clean-all.js | 2 +- scripts/clean.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/clean-all.js b/scripts/clean-all.js index 47aaec25c0..4320aae2d4 100644 --- a/scripts/clean-all.js +++ b/scripts/clean-all.js @@ -46,7 +46,7 @@ const { join } = require("node:path"); recursive: true, force: true, }); - fs.rmSync(join(__dirname, "/../packages/megalodon/built"), { + fs.rmSync(join(__dirname, "/../packages/megalodon/lib"), { recursive: true, force: true, }); diff --git a/scripts/clean.js b/scripts/clean.js index 39cbc77b90..727ddb66fb 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -23,5 +23,9 @@ const { join } = require("node:path"); recursive: true, force: true, }); + fs.rmSync(join(__dirname, "/../packages/megalodon/lib"), { + recursive: true, + force: true, + }); fs.rmSync(join(__dirname, "/../built"), { recursive: true, force: true }); })(); From 1166e8814950f0328b63cce0ba244c1ba8580887 Mon Sep 17 00:00:00 2001 From: naskya Date: Thu, 6 Jul 2023 15:39:55 +0000 Subject: [PATCH 18/37] chore: Translated using Weblate (Japanese) Currently translated at 100.0% (1816 of 1816 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ja/ --- locales/ja-JP.yml | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 9f2f825e55..05c4f3ab30 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1064,6 +1064,7 @@ _aboutMisskey: donate: "Calckeyに寄付" morePatrons: "他にも多くの方が支援してくれています。ありがとうございます! 🥰" patrons: "支援者" + patronsList: 寄付額ではなく時系列順に並んでいます。上記のリンクから寄付を行ってここにあなたのIDを載せましょう! _nsfw: respect: "閲覧注意のメディアは隠す" ignore: "閲覧注意のメディアを隠さない" @@ -1375,11 +1376,12 @@ _permissions: _auth: shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" shareAccessAsk: "アカウントへのアクセスを許可しますか?" - permissionAsk: "このアプリケーションは次の権限を要求しています" + permissionAsk: "このアプリケーションは次の権限を要求しています:" pleaseGoBack: "アプリケーションに戻り続行してください" callback: "アプリケーションに戻っています" denied: "アクセスを拒否しました" - copyAsk: "以下の認証コードをアプリケーションにコピーしてください" + copyAsk: "以下の認証コードをアプリケーションにコピーしてください:" + allPermissions: 全てのアクセス権 _antennaSources: all: "全ての投稿" homeTimeline: "フォローしているユーザーの投稿" @@ -1453,11 +1455,11 @@ _poll: remainingSeconds: "終了まであと{s}秒" _visibility: public: "公開" - publicDescription: "全てのユーザーに公開" + publicDescription: "全ての公開タイムラインに配信されます" home: "未収載" homeDescription: "ホームタイムラインのみに公開" followers: "フォロワー" - followersDescription: "自分のフォロワーのみに公開" + followersDescription: "フォロワーと会話相手のみに公開" specified: "ダイレクト" specifiedDescription: "指定したユーザーのみに公開" localOnly: "ローカルのみ" @@ -1890,14 +1892,14 @@ hiddenTags: 非表示にするハッシュタグ apps: "アプリ" _experiments: title: 試験的な機能 - postImportsCaption: + postImportsCaption: ユーザーが過去の投稿をCalckey・Misskey・Mastodon・Akkoma・Pleromaからインポートすることを許可します。キューが溜まっているときにインポートするとサーバーに負荷がかかる可能性があります。 enablePostImports: 投稿のインポートを有効にする sendModMail: モデレーション通知を送る deleted: 削除済み editNote: 投稿を編集 edited: '編集済み: {date} {time}' -signupsDisabled: +signupsDisabled: 現在、このサーバーでは新規登録が一般開放されていません。招待コードをお持ちの場合には、以下の欄に入力してください。招待コードをお持ちでない場合にも、新規登録を開放している他のサーバーには入れますよ! findOtherInstance: 他のサーバーを探す newer: 新しい投稿 @@ -1932,3 +1934,14 @@ isBot: このアカウントはBotです isLocked: このアカウントのフォローは承認制です isAdmin: 管理者 isPatron: Calckey 後援者 +_skinTones: + light: ペールオレンジ + mediumLight: ミディアムライト + medium: ミディアム + mediumDark: ミディアムダーク + yellow: 黄色 + dark: 茶色 +removeReaction: リアクションを取り消す +alt: 代替テキスト +swipeOnMobile: ページ間のスワイプを有効にする +reactionPickerSkinTone: 優先する絵文字のスキン色 From 9d9e069588264c6eeec3b8b313a57cd6c7dc0e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AA=A0=E8=AA=A0-ChengCheng?= Date: Thu, 6 Jul 2023 17:24:43 +0000 Subject: [PATCH 19/37] chore: Translated using Weblate (Chinese (Traditional)) Currently translated at 94.3% (1714 of 1816 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/zh_Hant/ --- locales/zh-TW.yml | 139 ++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 66 deletions(-) diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index b576c6b60b..3e5b6690ad 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1,6 +1,6 @@ _lang_: "繁體中文" headlineMisskey: "貼文連繫網路" -introMisskey: "歡迎! Calckey是一個免費,開放原碼,去中心化的社群網路🚀" +introMisskey: "歡迎! Calckey是一個開源、去中心化且永遠免費的社群網路平台!🚀" monthAndDay: "{month}月 {day}日" search: "搜尋" notifications: "通知" @@ -21,7 +21,7 @@ basicSettings: "基本設定" otherSettings: "其他設定" openInWindow: "在新視窗開啟" profile: "個人檔案" -timeline: "時間軸" +timeline: "時間線" noAccountDescription: "此用戶還沒有自我介紹。" login: "登入" loggingIn: "登入中" @@ -31,7 +31,7 @@ uploading: "上傳中..." save: "儲存" users: "使用者" addUser: "新增使用者" -favorite: "我的最愛" +favorite: "添加至我的最愛" favorites: "我的最愛" unfavorite: "從我的最愛中移除" favorited: "已添加至我的最愛。" @@ -43,7 +43,7 @@ copyContent: "複製內容" copyLink: "複製連結" delete: "刪除" deleteAndEdit: "刪除並編輯" -deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有情感、轉發和回覆也將會消失。" +deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有反應、轉發和回覆也會消失。" addToList: "加入至清單" sendMessage: "發送訊息" copyUsername: "複製使用者名稱" @@ -64,7 +64,7 @@ export: "匯出" files: "檔案" download: "下載" driveFileDeleteConfirm: "確定要刪除檔案「{name}」嗎?使用此附件的貼文也會跟著消失。" -unfollowConfirm: "確定要取消追隨{name}嗎?" +unfollowConfirm: "確定要取消追隨 「{name}」 嗎?" exportRequested: "已請求匯出。這可能會花一點時間。結束後檔案將會被放到雲端裡。" importRequested: "已請求匯入。這可能會花一點時間。" lists: "清單" @@ -95,9 +95,9 @@ followRequestPending: "追隨許可批准中" enterEmoji: "輸入表情符號" renote: "轉發" unrenote: "取消轉發" -renoted: "已轉傳。" +renoted: "已轉發。" cantRenote: "無法轉發此貼文。" -cantReRenote: "無法轉傳之前已經轉傳過的內容。" +cantReRenote: "無法轉發之前已經轉發過的內容。" quote: "引用" pinnedNote: "已置頂的貼文" pinned: "置頂" @@ -105,7 +105,7 @@ you: "您" clickToShow: "按一下以顯示" sensitive: "敏感內容" add: "新增" -reaction: "情感" +reaction: "反應" enableEmojiReaction: "啟用表情符號反應" showEmojisInReactionNotifications: "在反應通知中顯示表情符號" reactionSetting: "在選擇器中顯示反應" @@ -140,14 +140,14 @@ emojiUrl: "表情符號URL" addEmoji: "加入表情符號" settingGuide: "推薦設定" cacheRemoteFiles: "快取遠端檔案" -cacheRemoteFilesDescription: "禁用此設定會停止遠端檔案的緩存,從而節省儲存空間,但資料會因直接連線從而產生額外連接數據。" -flagAsBot: "此使用者是機器人" +cacheRemoteFilesDescription: "禁用此設定會停止遠端檔案的緩存,從而節省儲存空間,但資料會因直接連線從而產生額外數據花費。" +flagAsBot: "標記此帳號是機器人" flagAsBotDescription: "如果本帳戶是由程式控制,請啟用此選項。啟用後,會作為標示幫助其他開發者防止機器人之間產生無限互動的行為,並會調整Calckey內部系統將本帳戶識別為機器人。" -flagAsCat: "此使用者是貓" +flagAsCat: "你是喵咪嗎?w😺" flagAsCatDescription: "如果想將本帳戶標示為一隻貓,請開啟此標示!" -flagShowTimelineReplies: "在時間軸上顯示貼文的回覆" +flagShowTimelineReplies: "在時間線上顯示貼文的回覆" flagShowTimelineRepliesDescription: "啟用時,時間線除了顯示用戶的貼文以外,還會顯示用戶對其他貼文的回覆。" -autoAcceptFollowed: "自動追隨中使用者的追隨請求" +autoAcceptFollowed: "自動准予追隨中使用者的追隨請求" addAccount: "添加帳戶" loginFailed: "登入失敗" showOnRemote: "轉到所在伺服器顯示" @@ -157,7 +157,7 @@ setWallpaper: "設定桌布" removeWallpaper: "移除桌布" searchWith: "搜尋: {q}" youHaveNoLists: "你沒有任何清單" -followConfirm: "你真的要追隨{name}嗎?" +followConfirm: "你真的要追隨 「{name}」 嗎?" proxyAccount: "代理帳戶" proxyAccountDescription: "代理帳戶是在某些情況下充當其他伺服器用戶的帳戶。例如,當使用者將一個來自其他伺服器的帳戶放在列表中時,由於沒有其他使用者追蹤該帳戶,該指令不會傳送到該伺服器上,因此會由代理帳戶追蹤。" host: "主機" @@ -166,7 +166,7 @@ recipient: "收件人" annotation: "註解" federation: "站台聯邦" instances: "伺服器" -registeredAt: "初次觀測" +registeredAt: "初次註冊" latestRequestSentAt: "上次發送的請求" latestRequestReceivedAt: "上次收到的請求" latestStatus: "最後狀態" @@ -234,19 +234,19 @@ lookup: "查詢" announcements: "公告" imageUrl: "圖片URL" remove: "刪除" -removed: "已刪除" +removed: "已成功刪除" removeAreYouSure: "確定要刪掉「{x}」嗎?" deleteAreYouSure: "確定要刪掉「{x}」嗎?" resetAreYouSure: "確定要重設嗎?" saved: "已儲存" -messaging: "傳送訊息" +messaging: "訊息" upload: "上傳" keepOriginalUploading: "保留原圖" -keepOriginalUploadingDescription: "上傳圖片時保留原始圖片。關閉時,瀏覽器會在上傳時生成一張用於web發布的圖片。" +keepOriginalUploadingDescription: "上傳圖片時保留原始圖片。關閉時,瀏覽器會在上傳時自動產生用於貼文發布的圖片。" fromDrive: "從雲端空間" -fromUrl: "從URL" +fromUrl: "從網址" uploadFromUrl: "從網址上傳" -uploadFromUrlDescription: "您要上傳的文件的URL" +uploadFromUrlDescription: "您要上傳的文件的網址" uploadFromUrlRequested: "已請求上傳" uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。" explore: "探索" @@ -258,7 +258,7 @@ agreeTo: "我同意{0}" tos: "使用條款" start: "開始" home: "首頁" -remoteUserCaution: "由於該使用者來自遠端實例,因此資訊可能非即時的。" +remoteUserCaution: "由於該使用者來自遠端實例,因此資料可能是非即時的。" activity: "動態" images: "圖片" birthday: "生日" @@ -267,12 +267,12 @@ registeredDate: "註冊日期" location: "位置" theme: "外觀主題" themeForLightMode: "在淺色模式下使用的主題" -themeForDarkMode: "在黑暗模式下使用的主題" +themeForDarkMode: "在闇黑模式下使用的主題" light: "淺色" -dark: "黑暗" +dark: "闇黑" lightThemes: "明亮主題" -darkThemes: "黑暗主題" -syncDeviceDarkMode: "將黑暗模式與設備設置同步" +darkThemes: "闇黑主題" +syncDeviceDarkMode: "闇黑模式使用裝置設定" drive: "雲端硬碟" fileName: "檔案名稱" selectFile: "選擇檔案" @@ -281,19 +281,19 @@ selectFolder: "選擇資料夾" selectFolders: "選擇資料夾" renameFile: "重新命名檔案" folderName: "資料夾名稱" -createFolder: "新增資料夾" +createFolder: "創建資料夾" renameFolder: "重新命名資料夾" deleteFolder: "刪除資料夾" addFile: "加入附件" -emptyDrive: "雲端硬碟為空" -emptyFolder: "資料夾為空" +emptyDrive: "你的雲端硬碟沒有任何東西( ̄▽ ̄)\"" +emptyFolder: "資料夾裡面沒有東西(⊙_⊙;)" unableToDelete: "無法刪除" inputNewFileName: "輸入檔案名稱" inputNewDescription: "請輸入新標題" inputNewFolderName: "輸入新資料夾的名稱" circularReferenceFolder: "目標文件夾是您要移動的文件夾的子文件夾。" hasChildFilesOrFolders: "此文件夾不是空的,無法刪除。" -copyUrl: "複製URL" +copyUrl: "複製網址" rename: "重新命名" avatar: "大頭貼" banner: "橫幅" @@ -304,7 +304,7 @@ reload: "重新整理" doNothing: "無視" reloadConfirm: "確定要重新整理嗎?" watch: "關注" -unwatch: "取消追隨" +unwatch: "取消關注" accept: "接受" reject: "拒絕" normal: "正常" @@ -312,7 +312,7 @@ instanceName: "伺服器名稱" instanceDescription: "伺服器說明" maintainerName: "管理員名稱" maintainerEmail: "管理員郵箱" -tosUrl: "服務條款URL" +tosUrl: "服務條款網址" thisYear: "本年" thisMonth: "本月" today: "本日" @@ -323,23 +323,23 @@ pages: "頁面" integration: "整合" connectService: "己連結" disconnectService: "己斷開" -enableLocalTimeline: "開啟本地時間軸" -enableGlobalTimeline: "啟用公開時間軸" -disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。" +enableLocalTimeline: "開啟本地時間線" +enableGlobalTimeline: "啟用公開時間線" +disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和版主始終可以訪問所有的時間線。" registration: "註冊" enableRegistration: "開啟新使用者註冊" invite: "邀請" driveCapacityPerLocalAccount: "每個本地用戶的雲端空間大小" driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量" -inMb: "以Mbps為單位" -iconUrl: "圖像URL" -bannerUrl: "橫幅圖像URL" +inMb: "以MB為單位" +iconUrl: "圖標網址" +bannerUrl: "橫幅圖像網址" backgroundImageUrl: "背景圖片的來源網址" basicInfo: "基本資訊" pinnedUsers: "置頂用戶" -pinnedUsersDescription: "在「發現」頁面中使用換行標記想要置頂的使用者。" -pinnedPages: "釘選頁面" -pinnedPagesDescription: "輸入要固定至伺服器首頁的頁面路徑,以換行符分隔。" +pinnedUsersDescription: "在「探索」頁面中使用換行標記想要置頂的使用者。" +pinnedPages: "已釘選的頁面" +pinnedPagesDescription: "輸入要固定至伺服器首頁的頁面路徑,一行一個。" pinnedClipId: "置頂的摘錄ID" pinnedNotes: "已置頂的貼文" hcaptcha: "hCaptcha" @@ -482,7 +482,7 @@ promotion: "推廣" promote: "推廣" numberOfDays: "有效天數" hideThisNote: "隱藏此貼文" -showFeaturedNotesInTimeline: "在時間軸上顯示熱門推薦" +showFeaturedNotesInTimeline: "在時間線上顯示熱門推薦" objectStorage: "Object Storage (物件儲存)" useObjectStorage: "使用Object Storage" objectStorageBaseUrl: "根URL" @@ -502,7 +502,7 @@ objectStorageUseProxyDesc: "如果不使用代理進行API連接,請關閉" objectStorageSetPublicRead: "上傳時設定為\"public-read\"" serverLogs: "伺服器日誌" deleteAll: "刪除所有記錄" -showFixedPostForm: "於時間軸頁頂顯示「發送貼文」方框" +showFixedPostForm: "於時間線頁頂顯示「發送貼文」方框" newNoteRecived: "發現新的貼文" sounds: "音效" listen: "聆聽" @@ -661,8 +661,8 @@ repliedCount: "回覆數量" renotedCount: "轉發次數" followingCount: "正在跟隨的用戶數量" followersCount: "跟隨者數量" -sentReactionsCount: "情感發送次數" -receivedReactionsCount: "情感收到次數" +sentReactionsCount: "反應發送次數" +receivedReactionsCount: "反應收到次數" pollVotesCount: "已統計的投票數" pollVotedCount: "已投票數" yes: "確定" @@ -688,7 +688,7 @@ experimentalFeatures: "實驗中的功能" developer: "開發者" makeExplorable: "使自己的帳戶能夠在“探索”頁面中顯示" makeExplorableDescription: "如果關閉,帳戶將不會被顯示在\"探索\"頁面中。" -showGapBetweenNotesInTimeline: "分開顯示時間軸上的貼文" +showGapBetweenNotesInTimeline: "分開顯示時間線上的貼文" duplicate: "複製" left: "左" center: "置中" @@ -1089,8 +1089,8 @@ _wordMute: muteWords: "加入靜音文字" muteWordsDescription: "用空格分隔指定AND,用換行分隔指定OR。" muteWordsDescription2: "將關鍵字用斜線括起來表示正規表達式。" - softDescription: "隱藏時間軸中指定條件的貼文。" - hardDescription: "具有指定條件的貼文將不添加到時間軸。 即使您更改條件,未被添加的貼文也會被排除在外。" + softDescription: "隱藏時間線中指定條件的貼文。" + hardDescription: "具有指定條件的貼文將不添加到時間線。 即使您更改條件,未被添加的貼文也會被排除在外。" soft: "軟性靜音" hard: "硬性靜音" mutedNotes: "已靜音的貼文" @@ -1203,16 +1203,16 @@ _tutorial: step2_1: "首先,請完成你的個人資料。" step2_2: "通過提供一些關於你自己的資料,其他人會更容易了解他們是否想看到你的帖子或關注你。" step3_1: "現在是時候追隨一些人了!" - step3_2: "你的主頁和社交時間軸是基於你所追蹤的人,所以試著先追蹤幾個賬戶。\n點擊個人資料右上角的加號圈就可以關注它。" + step3_2: "你的主頁和社交時間線是基於你所追蹤的人,所以試著先追蹤幾個帳戶。\n點擊個人資料右上角的加號圈就可以關注它。" step4_1: "讓我們出去找你。" step4_2: "對於他們的第一條信息,有些人喜歡做 {introduction} 或一個簡單的 \"hello world!\"" - step5_1: "時間軸,到處都是時間軸!" - step5_2: "您的伺服器已啟用了{timelines}個時間軸。" - step5_3: "主 {icon} 時間軸是顯示你追蹤的帳號的帖子。" - step5_4: "本地 {icon} 時間軸是你可以看到伺服器中所有其他用戶的信息的時間軸。" - step5_5: "社交 {icon} 時間軸是顯示你的主時間軸 + 本地時間軸。" - step5_6: "推薦 {icon} 時間軸是顯示你的伺服器管理員推薦的帖文。" - step5_7: "全球 {icon} 時間軸是顯示來自所有其他連接的伺服器的帖文。" + step5_1: "時間線,到處都是時間線!" + step5_2: "您的伺服器已啟用了{timelines}個時間線。" + step5_3: "首頁 {icon} 時間線是顯示你追蹤的帳號的帖子。" + step5_4: "本地 {icon} 時間線是你可以看到伺服器中所有其他用戶的貼文的時間線。" + step5_5: "社交 {icon} 時間線是你的 首頁時間線 和 本地時間線 的結合體。" + step5_6: "推薦 {icon} 時間線是顯示你的伺服器管理員推薦的貼文。" + step5_7: "全球 {icon} 時間線是顯示來自所有其他連接的伺服器的貼文。" step6_1: "那麼,這裡是什麼地方?" step6_2: "你不只是加入Calckey。你已經加入了Fediverse的一個門戶,這是一個由成千上萬台服務器組成的互聯網絡。" step6_3: "每個服務器也有不同,而並不是所有的服務器都運行Calckey。但這個服務器確實是運行Calckey的! 你可能會覺得有點複雜,但你很快就會明白的。" @@ -1245,8 +1245,8 @@ _permissions: "write:notes": "撰寫或刪除貼文" "read:notifications": "查看通知" "write:notifications": "編輯通知" - "read:reactions": "查看情感" - "write:reactions": "編輯情感" + "read:reactions": "查看反應" + "write:reactions": "編輯反應" "write:votes": "投票" "read:pages": "顯示頁面" "write:pages": "編輯頁面" @@ -1284,7 +1284,7 @@ _weekday: _widgets: memo: "備忘錄" notifications: "通知" - timeline: "時間軸" + timeline: "時間線" calendar: "行事曆" trends: "發燒貼文" clock: "時鐘" @@ -1335,7 +1335,7 @@ _visibility: public: "公開" publicDescription: "發布給所有用戶" home: "不在主頁顯示" - homeDescription: "僅發送至首頁的時間軸" + homeDescription: "僅發送至首頁的時間線" followers: "追隨者" followersDescription: "僅發送至關注者" specified: "指定使用者" @@ -1403,7 +1403,7 @@ _instanceCharts: _timelines: home: "首頁" local: "本地" - social: "社群" + social: "社交" global: "公開" recommended: 推薦 _pages: @@ -1726,7 +1726,7 @@ _notification: pollEnded: "問卷調查結束" receiveFollowRequest: "已收到追隨請求" followRequestAccepted: "追隨請求已接受" - groupInvited: "加入社群邀請" + groupInvited: "群組加入邀請" app: "應用程式通知" _actions: followBack: "回關" @@ -1755,7 +1755,7 @@ _deck: main: "主列" widgets: "小工具" notifications: "通知" - tl: "時間軸" + tl: "時間線" antenna: "天線" list: "清單" mentions: "提及" @@ -1782,11 +1782,11 @@ enterSendsMessage: 在 Messaging 中按 Return 發送消息 (如關閉則是 Ctr migrationConfirm: "您確定要將你的帳戶遷移到 {account} 嗎? 一旦這樣做,你將無法復原,而你將無法再次正常使用您的帳戶。\n另外,請確保你已將此當前帳戶設置為您要遷移的帳戶。" customSplashIconsDescription: 每次用戶加載/重新加載頁面時,以換行符號分隔的自定啟動畫面圖標的網址將隨機顯示。請確保圖片位於靜態網址上,最好所有圖片解析度調整為 192x192。 -accountMoved: '該使用者已移至新帳戶:' +accountMoved: '該使用者已遷移至新帳戶:' showAds: 顯示廣告 noThankYou: 不用了,謝謝 selectInstance: 選擇伺服器 -enableRecommendedTimeline: 啟用推薦時間軸 +enableRecommendedTimeline: 啟用推薦時間線 antennaInstancesDescription: 分行列出一個伺服器 moveTo: 遷移此帳戶到新帳戶 moveToLabel: '請輸入你將會遷移到的帳戶:' @@ -1838,8 +1838,8 @@ pushNotification: 推送通知 subscribePushNotification: 啟用推送通知 unsubscribePushNotification: 禁用推送通知 pushNotificationAlreadySubscribed: 推送通知已經啟用 -recommendedInstancesDescription: 以每行分隔的推薦服務器出現在推薦的時間軸中。 不要添加 `https://`,只添加域名。 -searchPlaceholder: 搜尋 Calckey +recommendedInstancesDescription: 以每行分隔的推薦伺服器出現在推薦的時間線中。 不要添加 `https://`,只添加域名。 +searchPlaceholder: 在聯邦網路上搜尋 cw: 內容警告 selectChannel: 選擇一個頻道 newer: 較新 @@ -1848,3 +1848,10 @@ jumpToPrevious: 跳到上一個 removeReaction: 移除你的反應 listsDesc: 清單可以創建一個只有您指定用戶的時間線。 可以從時間線頁面訪問它們。 flagSpeakAsCatDescription: 在喵咪模式下你的貼文會被喵化ヾ(•ω•`)o +antennasDesc: "天線會顯示符合您設置條件的新貼文!\n 可以從時間線訪問它們。" +expandOnNoteClick: 點擊以打開貼文 +expandOnNoteClickDesc: 如果禁用,您仍然可以通過右鍵單擊菜單或單擊時間戳來打開貼文。 +hiddenTagsDescription: '列出您希望隱藏趨勢和探索的主題標籤(不帶 #)。 隱藏的主題標籤仍然可以通過其他方式發現。' +userSaysSomethingReasonQuote: '{name} 引用了一篇包含 {reason} 的貼文' +silencedInstancesDescription: 列出您想要靜音的伺服器的網址。 您列出的伺服器內的帳戶將被視為“沉默”,只能發出追隨請求,如果不追隨則不能提及本地帳戶。 + 這不會影響被阻止的伺服器。 From 5e6594d91d3738f3e5da6a60232e34ee13546fb5 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 18:58:24 +0200 Subject: [PATCH 20/37] [mastodon-client] Fail gracefully if user resolve fails --- packages/megalodon/src/misskey.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 5275c70f68..61464522a3 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1257,31 +1257,31 @@ export default class Misskey implements MegalodonInterface { } public async getMentions(text: string, cache: AccountCache): Promise { - console.log(`getting mentions for message: '${text}'`); const mentions :Entity.Mention[] = []; if (text == undefined) return mentions; - console.log('text is not undefined, continuing'); - const mentionMatch = text.matchAll(/(?<=^|\s)@(?.*?)(?:@(?.*?)|)(?=\s|$)/g); for (const m of mentionMatch) { - if (m.groups == null) - continue; + try { + if (m.groups == null) + continue; - const account = await this.getAccountByNameCached(m.groups.user, m.groups.host, cache); + const account = await this.getAccountByNameCached(m.groups.user, m.groups.host, cache); - if (account == null) - continue; + if (account == null) + continue; - mentions.push({ - id: account.id, - url: account.url, - username: account.username, - acct: account.acct - }); + mentions.push({ + id: account.id, + url: account.url, + username: account.username, + acct: account.acct + }); + } + catch {} } return mentions; From 7b64cf9688f8f0ac743026c46ad4b9807718a314 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 19:23:47 +0200 Subject: [PATCH 21/37] [mastodon-client] Fix global timeline --- .../src/server/api/mastodon/endpoints/timeline.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts index a155cc93ea..efadfe7860 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts @@ -45,13 +45,14 @@ export function apiTimelineMastodon(router: Router): void { const client = getClient(BASE_URL, accessTokens); try { const query: any = ctx.query; - const data = query.local - ? await client.getLocalTimeline( - convertTimelinesArgsId(argsToBools(limitToInt(query))), - ) - : await client.getPublicTimeline( - convertTimelinesArgsId(argsToBools(limitToInt(query))), - ); + const data = + query.local === "true" + ? await client.getLocalTimeline( + convertTimelinesArgsId(argsToBools(limitToInt(query))), + ) + : await client.getPublicTimeline( + convertTimelinesArgsId(argsToBools(limitToInt(query))), + ); ctx.body = data.data.map((status) => convertStatus(status)); } catch (e: any) { console.error(e); From d6a4b18744a073cd6628baf45b34da7f2a573cd5 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 19:41:32 +0200 Subject: [PATCH 22/37] [mastodon-client] Don't display unsupported notification types --- packages/megalodon/src/misskey.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 61464522a3..42268806f4 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -10,6 +10,7 @@ import Entity from './entity' import { MegalodonInterface, WebSocketInterface, NoImplementedError, ArgumentError, UnexpectedError } from './megalodon' import MegalodonEntity from "@/entity"; import fs from "node:fs"; +import MisskeyNotificationType from "./misskey/notification"; type AccountCache = { locks: AsyncLock, @@ -2238,7 +2239,11 @@ export default class Misskey implements MegalodonInterface { } return this.client .post>('/api/i/notifications', params) - .then(res => ({ ...res, data: res.data.map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) + .then(res => ({ + ...res, + data: res.data + .filter(p => p.type != MisskeyNotificationType.FollowRequestAccepted) // these aren't supported on mastodon + .map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) } public async getNotification(_id: string): Promise> { From 72887f54e0deb0824cc37fe8774654b6c84f7e74 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 20:15:24 +0200 Subject: [PATCH 23/37] [mastodon-client] populate user details for all notes --- .../src/server/api/mastodon/converters.ts | 6 +- packages/megalodon/src/misskey.ts | 79 +++++++++++++------ 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/converters.ts b/packages/backend/src/server/api/mastodon/converters.ts index 37c6283a11..cbaf5287f6 100644 --- a/packages/backend/src/server/api/mastodon/converters.ts +++ b/packages/backend/src/server/api/mastodon/converters.ts @@ -2,8 +2,10 @@ import { Entity } from "megalodon"; import { convertId, IdType } from "../index.js"; function simpleConvert(data: any) { - data.id = convertId(data.id, IdType.MastodonId); - return data; + // copy the object to bypass weird pass by reference bugs + const result = Object.assign({}, data); + result.id = convertId(data.id, IdType.MastodonId); + return result; } export function convertAccount(account: Entity.Account) { diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 42268806f4..4753eb4802 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -333,7 +333,7 @@ export default class Misskey implements MegalodonInterface { if (res.data.pinnedNotes) { return { ...res, - data: await Promise.all(res.data.pinnedNotes.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.pinnedNotes.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) } } return {...res, data: []} @@ -385,7 +385,7 @@ export default class Misskey implements MegalodonInterface { }) } return this.client.post>('/api/users/notes', params).then(async res => { - const statuses: Array = await Promise.all(res.data.map(note => this.noteWithMentions(note, this.baseUrlToHost(this.baseUrl), accountCache))) + const statuses: Array = await Promise.all(res.data.map(note => this.noteWithDetails(note, this.baseUrlToHost(this.baseUrl), accountCache))) return Object.assign(res, { data: statuses }) @@ -424,7 +424,7 @@ export default class Misskey implements MegalodonInterface { } return this.client.post>('/api/users/reactions', params).then(async res => { return Object.assign(res, { - data: await Promise.all(res.data.map(fav => this.noteWithMentions(fav.note, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(fav => this.noteWithDetails(fav.note, this.baseUrlToHost(this.baseUrl), accountCache))) }) }) } @@ -764,7 +764,7 @@ export default class Misskey implements MegalodonInterface { } return this.client.post>('/api/i/favorites', params).then(async res => { return Object.assign(res, { - data: await Promise.all(res.data.map(s => this.noteWithMentions(s.note, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(s => this.noteWithDetails(s.note, this.baseUrlToHost(this.baseUrl), accountCache))) }) }) } @@ -1222,7 +1222,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/create', params) .then(async res => ({ ...res, - data: await this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + data: await this.noteWithDetails(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) })) } @@ -1234,7 +1234,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({ ...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})); + .then(async res => ({ ...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})); } private getFreshAccountCache() :AccountCache { @@ -1244,12 +1244,22 @@ export default class Misskey implements MegalodonInterface { } } - public async noteWithMentions(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { - const status = await this.converter.note(n, host); - return status.mentions.length === 0 ? this.addMentionsToStatus(status, cache) : status; + public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { + const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); + return this.addMentionsToStatus(status, cache); } + public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise { + if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0) + status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account; + + return status; + } + public async addMentionsToStatus(status: Entity.Status, cache: AccountCache) : Promise { + if (status.mentions.length > 0) + return status; + status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { status.content = status.content.replace(`@${m.acct}`, `@${m.acct}`); @@ -1307,6 +1317,23 @@ export default class Misskey implements MegalodonInterface { }) } + public async getAccountCached(id: string, acct: string, cache: AccountCache): Promise { + return await cache.locks.acquire(acct, async () => { + const cacheHit = cache.accounts.find(p => p.id === id); + const account = cacheHit ?? (await this.getAccount(id)).data; + + if (!account) { + return null; + } + + if (cacheHit == null) { + cache.accounts.push(account); + } + + return account; + }) + } + public async editStatus( _id: string, _options: { @@ -1375,11 +1402,11 @@ export default class Misskey implements MegalodonInterface { return this.client.post>('/api/notes/children', params).then(async res => { const accountCache = this.getFreshAccountCache(); const conversation = await this.client.post>('/api/notes/conversation', params); - const parents = await Promise.all(conversation.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))); + const parents = await Promise.all(conversation.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))); const context: Entity.Context = { ancestors: parents.reverse(), - descendants: this.dfs(await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache)))) + descendants: this.dfs(await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache)))) } return { ...res, @@ -1492,7 +1519,7 @@ export default class Misskey implements MegalodonInterface { }) .then(async res => ({ ...res, - data: await this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + data: await this.noteWithDetails(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) })) } @@ -1507,7 +1534,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -1521,7 +1548,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -1535,7 +1562,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } public async muteStatus(_id: string): Promise> { @@ -1563,7 +1590,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -1577,7 +1604,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } // ====================================== @@ -1663,7 +1690,7 @@ export default class Misskey implements MegalodonInterface { noteId: status_id }) .then(async res => { - const note = await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + const note = await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) return {...res, data: note.poll} }) if (!res.data) { @@ -1768,7 +1795,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/global-timeline', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -1826,7 +1853,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/local-timeline', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -1890,7 +1917,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/search-by-tag', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -1945,7 +1972,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/timeline', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -2001,7 +2028,7 @@ export default class Misskey implements MegalodonInterface { } return this.client .post>('/api/notes/user-list-timeline', params) - .then(async res => ({ ...res, data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) + .then(async res => ({ ...res, data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } // ====================================== @@ -2444,7 +2471,7 @@ export default class Misskey implements MegalodonInterface { ...res, data: { accounts: [], - statuses: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))), + statuses: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))), hashtags: [] } })) @@ -2582,7 +2609,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -2596,7 +2623,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } public async getEmojiReactions(id: string): Promise>> { From c3f5836ac1f794580f6f7932ffb001294311665d Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 22:06:26 +0200 Subject: [PATCH 24/37] [mastodon-client] populate note details for notifications --- packages/megalodon/src/misskey.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 4753eb4802..85489f8be4 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1244,6 +1244,13 @@ export default class Misskey implements MegalodonInterface { } } + public async notificationWithDetails(n: MisskeyAPI.Entity.Notification, host: string, cache: AccountCache): Promise { + const notification = this.converter.notification(n, host); + if (n.note) + notification.status = await this.noteWithDetails(n.note, host, cache); + return notification; + } + public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); return this.addMentionsToStatus(status, cache); @@ -2264,13 +2271,15 @@ export default class Misskey implements MegalodonInterface { limit: 20 }) } + const cache = this.getFreshAccountCache(); return this.client .post>('/api/i/notifications', params) - .then(res => ({ + .then(async res => ({ ...res, - data: res.data + data: await Promise.all(res.data .filter(p => p.type != MisskeyNotificationType.FollowRequestAccepted) // these aren't supported on mastodon - .map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) + .map(n => this.notificationWithDetails(n, this.baseUrlToHost(this.baseUrl), cache))) + })) } public async getNotification(_id: string): Promise> { From 2d47cdf53feafac5d4d45abc03ebff0ba8c97699 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 22:40:29 +0200 Subject: [PATCH 25/37] [mastodon-client] implement favorited_by --- .../src/server/api/mastodon/endpoints/status.ts | 14 +++++++++++++- packages/megalodon/src/misskey.ts | 14 +++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index ec978bc843..3c58cf3a42 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -197,7 +197,19 @@ export function apiStatusMastodon(router: Router): void { router.get<{ Params: { id: string } }>( "/v1/statuses/:id/favourited_by", async (ctx) => { - ctx.body = []; + const BASE_URL = `${ctx.protocol}://${ctx.hostname}`; + const accessTokens = ctx.headers.authorization; + const client = getClient(BASE_URL, accessTokens); + try { + const data = await client.getStatusFavouritedBy( + convertId(ctx.params.id, IdType.CalckeyId), + ); + ctx.body = data.data.map((account) => convertAccount(account)); + } catch (e: any) { + console.error(e); + ctx.status = 401; + ctx.body = e.response.data; + } }, ); router.post<{ Params: { id: string } }>( diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 85489f8be4..dda108debe 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1487,11 +1487,15 @@ export default class Misskey implements MegalodonInterface { })) } - public async getStatusFavouritedBy(_id: string): Promise>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) + public async getStatusFavouritedBy(id: string): Promise>> { + return this.client + .post>('/api/notes/reactions', { + noteId: id + }) + .then(res => ({ + ...res, + data: res.data.map(n => this.converter.user(n.user)) + })) } public async favouriteStatus(id: string): Promise> { From f33ccfc98aba4705f31c973571f141c603a5fa2a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 22:51:07 +0200 Subject: [PATCH 26/37] [mastodon-client] populate user data for favorited_by and reblogged_by --- packages/megalodon/src/misskey.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index dda108debe..cc589197d5 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1481,9 +1481,9 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/renotes', { noteId: id }) - .then(res => ({ + .then(async res => ({ ...res, - data: res.data.map(n => this.converter.user(n.user)) + data: (await Promise.all(res.data.map(n => this.getAccount(n.user.id)))).map(p => p.data) })) } @@ -1492,9 +1492,9 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/reactions', { noteId: id }) - .then(res => ({ + .then(async res => ({ ...res, - data: res.data.map(n => this.converter.user(n.user)) + data: (await Promise.all(res.data.map(n => this.getAccount(n.user.id)))).map(p => p.data) })) } From 8323a33f97327c8f8a17df5e89eea17fed56beb2 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 23:18:43 +0200 Subject: [PATCH 27/37] [mastodon-client] populate details for quote and reblog fields --- packages/megalodon/src/misskey.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index cc589197d5..48950f943f 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1260,6 +1260,12 @@ export default class Misskey implements MegalodonInterface { if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0) status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account; + if (status.reblog != null) + status.reblog = await this.addUserDetailsToStatus(status.reblog, cache); + + if (status.quote != null) + status.quote = await this.addUserDetailsToStatus(status.quote, cache); + return status; } @@ -1267,6 +1273,12 @@ export default class Misskey implements MegalodonInterface { if (status.mentions.length > 0) return status; + if (status.reblog != null) + status.reblog = await this.addMentionsToStatus(status.reblog, cache); + + if (status.quote != null) + status.quote = await this.addMentionsToStatus(status.quote, cache); + status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { status.content = status.content.replace(`@${m.acct}`, `@${m.acct}`); From 7ffe30dcdb5b76ba61b7533eccb403cd92dfbf6e Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 23:42:19 +0200 Subject: [PATCH 28/37] [mastodon-client] fix search type param --- .../server/api/mastodon/endpoints/search.ts | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index df35b91167..c2f828ad74 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -30,21 +30,25 @@ export function apiSearchMastodon(router: Router): void { try { const query: any = convertTimelinesArgsId(limitToInt(ctx.query)); const type = query.type; - if (type) { - const data = await client.search(query.q, type, query); - ctx.body = data.data.accounts.map((account) => convertAccount(account)); - } else { - const acct = await client.search(query.q, "accounts", query); - const stat = await client.search(query.q, "statuses", query); - const tags = await client.search(query.q, "hashtags", query); - ctx.body = { - accounts: acct.data.accounts.map((account) => - convertAccount(account), - ), - statuses: stat.data.statuses.map((status) => convertStatus(status)), - hashtags: tags.data.hashtags, - }; - } + const acct = + !type || type === "accounts" + ? await client.search(query.q, "accounts", query) + : null; + const stat = + !type || type === "statuses" + ? await client.search(query.q, "statuses", query) + : null; + const tags = + !type || type === "hashtags" + ? await client.search(query.q, "hashtags", query) + : null; + ctx.body = { + accounts: + acct?.data?.accounts.map((account) => convertAccount(account)) ?? [], + statuses: + stat?.data?.statuses.map((status) => convertStatus(status)) ?? [], + hashtags: tags?.data?.hashtags ?? [], + }; } catch (e: any) { console.error(e); ctx.status = 401; From 9472248e1ca1cb73ad695c6c2b74bffcf5062161 Mon Sep 17 00:00:00 2001 From: freeplay Date: Fri, 7 Jul 2023 21:50:45 -0400 Subject: [PATCH 29/37] style: make background banner blur static --- packages/client/src/pages/user/home.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/client/src/pages/user/home.vue b/packages/client/src/pages/user/home.vue index adfebd4a26..24b150bc43 100644 --- a/packages/client/src/pages/user/home.vue +++ b/packages/client/src/pages/user/home.vue @@ -26,6 +26,7 @@ class="banner" :style="{ backgroundImage: `url('${user.bannerUrl}')`, + '--backgroundImageStatic': getStaticImageUrl(user.bannerUrl) }" >
@@ -384,6 +385,7 @@ import MkRemoteCaution from "@/components/MkRemoteCaution.vue"; import MkInfo from "@/components/MkInfo.vue"; import MkMoved from "@/components/MkMoved.vue"; import { getScrollPosition } from "@/scripts/scroll"; +import { getStaticImageUrl } from "@/scripts/get-static-image-url"; import number from "@/filters/number"; import { userPage } from "@/filters/user"; import * as os from "@/os"; @@ -513,7 +515,7 @@ onUnmounted(() => { content: ""; position: fixed; inset: 0; - background: var(--blur, inherit); + background: var(--blur, --backgroundImageStatic); background-size: cover; background-position: center; pointer-events: none; From 2dd7bdcfa1b99bf82cc06e3b79849bf8f454ec7b Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 8 Jul 2023 02:01:02 +0200 Subject: [PATCH 30/37] [mastodon-client] fix local instance mentions --- packages/megalodon/src/misskey.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 48950f943f..c7db1aad4b 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1281,6 +1281,8 @@ export default class Misskey implements MegalodonInterface { status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { + if (m.acct == m.username) + status.content = status.content.replace(`@${m.acct}@${this.baseUrlToHost(this.baseUrl)}`, `@${m.acct}`); status.content = status.content.replace(`@${m.acct}`, `@${m.acct}`); } return status; From 326b0ea40862795a0d057ed3f3c61a17a83d4726 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 8 Jul 2023 01:42:51 +0200 Subject: [PATCH 31/37] [mastodon-client] fix polls --- packages/megalodon/src/entities/poll.ts | 1 + packages/megalodon/src/megalodon.ts | 2 +- packages/megalodon/src/misskey.ts | 32 +++++++++++--------- packages/megalodon/src/misskey/api_client.ts | 9 +++--- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/megalodon/src/entities/poll.ts b/packages/megalodon/src/entities/poll.ts index 69706e8ae1..c4f8f4f6df 100644 --- a/packages/megalodon/src/entities/poll.ts +++ b/packages/megalodon/src/entities/poll.ts @@ -9,5 +9,6 @@ namespace Entity { votes_count: number options: Array voted: boolean + own_votes: Array } } diff --git a/packages/megalodon/src/megalodon.ts b/packages/megalodon/src/megalodon.ts index 74966ccf4b..1cd0a7db3a 100644 --- a/packages/megalodon/src/megalodon.ts +++ b/packages/megalodon/src/megalodon.ts @@ -841,7 +841,7 @@ export interface MegalodonInterface { * @param choices Array of own votes containing index for each option (starting from 0). * @return Poll */ - votePoll(id: string, choices: Array, status_id?: string | null): Promise> + votePoll(id: string, choices: Array): Promise> // ====================================== // statuses/scheduled_statuses // ====================================== diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index c7db1aad4b..07826f3164 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1688,31 +1688,35 @@ export default class Misskey implements MegalodonInterface { // ====================================== // statuses/polls // ====================================== - public async getPoll(_id: string): Promise> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) + public async getPoll(id: string): Promise> { + const res = await this.getStatus(id); + if (res.data.poll == null) + throw new Error('poll not found'); + return { ...res, data: res.data.poll } } /** * POST /api/notes/polls/vote */ - public async votePoll(_id: string, choices: Array, status_id?: string | null): Promise> { - if (!status_id) { + public async votePoll(id: string, choices: Array): Promise> { + if (!id) { return new Promise((_, reject) => { - const err = new ArgumentError('status_id is required') + const err = new ArgumentError('id is required') reject(err) }) } - const params = { - noteId: status_id, - choice: choices[0] - } - await this.client.post<{}>('/api/notes/polls/vote', params) + + for (const c of choices) { + const params = { + noteId: id, + choice: +c + } + await this.client.post<{}>('/api/notes/polls/vote', params) + } + const res = await this.client .post('/api/notes/show', { - noteId: status_id + noteId: id }) .then(async res => { const note = await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 1833f9956b..180ec6fdbb 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -275,18 +275,19 @@ namespace MisskeyAPI { } } - poll = (p: Entity.Poll): MegalodonEntity.Poll => { + poll = (p: Entity.Poll, id: string): MegalodonEntity.Poll => { const now = dayjs() const expire = dayjs(p.expiresAt) const count = p.choices.reduce((sum, choice) => sum + choice.votes, 0) return { - id: '', + id: id, expires_at: p.expiresAt, expired: now.isAfter(expire), multiple: p.multiple, votes_count: count, options: p.choices.map(c => this.choice(c)), - voted: p.choices.some(c => c.isVoted) + voted: p.choices.some(c => c.isVoted), + own_votes: p.choices.filter(c => c.isVoted).map(c => p.choices.indexOf(c)) } } @@ -318,7 +319,7 @@ namespace MisskeyAPI { mentions: [], tags: [], card: null, - poll: n.poll ? this.poll(n.poll) : null, + poll: n.poll ? this.poll(n.poll, n.id) : null, application: null, language: null, pinned: null, From 770e8bdf6d4eedfac800f960a26184097819d8e1 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 8 Jul 2023 02:37:11 +0200 Subject: [PATCH 32/37] [mastodon-client] render bio newlines correctly --- packages/megalodon/src/misskey/api_client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 180ec6fdbb..7f1409c706 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -161,7 +161,7 @@ namespace MisskeyAPI { followers_count: u.followersCount, following_count: u.followingCount, statuses_count: u.notesCount, - note: u.description, + note: u.description?.replace(/\n|\\n/g, '
') ?? '', url: acctUrl, avatar: u.avatarUrl, avatar_static: u.avatarUrl, From 42ac4510eb9aa8a9e165338f7ca5b3719b0df5af Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 8 Jul 2023 03:24:11 +0200 Subject: [PATCH 33/37] [mastodon-client] handle user & note URLs in search --- .../server/api/mastodon/endpoints/search.ts | 1 + packages/megalodon/src/misskey.ts | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index c2f828ad74..8a48175579 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -42,6 +42,7 @@ export function apiSearchMastodon(router: Router): void { !type || type === "hashtags" ? await client.search(query.q, "hashtags", query) : null; + ctx.body = { accounts: acct?.data?.accounts.map((account) => convertAccount(account)) ?? [], diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 07826f3164..f2befd31e3 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -2395,6 +2395,32 @@ export default class Misskey implements MegalodonInterface { switch (type) { case 'accounts': { + if (q.startsWith("http://") || q.startsWith("https://")) { + return this.client.post('/api/ap/show', {uri: q}).then(async res => { + if (res.status != 200 || res.data.type != 'User') { + res.status = 200; + res.statusText = "OK"; + res.data = { + accounts: [], + statuses: [], + hashtags: [] + }; + + return res; + } + + const account = await this.converter.userDetail(res.data.object as MisskeyAPI.Entity.UserDetail, this.baseUrlToHost(this.baseUrl)); + + return { + ...res, + data: { + accounts: options?.max_id && options?.max_id >= account.id ? [] : [account], + statuses: [], + hashtags: [] + } + }; + }) + } let params = { query: q } @@ -2468,6 +2494,32 @@ export default class Misskey implements MegalodonInterface { })) } case 'statuses': { + if (q.startsWith("http://") || q.startsWith("https://")) { + return this.client.post('/api/ap/show', {uri: q}).then(async res => { + if (res.status != 200 || res.data.type != 'Note') { + res.status = 200; + res.statusText = "OK"; + res.data = { + accounts: [], + statuses: [], + hashtags: [] + }; + + return res; + } + + const post = await this.noteWithDetails(res.data.object as MisskeyAPI.Entity.Note, this.baseUrlToHost(this.baseUrl), accountCache); + + return { + ...res, + data: { + accounts: [], + statuses: options?.max_id && options.max_id >= post.id ? [] : [post], + hashtags: [] + } + } + }) + } let params = { query: q } From f6f00100a4d9c3e12a5fc265d532ef7bd57fe767 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 8 Jul 2023 03:59:52 +0200 Subject: [PATCH 34/37] increase ap/show rate limit --- packages/backend/src/server/api/endpoints/ap/show.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 3dd168d718..c25f0a8018 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -10,7 +10,7 @@ import type { Note } from "@/models/entities/note.js"; import type { CacheableLocalUser, User } from "@/models/entities/user.js"; import { isActor, isPost, getApId } from "@/remote/activitypub/type.js"; import type { SchemaType } from "@/misc/schema.js"; -import { HOUR } from "@/const.js"; +import { MINUTE } from "@/const.js"; import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import { updateQuestion } from "@/remote/activitypub/models/question.js"; import { populatePoll } from "@/models/repositories/note.js"; @@ -22,8 +22,8 @@ export const meta = { requireCredential: true, limit: { - duration: HOUR, - max: 30, + duration: MINUTE, + max: 10, }, errors: { From 679d89fa59bf4628e6e27ca73af8630080d7a063 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Fri, 7 Jul 2023 20:44:41 -0700 Subject: [PATCH 35/37] build: :zap: build megalodon with swc Do it right this time --- packages/README.md | 2 +- packages/megalodon/.swcrc | 19 +++++++++++++++++++ packages/megalodon/package.json | 9 +++++++-- pnpm-lock.yaml | 16 +++++++++++++--- 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 packages/megalodon/.swcrc diff --git a/packages/README.md b/packages/README.md index 0ed7c64039..ed4b8f6c45 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,4 +7,4 @@ This directory contains all of the packages Calckey uses. - `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 - `calckey-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/calckey-js) for public use -- `megalodon`: TypeScript library used for partial Mastodon API compatibility +- `megalodon`: TypeScript library used for Mastodon API compatibility diff --git a/packages/megalodon/.swcrc b/packages/megalodon/.swcrc new file mode 100644 index 0000000000..c590064ecd --- /dev/null +++ b/packages/megalodon/.swcrc @@ -0,0 +1,19 @@ +{ + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "parser": { + "syntax": "typescript", + "dynamicImport": true, + "decorators": true + }, + "transform": { + "decoratorMetadata": true + }, + "target": "es2022" + }, + "minify": false, + "module": { + "type": "commonjs", + "strict": true + } +} diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json index 43479b2e73..646b3040b2 100644 --- a/packages/megalodon/package.json +++ b/packages/megalodon/package.json @@ -4,7 +4,7 @@ "main": "./lib/src/index.js", "typings": "./lib/src/index.d.ts", "scripts": { - "build": "tsc -p ./", + "build": "pnpm swc src -d lib/src -D", "lint": "eslint --ext .js,.ts src", "doc": "typedoc --out ../docs ./src", "test": "NODE_ENV=test jest -u --maxWorkers=3" @@ -49,6 +49,8 @@ "async-lock": "1.4.0" }, "devDependencies": { + "@swc/cli": "^0.1.62", + "@swc/core": "^1.3.62", "@types/core-js": "^2.5.0", "@types/form-data": "^2.5.0", "@types/jest": "^29.4.0", @@ -77,5 +79,8 @@ "directories": { "lib": "lib", "test": "test" - } + }, + "optionalDependencies": { + "@swc/core-android-arm64": "1.3.11" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b18c938542..b9522c4346 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -789,7 +789,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e + version: github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -970,7 +970,17 @@ importers: ws: specifier: 8.12.0 version: 8.12.0 + optionalDependencies: + '@swc/core-android-arm64': + specifier: 1.3.11 + version: 1.3.11 devDependencies: + '@swc/cli': + specifier: ^0.1.62 + version: 0.1.62(@swc/core@1.3.62)(chokidar@3.3.1) + '@swc/core': + specifier: ^1.3.62 + version: 1.3.62 '@types/async-lock': specifier: 1.4.0 version: 1.4.0 @@ -17429,8 +17439,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/9d16541664dc8fef3201ae9b647477070676a52e} + github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/15fd9504f943763a057ff803ee2009ec0524c96b} name: emojilib version: 3.0.10 dev: true From c8ae0cfb9546ee43d3cd5095ebc2b84cfffcf89c Mon Sep 17 00:00:00 2001 From: Kainoa Kanter Date: Sat, 8 Jul 2023 16:56:54 +0000 Subject: [PATCH 36/37] revert 679d89fa59bf4628e6e27ca73af8630080d7a063 revert build: :zap: build megalodon with swc Do it right this time --- packages/README.md | 2 +- packages/megalodon/.swcrc | 19 ------------------- packages/megalodon/package.json | 9 ++------- pnpm-lock.yaml | 16 +++------------- 4 files changed, 6 insertions(+), 40 deletions(-) delete mode 100644 packages/megalodon/.swcrc diff --git a/packages/README.md b/packages/README.md index ed4b8f6c45..0ed7c64039 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,4 +7,4 @@ This directory contains all of the packages Calckey uses. - `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 - `calckey-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/calckey-js) for public use -- `megalodon`: TypeScript library used for Mastodon API compatibility +- `megalodon`: TypeScript library used for partial Mastodon API compatibility diff --git a/packages/megalodon/.swcrc b/packages/megalodon/.swcrc deleted file mode 100644 index c590064ecd..0000000000 --- a/packages/megalodon/.swcrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/swcrc", - "jsc": { - "parser": { - "syntax": "typescript", - "dynamicImport": true, - "decorators": true - }, - "transform": { - "decoratorMetadata": true - }, - "target": "es2022" - }, - "minify": false, - "module": { - "type": "commonjs", - "strict": true - } -} diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json index 646b3040b2..43479b2e73 100644 --- a/packages/megalodon/package.json +++ b/packages/megalodon/package.json @@ -4,7 +4,7 @@ "main": "./lib/src/index.js", "typings": "./lib/src/index.d.ts", "scripts": { - "build": "pnpm swc src -d lib/src -D", + "build": "tsc -p ./", "lint": "eslint --ext .js,.ts src", "doc": "typedoc --out ../docs ./src", "test": "NODE_ENV=test jest -u --maxWorkers=3" @@ -49,8 +49,6 @@ "async-lock": "1.4.0" }, "devDependencies": { - "@swc/cli": "^0.1.62", - "@swc/core": "^1.3.62", "@types/core-js": "^2.5.0", "@types/form-data": "^2.5.0", "@types/jest": "^29.4.0", @@ -79,8 +77,5 @@ "directories": { "lib": "lib", "test": "test" - }, - "optionalDependencies": { - "@swc/core-android-arm64": "1.3.11" - } + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9522c4346..b18c938542 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -789,7 +789,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b + version: github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -970,17 +970,7 @@ importers: ws: specifier: 8.12.0 version: 8.12.0 - optionalDependencies: - '@swc/core-android-arm64': - specifier: 1.3.11 - version: 1.3.11 devDependencies: - '@swc/cli': - specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62)(chokidar@3.3.1) - '@swc/core': - specifier: ^1.3.62 - version: 1.3.62 '@types/async-lock': specifier: 1.4.0 version: 1.4.0 @@ -17439,8 +17429,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/15fd9504f943763a057ff803ee2009ec0524c96b} + github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/9d16541664dc8fef3201ae9b647477070676a52e} name: emojilib version: 3.0.10 dev: true From ab19e684179bde332a97d4b503377fd686b404e0 Mon Sep 17 00:00:00 2001 From: freeplay Date: Sat, 8 Jul 2023 13:06:16 -0400 Subject: [PATCH 37/37] fix: banner blur --- packages/client/src/pages/user/home.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/client/src/pages/user/home.vue b/packages/client/src/pages/user/home.vue index 24b150bc43..54e4ab10c8 100644 --- a/packages/client/src/pages/user/home.vue +++ b/packages/client/src/pages/user/home.vue @@ -26,7 +26,7 @@ class="banner" :style="{ backgroundImage: `url('${user.bannerUrl}')`, - '--backgroundImageStatic': getStaticImageUrl(user.bannerUrl) + '--backgroundImageStatic': defaultStore.state.useBlurEffect ? `url('${getStaticImageUrl(user.bannerUrl)}')` : null }" >
@@ -388,6 +388,7 @@ import { getScrollPosition } from "@/scripts/scroll"; import { getStaticImageUrl } from "@/scripts/get-static-image-url"; import number from "@/filters/number"; import { userPage } from "@/filters/user"; +import { defaultStore } from "@/store"; import * as os from "@/os"; import { i18n } from "@/i18n"; import { $i } from "@/account"; @@ -515,7 +516,7 @@ onUnmounted(() => { content: ""; position: fixed; inset: 0; - background: var(--blur, --backgroundImageStatic); + background: var(--backgroundImageStatic); background-size: cover; background-position: center; pointer-events: none;