summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2024-10-14 15:52:02 +0000
committerHazelnoot <acomputerdog@gmail.com>2024-10-14 15:52:02 +0000
commitb15f25758a2b33aa9b9136f005c805617a2f650a (patch)
tree1c9c375ab2743a339ee8b8b7b80a7839fd3e4434
parentmerge: try to avoid `insert` races in `FederatedInstanceService` (!683) (diff)
parentrestore missing hasPendingReceivedFollowRequest in navbar (diff)
downloadsharkey-b15f25758a2b33aa9b9136f005c805617a2f650a.tar.gz
sharkey-b15f25758a2b33aa9b9136f005c805617a2f650a.tar.bz2
sharkey-b15f25758a2b33aa9b9136f005c805617a2f650a.zip
merge: feat: Allow users to view pending follow requests they sent (!663)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663 Approved-by: Hazelnoot <acomputerdog@gmail.com> Approved-by: Marie <github@yuugi.dev>
-rw-r--r--locales/en-US.yml1
-rw-r--r--packages/backend/src/core/entities/UserEntityService.ts8
-rw-r--r--packages/backend/src/models/json-schema/user.ts4
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts3
-rw-r--r--packages/backend/src/server/api/endpoints.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/following/requests/sent.ts77
-rw-r--r--packages/backend/test/e2e/users.ts4
-rw-r--r--packages/frontend/src/navbar.ts2
-rw-r--r--packages/frontend/src/pages/follow-requests.vue92
-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.ts4
-rw-r--r--packages/misskey-js/src/autogen/entities.ts2
-rw-r--r--packages/misskey-js/src/autogen/types.ts73
14 files changed, 257 insertions, 34 deletions
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 70c06ab326..2fb4700fcf 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -111,6 +111,7 @@ followRequest: "Send follow request"
followRequests: "Follow requests"
unfollow: "Unfollow"
followRequestPending: "Follow request pending"
+pendingFollowRequests: "Pending follow requests"
enterEmoji: "Enter an emoji"
renote: "Boost"
unrenote: "Remove boost"
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index d465e2cd4c..fc66f7a507 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -375,6 +375,13 @@ export class UserEntityService implements OnModuleInit {
}
@bindThis
+ public async getHasPendingSentFollowRequest(userId: MiUser['id']): Promise<boolean> {
+ return this.followRequestsRepository.existsBy({
+ followerId: userId,
+ });
+ }
+
+ @bindThis
public getOnlineStatus(user: MiUser): 'unknown' | 'online' | 'active' | 'offline' {
if (user.hideOnlineStatus) return 'unknown';
if (user.lastActiveDate == null) return 'unknown';
@@ -642,6 +649,7 @@ export class UserEntityService implements OnModuleInit {
hasUnreadChannel: false, // 後方互換性のため
hasUnreadNotification: notificationsInfo?.hasUnread, // 後方互換性のため
hasPendingReceivedFollowRequest: this.getHasPendingReceivedFollowRequest(user.id),
+ hasPendingSentFollowRequest: this.getHasPendingSentFollowRequest(user.id),
unreadNotificationsCount: notificationsInfo?.unreadCount,
mutedWords: profile!.mutedWords,
hardMutedWords: profile!.hardMutedWords,
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index 24b6c50e93..0eef413759 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -578,6 +578,10 @@ export const packedMeDetailedOnlySchema = {
type: 'boolean',
nullable: false, optional: false,
},
+ hasPendingSentFollowRequest: {
+ type: 'boolean',
+ nullable: false, optional: false,
+ },
unreadNotificationsCount: {
type: 'number',
nullable: false, optional: false,
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index c90a23d7b5..8434e7e8e3 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -189,6 +189,7 @@ import * as ep___following_invalidate from './endpoints/following/invalidate.js'
import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
import * as ep___following_requests_list from './endpoints/following/requests/list.js';
+import * as ep___following_requests_sent from './endpoints/following/requests/sent.js';
import * as ep___following_requests_reject from './endpoints/following/requests/reject.js';
import * as ep___gallery_featured from './endpoints/gallery/featured.js';
import * as ep___gallery_popular from './endpoints/gallery/popular.js';
@@ -586,6 +587,7 @@ const $following_invalidate: Provider = { provide: 'ep:following/invalidate', us
const $following_requests_accept: Provider = { provide: 'ep:following/requests/accept', useClass: ep___following_requests_accept.default };
const $following_requests_cancel: Provider = { provide: 'ep:following/requests/cancel', useClass: ep___following_requests_cancel.default };
const $following_requests_list: Provider = { provide: 'ep:following/requests/list', useClass: ep___following_requests_list.default };
+const $following_requests_sent: Provider = { provide: 'ep:following/requests/sent', useClass: ep___following_requests_sent.default };
const $following_requests_reject: Provider = { provide: 'ep:following/requests/reject', useClass: ep___following_requests_reject.default };
const $gallery_featured: Provider = { provide: 'ep:gallery/featured', useClass: ep___gallery_featured.default };
const $gallery_popular: Provider = { provide: 'ep:gallery/popular', useClass: ep___gallery_popular.default };
@@ -987,6 +989,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
$following_requests_accept,
$following_requests_cancel,
$following_requests_list,
+ $following_requests_sent,
$following_requests_reject,
$gallery_featured,
$gallery_popular,
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index e93e57f907..bb5c71d78c 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -195,6 +195,7 @@ import * as ep___following_invalidate from './endpoints/following/invalidate.js'
import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
import * as ep___following_requests_list from './endpoints/following/requests/list.js';
+import * as ep___following_requests_sent from './endpoints/following/requests/sent.js';
import * as ep___following_requests_reject from './endpoints/following/requests/reject.js';
import * as ep___gallery_featured from './endpoints/gallery/featured.js';
import * as ep___gallery_popular from './endpoints/gallery/popular.js';
@@ -590,6 +591,7 @@ const eps = [
['following/requests/accept', ep___following_requests_accept],
['following/requests/cancel', ep___following_requests_cancel],
['following/requests/list', ep___following_requests_list],
+ ['following/requests/sent', ep___following_requests_sent],
['following/requests/reject', ep___following_requests_reject],
['gallery/featured', ep___gallery_featured],
['gallery/popular', ep___gallery_popular],
diff --git a/packages/backend/src/server/api/endpoints/following/requests/sent.ts b/packages/backend/src/server/api/endpoints/following/requests/sent.ts
new file mode 100644
index 0000000000..6325f01bb8
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/following/requests/sent.ts
@@ -0,0 +1,77 @@
+/*
+ * 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 { QueryService } from '@/core/QueryService.js';
+import type { FollowRequestsRepository } from '@/models/_.js';
+import { FollowRequestEntityService } from '@/core/entities/FollowRequestEntityService.js';
+import { DI } from '@/di-symbols.js';
+
+export const meta = {
+ tags: ['following', 'account'],
+
+ requireCredential: true,
+
+ kind: 'read:following',
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ properties: {
+ id: {
+ type: 'string',
+ optional: false, nullable: false,
+ format: 'id',
+ },
+ follower: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'UserLite',
+ },
+ followee: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'UserLite',
+ },
+ },
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
+ },
+ required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ @Inject(DI.followRequestsRepository)
+ private followRequestsRepository: FollowRequestsRepository,
+
+ private followRequestEntityService: FollowRequestEntityService,
+ private queryService: QueryService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const query = this.queryService.makePaginationQuery(this.followRequestsRepository.createQueryBuilder('request'), ps.sinceId, ps.untilId)
+ .andWhere('request.followerId = :meId', { meId: me.id });
+
+ const requests = await query
+ .limit(ps.limit)
+ .getMany();
+
+ return await this.followRequestEntityService.packMany(requests, me);
+ });
+ }
+}
diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts
index eb56f7bebf..e5057d0489 100644
--- a/packages/backend/test/e2e/users.ts
+++ b/packages/backend/test/e2e/users.ts
@@ -7,9 +7,9 @@ process.env.NODE_ENV = 'test';
import * as assert from 'assert';
import { inspect } from 'node:util';
-import { DEFAULT_POLICIES } from '@/core/RoleService.js';
import { api, post, role, signup, successfulApiCall, uploadFile } from '../utils.js';
import type * as misskey from 'misskey-js';
+import { DEFAULT_POLICIES } from '@/core/RoleService.js';
describe('ユーザー', () => {
// エンティティとしてのユーザーを主眼においたテストを記述する
@@ -139,6 +139,7 @@ describe('ユーザー', () => {
hasUnreadNotification: user.hasUnreadNotification,
unreadNotificationsCount: user.unreadNotificationsCount,
hasPendingReceivedFollowRequest: user.hasPendingReceivedFollowRequest,
+ hasPendingSentFollowRequest: user.hasPendingSentFollowRequest,
unreadAnnouncements: user.unreadAnnouncements,
mutedWords: user.mutedWords,
hardMutedWords: user.hardMutedWords,
@@ -378,6 +379,7 @@ describe('ユーザー', () => {
assert.strictEqual(response.hasUnreadNotification, false);
assert.strictEqual(response.unreadNotificationsCount, 0);
assert.strictEqual(response.hasPendingReceivedFollowRequest, false);
+ assert.strictEqual(response.hasPendingSentFollowRequest, false);
assert.deepStrictEqual(response.unreadAnnouncements, []);
assert.deepStrictEqual(response.mutedWords, []);
assert.deepStrictEqual(response.mutedInstances, []);
diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts
index b6385b5ad2..e545b8ff73 100644
--- a/packages/frontend/src/navbar.ts
+++ b/packages/frontend/src/navbar.ts
@@ -41,7 +41,7 @@ export const navbarItemDef = reactive({
followRequests: {
title: i18n.ts.followRequests,
icon: 'ti ti-user-plus',
- show: computed(() => $i != null && $i.isLocked),
+ show: computed(() => $i != null && ($i.isLocked || $i.hasPendingReceivedFollowRequest || $i.hasPendingSentFollowRequest)),
indicated: computed(() => $i != null && $i.hasPendingReceivedFollowRequest),
to: '/my/follow-requests',
},
diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue
index d50887b2e9..400dfdbe6d 100644
--- a/packages/frontend/src/pages/follow-requests.vue
+++ b/packages/frontend/src/pages/follow-requests.vue
@@ -5,39 +5,43 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkStickyContainer>
- <template #header><MkPageHeader/></template>
+ <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="800">
- <MkPagination ref="paginationComponent" :pagination="pagination">
- <template #empty>
- <div class="_fullinfo">
- <img :src="infoImageUrl" class="_ghost"/>
- <div>{{ i18n.ts.noFollowRequests }}</div>
- </div>
- </template>
- <template #default="{items}">
- <div class="mk-follow-requests">
- <div v-for="req in items" :key="req.id" class="user _panel">
- <MkAvatar class="avatar" :user="req.follower" indicator link preview/>
- <div class="body">
- <div class="name">
- <MkA v-user-preview="req.follower.id" class="name" :to="userPage(req.follower)"><MkUserName :user="req.follower"/></MkA>
- <p class="acct">@{{ acct(req.follower) }}</p>
- </div>
- <div class="commands">
- <MkButton class="command" rounded primary @click="accept(req.follower)"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
- <MkButton class="command" rounded danger @click="reject(req.follower)"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+ <MkHorizontalSwipe v-model:tab="tab" :tabs="headerTabs">
+ <div :key="tab" class="_gaps">
+ <MkPagination ref="paginationComponent" :pagination="pagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" class="_ghost"/>
+ <div>{{ i18n.ts.noFollowRequests }}</div>
+ </div>
+ </template>
+ <template #default="{items}">
+ <div class="mk-follow-requests">
+ <div v-for="req in items" :key="req.id" class="user _panel">
+ <MkAvatar class="avatar" :user="displayUser(req)" indicator link preview/>
+ <div class="body">
+ <div class="name">
+ <MkA v-user-preview="displayUser(req).id" class="name" :to="userPage(displayUser(req))"><MkUserName :user="displayUser(req)"/></MkA>
+ <p class="acct">@{{ acct(displayUser(req)) }}</p>
+ </div>
+ <div v-if="tab === 'list'" class="commands">
+ <MkButton class="command" rounded primary @click="accept(displayUser(req))"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
+ <MkButton class="command" rounded danger @click="reject(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+ </div>
+ </div>
</div>
</div>
- </div>
- </div>
- </template>
- </MkPagination>
+ </template>
+ </MkPagination>
+ </div>
+ </MkHorizontalSwipe>
</MkSpacer>
</MkStickyContainer>
</template>
<script lang="ts" setup>
-import { shallowRef, computed } from 'vue';
+import { shallowRef, computed, ref } from 'vue';
import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
import { userPage, acct } from '@/filters/user.js';
@@ -45,29 +49,53 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { infoImageUrl } from '@/instance.js';
+import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
+import { $i } from '@/account';
const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
-const pagination = {
- endpoint: 'following/requests/list' as const,
- limit: 10,
-};
+const pagination = computed(() => tab.value === 'list'
+ ? {
+ endpoint: 'following/requests/list' as const,
+ limit: 10,
+ }
+ : {
+ endpoint: 'following/requests/sent' as const,
+ limit: 10,
+ },
+);
function accept(user) {
misskeyApi('following/requests/accept', { userId: user.id }).then(() => {
- paginationComponent.value.reload();
+ paginationComponent.value?.reload();
});
}
function reject(user) {
misskeyApi('following/requests/reject', { userId: user.id }).then(() => {
- paginationComponent.value.reload();
+ paginationComponent.value?.reload();
});
}
+function displayUser(req) {
+ return tab.value === 'list' ? req.follower : req.followee;
+}
+
const headerActions = computed(() => []);
-const headerTabs = computed(() => []);
+const headerTabs = computed(() => [
+ {
+ key: 'list',
+ title: i18n.ts.followRequests,
+ icon: 'ph-envelope ph-bold ph-lg',
+ }, {
+ key: 'sent',
+ title: i18n.ts.pendingFollowRequests,
+ icon: 'ph-paper-plane-tilt ph-bold ph-lg',
+ },
+]);
+
+const tab = ref($i?.isLocked || !$i.hasPendingSentFollowRequest ? 'list' : 'sent');
definePageMetadata(() => ({
title: i18n.ts.followRequests,
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index d2a82f4901..b85bbd4421 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -1502,6 +1502,8 @@ declare namespace entities {
FollowingRequestsCancelResponse,
FollowingRequestsListRequest,
FollowingRequestsListResponse,
+ FollowingRequestsSentRequest,
+ FollowingRequestsSentResponse,
FollowingRequestsRejectRequest,
GalleryFeaturedRequest,
GalleryFeaturedResponse,
@@ -2024,6 +2026,12 @@ type FollowingRequestsListResponse = operations['following___requests___list']['
type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json'];
// @public (undocumented)
+type FollowingRequestsSentRequest = operations['following___requests___sent']['requestBody']['content']['application/json'];
+
+// @public (undocumented)
+type FollowingRequestsSentResponse = operations['following___requests___sent']['responses']['200']['content']['application/json'];
+
+// @public (undocumented)
type FollowingUpdateAllRequest = operations['following___update-all']['requestBody']['content']['application/json'];
// @public (undocumented)
diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
index 20e3a6e545..9a3d2849b9 100644
--- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts
+++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
@@ -2032,6 +2032,17 @@ declare module '../api.js' {
/**
* No description provided.
*
+ * **Credential required**: *Yes* / **Permission**: *read:following*
+ */
+ request<E extends 'following/requests/sent', P extends Endpoints[E]['req']>(
+ endpoint: E,
+ params: P,
+ credential?: string | null,
+ ): Promise<SwitchCaseResponseType<E, P>>;
+
+ /**
+ * No description provided.
+ *
* **Credential required**: *Yes* / **Permission**: *write:following*
*/
request<E extends 'following/requests/reject', P extends Endpoints[E]['req']>(
diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts
index 2652f40cf9..95c75d2b52 100644
--- a/packages/misskey-js/src/autogen/endpoint.ts
+++ b/packages/misskey-js/src/autogen/endpoint.ts
@@ -280,6 +280,8 @@ import type {
FollowingRequestsCancelResponse,
FollowingRequestsListRequest,
FollowingRequestsListResponse,
+ FollowingRequestsSentRequest,
+ FollowingRequestsSentResponse,
FollowingRequestsRejectRequest,
GalleryFeaturedRequest,
GalleryFeaturedResponse,
@@ -774,6 +776,7 @@ export type Endpoints = {
'following/requests/accept': { req: FollowingRequestsAcceptRequest; res: EmptyResponse };
'following/requests/cancel': { req: FollowingRequestsCancelRequest; res: FollowingRequestsCancelResponse };
'following/requests/list': { req: FollowingRequestsListRequest; res: FollowingRequestsListResponse };
+ 'following/requests/sent': { req: FollowingRequestsSentRequest; res: FollowingRequestsSentResponse };
'following/requests/reject': { req: FollowingRequestsRejectRequest; res: EmptyResponse };
'gallery/featured': { req: GalleryFeaturedRequest; res: GalleryFeaturedResponse };
'gallery/popular': { req: EmptyRequest; res: GalleryPopularResponse };
@@ -1170,6 +1173,7 @@ export const endpointReqTypes: Record<keyof Endpoints, 'application/json' | 'mul
'following/requests/accept': 'application/json',
'following/requests/cancel': 'application/json',
'following/requests/list': 'application/json',
+ 'following/requests/sent': 'application/json',
'following/requests/reject': 'application/json',
'gallery/featured': 'application/json',
'gallery/popular': 'application/json',
diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts
index fc14551f3f..a0b6bce63c 100644
--- a/packages/misskey-js/src/autogen/entities.ts
+++ b/packages/misskey-js/src/autogen/entities.ts
@@ -283,6 +283,8 @@ export type FollowingRequestsCancelRequest = operations['following___requests___
export type FollowingRequestsCancelResponse = operations['following___requests___cancel']['responses']['200']['content']['application/json'];
export type FollowingRequestsListRequest = operations['following___requests___list']['requestBody']['content']['application/json'];
export type FollowingRequestsListResponse = operations['following___requests___list']['responses']['200']['content']['application/json'];
+export type FollowingRequestsSentRequest = operations['following___requests___sent']['requestBody']['content']['application/json'];
+export type FollowingRequestsSentResponse = operations['following___requests___sent']['responses']['200']['content']['application/json'];
export type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json'];
export type GalleryFeaturedRequest = operations['gallery___featured']['requestBody']['content']['application/json'];
export type GalleryFeaturedResponse = operations['gallery___featured']['responses']['200']['content']['application/json'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 0453fd0a36..4bebaf8d9a 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -1770,6 +1770,15 @@ export type paths = {
*/
post: operations['following___requests___list'];
};
+ '/following/requests/sent': {
+ /**
+ * following/requests/sent
+ * @description No description provided.
+ *
+ * **Credential required**: *Yes* / **Permission**: *read:following*
+ */
+ post: operations['following___requests___sent'];
+ };
'/following/requests/reject': {
/**
* following/requests/reject
@@ -3962,6 +3971,7 @@ export type components = {
hasUnreadChannel: boolean;
hasUnreadNotification: boolean;
hasPendingReceivedFollowRequest: boolean;
+ hasPendingSentFollowRequest: boolean;
unreadNotificationsCount: number;
mutedWords: string[][];
hardMutedWords: string[][];
@@ -16245,6 +16255,69 @@ export type operations = {
};
};
/**
+ * following/requests/sent
+ * @description No description provided.
+ *
+ * **Credential required**: *Yes* / **Permission**: *read:following*
+ */
+ following___requests___sent: {
+ requestBody: {
+ content: {
+ 'application/json': {
+ /** Format: misskey:id */
+ sinceId?: string;
+ /** Format: misskey:id */
+ untilId?: string;
+ /** @default 10 */
+ limit?: number;
+ };
+ };
+ };
+ responses: {
+ /** @description OK (with results) */
+ 200: {
+ content: {
+ 'application/json': {
+ /** Format: id */
+ id: string;
+ follower: components['schemas']['UserLite'];
+ followee: components['schemas']['UserLite'];
+ }[];
+ };
+ };
+ /** @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'];
+ };
+ };
+ };
+ };
+ /**
* following/requests/reject
* @description No description provided.
*