diff --git a/locales/en-US.yml b/locales/en-US.yml index d493f332f5..c6c442df7c 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1112,6 +1112,8 @@ isModerator: "Moderator" isAdmin: "Administrator" isPatron: "Calckey Patron" reactionPickerSkinTone: "Preferred emoji skin tone" +enableServerMachineStats: "Enable server hardware statistics" +enableIdenticonGeneration: "Enable Identicon generation" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fa3c3f1cc1..9f2f825e55 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -978,6 +978,8 @@ enableCustomKaTeXMacro: "カスタムKaTeXマクロを有効にする" preventAiLearning: "AIによる学習を防止" preventAiLearningDescription: "投稿したノート、添付した画像などのコンテンツを学習の対象にしないようAIに要求します。これはnoaiフラグをHTMLレスポンスに含めることによって実現されます。" noGraze: "ブラウザの拡張機能「Graze for Mastodon」は、Calckeyの動作を妨げるため、無効にしてください。" +enableServerMachineStats: "サーバーのマシン情報を公開する" +enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にする" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。" diff --git a/packages/backend/assets/avatar.png b/packages/backend/assets/avatar.png new file mode 100644 index 0000000000..ee22bdb3c8 Binary files /dev/null and b/packages/backend/assets/avatar.png differ diff --git a/packages/backend/migration/1688280713783-add-meta-options.js b/packages/backend/migration/1688280713783-add-meta-options.js new file mode 100644 index 0000000000..e97a95c423 --- /dev/null +++ b/packages/backend/migration/1688280713783-add-meta-options.js @@ -0,0 +1,21 @@ +export class AddMetaOptions1688280713783 { + name = "AddMetaOptions1688280713783"; + + async up(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" ADD "enableServerMachineStats" boolean NOT NULL DEFAULT false`, + ); + await queryRunner.query( + `ALTER TABLE "meta" ADD "enableIdenticonGeneration" boolean NOT NULL DEFAULT true`, + ); + } + + async down(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "enableIdenticonGeneration"`, + ); + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "enableServerMachineStats"`, + ); + } +} diff --git a/packages/backend/src/daemons/server-stats.ts b/packages/backend/src/daemons/server-stats.ts index c936d619ab..ba74278762 100644 --- a/packages/backend/src/daemons/server-stats.ts +++ b/packages/backend/src/daemons/server-stats.ts @@ -1,6 +1,7 @@ import si from "systeminformation"; import Xev from "xev"; import * as osUtils from "os-utils"; +import { fetchMeta } from "@/misc/fetch-meta.js"; import meilisearch from "../db/meilisearch.js"; const ev = new Xev(); @@ -20,6 +21,9 @@ export default function () { ev.emit(`serverStatsLog:${x.id}`, log.slice(0, x.length || 50)); }); + const meta = fetchMeta(); + if (!meta.enableServerMachineStats) return; + async function tick() { const cpu = await cpuUsage(); const memStats = await mem(); diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index dd3c5b3b72..200ef50552 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -546,4 +546,14 @@ export class Meta { default: {}, }) public experimentalFeatures: Record; + + @Column("boolean", { + default: false, + }) + public enableServerMachineStats: boolean; + + @Column("boolean", { + default: true, + }) + public enableIdenticonGeneration: boolean; } diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 3193301275..50317d4a81 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -481,6 +481,16 @@ export const meta = { }, }, }, + enableServerMachineStats: { + type: "boolean", + optional: false, + nullable: false, + }, + enableIdenticonGeneration: { + type: "boolean", + optional: false, + nullable: false, + }, }, }, } as const; @@ -592,5 +602,7 @@ export default define(meta, paramDef, async (ps, me) => { enableIpLogging: instance.enableIpLogging, enableActiveEmailValidation: instance.enableActiveEmailValidation, experimentalFeatures: instance.experimentalFeatures, + enableServerMachineStats: instance.enableServerMachineStats, + enableIdenticonGeneration: instance.enableIdenticonGeneration, }; }); diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index 81bb053db4..746eae6621 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -2,11 +2,13 @@ import * as os from "node:os"; import si from "systeminformation"; import define from "../define.js"; import meilisearch from "@/db/meilisearch.js"; +import { fetchMeta } from "@/misc/fetch-meta.js"; export const meta = { requireCredential: false, requireCredentialPrivateMode: true, - + allowGet: true, + cacheSec: 30, tags: ["meta"], } as const; @@ -29,6 +31,23 @@ export default define(meta, paramDef, async () => { } } + const instanceMeta = await fetchMeta(); + if (!instanceMeta.enableServerMachineStats) { + return { + machine: 'Not specified', + cpu: { + model: 'Not specified', + cores: 0, + }, + mem: { + total: 0, + }, + fs: { + total: 0, + used: 0, + }, + }; + } return { machine: os.hostname(), cpu: { diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts index 95d570eb3d..7f8d0ed718 100644 --- a/packages/backend/src/server/index.ts +++ b/packages/backend/src/server/index.ts @@ -16,6 +16,7 @@ import { IsNull } from "typeorm"; import config from "@/config/index.js"; import Logger from "@/services/logger.js"; import { UserProfiles, Users } from "@/models/index.js"; +import { fetchMeta } from "@/misc/fetch-meta.js"; import { genIdenticon } from "@/misc/gen-identicon.js"; import { createTemp } from "@/misc/create-temp.js"; import { publishMainStream } from "@/services/stream.js"; @@ -125,10 +126,16 @@ router.get("/avatar/@:acct", async (ctx) => { }); router.get("/identicon/:x", async (ctx) => { - const [temp, cleanup] = await createTemp(); - await genIdenticon(ctx.params.x, fs.createWriteStream(temp)); - ctx.set("Content-Type", "image/png"); - ctx.body = fs.createReadStream(temp).on("close", () => cleanup()); + const meta = await fetchMeta(); + if (meta.enableIdenticonGeneration) { + const [temp, cleanup] = await createTemp(); + await genIdenticon(ctx.params.x, fs.createWriteStream(temp)); + ctx.set("Content-Type", "image/png"); + ctx.body = fs.createReadStream(temp).on("close", () => cleanup()); + } + else { + ctx.redirect("/static-assets/avatar.png") + } }); mastoRouter.get("/oauth/authorize", async (ctx) => { diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index e67c44b0a4..0e83250bac 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -343,6 +343,17 @@ + + + + + + + + + + + @@ -442,6 +453,8 @@ let libreTranslateApiUrl: string = $ref(""); let libreTranslateApiKey: string = $ref(""); let defaultReaction: string = $ref(""); let defaultReactionCustom: string = $ref(""); +let enableServerMachineStats: boolean = $ref(false); +let enableIdenticonGeneration: boolean = $ref(false); async function init() { const meta = await os.api("admin/meta"); @@ -482,6 +495,8 @@ async function init() { defaultReactionCustom = ["⭐", "👍", "❤️"].includes(meta.defaultReaction) ? "" : meta.defaultReaction; + enableServerMachineStats = meta.enableServerMachineStats; + enableIdenticonGeneration = meta.enableIdenticonGeneration; } function save() { @@ -521,6 +536,8 @@ function save() { libreTranslateApiUrl, libreTranslateApiKey, defaultReaction, + enableServerMachineStats, + enableIdenticonGeneration, }).then(() => { fetchInstance(); }); diff --git a/packages/client/src/widgets/server-metric/index.vue b/packages/client/src/widgets/server-metric/index.vue index cf84212b1e..49dc59ea27 100644 --- a/packages/client/src/widgets/server-metric/index.vue +++ b/packages/client/src/widgets/server-metric/index.vue @@ -106,7 +106,7 @@ const { widgetProps, configure, save } = useWidgetPropsManager( const meta = ref(null); -os.api("server-info", {}).then((res) => { +os.apiGet("server-info", {}).then((res) => { meta.value = res; });