summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-03-25 13:41:12 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2025-03-25 13:41:12 +0900
commitc51e862b7de460cd7c1b57a63a002156bbfe1b49 (patch)
tree2c6742d38fcc1683a84291ace41d8247182c502c /packages
parentfix(backend): 自分がオーナーではない参加中のルームにメッ... (diff)
downloadsharkey-c51e862b7de460cd7c1b57a63a002156bbfe1b49.tar.gz
sharkey-c51e862b7de460cd7c1b57a63a002156bbfe1b49.tar.bz2
sharkey-c51e862b7de460cd7c1b57a63a002156bbfe1b49.zip
enhance: 送信したチャットルームへの招待を確認できるように
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/src/core/ChatService.ts10
-rw-r--r--packages/backend/src/server/api/endpoint-list.ts1
-rw-r--r--packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts67
-rw-r--r--packages/frontend/src/pages/chat/room.members.vue32
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md8
-rw-r--r--packages/misskey-js/src/autogen/apiClientJSDoc.ts11
-rw-r--r--packages/misskey-js/src/autogen/endpoint.ts3
-rw-r--r--packages/misskey-js/src/autogen/entities.ts2
-rw-r--r--packages/misskey-js/src/autogen/types.ts69
9 files changed, 200 insertions, 3 deletions
diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts
index 3b73a0f6ba..062ca96f17 100644
--- a/packages/backend/src/core/ChatService.ts
+++ b/packages/backend/src/core/ChatService.ts
@@ -548,6 +548,16 @@ export class ChatService {
}
@bindThis
+ public async getSentRoomInvitationsWithPagination(roomId: MiChatRoom['id'], limit: number, sinceId?: MiChatRoomInvitation['id'] | null, untilId?: MiChatRoomInvitation['id'] | null) {
+ const query = this.queryService.makePaginationQuery(this.chatRoomInvitationsRepository.createQueryBuilder('invitation'), sinceId, untilId)
+ .where('invitation.roomId = :roomId', { roomId });
+
+ const invitations = await query.take(limit).getMany();
+
+ return invitations;
+ }
+
+ @bindThis
public async getOwnedRoomsWithPagination(ownerId: MiUser['id'], limit: number, sinceId?: MiChatRoom['id'] | null, untilId?: MiChatRoom['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomsRepository.createQueryBuilder('room'), sinceId, untilId)
.where('room.ownerId = :ownerId', { ownerId });
diff --git a/packages/backend/src/server/api/endpoint-list.ts b/packages/backend/src/server/api/endpoint-list.ts
index 9bb29e138b..c8cb87e0ab 100644
--- a/packages/backend/src/server/api/endpoint-list.ts
+++ b/packages/backend/src/server/api/endpoint-list.ts
@@ -417,5 +417,6 @@ export * as 'chat/rooms/members' from './endpoints/chat/rooms/members.js';
export * as 'chat/rooms/invitations/create' from './endpoints/chat/rooms/invitations/create.js';
export * as 'chat/rooms/invitations/ignore' from './endpoints/chat/rooms/invitations/ignore.js';
export * as 'chat/rooms/invitations/inbox' from './endpoints/chat/rooms/invitations/inbox.js';
+export * as 'chat/rooms/invitations/outbox' from './endpoints/chat/rooms/invitations/outbox.js';
export * as 'chat/history' from './endpoints/chat/history.js';
export * as 'v2/admin/emoji/list' from './endpoints/v2/admin/emoji/list.js';
diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts
new file mode 100644
index 0000000000..12d496e94b
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts
@@ -0,0 +1,67 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import ms from 'ms';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { DI } from '@/di-symbols.js';
+import { ApiError } from '@/server/api/error.js';
+import { ChatService } from '@/core/ChatService.js';
+import { ChatEntityService } from '@/core/entities/ChatEntityService.js';
+
+export const meta = {
+ tags: ['chat'],
+
+ requireCredential: true,
+
+ kind: 'read:chat',
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'ChatRoomInvitation',
+ },
+ },
+
+ errors: {
+ noSuchRoom: {
+ message: 'No such room.',
+ code: 'NO_SUCH_ROOM',
+ id: 'a3c6b309-9717-4316-ae94-a69b53437237',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ roomId: { type: 'string', format: 'misskey:id' },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 },
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['roomId'],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private chatService: ChatService,
+ private chatEntityService: ChatEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const room = await this.chatService.findMyRoomById(me.id, ps.roomId);
+ if (room == null) {
+ throw new ApiError(meta.errors.noSuchRoom);
+ }
+
+ const invitations = await this.chatService.getSentRoomInvitationsWithPagination(ps.roomId, ps.limit, ps.sinceId, ps.untilId);
+ return this.chatEntityService.packRoomInvitations(invitations, me);
+ });
+ }
+}
diff --git a/packages/frontend/src/pages/chat/room.members.vue b/packages/frontend/src/pages/chat/room.members.vue
index d20216a81c..2b31efab38 100644
--- a/packages/frontend/src/pages/chat/room.members.vue
+++ b/packages/frontend/src/pages/chat/room.members.vue
@@ -18,6 +18,18 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkUserCardMini :user="membership.user"/>
</MkA>
</div>
+
+ <template v-if="isOwner">
+ <hr>
+
+ <div>{{ i18n.ts._chat.sentInvitations }}</div>
+
+ <div v-for="invitation in invitations" :key="invitation.id" :class="$style.invitation">
+ <MkA :class="$style.invitationBody" :to="`${userPage(invitation.user)}`">
+ <MkUserCardMini :user="invitation.user"/>
+ </MkA>
+ </div>
+ </template>
</div>
</template>
@@ -47,12 +59,20 @@ const isOwner = computed(() => {
});
const memberships = ref<Misskey.entities.ChatRoomMembership[]>([]);
+const invitations = ref<Misskey.entities.ChatRoomInvitation[]>([]);
onMounted(async () => {
memberships.value = await misskeyApi('chat/rooms/members', {
roomId: props.room.id,
limit: 50,
});
+
+ if (isOwner.value) {
+ invitations.value = await misskeyApi('chat/rooms/invitations/outbox', {
+ roomId: props.room.id,
+ limit: 50,
+ });
+ }
});
</script>
@@ -65,9 +85,15 @@ onMounted(async () => {
flex: 1;
min-width: 0;
margin-right: 8px;
+}
- &:hover {
- text-decoration: none;
- }
+.invitation {
+ display: flex;
+}
+
+.invitationBody {
+ flex: 1;
+ min-width: 0;
+ margin-right: 8px;
}
</style>
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index e79cd794a6..8610a21304 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -1047,6 +1047,12 @@ type ChatRoomsInvitationsInboxRequest = operations['chat___rooms___invitations__
type ChatRoomsInvitationsInboxResponse = operations['chat___rooms___invitations___inbox']['responses']['200']['content']['application/json'];
// @public (undocumented)
+type ChatRoomsInvitationsOutboxRequest = operations['chat___rooms___invitations___outbox']['requestBody']['content']['application/json'];
+
+// @public (undocumented)
+type ChatRoomsInvitationsOutboxResponse = operations['chat___rooms___invitations___outbox']['responses']['200']['content']['application/json'];
+
+// @public (undocumented)
type ChatRoomsJoiningRequest = operations['chat___rooms___joining']['requestBody']['content']['application/json'];
// @public (undocumented)
@@ -1619,6 +1625,8 @@ declare namespace entities {
ChatRoomsInvitationsIgnoreResponse,
ChatRoomsInvitationsInboxRequest,
ChatRoomsInvitationsInboxResponse,
+ ChatRoomsInvitationsOutboxRequest,
+ ChatRoomsInvitationsOutboxResponse,
ChatRoomsJoinRequest,
ChatRoomsJoinResponse,
ChatRoomsJoiningRequest,
diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
index e12ba0d6b2..e5d0b94a10 100644
--- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts
+++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
@@ -1691,6 +1691,17 @@ declare module '../api.js' {
/**
* No description provided.
*
+ * **Credential required**: *Yes* / **Permission**: *read:chat*
+ */
+ request<E extends 'chat/rooms/invitations/outbox', P extends Endpoints[E]['req']>(
+ endpoint: E,
+ params: P,
+ credential?: string | null,
+ ): Promise<SwitchCaseResponseType<E, P>>;
+
+ /**
+ * No description provided.
+ *
* **Credential required**: *Yes* / **Permission**: *write:chat*
*/
request<E extends 'chat/rooms/join', P extends Endpoints[E]['req']>(
diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts
index 558f4ab514..1dfdb53320 100644
--- a/packages/misskey-js/src/autogen/endpoint.ts
+++ b/packages/misskey-js/src/autogen/endpoint.ts
@@ -235,6 +235,8 @@ import type {
ChatRoomsInvitationsIgnoreResponse,
ChatRoomsInvitationsInboxRequest,
ChatRoomsInvitationsInboxResponse,
+ ChatRoomsInvitationsOutboxRequest,
+ ChatRoomsInvitationsOutboxResponse,
ChatRoomsJoinRequest,
ChatRoomsJoinResponse,
ChatRoomsJoiningRequest,
@@ -784,6 +786,7 @@ export type Endpoints = {
'chat/rooms/invitations/create': { req: ChatRoomsInvitationsCreateRequest; res: ChatRoomsInvitationsCreateResponse };
'chat/rooms/invitations/ignore': { req: ChatRoomsInvitationsIgnoreRequest; res: ChatRoomsInvitationsIgnoreResponse };
'chat/rooms/invitations/inbox': { req: ChatRoomsInvitationsInboxRequest; res: ChatRoomsInvitationsInboxResponse };
+ 'chat/rooms/invitations/outbox': { req: ChatRoomsInvitationsOutboxRequest; res: ChatRoomsInvitationsOutboxResponse };
'chat/rooms/join': { req: ChatRoomsJoinRequest; res: ChatRoomsJoinResponse };
'chat/rooms/joining': { req: ChatRoomsJoiningRequest; res: ChatRoomsJoiningResponse };
'chat/rooms/leave': { req: ChatRoomsLeaveRequest; res: ChatRoomsLeaveResponse };
diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts
index bb21272e01..0e3ca7202e 100644
--- a/packages/misskey-js/src/autogen/entities.ts
+++ b/packages/misskey-js/src/autogen/entities.ts
@@ -238,6 +238,8 @@ export type ChatRoomsInvitationsIgnoreRequest = operations['chat___rooms___invit
export type ChatRoomsInvitationsIgnoreResponse = operations['chat___rooms___invitations___ignore']['responses']['200']['content']['application/json'];
export type ChatRoomsInvitationsInboxRequest = operations['chat___rooms___invitations___inbox']['requestBody']['content']['application/json'];
export type ChatRoomsInvitationsInboxResponse = operations['chat___rooms___invitations___inbox']['responses']['200']['content']['application/json'];
+export type ChatRoomsInvitationsOutboxRequest = operations['chat___rooms___invitations___outbox']['requestBody']['content']['application/json'];
+export type ChatRoomsInvitationsOutboxResponse = operations['chat___rooms___invitations___outbox']['responses']['200']['content']['application/json'];
export type ChatRoomsJoinRequest = operations['chat___rooms___join']['requestBody']['content']['application/json'];
export type ChatRoomsJoinResponse = operations['chat___rooms___join']['responses']['200']['content']['application/json'];
export type ChatRoomsJoiningRequest = operations['chat___rooms___joining']['requestBody']['content']['application/json'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 31bc34e473..3acef22101 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -1484,6 +1484,15 @@ export type paths = {
*/
post: operations['chat___rooms___invitations___inbox'];
};
+ '/chat/rooms/invitations/outbox': {
+ /**
+ * chat/rooms/invitations/outbox
+ * @description No description provided.
+ *
+ * **Credential required**: *Yes* / **Permission**: *read:chat*
+ */
+ post: operations['chat___rooms___invitations___outbox'];
+ };
'/chat/rooms/join': {
/**
* chat/rooms/join
@@ -14738,6 +14747,66 @@ export type operations = {
};
};
/**
+ * chat/rooms/invitations/outbox
+ * @description No description provided.
+ *
+ * **Credential required**: *Yes* / **Permission**: *read:chat*
+ */
+ chat___rooms___invitations___outbox: {
+ requestBody: {
+ content: {
+ 'application/json': {
+ /** Format: misskey:id */
+ roomId: string;
+ /** @default 30 */
+ limit?: number;
+ /** Format: misskey:id */
+ sinceId?: string;
+ /** Format: misskey:id */
+ untilId?: string;
+ };
+ };
+ };
+ responses: {
+ /** @description OK (with results) */
+ 200: {
+ content: {
+ 'application/json': components['schemas']['ChatRoomInvitation'][];
+ };
+ };
+ /** @description Client error */
+ 400: {
+ content: {
+ 'application/json': components['schemas']['Error'];
+ };
+ };
+ /** @description Authentication error */
+ 401: {
+ content: {
+ 'application/json': components['schemas']['Error'];
+ };
+ };
+ /** @description Forbidden error */
+ 403: {
+ content: {
+ 'application/json': components['schemas']['Error'];
+ };
+ };
+ /** @description I'm Ai */
+ 418: {
+ content: {
+ 'application/json': components['schemas']['Error'];
+ };
+ };
+ /** @description Internal server error */
+ 500: {
+ content: {
+ 'application/json': components['schemas']['Error'];
+ };
+ };
+ };
+ };
+ /**
* chat/rooms/join
* @description No description provided.
*