From 3b71c6393e702a45d1ffeaa8a8dcd65e76a4d88f Mon Sep 17 00:00:00 2001 From: suzulu Date: Wed, 12 Feb 2025 20:11:44 +0900 Subject: [PATCH 01/12] rebuild i18n --- locales/index.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/locales/index.d.ts b/locales/index.d.ts index d88ff02ee93..be0e5b6cb95 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5588,6 +5588,10 @@ export interface Locale extends ILocale { * CWに絵文字を挿入 */ "cwInsertEmoji": string; + /** + * サーバーと一緒にリアクションもミュートする + */ + "reactionAndServerMute": string; "_accountSettings": { /** * コンテンツの表示にログインを必須にする From 45a6de07d0992ffe14aa3dbff93bcffbd603e020 Mon Sep 17 00:00:00 2001 From: suzulu Date: Wed, 12 Feb 2025 20:12:10 +0900 Subject: [PATCH 02/12] =?UTF-8?q?point/send=E3=82=A8=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/models/Notification.ts | 6 ++ .../backend/src/server/api/EndpointsModule.ts | 4 ++ packages/backend/src/server/api/endpoints.ts | 2 + .../src/server/api/endpoints/point/send.ts | 63 +++++++++++++++++++ packages/misskey-js/etc/misskey-js.api.md | 3 + 5 files changed, 78 insertions(+) create mode 100644 packages/backend/src/server/api/endpoints/point/send.ts diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index c0cfc1c5631..0aac7e2ff5d 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -58,6 +58,12 @@ export type MiNotification = { id: string; createdAt: string; loginBonus: number; +} | { + type: 'sendPoint'; + id: string; + createdAt: string; + getPoint: number; + senderId: MiUser['id']; } | { type: 'pollEnded'; id: string; diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index c97681942b2..072869fb74e 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -394,6 +394,7 @@ import * as ep___users_search from './endpoints/users/search.js'; import * as ep___users_show from './endpoints/users/show.js'; import * as ep___users_achievements from './endpoints/users/achievements.js'; import * as ep___users_updateMemo from './endpoints/users/update-memo.js'; +import * as ep___point_send from './endpoints/point/send.js'; import * as ep___fetchRss from './endpoints/fetch-rss.js'; import * as ep___fetchExternalResources from './endpoints/fetch-external-resources.js'; import * as ep___retention from './endpoints/retention.js'; @@ -801,6 +802,7 @@ const $users_search: Provider = { provide: 'ep:users/search', useClass: ep___use const $users_show: Provider = { provide: 'ep:users/show', useClass: ep___users_show.default }; const $users_achievements: Provider = { provide: 'ep:users/achievements', useClass: ep___users_achievements.default }; const $users_updateMemo: Provider = { provide: 'ep:users/update-memo', useClass: ep___users_updateMemo.default }; +const $point_send: Provider = { provide: 'ep:point/send', useClass: ep___point_send.default }; const $fetchRss: Provider = { provide: 'ep:fetch-rss', useClass: ep___fetchRss.default }; const $fetchExternalResources: Provider = { provide: 'ep:fetch-external-resources', useClass: ep___fetchExternalResources.default }; const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention.default }; @@ -1211,6 +1213,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $users_show, $users_achievements, $users_updateMemo, + $point_send, $fetchRss, $fetchExternalResources, $retention, @@ -1612,6 +1615,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $users_show, $users_achievements, $users_updateMemo, + $point_send, $fetchRss, $fetchExternalResources, $retention, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index ad96657f744..509b405a89e 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -403,6 +403,7 @@ import * as ep___users_search from './endpoints/users/search.js'; import * as ep___users_show from './endpoints/users/show.js'; import * as ep___users_achievements from './endpoints/users/achievements.js'; import * as ep___users_updateMemo from './endpoints/users/update-memo.js'; +import * as ep___point_send from './endpoints/point/send.js'; import * as ep___fetchRss from './endpoints/fetch-rss.js'; import * as ep___fetchExternalResources from './endpoints/fetch-external-resources.js'; import * as ep___retention from './endpoints/retention.js'; @@ -806,6 +807,7 @@ const eps = [ ['users/show', ep___users_show], ['users/achievements', ep___users_achievements], ['users/update-memo', ep___users_updateMemo], + ['point/send', ep___point_send], ['fetch-rss', ep___fetchRss], ['fetch-external-resources', ep___fetchExternalResources], ['retention', ep___retention], diff --git a/packages/backend/src/server/api/endpoints/point/send.ts b/packages/backend/src/server/api/endpoints/point/send.ts new file mode 100644 index 00000000000..ab52993a3d9 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/point/send.ts @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { UsersRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; +import { NotificationService } from '@/core/NotificationService.js'; + +export const meta = { + tag: ['point'], + requireCredential: true, + kind: 'write:points', + secure: true, +} as const; + +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + points: { type: 'number' }, + }, + required: ['userId', 'points'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + private notificationService: NotificationService, + ) { + super(meta, paramDef, async (ps, me) => { + const sender = await this.usersRepository.findOneBy({ id: me.id }); + const user = await this.usersRepository.findOneBy({ id: ps.userId }); + + if (sender == null || user == null) { + throw new Error('user not found'); + } + //送れるかどうかチェック + if (sender.getPoints < ps.points) { + throw new Error('not enough points'); + } + + //ポイントを送る + await this.usersRepository.update(sender.id, { + getPoints: sender.getPoints - ps.points, + }); + await this.usersRepository.update(user.id, { + getPoints: user.getPoints + ps.points, + }); + + this.notificationService.createNotification(user.id, 'sendPoint', { + getPoint: ps.points, + senderId: sender.id, + }); + + return {}; + }); + } +} diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 26d53b9f8c2..cb76d5fe3e6 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -1865,6 +1865,7 @@ declare namespace entities { UsersAchievementsRequest, UsersAchievementsResponse, UsersUpdateMemoRequest, + PointSendRequest, FetchRssRequest, FetchRssResponse, FetchExternalResourcesRequest, @@ -3525,6 +3526,8 @@ type UsersShowResponse = operations['users___show']['responses']['200']['content // @public (undocumented) type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['content']['application/json']; +// @public (undocumented) +type PointSendRequest = operations['point___send']['requestBody']['content']['application/json'] // Warnings were encountered during analysis: // // src/entities.ts:50:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts From 4774311527027e8937ca8102e493f9307be6c970 Mon Sep 17 00:00:00 2001 From: suzulu Date: Sun, 16 Feb 2025 03:01:47 +0900 Subject: [PATCH 03/12] =?UTF-8?q?=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88?= =?UTF-8?q?=E9=80=81=E4=BF=A1=E3=83=9D=E3=83=AA=E3=82=B7=E3=83=BC=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + packages/backend/src/core/RoleService.ts | 3 +++ packages/frontend-shared/js/const.ts | 1 + .../frontend/src/pages/admin/roles.editor.vue | 21 ++++++++++++++++++- packages/frontend/src/pages/admin/roles.vue | 7 +++++++ 6 files changed, 36 insertions(+), 1 deletion(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index be0e5b6cb95..c21ea823626 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -7357,6 +7357,10 @@ export interface Locale extends ILocale { * ログインボーナスの付与 */ "loginBonusGrantEnabled": string; + /** + * ポイントの送信 + */ + "canSendPoints": string; /** * 絵文字ピッカーのプロファイルの上限数(最大5) */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 88e4863be2a..13b44357d9f 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1900,6 +1900,7 @@ _role: _options: gtlAvailable: "グローバルタイムラインの閲覧" loginBonusGrantEnabled: "ログインボーナスの付与" + canSendPoints: "ポイントの送信" emojiPickerProfileLimit: "絵文字ピッカーのプロファイルの上限数(最大5)" ltlAvailable: "ローカルタイムラインの閲覧" canPublicNote: "パブリック投稿の許可" diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index f553fa744c0..f2d8581924c 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -65,6 +65,7 @@ export type RolePolicies = { listPinnedLimit: number; localTimelineAnyLimit: number; loginBonusGrantEnabled: boolean; + canSendPoints: boolean; canImportAntennas: boolean; canImportBlocking: boolean; canImportFollowing: boolean; @@ -111,6 +112,7 @@ export const DEFAULT_POLICIES: RolePolicies = { listPinnedLimit: 2, localTimelineAnyLimit: 3, loginBonusGrantEnabled: true, + canSendPoints: false, }; @Injectable() @@ -423,6 +425,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { listPinnedLimit: calc('listPinnedLimit', vs => Math.max(...vs)), localTimelineAnyLimit: calc('localTimelineAnyLimit', vs => Math.max(...vs)), loginBonusGrantEnabled: calc('loginBonusGrantEnabled', vs => vs.some(v => v === true)), + canSendPoints: calc('canSendPoints', vs => vs.some(v => v === true)), }; } diff --git a/packages/frontend-shared/js/const.ts b/packages/frontend-shared/js/const.ts index db1e8f518f3..b2c6b141008 100644 --- a/packages/frontend-shared/js/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -109,6 +109,7 @@ export const ROLE_POLICIES = [ 'listPinnedLimit', 'localTimelineAnyLimit', 'loginBonusGrantEnabled', + 'canSendPoints', 'canImportAntennas', 'canImportBlocking', 'canImportFollowing', diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index f59d914132c..b8c016fedcc 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -427,7 +427,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +