diff --git a/.config/LICENSE b/.config/LICENSE new file mode 100644 index 0000000000..342509dec1 --- /dev/null +++ b/.config/LICENSE @@ -0,0 +1,13 @@ +Copyright 2023 Calckey + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/.gitignore b/.gitignore index 29377540d8..6bf2ea1b14 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ coverage !/.config/devenv.yml !/.config/docker_example.env !/.config/helm_values_example.yml +!/.config/LICENSE #docker dev config /dev/docker-compose.yml diff --git a/CALCKEY.md b/CALCKEY.md index 5a8bbd8ff7..619155238c 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -137,7 +137,7 @@ - 👍 also triggers generic like/favorite - [Add additional background for acrylic popups if backdrop-filter is unsupported](https://github.com/misskey-dev/misskey/pull/8671) - [Add parameters to MFM rotate](https://github.com/misskey-dev/misskey/pull/8549) -- Many changes from [Foundkey](https://akkoma.dev/FoundKeyGang/Foundkey) +- Many changes from [FoundKey](https://akkoma.dev/FoundKeyGang/FoundKey) - https://akkoma.dev/FoundKeyGang/FoundKey/commit/0ece67b04c3f0365057624c1068808276ccab981: refactor pages/auth.form.vue to composition API - https://akkoma.dev/FoundKeyGang/FoundKey/commit/4bc9610d8bf5af736b5e89e4782395705de45d7d: remove unnecessary joins - https://akkoma.dev/FoundKeyGang/FoundKey/commit/9ee609d70082f7a6dc119a5d83c0e7c5e1208676: enhance privacy of notes diff --git a/CHANGELOG.md b/CHANGELOG.md index 988156a72d..b9a998f627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2704,7 +2704,7 @@ Co-committed-by: naskya Passwords will be automatically re-hashed on sign-in. All new password hashes will be argon2 by default. This uses argon2id and is not configurable. In the very unlikely case someone has more specific needs, a fork is recommended. ChangeLog: Added Co-authored-by: Chloe Kudryavtsev -Breaks Calckey -> Misskey migration, but fixes Foundkey -> Calckey migration +Breaks Calckey -> Misskey migration, but fixes FoundKey -> Calckey migration - Add argon diff --git a/COPYING b/COPYING index 138ed7db1b..d4b71b42ed 100644 --- a/COPYING +++ b/COPYING @@ -1,15 +1,24 @@ -Unless otherwise stated this repository is -Copyright © 2014-2022 syuilo and contributers -Copyright © 2022 thatonecalculator and contributers +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 And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE. +--- -Calckey includes several third-party Open-Source softwares. +These specific configuration directories: -Emoji keywords for Unicode 11 and below by Mu-An Chiou -License: MIT -https://github.com/muan/emojilib/blob/master/LICENSE +- .config/ +- custom/assets/ + +and their contents are +Copyright © 2022-2023 Kainoa Kanter and 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. + +--- + +Calckey includes several third-party open-source softwares and software libraries. RsaSignature2017 implementation by Transmute Industries Inc License: MIT @@ -23,6 +32,6 @@ Chiptune2.js by Simon Gündling License: MIT https://github.com/deskjet/chiptune2.js#license -libopenmpt (as part of openmpt) by OpenMPT -License: BSD 3-Clause -https://github.com/OpenMPT/openmpt/blob/master/LICENSE +Licenses for all softwares and software libraries installed via the Node Package Manager ("npm") can be found by running the following shell command in the root directory of this repository: + +pnpm licenses list diff --git a/README.md b/README.md index 2e6907e306..a2465cc092 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,14 @@ # 🌠 Getting started +Want to just join a Calckey server? View the list here, pick one, and join: + +### https://calckey.org/join + +--- + +Want to make your own? Keep reading! + This guide will work for both **starting from scratch** and **migrating from Misskey**. ## 🔰 Easy installers @@ -208,9 +216,9 @@ Please don't use ElasticSearch unless you already have an ElasticSearch setup an - Edit `.config/default.yml`, making sure to fill out required fields. - Also copy and edit `.config/docker_example.env` to `.config/docker.env` if you're using Docker. -## 🚚 Migrating from Misskey to Calckey +## 🚚 Migrating from Misskey/FoundKey to Calckey -For migrating from Misskey v13, Misskey v12, and Foundkey, read [this document](https://codeberg.org/calckey/calckey/src/branch/develop/docs/migrate.md). +For migrating from Misskey v13, Misskey v12, and FoundKey, read [this document](https://codeberg.org/calckey/calckey/src/branch/develop/docs/migrate.md). ## 🌐 Web proxy diff --git a/custom/assets/LICENSE b/custom/assets/LICENSE new file mode 100644 index 0000000000..342509dec1 --- /dev/null +++ b/custom/assets/LICENSE @@ -0,0 +1,13 @@ +Copyright 2023 Calckey + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/docs/migrate.md b/docs/migrate.md index 7e9653e70f..3c43af8095 100644 --- a/docs/migrate.md +++ b/docs/migrate.md @@ -1,10 +1,11 @@ -# 🚚 Migrating from Misskey to Calckey +# 🚚 Migrating from Misskey/FoundKey to Calckey -The following procedure may not work depending on your environment and version of Misskey. +All the guides below assume you're starting in the root of the repo directory. -**Make sure you** -- **stopped all master and worker processes of Misskey.** -- **have backups of the database before performing any commands.** +### Before proceeding + +- **Ensure you have stopped all master and worker processes of Misskey.** +- **Ensure you have backups of the database before performing any commands.** ## Misskey v13 and above @@ -77,15 +78,16 @@ NODE_ENV=production pnpm run migrate # build using prefered method ``` -## Foundkey +## FoundKey ```sh cd packages/backend +sed -i '12s/^/\/\//' ./migration/1663399074403-resize-comments-drive-file.js LINE_NUM="$(npx typeorm migration:show -d ormconfig.js | grep -n uniformThemecolor1652859567549 | cut -d ':' -f 1)" -NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | nl)" +NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | wc -l)" -for i in $(seq 1 $NUM_MIGRAIONS); do +for i in $(seq 1 $NUM_MIGRATIONS); do npx typeorm migration:revert -d ormconfig.js done @@ -100,4 +102,4 @@ NODE_ENV=production pnpm run migrate ## Reverse -You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to Foundkey, though. +You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to FoundKey, although this is not recommended due to FoundKey being end-of-life. diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 6cda10f969..1f291ac22d 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -2144,3 +2144,6 @@ _skinTones: swipeOnMobile: Permet lliscar entre pàgines enableIdenticonGeneration: Habilitar la generació d'Identicon enableServerMachineStats: Habilitar les estadístiques del maquinari del servidor +showPopup: Notificar els usuaris amb una finestra emergent +showWithSparkles: Mostra amb espurnes +youHaveUnreadAnnouncements: Tens anuncis sense llegir diff --git a/locales/en-US.yml b/locales/en-US.yml index d0f0c8f47e..35c4d6ef61 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -645,6 +645,7 @@ useBlurEffectForModal: "Use blur effect for modals" useFullReactionPicker: "Use full-size reaction picker" width: "Width" height: "Height" +xl: "XL" large: "Big" medium: "Medium" small: "Small" @@ -1118,6 +1119,9 @@ enableIdenticonGeneration: "Enable Identicon generation" showPopup: "Notify users with popup" showWithSparkles: "Show with sparkles" youHaveUnreadAnnouncements: "You have unread announcements" +donationLink: "Link to donation page" +neverShow: "Don't show again" +remindMeLater: "Maybe later" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing @@ -1216,6 +1220,10 @@ _aboutMisskey: source: "Source code" translation: "Translate Calckey" donate: "Donate to Calckey" + donateTitle: "Enjoying Calckey?" + pleaseDonateToCalckey: "Please consider donating to Calckey to support its development." + 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! 🥰" patrons: "Calckey patrons" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 95fb7bcf88..fe03d1f415 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -983,6 +983,8 @@ enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にす showPopup: "ポップアップを表示してユーザーに知らせる" showWithSparkles: "タイトルをキラキラさせる" youHaveUnreadAnnouncements: "未読のお知らせがあります" +neverShow: "今後表示しない" +remindMeLater: "また後で" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。" diff --git a/package.json b/package.json index ec899739fb..a0bb72c8f5 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,16 @@ { "name": "calckey", - "version": "14.0.0-rc3", + "version": "14.0.0-dev71", "codename": "aqua", "repository": { "type": "git", "url": "https://codeberg.org/calckey/calckey.git" }, - "packageManager": "pnpm@8.6.6", + "packageManager": "pnpm@8.6.7", "private": true, "scripts": { - "rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp", - "build": "pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp", + "rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp", + "build": "pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp", "start": "pnpm --filter backend run start", "start:test": "pnpm --filter backend run start:test", "init": "pnpm run migrate", @@ -21,13 +21,13 @@ "watch": "pnpm run dev", "dev": "pnpm node ./scripts/dev.js", "dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start", - "lint": "pnpm -r run lint", + "lint": "pnpm -r --parallel run lint", "cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts", "cy:run": "cypress run", "e2e": "start-server-and-test start:test http://localhost:61812 cy:run", "mocha": "pnpm --filter backend run mocha", "test": "pnpm run mocha", - "format": "pnpm -r run format", + "format": "pnpm -r --parallel run format", "clean": "pnpm node ./scripts/clean.js", "clean-all": "pnpm node ./scripts/clean-all.js", "cleanall": "pnpm run clean-all" @@ -36,17 +36,17 @@ "chokidar": "^3.3.1" }, "dependencies": { - "@bull-board/api": "5.2.0", - "@bull-board/ui": "5.2.0", + "@bull-board/api": "5.6.0", + "@bull-board/ui": "5.6.0", "@napi-rs/cli": "^2.16.1", "@tensorflow/tfjs": "^3.21.0", "js-yaml": "4.1.0", "seedrandom": "^3.0.5" }, "devDependencies": { - "@types/node": "18.11.18", - "@types/gulp": "4.0.10", - "@types/gulp-rename": "2.0.1", + "@types/gulp": "4.0.13", + "@types/gulp-rename": "2.0.2", + "@types/node": "20.4.1", "chalk": "4.1.2", "cross-env": "7.0.3", "cypress": "10.11.0", @@ -59,6 +59,6 @@ "install-peers": "^1.0.4", "rome": "^12.1.3", "start-server-and-test": "1.15.2", - "typescript": "4.9.4" + "typescript": "5.1.6" } } diff --git a/packages/backend/migration/1689136347561-donation-link.js b/packages/backend/migration/1689136347561-donation-link.js new file mode 100644 index 0000000000..dbe0ed7c8e --- /dev/null +++ b/packages/backend/migration/1689136347561-donation-link.js @@ -0,0 +1,15 @@ +export class DonationLink1689136347561 { + name = "DonationLink1689136347561"; + + async up(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" ADD "donationLink" character varying(256)`, + ); + } + + async down(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "DonationLink1689136347561"`, + ); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index ec6451f61c..e249b5d3fe 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -25,16 +25,16 @@ "@tensorflow/tfjs-node": "3.21.1" }, "dependencies": { - "@bull-board/api": "5.2.0", - "@bull-board/koa": "5.2.0", - "@bull-board/ui": "5.2.0", + "@bull-board/api": "5.6.0", + "@bull-board/koa": "5.6.0", + "@bull-board/ui": "5.6.0", "@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", "@peertube/http-signature": "1.7.0", - "@redocly/openapi-core": "1.0.0-beta.120", + "@redocly/openapi-core": "1.0.0-beta.131", "@sinonjs/fake-timers": "9.1.2", "@syuilo/aiscript": "0.11.1", "@tensorflow/tfjs": "^4.2.0", @@ -45,17 +45,17 @@ "autobind-decorator": "2.4.0", "autolinker": "4.0.0", "autwh": "0.1.0", - "aws-sdk": "2.1277.0", + "aws-sdk": "2.1413.0", "axios": "^1.4.0", "bcryptjs": "2.4.3", - "blurhash": "1.1.5", + "blurhash": "2.0.5", "bull": "4.10.4", "cacheable-lookup": "7.0.0", "calckey-js": "workspace:*", "cbor": "8.1.0", - "chalk": "5.2.0", + "chalk": "5.3.0", "chalk-template": "0.4.0", - "chokidar": "3.5.3", + "chokidar": "^3.5.3", "cli-highlight": "2.1.11", "color-convert": "2.0.1", "content-disposition": "0.5.4", @@ -68,15 +68,15 @@ "got": "12.5.3", "hpagent": "0.1.2", "ioredis": "5.3.2", - "ip-cidr": "3.0.11", + "ip-cidr": "3.1.0", "is-svg": "4.3.2", "js-yaml": "4.1.0", "jsdom": "20.0.3", "jsonld": "8.2.0", - "jsrsasign": "10.6.1", - "koa": "2.13.4", + "jsrsasign": "10.8.6", + "koa": "2.14.2", "koa-body": "^6.0.1", - "koa-bodyparser": "4.3.0", + "koa-bodyparser": "4.4.1", "koa-favicon": "2.1.0", "koa-json-body": "5.3.0", "koa-logger": "3.2.1", @@ -98,9 +98,9 @@ "nsfwjs": "2.4.2", "oauth": "^0.10.0", "os-utils": "0.0.14", - "otpauth": "^9.1.2", + "otpauth": "^9.1.3", "parse5": "7.1.2", - "pg": "8.11.0", + "pg": "8.11.1", "private-ip": "2.3.4", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", @@ -110,7 +110,7 @@ "qs": "6.11.2", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.19.0", + "re2": "1.19.1", "redis-lock": "0.1.4", "redis-semaphore": "5.3.1", "reflect-metadata": "0.1.13", @@ -119,7 +119,7 @@ "rss-parser": "3.13.0", "sanitize-html": "2.10.0", "seedrandom": "^3.0.5", - "semver": "7.5.1", + "semver": "7.5.4", "sharp": "0.32.1", "sonic-channel": "^1.3.1", "stringz": "2.1.0", @@ -130,27 +130,26 @@ "tinycolor2": "1.5.2", "tmp": "0.2.1", "twemoji-parser": "14.0.0", - "typeorm": "0.3.11", + "typeorm": "0.3.17", "ulid": "2.3.0", "uuid": "9.0.0", - "web-push": "3.6.1", + "web-push": "3.6.3", "websocket": "1.0.34", "xev": "3.0.2" }, "devDependencies": { "@swc/cli": "^0.1.62", - "@swc/core": "^1.3.62", + "@swc/core": "^1.3.68", "@types/adm-zip": "^0.5.0", "@types/bcryptjs": "2.4.2", - "@types/bull": "3.15.9", "@types/cbor": "6.0.0", "@types/escape-regexp": "0.0.1", - "@types/fluent-ffmpeg": "2.1.20", + "@types/fluent-ffmpeg": "2.1.21", "@types/js-yaml": "4.0.5", - "@types/jsdom": "20.0.1", - "@types/jsonld": "1.5.8", - "@types/jsrsasign": "10.5.4", - "@types/koa": "2.13.5", + "@types/jsdom": "21.1.1", + "@types/jsonld": "1.5.9", + "@types/jsrsasign": "10.5.8", + "@types/koa": "2.13.6", "@types/koa-bodyparser": "4.3.10", "@types/koa-cors": "0.0.2", "@types/koa-favicon": "2.0.21", @@ -169,7 +168,7 @@ "@types/probe-image-size": "^7.2.0", "@types/pug": "2.0.6", "@types/punycode": "2.1.0", - "@types/qrcode": "1.5.0", + "@types/qrcode": "1.5.1", "@types/qs": "6.9.7", "@types/random-seed": "0.3.3", "@types/ratelimiter": "3.4.4", @@ -177,17 +176,16 @@ "@types/rename": "1.0.4", "@types/sanitize-html": "2.9.0", "@types/semver": "7.5.0", - "@types/sharp": "0.31.1", "@types/sinonjs__fake-timers": "8.1.2", "@types/tinycolor2": "1.4.3", "@types/tmp": "0.2.3", - "@types/uuid": "8.3.4", + "@types/uuid": "9.0.2", "@types/web-push": "3.3.2", "@types/websocket": "1.0.5", - "@types/ws": "8.5.4", + "@types/ws": "8.5.5", "autobind-decorator": "2.4.0", "cross-env": "7.0.3", - "eslint": "^8.42.0", + "eslint": "^8.44.0", "execa": "6.1.0", "json5": "2.2.3", "json5-loader": "4.0.1", @@ -195,11 +193,11 @@ "pug": "3.0.2", "strict-event-emitter-types": "2.0.0", "swc-loader": "^0.2.3", - "ts-loader": "9.4.3", + "ts-loader": "9.4.4", "ts-node": "10.9.1", "tsconfig-paths": "4.2.0", - "typescript": "5.1.3", - "webpack": "^5.85.1", + "typescript": "5.1.6", + "webpack": "^5.88.1", "ws": "8.13.0" } } diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index 2ae3ceccd4..13a112ce57 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -20,8 +20,6 @@ export function nyaize(text: string): string { ) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") - // zh-CN, zh-TW - .replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵") // el-GR .replaceAll("να", "νια") .replaceAll("ΝΑ", "ΝΙΑ") diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 200ef50552..d3de7ba53b 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -556,4 +556,10 @@ export class Meta { default: true, }) public enableIdenticonGeneration: boolean; + + @Column("varchar", { + length: 256, + nullable: true, + }) + public donationLink: string | null; } diff --git a/packages/backend/src/queue/processors/background/index-all-notes.ts b/packages/backend/src/queue/processors/background/index-all-notes.ts index 1dce4406a9..c0275b420a 100644 --- a/packages/backend/src/queue/processors/background/index-all-notes.ts +++ b/packages/backend/src/queue/processors/background/index-all-notes.ts @@ -1,4 +1,5 @@ import type Bull from "bull"; +import type { DoneCallback } from "bull"; import { queueLogger } from "../../logger.js"; import { Notes } from "@/models/index.js"; @@ -11,7 +12,7 @@ const logger = queueLogger.createSubLogger("index-all-notes"); export default async function indexAllNotes( job: Bull.Job>, - done: () => void, + done: DoneCallback, ): Promise { logger.info("Indexing all notes..."); @@ -20,7 +21,7 @@ export default async function indexAllNotes( let total: number = (job.data.total as number) ?? 0; let running = true; - const take = 100000; + const take = 10000; const batch = 100; while (running) { logger.info( @@ -41,13 +42,14 @@ export default async function indexAllNotes( }, relations: ["user"], }); - } catch (e) { + } catch (e: any) { logger.error(`Failed to query notes ${e}`); - continue; + done(e); + break; } if (notes.length === 0) { - job.progress(100); + await job.progress(100); running = false; break; } @@ -55,7 +57,7 @@ export default async function indexAllNotes( try { const count = await Notes.count(); total = count; - job.update({ indexedCount, cursor, total }); + await job.update({ indexedCount, cursor, total }); } catch (e) {} for (let i = 0; i < notes.length; i += batch) { @@ -69,12 +71,12 @@ export default async function indexAllNotes( indexedCount += chunk.length; const pct = (indexedCount / total) * 100; - job.update({ indexedCount, cursor, total }); - job.progress(+pct.toFixed(1)); + await job.update({ indexedCount, cursor, total }); + await job.progress(+pct.toFixed(1)); logger.info(`Indexed notes ${indexedCount}/${total ? total : "?"}`); } cursor = notes[notes.length - 1].id; - job.update({ indexedCount, cursor, total }); + await job.update({ indexedCount, cursor, total }); if (notes.length < take) { running = false; diff --git a/packages/backend/src/queue/processors/db/import-masto-post.ts b/packages/backend/src/queue/processors/db/import-masto-post.ts index 317ba7b1bd..efa4adf3f3 100644 --- a/packages/backend/src/queue/processors/db/import-masto-post.ts +++ b/packages/backend/src/queue/processors/db/import-masto-post.ts @@ -50,7 +50,7 @@ export async function importMastoPost( text: text || undefined, reply, renote: null, - cw: post.sensitive, + cw: post.object.sensitive ? post.object.summary : undefined, localOnly: false, visibility: "hidden", visibleUsers: [], diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 50317d4a81..6c3bb5041d 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -491,6 +491,11 @@ export const meta = { optional: false, nullable: false, }, + donationLink: { + type: "string", + optional: true, + nullable: true, + } }, }, } as const; @@ -604,5 +609,6 @@ export default define(meta, paramDef, async (ps, me) => { experimentalFeatures: instance.experimentalFeatures, enableServerMachineStats: instance.enableServerMachineStats, enableIdenticonGeneration: instance.enableIdenticonGeneration, + donationLink: instance.donationLink, }; }); diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index cf22c6c489..16e49a85a8 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -177,6 +177,9 @@ export const paramDef = { postImports: { type: "boolean" }, }, }, + enableServerMachineStats: { type: "boolean" }, + enableIdenticonGeneration: { type: "boolean" }, + donationLink: { type: "string", nullable: true }, }, required: [], } as const; @@ -568,6 +571,21 @@ export default define(meta, paramDef, async (ps, me) => { set.experimentalFeatures = ps.experimentalFeatures || undefined; } + if (ps.enableServerMachineStats !== undefined) { + set.enableServerMachineStats = ps.enableServerMachineStats; + } + + if (ps.enableIdenticonGeneration !== undefined) { + set.enableIdenticonGeneration = ps.enableIdenticonGeneration; + } + + if (ps.donationLink !== undefined) { + set.donationLink = ps.donationLink; + if (set.donationLink && !/^https?:\/\//i.test(set.donationLink)) { + set.donationLink = `https://${set.donationLink}`; + } + } + await db.transaction(async (transactionalEntityManager) => { const metas = await transactionalEntityManager.find(Meta, { order: { diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 673a0266c8..dfb589a431 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -389,6 +389,11 @@ export const meta = { nullable: false, default: "⭐", }, + donationLink: { + type: "string", + optional: "true", + nullable: true, + } }, }, } as const; @@ -491,6 +496,7 @@ export default define(meta, paramDef, async (ps, me) => { translatorAvailable: instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null, defaultReaction: instance.defaultReaction, + donationLink: instance.donationLink, ...(ps.detail ? { diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index e778c49467..72dce19511 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -247,7 +247,7 @@ export default class Connection { for (const obj of objs) { const { type, body } = obj; - console.log(type, body); + // console.log(type, body); switch (type) { case "readNotification": this.onReadNotification(body); diff --git a/packages/client/package.json b/packages/client/package.json index 5864733757..87fd282f94 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -16,7 +16,7 @@ "@syuilo/aiscript": "0.11.1", "@types/escape-regexp": "0.0.1", "@types/glob": "8.1.0", - "@types/gulp": "4.0.11", + "@types/gulp": "4.0.13", "@types/gulp-rename": "2.0.2", "@types/katex": "0.16.0", "@types/matter-js": "0.18.2", @@ -29,8 +29,8 @@ "@vue/compiler-sfc": "3.3.4", "autobind-decorator": "2.4.0", "autosize": "5.0.2", - "blurhash": "1.1.5", - "broadcast-channel": "4.19.1", + "blurhash": "2.0.5", + "broadcast-channel": "5.1.0", "browser-image-resizer": "github:misskey-dev/browser-image-resizer", "calckey-js": "workspace:*", "chart.js": "4.3.0", @@ -39,57 +39,58 @@ "chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-zoom": "2.0.1", "city-timezones": "^1.2.1", - "compare-versions": "5.0.3", + "compare-versions": "6.0.0", "cropperjs": "2.0.0-beta.2", "cross-env": "7.0.3", "cypress": "10.11.0", "date-fns": "2.30.0", "emojilib": "github:thatonecalculator/emojilib", "escape-regexp": "0.0.1", - "eventemitter3": "4.0.7", - "focus-trap": "^7.4.3", + "eventemitter3": "5.0.1", + "fast-blurhash": "^1.1.2", + "focus-trap": "^7.5.2", "focus-trap-vue": "^4.0.2", - "gsap": "^3.11.5", + "gsap": "^3.12.2", "idb-keyval": "6.2.1", "insert-text-at-cursor": "0.3.0", "json5": "2.2.3", - "katex": "0.16.7", + "katex": "0.16.8", "libopenmpt-wasm": "github:TheEssem/libopenmpt-packaging#build", "matter-js": "0.18.0", "mfm-js": "0.23.3", - "photoswipe": "5.3.7", + "photoswipe": "5.3.8", "prettier": "3.0.0", "prettier-plugin-vue": "1.1.6", "prismjs": "1.29.0", - "punycode": "2.1.1", + "punycode": "2.3.0", "querystring": "0.2.1", "rndstr": "1.0.0", - "rollup": "3.23.1", + "rollup": "3.26.2", "s-age": "1.1.2", - "sass": "1.62.1", + "sass": "1.63.6", "seedrandom": "3.0.5", "start-server-and-test": "1.15.2", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "swiper": "9.3.2", + "swiper": "10.0.4", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", "three": "0.146.0", "throttle-debounce": "5.0.0", - "tinycolor2": "1.5.2", - "tsc-alias": "1.8.6", + "tinycolor2": "1.6.0", + "tsc-alias": "1.8.7", "tsconfig-paths": "4.2.0", "twemoji-parser": "14.0.0", - "typescript": "5.1.3", + "typescript": "5.1.6", "unicode-emoji-json": "^0.4.0", "uuid": "9.0.0", "vanilla-tilt": "1.8.0", - "vite": "4.3.9", + "vite": "4.4.2", "vite-plugin-compression": "^0.5.1", "vue": "3.3.4", + "vue-draggable-plus": "^0.2.2", "vue-isyourpasswordsafe": "^2.0.0", "vue-plyr": "^7.0.0", - "vue-prism-editor": "2.0.0-alpha.2", - "vuedraggable": "4.1.0" + "vue-prism-editor": "2.0.0-alpha.2" } } diff --git a/packages/client/src/components/MkAnnouncement.vue b/packages/client/src/components/MkAnnouncement.vue index 24bf886dd8..bd1091b7f2 100644 --- a/packages/client/src/components/MkAnnouncement.vue +++ b/packages/client/src/components/MkAnnouncement.vue @@ -5,6 +5,13 @@ {{ title }}

{{ title }}

+
+ +
+ {{ i18n.ts.updatedAt }}: + +
+
{ } } +.time { + font-size: 0.8rem; +} + .gotIt { margin: 8px 0 0 0; } diff --git a/packages/client/src/components/MkCropperDialog.vue b/packages/client/src/components/MkCropperDialog.vue index b7d25bd35d..748132fbca 100644 --- a/packages/client/src/components/MkCropperDialog.vue +++ b/packages/client/src/components/MkCropperDialog.vue @@ -13,7 +13,9 @@ diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index 63465f38b5..cb0942a338 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -409,7 +409,6 @@ export default defineComponent({ key: Math.random(), to: `/tags/${encodeURIComponent(token.props.hashtag)}`, style: "color:var(--hashtag);", - class: "_link", }, `#${token.props.hashtag}`, ), diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts index 11b9a2edac..66be0430dc 100644 --- a/packages/client/src/init.ts +++ b/packages/client/src/init.ts @@ -450,6 +450,29 @@ function checkForSplash() { } localStorage.setItem("lastUsed", Date.now().toString()); + const latestDonationInfoShownAt = localStorage.getItem( + "latestDonationInfoShownAt", + ); + const neverShowDonationInfo = localStorage.getItem("neverShowDonationInfo"); + if ( + neverShowDonationInfo !== "true" && + new Date($i.createdAt).getTime() < Date.now() - 1000 * 60 * 60 * 24 * 3 && + !location.pathname.startsWith("/miauth") + ) { + if ( + latestDonationInfoShownAt == null || + new Date(latestDonationInfoShownAt).getTime() < + Date.now() - 1000 * 60 * 60 * 24 * 30 + ) { + popup( + defineAsyncComponent(() => import("@/components/MkDonation.vue")), + {}, + {}, + "closed", + ); + } + } + if ("Notification" in window) { // 許可を得ていなかったらリクエスト if (Notification.permission === "default") { diff --git a/packages/client/src/pages/about-calckey.vue b/packages/client/src/pages/about-calckey.vue index 6899c4de0f..fb508239bb 100644 --- a/packages/client/src/pages/about-calckey.vue +++ b/packages/client/src/pages/about-calckey.vue @@ -101,8 +101,9 @@ > - {{ i18n.ts.tos }} + + + {{ + i18n.t("_aboutMisskey.donateHost", { + host: $instance.name || host, + }) + }} + + @@ -163,7 +178,7 @@ - diff --git a/packages/client/src/pages/tag.vue b/packages/client/src/pages/tag.vue index d60bee652a..e9a1792a03 100644 --- a/packages/client/src/pages/tag.vue +++ b/packages/client/src/pages/tag.vue @@ -41,7 +41,7 @@