diff --git a/packages/backend/migration/1695937489995-enableAchievements.js b/packages/backend/migration/1695937489995-enableAchievements.js new file mode 100644 index 000000000..2c20971ff --- /dev/null +++ b/packages/backend/migration/1695937489995-enableAchievements.js @@ -0,0 +1,11 @@ +export class EnableAchievements1695937489995 { + name = 'EnableAchievements1695937489995' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "enableAchievements" boolean NOT NULL DEFAULT true`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableAchievements"`); + } +} \ No newline at end of file diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index e69bef8e9..b699eec8e 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -449,6 +449,11 @@ export class MiMeta { }) public enableIdenticonGeneration: boolean; + @Column('boolean', { + default: true, + }) + public enableAchievements: boolean; + @Column('jsonb', { default: { }, }) diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index c3ba07cdd..c9a16cd89 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -282,6 +282,10 @@ export const meta = { type: 'boolean', optional: false, nullable: false, }, + enableAchievements: { + type: 'boolean', + optional: false, nullable: false, + }, enableIdenticonGeneration: { type: 'boolean', optional: false, nullable: false, @@ -396,6 +400,7 @@ export default class extends Endpoint { // eslint- enableChartsForRemoteUser: instance.enableChartsForRemoteUser, enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances, enableServerMachineStats: instance.enableServerMachineStats, + enableAchievements: instance.enableAchievements, enableIdenticonGeneration: instance.enableIdenticonGeneration, policies: { ...DEFAULT_POLICIES, ...instance.policies }, manifestJsonOverride: instance.manifestJsonOverride, 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 ea6ebdd1f..9f6ad8e10 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -104,6 +104,7 @@ export const paramDef = { enableChartsForRemoteUser: { type: 'boolean' }, enableChartsForFederatedInstances: { type: 'boolean' }, enableServerMachineStats: { type: 'boolean' }, + enableAchievements: { type: 'boolean' }, enableIdenticonGeneration: { type: 'boolean' }, serverRules: { type: 'array', items: { type: 'string' } }, preservedUsernames: { type: 'array', items: { type: 'string' } }, @@ -425,6 +426,10 @@ export default class extends Endpoint { // eslint- set.enableServerMachineStats = ps.enableServerMachineStats; } + if (ps.enableAchievements !== undefined) { + set.enableAchievements = ps.enableAchievements; + } + if (ps.enableIdenticonGeneration !== undefined) { set.enableIdenticonGeneration = ps.enableIdenticonGeneration; } diff --git a/packages/backend/src/server/api/endpoints/i/claim-achievement.ts b/packages/backend/src/server/api/endpoints/i/claim-achievement.ts index b24b3438d..303c0a7f8 100644 --- a/packages/backend/src/server/api/endpoints/i/claim-achievement.ts +++ b/packages/backend/src/server/api/endpoints/i/claim-achievement.ts @@ -6,6 +6,7 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { AchievementService, ACHIEVEMENT_TYPES } from '@/core/AchievementService.js'; +import { MetaService } from '@/core/MetaService.js'; export const meta = { requireCredential: true, @@ -24,8 +25,12 @@ export const paramDef = { export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( private achievementService: AchievementService, + private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { + const meta = await this.metaService.fetch(); + if (!meta.enableAchievements) return; + await this.achievementService.create(me.id, ps.name); }); } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index fa6486ed1..976380e6f 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -304,6 +304,7 @@ export default class extends Endpoint { // eslint- enableHcaptcha: instance.enableHcaptcha, hcaptchaSiteKey: instance.hcaptchaSiteKey, enableRecaptcha: instance.enableRecaptcha, + enableAchievements: instance.enableAchievements, recaptchaSiteKey: instance.recaptchaSiteKey, enableTurnstile: instance.enableTurnstile, turnstileSiteKey: instance.turnstileSiteKey, diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts index 7f182a98f..a7e8f512a 100644 --- a/packages/frontend/src/navbar.ts +++ b/packages/frontend/src/navbar.ts @@ -12,6 +12,7 @@ import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { ui } from '@/config.js'; import { unisonReload } from '@/scripts/unison-reload.js'; +import { instance } from './instance.js'; export const navbarItemDef = reactive({ notifications: { @@ -104,7 +105,7 @@ export const navbarItemDef = reactive({ achievements: { title: i18n.ts.achievements, icon: 'ti ti-medal', - show: computed(() => $i != null), + show: computed(() => $i != null && instance.enableAchievements), to: '/my/achievements', }, ui: { diff --git a/packages/frontend/src/pages/admin/other-settings.vue b/packages/frontend/src/pages/admin/other-settings.vue index 7574c9d7d..1eadf54c7 100644 --- a/packages/frontend/src/pages/admin/other-settings.vue +++ b/packages/frontend/src/pages/admin/other-settings.vue @@ -16,6 +16,13 @@ SPDX-License-Identifier: AGPL-3.0-only +
+ + + + +
+
@@ -53,6 +60,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js'; import MkSwitch from '@/components/MkSwitch.vue'; let enableServerMachineStats: boolean = $ref(false); +let enableAchievements: boolean = $ref(false); let enableIdenticonGeneration: boolean = $ref(false); let enableChartsForRemoteUser: boolean = $ref(false); let enableChartsForFederatedInstances: boolean = $ref(false); @@ -60,6 +68,7 @@ let enableChartsForFederatedInstances: boolean = $ref(false); async function init() { const meta = await os.api('admin/meta'); enableServerMachineStats = meta.enableServerMachineStats; + enableAchievements = meta.enableAchievements; enableIdenticonGeneration = meta.enableIdenticonGeneration; enableChartsForRemoteUser = meta.enableChartsForRemoteUser; enableChartsForFederatedInstances = meta.enableChartsForFederatedInstances; @@ -68,6 +77,7 @@ async function init() { function save() { os.apiWithDialog('admin/update-meta', { enableServerMachineStats, + enableAchievements, enableIdenticonGeneration, enableChartsForRemoteUser, enableChartsForFederatedInstances, diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index edc5bb273..0f874875f 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -344,6 +344,7 @@ export type LiteInstanceMetadata = { enableTwitterIntegration: boolean; enableGithubIntegration: boolean; enableDiscordIntegration: boolean; + enableAchievements: boolean; enableServiceWorker: boolean; emojis: CustomEmoji[]; defaultDarkTheme: string | null;